Android視頻錄制功能的實現(xiàn)步驟
官方使用指南請查看Google音頻和視頻指南
視頻錄制基本步驟
1.申明權(quán)限
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <--如果錄制的視頻保存在外部SD卡,還需要添加以下權(quán)限-> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
注意:RECORD_AUDIO為危險權(quán)限,從Android 6.0開始(API級別23)開始,需要動態(tài)獲取。
2.視頻錄制參數(shù)配置
import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.text.TextUtils; /** * @author Created by LRH * @description 視頻錄制參數(shù)(參數(shù)可自行拓展) * @date 2021/1/19 13:54 */ public class VideoRecorderConfig { //Camera private Camera camera; //攝像頭預(yù)覽寬度 private int videoWidth; //攝像頭預(yù)覽高度 private int videoHeight; //攝像頭預(yù)覽偏轉(zhuǎn)角度 private int cameraRotation; //保存的文件路徑 private String path; //由于Camera使用的是SurfaceTexture,所以這里使用了SurfaceTexture //也可使用SurfaceHolder private SurfaceTexture mSurfaceTexture; private int cameraId = 0; public SurfaceTexture getSurfaceTexture() { return mSurfaceTexture; } public void setSurfaceTexture(SurfaceTexture surfaceTexture) { mSurfaceTexture = surfaceTexture; } public Camera getCamera() { return camera; } public void setCamera(Camera camera) { this.camera = camera; } public int getVideoWidth() { return videoWidth; } public void setVideoWidth(int videoWidth) { this.videoWidth = videoWidth; } public int getVideoHeight() { return videoHeight; } public void setVideoHeight(int videoHeight) { this.videoHeight = videoHeight; } public int getCameraRotation() { return cameraRotation; } public void setCameraRotation(int cameraRotation) { this.cameraRotation = cameraRotation; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public int getCameraId() { return cameraId; } public void setCameraId(int cameraId) { this.cameraId = cameraId; } public boolean checkParam() { return mSurfaceTexture != null && camera != null && videoWidth > 0 && videoHeight > 0 && !TextUtils.isEmpty(path); } }
3.視頻錄制接口封裝(使用MediaRecorder)
import android.media.CamcorderProfile; import android.media.MediaRecorder; import android.os.Build; import android.view.Surface; import com.emp.yjy.baselib.utils.LogUtils; import java.io.IOException; /** * @author Created by LRH * @description * @date 2021/1/19 13:53 */ public class VideoRecorder { private static final String TAG = "VideoRecord"; private MediaRecorder mRecorder; public VideoRecorder() { } /** * 開始錄制 * * @param config * @return */ public boolean startRecord(VideoRecorderConfig config, MediaRecorder.OnErrorListener listener) { if (config == null || !config.checkParam()) { LogUtils.e(TAG, "參數(shù)錯誤"); return false; } if (mRecorder == null) { mRecorder = new MediaRecorder(); } mRecorder.reset(); if (listener != null) { mRecorder.setOnErrorListener(listener); } config.getCamera().unlock(); mRecorder.setCamera(config.getCamera()); //設(shè)置音頻通道 // mRecorder.setAudioChannels(1); //聲音源 // AudioSource.DEFAULT:默認(rèn)音頻來源 // AudioSource.MIC:麥克風(fēng)(常用) // AudioSource.VOICE_UPLINK:電話上行 // AudioSource.VOICE_DOWNLINK:電話下行 // AudioSource.VOICE_CALL:電話、含上下行 // AudioSource.CAMCORDER:攝像頭旁的麥克風(fēng) // AudioSource.VOICE_RECOGNITION:語音識別 // AudioSource.VOICE_COMMUNICATION:語音通信 mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); //視頻源 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); try { //推薦使用以下代碼進(jìn)行參數(shù)配置 CamcorderProfile bestCamcorderProfile = getBestCamcorderProfile(config.getCameraId()); mRecorder.setProfile(bestCamcorderProfile); } catch (Exception e) { //設(shè)置輸出格式 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //聲音編碼格式 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); //視頻編碼格式 mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); } //設(shè)置視頻的長寬 mRecorder.setVideoSize(config.getVideoWidth(), config.getVideoHeight()); // 設(shè)置取樣幀率 mRecorder.setVideoFrameRate(30); // mRecorder.setAudioEncodingBitRate(44100); // 設(shè)置比特率(比特率越高質(zhì)量越高同樣也越大) mRecorder.setVideoEncodingBitRate(800 * 1024); // 這里是調(diào)整旋轉(zhuǎn)角度(前置和后置的角度不一樣) mRecorder.setOrientationHint(config.getCameraRotation()); // 設(shè)置記錄會話的最大持續(xù)時間(毫秒) mRecorder.setMaxDuration(15 * 1000); //設(shè)置輸出的文件路徑 mRecorder.setOutputFile(config.getPath()); //設(shè)置預(yù)覽對象(可以使用SurfaceHoler代替) mRecorder.setPreviewDisplay(new Surface(config.getSurfaceTexture())); //預(yù)處理 try { mRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); return false; } //開始錄制 mRecorder.start(); return true; } /** * 停止錄制 */ public void stopRecord() { if (mRecorder != null) { try { mRecorder.stop(); mRecorder.reset(); mRecorder.release(); mRecorder = null; } catch (Exception e) { e.printStackTrace(); LogUtils.e(TAG, e.getMessage()); } } } /** * 暫停錄制 * * @return */ public boolean pause() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && mRecorder != null) { mRecorder.pause(); return true; } return false; } /** * 繼續(xù)錄制 * * @return */ public boolean resume() { if (mRecorder != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mRecorder.resume(); return true; } return false; } } public CamcorderProfile getBestCamcorderProfile(int cameraID){ CamcorderProfile profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_LOW); if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_480P)){ //對比下面720 這個選擇 每幀不是很清晰 profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_480P); profile.videoBitRate = profile.videoBitRate/5; return profile; } if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_720P)){ //對比上面480 這個選擇 動作大時馬賽克!! profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_720P); profile.videoBitRate = profile.videoBitRate/35; return profile; } if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_CIF)){ profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_CIF); return profile; } if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_QVGA)){ profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_QVGA); return profile; } return profile; }
3.使用示例
public void recordVideo(CustomCameraView CameraView) { VideoRecorderConfig config = new VideoRecorderConfig(); String path = App.sGlobalContext.getExternalFilesDir("video").getAbsolutePath() + File.separator + "test1.mp4"; config.setCamera(CameraView.getCamera()); config.setCameraRotation(CameraView.getCameraRotation()); config.setVideoHeight(CameraView.getCameraSize().height); config.setVideoWidth(CameraView.getCameraSize().width); config.setPath(path); config.setSurfaceTexture(CameraView.getSurfaceTexture()); config.setCameraId(0); VideoRecorder record = new VideoRecorder(); boolean start = record.startRecord(config, null); int duration = 15_000; while (duration > 0) { if (duration == 10_000) { boolean pause = record.pause(); LogUtils.e(TAG, "暫停錄制" + pause); } if (duration == 5_000) { boolean resume = record.resume(); LogUtils.e(TAG, "重新開始錄制" + resume); } SystemClock.sleep(1_000); duration -= 1_000; } record.stopRecord(); LogUtils.d(TAG, "停止錄制"); }
其中CustomCameraView
為自己封裝的相機(jī)庫
到此這篇關(guān)于Android視頻錄制功能的實現(xiàn)步驟的文章就介紹到這了,更多相關(guān)Android視頻錄制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android布局之GridLayout網(wǎng)格布局
網(wǎng)格布局標(biāo)簽是GridLayout。這個布局是android4.0新增的布局。這個布局只有4.0之后的版本才能使用。本文給大家介紹Android布局之GridLayout網(wǎng)格布局相關(guān)知識,感興趣的朋友一起學(xué)習(xí)吧2015-12-12如何設(shè)置Android studio 3.0顯示光標(biāo)返回上一次瀏覽位置的箭頭圖標(biāo)
這篇文章主要介紹了如何設(shè)置Android studio 3.0顯示光標(biāo)返回上一次瀏覽位置的箭頭圖標(biāo) 很多朋友反映剛升級了Android studio 3.0,發(fā)現(xiàn)光標(biāo)返回上一次瀏覽位置的箭頭圖標(biāo)沒有了,下文給大家介紹的非常詳細(xì),需要的朋友可以參考下2017-11-11Android使用自定義View實現(xiàn)餅狀圖的實例代碼
這篇文章主要介紹了Android使用自定義View實現(xiàn)餅狀圖的實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05Android實現(xiàn)收到新短信后自動發(fā)郵件功能
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)收到新短信后自動發(fā)郵件功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-059個非常棒的Android代碼編輯器 移動開發(fā)者的最愛
這篇文章主要為大家分享了9個非常棒的Android代碼編輯器,據(jù)說這可是移動開發(fā)者的最愛,知道是哪九個Android代碼編輯器2015-12-12Android實現(xiàn)單頁顯示3個Item的ViewPager炫酷切換效果
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)單頁顯示3個Item的ViewPager炫酷切換效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10