Android使用MediaRecorder類進(jìn)行錄制視頻
腳本之家提醒大家使用MediaRecorder錄音錄像的設(shè)置代碼步驟一定要按照API指定的順序來(lái)設(shè)置,否則報(bào)錯(cuò)
步驟為:
1、設(shè)置視頻源,音頻源,即輸入源
2、設(shè)置輸出格式
3、設(shè)置音視頻的編碼格式
一、首先看布局文件,這里有一個(gè)SurfaceView,這是一個(gè)繪制容器,可以直接從內(nèi)存或者DMA等硬件接口取得圖像數(shù)據(jù),
<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">
<!-- 開(kāi)始錄制按鈕 -->
<Button
android:id="@+id/startRecord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="btnStartRecord"
android:text="開(kāi)始錄制"
/>
<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、首先看下成員變量
// 開(kāi)始錄制,停止錄制按鈕 private Button startRecord,stopRecord; // 顯示預(yù)覽的SurfaceView private SurfaceView surfaceView; // 標(biāo)記,判斷當(dāng)前是否正在錄制 boolean isRunning = false; // 錄制類 private MediaRecorder recorder; // 存儲(chǔ)文件 private File saveFile;
2、onCreate()方法中進(jìn)行一些初始化
startRecord = (Button) findViewById(R.id.startRecord);
stopRecord = (Button) findViewById(R.id.stopRecord);
surfaceView = (SurfaceView) findViewById(R.id.surView);
// onCreate()初始化 ,一開(kāi)始肯定沒(méi)有開(kāi)始錄制,所以停止按鈕不可點(diǎn)擊
stopRecord.setEnabled(false);
// 設(shè)置Surface不需要維護(hù)自己的緩沖區(qū)
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// 設(shè)置分辨率
surfaceView.getHolder().setFixedSize(320, 280);
// 設(shè)置該組件不會(huì)讓屏幕自動(dòng)關(guān)閉
surfaceView.getHolder().setKeepScreenOn(true);
3、現(xiàn)在看“開(kāi)始錄制”監(jiān)聽(tīng)事件
----3.1
創(chuàng)建MediaRecorder對(duì)象 recorder = new MediaRecorder(); recorder.reset();
----3.2 設(shè)置三步,順序固定
//1.設(shè)置采集聲音 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); //設(shè)置采集圖像 recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); //2.設(shè)置視頻,音頻的輸出格式 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //3.設(shè)置音頻的編碼格式 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); //設(shè)置圖像的編碼格式 recorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
----3.3 其他可選設(shè)置,更多請(qǐng)查看API
//設(shè)置立體聲 recorder.setAudioChannels(2); //設(shè)置最大錄像時(shí)間 單位:毫秒 recorder.setMaxDuration(600000); //設(shè)置最大錄制的大小 單位,字節(jié) recorder.setMaxFileSize(1024*1024); //音頻一秒鐘包含多少數(shù)據(jù)位 recorder.setAudioEncodingBitRate(128); //設(shè)置選擇角度,順時(shí)針?lè)较?,因?yàn)槟J(rèn)是逆向90度的,這樣圖像就是正常顯示了,這里設(shè)置的是觀看保存后的視頻的角度 recorder.setOrientationHint(90); //設(shè)置錄像的分辨率 recorder.setVideoSize(176, 144);
----3.4 設(shè)置文件存儲(chǔ)路徑,這里簡(jiǎn)陋了,實(shí)際開(kāi)發(fā)中需要判斷是否有外部存儲(chǔ),是否有目標(biāo)目錄 ,是否已經(jīng)存在相同名字的文件 等問(wèn)題
//設(shè)置輸出文件路徑
saveFile = new File(Environment.getExternalStorageDirectory()
.getCanonicalFile() + "/myvideo.mp4");
recorder.setOutputFile(saveFile.getAbsolutePath());
----3.5 使用SurfaceView進(jìn)行預(yù)覽
recorder.setPreviewDisplay(surfaceView.getHolder().getSurface());
----3.6 開(kāi)始錄制
recorder.prepare(); //開(kāi)始錄制 recorder.start(); //讓開(kāi)始按鈕不可點(diǎn)擊,停止按鈕可點(diǎn)擊 startRecord.setEnabled(false); stopRecord.setEnabled(true); isRunning = true;
----3.7 停止錄制
//停止錄制 recorder.stop(); //釋放資源 recorder.release(); recorder = null; //設(shè)置開(kāi)始按鈕可點(diǎn)擊,停止按鈕不可點(diǎn)擊 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 {
// 開(kāi)始錄制,停止錄制按鈕
private Button startRecord,stopRecord;
// 顯示預(yù)覽的SurfaceView
private SurfaceView surfaceView;
// 標(biāo)記,判斷當(dāng)前是否正在錄制
boolean isRunning = false;
// 錄制類
private MediaRecorder recorder;
// 存儲(chǔ)文件
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()初始化 ,一開(kāi)始肯定沒(méi)有開(kāi)始錄制,所以停止按鈕不可點(diǎn)擊
stopRecord.setEnabled(false);
// 設(shè)置Surface不需要維護(hù)自己的緩沖區(qū)
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// 設(shè)置分辨率
surfaceView.getHolder().setFixedSize(, );
// 設(shè)置該組件不會(huì)讓屏幕自動(dòng)關(guān)閉
surfaceView.getHolder().setKeepScreenOn(true);
}
/**
* 開(kāi)始錄制
* @param view
*/
public void btnStartRecord(View view) {
// 首先判斷當(dāng)前是否處理視頻錄制狀態(tài),只有不是錄制狀態(tài)的時(shí)候,才可以開(kāi)始錄制
if (!isRunning){
try {
//創(chuàng)建MediaRecorder對(duì)象
recorder = new MediaRecorder();
recorder.reset();
//.設(shè)置采集聲音
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//設(shè)置采集圖像
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//.設(shè)置視頻,音頻的輸出格式
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_);
//.設(shè)置音頻的編碼格式
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//設(shè)置圖像的編碼格式
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H);
//設(shè)置立體聲
recorder.setAudioChannels();
//設(shè)置最大錄像時(shí)間 單位:毫秒
recorder.setMaxDuration();
//設(shè)置最大錄制的大小 單位,字節(jié)
recorder.setMaxFileSize(*);
//音頻一秒鐘包含多少數(shù)據(jù)位
recorder.setAudioEncodingBitRate();
//設(shè)置選擇角度,順時(shí)針?lè)较颍驗(yàn)槟J(rèn)是逆向度的,這樣圖像就是正常顯示了,這里設(shè)置的是觀看保存后的視頻的角度
recorder.setOrientationHint();
//設(shè)置輸出文件路徑
// saveFile = FileUtils.getMediaRecoderFolder(this);
saveFile = new File(Environment.getExternalStorageDirectory()
.getCanonicalFile() + "/myvideo.mp");
// recorder.setVideoSize(, );
// recorder.setVideoFrameRate();
recorder.setOutputFile(saveFile.getAbsolutePath());
//使用SurfaceView預(yù)覽
recorder.setPreviewDisplay(surfaceView.getHolder().getSurface());
recorder.prepare();
//開(kāi)始錄制
recorder.start();
//讓開(kāi)始按鈕不可點(diǎn)擊,停止按鈕可點(diǎn)擊
startRecord.setEnabled(false);
stopRecord.setEnabled(true);
isRunning = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 結(jié)束錄制
* @param view
*/
public void btnStopRecord(View view) {
if (isRunning){
//停止錄制
recorder.stop();
//釋放資源
recorder.release();
recorder = null;
//設(shè)置開(kāi)始按鈕可點(diǎn)擊,停止按鈕不可點(diǎn)擊
startRecord.setEnabled(true);
stopRecord.setEnabled(false);
}
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
}
本例子只是一個(gè)簡(jiǎn)單的Demo,用于給剛接觸MediaRecorder音頻錄制的coder學(xué)習(xí),存在一些Bug和不足,各位coder可以繼續(xù)拓展
不足:
1、只有當(dāng)點(diǎn)擊“開(kāi)始錄制”的時(shí)候SurfaceView組件才可以看到攝像頭拍攝的預(yù)覽,否則是一篇黑,這里可以看下Canera類,進(jìn)行相應(yīng)的調(diào)整
2、保存路徑,需要判斷是否有外部存儲(chǔ),存儲(chǔ)空間是否足夠,路徑是否不存在,是否有已有的文件名相同的文件存在等問(wèn)題,設(shè)置文件的名字,我這里是固定路徑固定文件名
3、攝像預(yù)覽效果是有90度旋轉(zhuǎn)的,這里需要大家個(gè)人去看下MedioRecoder的API 去進(jìn)行設(shè)置
4、沒(méi)有設(shè)置對(duì)焦,像素不清楚,攝像寬高變形
相關(guān)文章
解決RecyclerView無(wú)法onItemClick問(wèn)題的兩種方法
這篇文章主要介紹了解決RecyclerView無(wú)法onItemClick問(wèn)題的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看下吧2016-07-07
Android 出現(xiàn)“Can''t bind to local 8602 for debugger”錯(cuò)誤的解決方法
這篇文章主要介紹了Android 出現(xiàn)“Can't bind to local 8602 for debugger”錯(cuò)誤的解決方法的相關(guān)資料,需要的朋友可以參考下2017-03-03
Android編程顯示網(wǎng)絡(luò)上的圖片實(shí)例詳解
這篇文章主要介紹了Android編程顯示網(wǎng)絡(luò)上的圖片,結(jié)合實(shí)例形式詳細(xì)分析了Android顯示網(wǎng)絡(luò)圖片的流程與具體操作技巧,需要的朋友可以參考下2016-10-10
Android用TextView實(shí)現(xiàn)跑馬燈效果代碼
大家好,本篇文章主要講的是Android?TextView實(shí)現(xiàn)跑馬燈效果代碼,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01
融會(huì)貫通Android?Jetpack?Compose中的Snackbar
這篇文章主要為大家介紹了融會(huì)貫通Android?Jetpack?Compose中的Snackbar方法及使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Android實(shí)現(xiàn)大圖滾動(dòng)顯示效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)大圖滾動(dòng)顯示效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
Android?Compose之Animatable動(dòng)畫(huà)停止使用詳解
這篇文章主要為大家介紹了Android?Compose之Animatable動(dòng)畫(huà)停止使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03

