1. 程式人生 > >Android 小視訊錄製

Android 小視訊錄製

一·視訊錄製介面 SurfaceView 的使用 SurfaceView我們可以把它當作一個容器,它放在所有視窗的下面·提供了一個可見區域,通過SurfaceHolder介面訪問這個surface,getHolder()方法可以得到這個介面,它相當於SurfaceView 的控制器 然後通過呼叫addCallback();方法就可以進入它的生命週期開始使用 二·Camera的使用 1.在 Android Manifest.xml 中宣告相機許可權 2. 開啟相機裝置 3. 配置相機引數 4. 設定相機預覽方向 5. ~~使用 6. 釋放相機裝置 三·視訊錄製控制元件MediaRecorder的使用
 對MediaRecorder的總結(乾貨) http://blog.csdn.net/qisan__/article/details/79251205


許可權 <uses-permissionandroid:name="android.permission.CAMERA"/> <uses-permissionandroid:name="android.permission.RECORD_AUDIO"/> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 1:設定SurfaceView: SurfaceView surfaceView = (SurfaceView) findViewById(R.id.record_surfaceView); 拿到SurfaceView的控制器 mSurfaceHolder = surfaceView.getHolder(); 設定型別 mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 四種SurfaceView的型別 SURFACE_TYPE_NORMAL:用RAM快取原生資料的普通Surface SURFACE_TYPE_HARDWARE:適用於DMA(Direct memory access )引擎和硬體加速的Surface SURFACE_TYPE_GPU:適用於GPU加速的Surface SURFACE_TYPE_PUSH_BUFFERS:表明該Surface不包含原生資料,Surface用到的資料由其他物件提供,在Camera影象預覽中就使用該型別的Surface,有Camera負責提供給預覽Surface資料,這樣影象預覽會比較流暢。如果設定這種型別則就不能呼叫lockCanvas來獲取Canvas物件了。 設定解析度 mSurfaceHolder.setFixedSize(320, 280); 設定該元件不會讓螢幕自動關閉 mSurfaceHolder.setKeepScreenOn(true); 實現CallBack初始化SurfaceHolder進入生命週期 mSurfaceHolder.addCallback(mCallBack); private SurfaceHolder.Callback mCallBack = new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { 初始化相機 initCamera(); } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) { if (mSurfaceHolder.getSurface() == null) { return; } } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { 關閉相機 stopCamera(); } }; 2·初始化相機並且配置 private void initCamera() { if (mCamera != null) { stopCamera(); } //預設啟動後置攝像頭 mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); if (mCamera == null) { Toast.makeText(this, "未能獲取到相機!", Toast.LENGTH_SHORT).show(); return; } try { //顯示映視 mCamera.setPreviewDisplay(mSurfaceHolder); //配置CameraParams if (mCamera != null) { Camera.Parameters params = mCamera.getParameters(); //設定相機的橫豎螢幕 if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) { //豎屏 params.set("orientation", "portrait"); mCamera.setDisplayOrientation(90); } else { //橫屏 params.set("orientation", "landscape"); mCamera.setDisplayOrientation(0); } //設定聚焦模式 params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); //縮短Recording啟動時間 params.setRecordingHint(true); //是否支援影像穩定能力,支援則開啟 if (params.isVideoStabilizationSupported()) params.setVideoStabilization(true); mCamera.setParameters(params); } //啟動相機預覽 mCamera.startPreview(); } catch (IOException e) { Log.d("TAG", "Error starting camera preview: " + e.getMessage()); } } 設定停止相機工作方法 private void stopCamera() { if (mCamera != null) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera = null; } } 基本都是固定的套路 接下來給開始和停止按鈕設定點選事件 開始呼叫star(); 停止呼叫stop(); private void Start() { 判斷路徑File物件是否建立成功或者有此路徑 boolean creakOk = createRecordDir(); if (!creakOk) { return; } 初始化相機 initCamera(); 設定錄影前需要將相機解鎖 (非常重要) mCamera.unlock(); 初始化MediaRecorder
setConfigRecord(); try { //開始錄製 mediaRecorder.prepare(); mediaRecorder.start(); } catch (IOException e) { e.printStackTrace(); } 把是否正在錄製的狀態改變 isRecording = true; } private void setConfigRecord() { mediaRecorder = new MediaRecorder(); 建立 mediaRecorder.reset(); 設定為空閒模式 可以賦屬性了 mediaRecorder.setCamera(mCamera); 設定一個攝像頭用於錄製。 mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() { @Override public void onError(MediaRecorder mr, int what, int extra) { try { if (mediaRecorder != null) { mediaRecorder.reset(); } } catch (Exception e) { e.printStackTrace(); } } }); 記錄錄製時出現的錯誤的監聽器,呼叫reset();方法設定為空閒模式 //使用SurfaceView預覽 mediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); //1.設定採集聲音 mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); //設定採集影象 mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); //2.設定視訊,音訊的輸出格式 mp4 mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); //3.設定音訊的編碼格式 mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); //設定影象的編碼格式 mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); //音訊一秒鐘包含多少資料位 CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P); mediaRecorder.setAudioEncodingBitRate(44100); if (mProfile.videoBitRate > 2 * 1024 * 1024) mediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024); else mediaRecorder.setVideoEncodingBitRate(1024 * 1024); mediaRecorder.setVideoFrameRate(mProfile.videoFrameRate); //設定選擇角度,順時針方向,因為預設是逆向90度的,這樣影象就是正常顯示了,這裡設定的是觀看儲存後的視訊的角度 mediaRecorder.setOrientationHint(90); //設定錄影的解析度 mediaRecorder.setVideoSize(352, 288); 儲存 mediaRecorder.setOutputFile(mVecordFile.getAbsolutePath()); } 判斷路徑File物件是否建立成功或者有此路徑返回Boolean值 private boolean createRecordDir() { if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { Toast.makeText(this, "請檢視您的SD卡是否存在!", Toast.LENGTH_SHORT).show(); return false; } File targetDir = Environment. getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES); if (!targetDir.exists()) { targetDir.mkdirs(); } mVecordFile = new File(targetDir, SystemClock.currentThreadTimeMillis() + ".mp4"); return true; } private void stop() { if (isRecording && mediaRecorder != null) { 將監聽還有預覽設定為空避免崩潰 mediaRecorder.setOnErrorListener(null); mediaRecorder.setPreviewDisplay(null); //停止錄製 mediaRecorder.stop(); mediaRecorder.reset(); //釋放資源 mediaRecorder.release(); mediaRecorder = null; isRecording = false; } 吐司一下視屏存放位置 Toast.makeText(this, ""+mVecordFile.getAbsolutePath(), Toast.LENGTH_LONG).show(); }