Android 小視訊錄製
阿新 • • 發佈:2019-01-31
一·視訊錄製介面 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();
}
許可權 <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