雲棲社區提醒大家使用MediaRecorder錄音錄影的設定代碼步驟一定要按照API指定的順序來設定,否則報錯
步驟為:
1、設定視頻源,音頻源,即輸入源
2、設定輸出格式
3、設定音視頻的編碼格式
一、首先看布局檔案,這裡有一個SurfaceView,這是一個繪製容器,可以直接從記憶體或者DMA等硬體介面取得映像資料,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.xqx.mediarecorder.app.WorkRecorder"> <!-- 開始錄製按鈕 --> <Button android:id="@+id/startRecord" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="btnStartRecord" android:text="開始錄製" /> <Button android:id="@+id/stopRecord" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="btnStopRecord" android:text="停止錄製" /> <SurfaceView android:id="@+id/surView" android:layout_width="match_parent" android:layout_height="match_parent"/></LinearLayout>
二、Activity 代碼
1、首先看下成員變數
// 開始錄製,停止錄製按鈕 private Button startRecord,stopRecord; // 顯示預覽的SurfaceView private SurfaceView surfaceView; // 標記,判斷當前是否正在錄製 boolean isRunning = false; // 錄製類 private MediaRecorder recorder; // 隱藏檔 private File saveFile;
2、onCreate()方法中進行一些初始化
startRecord = (Button) findViewById(R.id.startRecord);
stopRecord = (Button) findViewById(R.id.stopRecord);
surfaceView = (SurfaceView) findViewById(R.id.surView);
// onCreate()初始化 ,一開始肯定沒有開始錄製,所以停止按鈕不可點擊
stopRecord.setEnabled(false);
// 設定Surface不需要維護自己的緩衝區
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// 設定解析度
surfaceView.getHolder().setFixedSize(320, 280);
// 設定該組件不會讓螢幕自動關閉
surfaceView.getHolder().setKeepScreenOn(true);
3、現在看“開始錄製”監聽事件
----3.1
建立MediaRecorder對象 recorder = new MediaRecorder(); recorder.reset();
----3.2 設定三步,順序固定
//1.設定採集聲音recorder.setAudioSource(MediaRecorder.AudioSource.MIC);//設定採集映像recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//2.設定視頻,音訊輸出格式recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//3.設定音訊編碼格式recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);//設定映像的編碼格式recorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
----3.3 其他可選設定,更多請查看API
//設定立體聲recorder.setAudioChannels(2);//設定最大錄影時間 單位:毫秒recorder.setMaxDuration(600000);//設定最大錄製的大小 單位,位元組recorder.setMaxFileSize(1024*1024);//音頻一秒鐘包含多少資料位元recorder.setAudioEncodingBitRate(128);//設定選擇角度,順時針方向,因為預設是逆向90度的,這樣映像就是正常顯示了,這裡設定的是觀看儲存後的視頻的角度recorder.setOrientationHint(90);//設定錄影的解析度recorder.setVideoSize(176, 144);
----3.4 設定檔案儲存體路徑,這裡簡陋了,實際開發中需要判斷是否有外部儲存,是否有目標目錄 ,是否已經存在相同名字的檔案 等問題
//設定輸出檔案路徑
saveFile = new File(Environment.getExternalStorageDirectory() .getCanonicalFile() + "/myvideo.mp4");recorder.setOutputFile(saveFile.getAbsolutePath());
----3.5 使用SurfaceView進行預覽
recorder.setPreviewDisplay(surfaceView.getHolder().getSurface());
----3.6 開始錄製
recorder.prepare();//開始錄製recorder.start();//讓開始按鈕不可點擊,停止按鈕可點擊startRecord.setEnabled(false);stopRecord.setEnabled(true);isRunning = true;
----3.7 停止錄製
//停止錄製recorder.stop();//釋放資源recorder.release();recorder = null;//設定開始按鈕可點擊,停止按鈕不可點擊startRecord.setEnabled(true);stopRecord.setEnabled(false);
完整代碼:
package com.xqx.mediarecorder.app; import android.app.Activity; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; import android.hardware.Camera; import java.io.File; import java.io.IOException; public class WorkRecorder extends Activity implements Camera.PreviewCallback { // 開始錄製,停止錄製按鈕 private Button startRecord,stopRecord; // 顯示預覽的SurfaceView private SurfaceView surfaceView; // 標記,判斷當前是否正在錄製 boolean isRunning = false; // 錄製類 private MediaRecorder recorder; // 隱藏檔 private File saveFile; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_work_recorder); startRecord = (Button) findViewById(R.id.startRecord); stopRecord = (Button) findViewById(R.id.stopRecord); surfaceView = (SurfaceView) findViewById(R.id.surView); // onCreate()初始化 ,一開始肯定沒有開始錄製,所以停止按鈕不可點擊 stopRecord.setEnabled(false); // 設定Surface不需要維護自己的緩衝區 surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 設定解析度 surfaceView.getHolder().setFixedSize(, ); // 設定該組件不會讓螢幕自動關閉 surfaceView.getHolder().setKeepScreenOn(true); } /** * 開始錄製 * @param view */ public void btnStartRecord(View view) { // 首先判斷當前是否處理視頻錄製狀態,只有不是錄製狀態的時候,才可以開始錄製 if (!isRunning){ try { //建立MediaRecorder對象 recorder = new MediaRecorder(); recorder.reset(); //.設定採集聲音 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); //設定採集映像 recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); //.設定視頻,音訊輸出格式 recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_); //.設定音訊編碼格式 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); //設定映像的編碼格式 recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H); //設定立體聲 recorder.setAudioChannels(); //設定最大錄影時間 單位:毫秒 recorder.setMaxDuration(); //設定最大錄製的大小 單位,位元組 recorder.setMaxFileSize(*); //音頻一秒鐘包含多少資料位元 recorder.setAudioEncodingBitRate(); //設定選擇角度,順時針方向,因為預設是逆向度的,這樣映像就是正常顯示了,這裡設定的是觀看儲存後的視頻的角度 recorder.setOrientationHint(); //設定輸出檔案路徑 // saveFile = FileUtils.getMediaRecoderFolder(this); saveFile = new File(Environment.getExternalStorageDirectory() .getCanonicalFile() + "/myvideo.mp"); // recorder.setVideoSize(, ); // recorder.setVideoFrameRate(); recorder.setOutputFile(saveFile.getAbsolutePath()); //使用SurfaceView預覽 recorder.setPreviewDisplay(surfaceView.getHolder().getSurface()); recorder.prepare(); //開始錄製 recorder.start(); //讓開始按鈕不可點擊,停止按鈕可點擊 startRecord.setEnabled(false); stopRecord.setEnabled(true); isRunning = true; } catch (IOException e) { e.printStackTrace(); } } } /** * 結束錄製 * @param view */ public void btnStopRecord(View view) { if (isRunning){ //停止錄製 recorder.stop(); //釋放資源 recorder.release(); recorder = null; //設定開始按鈕可點擊,停止按鈕不可點擊 startRecord.setEnabled(true); stopRecord.setEnabled(false); } } @Override public void onPreviewFrame(byte[] data, Camera camera) { } }
本例子只是一個簡單的Demo,用於給剛接觸MediaRecorder音頻錄製的coder學習,存在一些Bug和不足,各位coder可以繼續拓展
不足:
1、只有當點擊“開始錄製”的時候SurfaceView組件才可以看到網路攝影機拍攝的預覽,否則是一篇黑,這裡可以看下Canera類,進行相應的調整
2、儲存路徑,需要判斷是否有外部儲存,儲存空間是否足夠,路徑是否不存在,是否有已有的檔案名稱相同的檔案存在等問題,設定檔案的名字,我這裡是固定路徑固定檔案名稱
3、攝像預覽效果是有90度旋轉的,這裡需要大家個人去看下MedioRecoder的API 去進行設定
4、沒有設定對焦,像素不清楚,攝像寬高變形