aac mediarecorder录制_Android音视频录制之MediaRecorder+camera
前言
本篇介紹使用Android 中視頻錄制,錄制工具是:
MediaRecorder : 視頻編碼封裝
camera : 視頻畫面原始數據采集
TextureView : 提供預覽畫面
MediaRecorder基本api介紹
MediaRecorder是android中面向應用層的封裝,用于提供便捷的音視頻編碼封裝操作,在使用的過程中要嚴格按照官方指定的生命周期調用順序,即下圖所示的使用步驟
image.png
從圖中可以看出,MediaRecorder的生命周期有以下幾個階段,并且必須按順序執行
initial : 在MediaRecorder被創建(剛new 出來)或者滴啊用reset()方法后,會處于該狀態
initialized : 當調用setAudioSource()或者setVideoSource()后,處于該狀態。這兩個方法主要用于設置音視頻的源配置,通常音頻是麥克風,視頻是攝像頭。該狀態可以通過調用reset()方法回到initial狀態
DataSourceConfigured : 當調用setOutputFormat()方法后,會處于該狀態。該方法主要用于設置輸出的文件格式,可以是音視頻如MP4,也可以是單獨的音頻如mp3。當處于該狀態之后,可以進一步設置音頻和視頻的配置參數,例如音頻封裝格式,采樣率,視頻碼率,幀率等等該狀態可以通過調用reset()方法回到initial狀態
Prepared : 在上面幾個步驟都配置好之后,可以通過調用prepare()方法進入該狀態,只有處于該狀態,才能調用start()
Recording : 通過調用start()方法進入該狀態,該狀態就是真正開始進行視頻錄制編碼的階段,通過調用stop()或者reset()可以回到initial狀態
error狀態 : 當錄制過程中發生次錯誤時,會進入該狀態,調用reset()方法回到initial狀態。
release : 只有在initial狀態才可以通過調用release()方法進入該狀態,釋放所占用的系統資源
編碼的步驟
在開始編碼之前,應該先規劃一下編碼的步驟,因為錄制視頻需要預覽畫面,所以我們肯定需要構建一個預覽的界面,通過camera+TextureView可以實現,音頻不需要預覽。構建好預覽畫面之后,就是開始配置MediaRecorder開始錄制了。
配置Camera
demo只演示后置攝像頭的捕捉,因為使用MediaRecorder進行錄制無法處理幀數據,在切換前置攝像頭之后,視頻會出現左右翻轉的問題,無法通過單純的旋轉解決,暫時還沒找到方法。
camera的配置重點
預覽尺寸,預覽尺寸的寬高比應該盡量和TextureView的寬高比一致,這樣可以保證畫面不變形;
對焦模式,對焦模式一般首選FOCUS_MODE_CONTINUOUS_VIDEO,如果機型不包含,則選擇FOCUS_MODE_CONTINUOUS_PICTURE,如果還不包含,則選擇FOCUS_MODE_AUTO,然后通過手指點擊重新對焦(手指點擊TextureView,調用mCamera.autoFocus(null););
預覽界面旋轉,由于傳感器方向和手機自然方向不一致,所以需要調整預覽界面進行一定的旋轉,旋轉的角度大小可以通過google官方提供的方法計算,查看mCamera.setDisplayOrientation(mRotationDegree);方法源碼查看注釋里有這段代碼(shift/command+鼠標左鍵點擊方法)
示例代碼
/**
* 初始化相機
*/
private void initCamera() {
if (mSurfaceTexture == null) return;
if (mCamera != null) {
releaseCamera();
}
mCamera = Camera.open(mCameraId);
if (mCamera == null) {
Toast.makeText(this, "沒有可用相機", Toast.LENGTH_SHORT).show();
return;
}
try {
mCamera.setPreviewTexture(mSurfaceTexture);
mRotationDegree = CameraUtil.getCameraDisplayOrientation(this, mCameraId);
mCamera.setDisplayOrientation(mRotationDegree);
setCameraParameter(mCamera);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 設置相機的參數
*
* @param camera
*/
private void setCameraParameter(Camera camera) {
if (camera == null) return;
Camera.Parameters parameters = camera.getParameters();
//獲取相機支持的>=20fps的幀率,用于設置給MediaRecorder
//因為獲取的數值是*1000的,所以要除以1000
List previewFpsRange = parameters.getSupportedPreviewFpsRange();
for (int[] ints : previewFpsRange) {
if (ints[0] >= 20000) {
mFps = ints[0] / 1000;
break;
}
}
//設置聚焦模式
List focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
} else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
//設置預覽尺寸,因為預覽的尺寸和最終是錄制視頻的尺寸無關,所以我們選取最大的數值
//通常最大的是手機的分辨率,這樣可以讓預覽畫面盡可能清晰并且尺寸不變形,前提是TextureView的尺寸是全屏或者接近全屏
List supportedPreviewSizes = parameters.getSupportedPreviewSizes();
parameters.setPreviewSize(supportedPreviewSizes.get(0).width, supportedPreviewSizes.get(0).height);
//縮短Recording啟動時間
parameters.setRecordingHint(true);
//是否支持影像穩定能力,支持則開啟
if (parameters.isVideoStabilizationSupported())
parameters.setVideoStabilization(true);
camera.setParameters(parameters);
}
配置MediaRecorder
按照生命周期進行每一步的配置,重點關注
編碼參數,配置MediaRecorder的編碼參數有兩種方式;
通過系統提供的CamcorderProfile類,搭配mMediaRecorder.setProfile(profile);方法進行設置,CamcorderProfile對象包含了輸出封裝格式,視頻編碼格式,幀率,碼率,分辨率,音頻采樣率,聲道數,碼率等參數。
示例代碼
/**
* 通過系統的CamcorderProfile設置MediaRecorder的錄制參數
* 首先查看系統是否包含對應質量的封裝參數,然后再設置,根據具體需要的視頻質量進行判斷和設置
*/
private void setProfile() {
CamcorderProfile profile = null;
if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_1080P)) {
profile = CamcorderProfile.get(CamcorderProfile.QUALITY_1080P);
} else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)) {
profile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
} else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)) {
profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
}
if (profile != null) {
mMediaRecorder.setProfile(profile);
}
}
自定義參數,通過profile可以一步到位配置各個參數,但是缺點是沒辦法設置自己想要的視頻清晰度,因為視頻清晰度是根據碼率和分辨率決定的,而每個profile已經固定了碼率和分辨率,所以無法進行調整。這種情況我們就可以自己配置參數。
需要注意
幀率不可以隨便定義,如果系統不支持就會報錯。應該先通過camera獲取支持的幀率,然后再設置。
視頻尺寸的大小,可以根據需要的質量,比如需要高清720的尺寸,那么先獲取系統720p的profile,然后取profile.videoFrameWidth; profile.videoFrameHeight作為輸出寬高。我這里為了方便直接寫了1280:720,大部分手機都尺寸這個參數。
示例代碼
/**
* 自定義MediaRecorder的錄制參數
*/
private void setConfig() {
//設置封裝格式 默認是MP4
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
//音頻編碼
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//圖像編碼
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
//聲道
mMediaRecorder.setAudioChannels(1);
//設置最大錄像時間 單位:毫秒
mMediaRecorder.setMaxDuration(60 * 1000);
//設置最大錄制的大小60M 單位,字節
mMediaRecorder.setMaxFileSize(60 * 1024 * 1024);
//再用44.1Hz采樣率
mMediaRecorder.setAudioEncodingBitRate(22050);
//設置幀率,該幀率必須是硬件支持的,可以通過Camera.CameraParameter.getSupportedPreviewFpsRange()方法獲取相機支持的幀率
mMediaRecorder.setVideoFrameRate(mFps);
//設置碼率
mMediaRecorder.setVideoEncodingBitRate(500 * 1024 * 8);
//設置視頻尺寸,通常搭配碼率一起使用,可調整視頻清晰度
mMediaRecorder.setVideoSize(1280, 720);
}
錄制的控制
控制流代碼如下 chronometer是用于計時的
/**
* 開始錄制和停止錄制
*
* @param v
*/
public void control(View v) {
if (mStatus == RecorderStatus.RECORDING) {
stopRecord();
} else {
startRecord();
}
}
/**
* 開始錄制
*/
private void startRecord() {
initCamera();
mCamera.unlock();
initMediaRecorder();
try {
mMediaRecorder.prepare();
mMediaRecorder.start();
} catch (IOException e) {
e.printStackTrace();
}
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();
mStatus = RecorderStatus.RECORDING;
}
/**
* 停止錄制
*/
private void stopRecord() {
releaseMediaRecorder();
releaseCamera();
}
視頻錄制好之后可以在手機目錄aaamedia文件夾下找到,以aaa開頭方便查找!
總結
以上是生活随笔為你收集整理的aac mediarecorder录制_Android音视频录制之MediaRecorder+camera的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pytest-allure美化——定制化
- 下一篇: 黄一老师讲述贷款“黑名单”小心别上了黑名