Android音視頻開發(六)MediaRecorder錄製視頻

簡介

安卓api提供了Camera類控制相機捕獲圖像,在api21以後,安卓也提供了Camera2,Camera變得過時了,但爲了兼容性,這裏還是使用Camera。
對於錄製視頻,可以使用MediaRecorder,這個可看安卓官方api文檔

使用

使用Camera進行拍照攝像前,你得先申請權限:

<!-- 相機權限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 錄音權限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 相機模塊 -->
<uses-feature android:name="android.hardware.camera"/>
<!-- 自動對焦模塊 -->
<uses-feature android:name="android.hardware.camera.autofocus"/>

接着,是相機預覽流程:

  1. Camera.open(int)獲取Camera實例
  2. setParameters設置相機參數
  3. setDisplayOrientation設置正確預覽方向
  4. 關聯SurfaceView,用於展示預覽畫面
  5. startPreview開始預覽,stopPreview停止預覽
  6. release釋放相機資源

錄像流程:

  1. 創建MediaRecorder對象,用於錄製音頻視頻
  2. 關聯MediaRecorder和Camera,捕獲從Camera傳來的畫面
  3. 設置MediaRecorder相關參數,視頻格式、編碼、大小等等
  4. setOrientationHint可設置視頻最終旋轉角度
  5. start開始錄製,stop停止錄製
  6. release釋放資源

爲了防止篇幅過長,我這裏就不展示全部代碼了,詳細代碼請看:github源碼

接下來我會就其中一些關鍵點列舉出來:

視頻質量

視頻質量直接影響視頻清晰度和文件大小,這個可以根據個人需求調整,碼率不宜過小也不宜過大。

/**
     * 獲取適合的視頻質量配置
     * 影響視頻清晰度和文件大小,根據自身需要調整
     * @param cameraID 攝像頭ID
     */
    fun getBestCamcorderProfile(cameraID: Int): CamcorderProfile? {
        var profile: CamcorderProfile? = null
        when {
            CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_1080P) -> { //1080P,優先
                profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_1080P)
            }
            CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_720P) -> { //720P
                profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_720P)
            }
            CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_480P) -> { //480P
                profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_480P)
            }
            CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_HIGH) -> {//高品質
                profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_HIGH)
                profile.videoBitRate /= 8
                return profile
            }
            CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_CIF) -> {
                profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_CIF)
                return profile
            }
            CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_QVGA) -> {
                profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_QVGA)
            }
            CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_LOW) -> {
                profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_LOW)
            }
        }
        if (profile != null) {
            //視頻碼率
            profile.videoBitRate = 6000000
        }
        return profile
    }

視頻預覽角度

 /**
     * 根據屏幕方向獲取對應預覽角度
     * setDisplayOrientation只能改變預覽的角度,與視頻最終結果角度無關
     * @param cameraID 相機ID
     */
    fun getCameraPreviewOrientation(cameraID: Int, activity: Activity): Int {
        val info = Camera.CameraInfo();
        Camera.getCameraInfo(cameraID, info);
        //屏幕選擇角度
        val rotation = activity.windowManager.defaultDisplay.rotation
        var degrees = 0
        when (rotation) {
            Surface.ROTATION_0 ->
                degrees = 0
            Surface.ROTATION_90 ->
                degrees = 90
            Surface.ROTATION_180 ->
                degrees = 180
            Surface.ROTATION_270 ->
                degrees = 270
        }
        var result = 90
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360
            result = (360 - result) % 360
        } else {
            result = (info.orientation - degrees + 360) % 360
        }
        return result;
    }

相機預覽

 /**
     * 初始化相機設置並開啓預覽
     */
    private fun startPreview() {
        try {
            //開啓後置攝像頭
            camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK)
              //設置預覽角度
            val rotation = CameraUtil.getCameraPreviewOrientation(Camera.CameraInfo.CAMERA_FACING_BACK,this)
            camera?.setDisplayOrientation(rotation)
            // 在SurfaceView上預覽
            camera?.setPreviewDisplay(sv_camera.holder)
            val parameters = camera?.getParameters()
              //獲取支持的預覽大小,注意這裏獲取的寬高是根據橫屏的
            val sizes = parameters?.supportedPreviewSizes
            //寬高建議根據橫豎屏切換
            val previewSize =
                CameraUtil.findFitPreviewSize(sv_camera.height,sv_camera.width,sizes)
            if (previewSize != null) {
                //設置預覽大小
                parameters?.setPreviewSize(previewSize.width, previewSize.height)
            }
            //設置自動對焦模式
            CameraUtil.setAutoFocusMode(parameters)
            camera?.setParameters(parameters)
            //開始預覽
            camera?.startPreview()
        } catch (e: Exception) {
            Log.e("Test", "出錯了", e)
        }
    }

視頻錄製

    /**
     * 開始錄製
     * 注意方法調用的先後順序
     */
    private fun startRecorder() {
        if (camera == null) {
            return
        }
        if (recorder != null) {
            stopRecord()
        }
        try {
            val videoSize = CameraUtil.findFitVideoSize(camera!!.parameters,
                sv_camera.height / sv_camera.width.toFloat()
            )
            //先停止camera預覽,釋放camera
            camera?.stopPreview()
            camera?.unlock()
            //創建MediaRecorder對象
            recorder = MediaRecorder()
            //關聯camera
            recorder?.setCamera(camera)
            //設置視頻角度;
            val rotation =
                CameraUtil.getCameraPreviewOrientation(Camera.CameraInfo.CAMERA_FACING_BACK, this)
            recorder?.setOrientationHint(rotation)
            //設置預覽區域
            recorder?.setPreviewDisplay(sv_camera.holder.surface)
            //設置音頻來源
            recorder?.setAudioSource(MediaRecorder.AudioSource.MIC)
            //設置視頻來源,來自攝像頭
            recorder?.setVideoSource(MediaRecorder.VideoSource.CAMERA)

            //設置輸出格式
//            recorder?.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
            val profile = CameraUtil.getBestCamcorderProfile(Camera.CameraInfo.CAMERA_FACING_BACK)
            if (profile != null) {
                //設置視頻碼率
                recorder?.setProfile(profile)
            }
            //設置視頻幀率,注意設備支持
            recorder?.setVideoFrameRate(30)
            //設置視頻寬高
            recorder?.setVideoSize(videoSize.width, videoSize.height)
            val file =
                File(getExternalFilesDir(Environment.DIRECTORY_MOVIES)?.absolutePath, "test.mp4")
            //設置音頻文件的存儲位置 {
            recorder?.setOutputFile(file.absolutePath)
            //準備
            recorder?.prepare()
            //開始錄製
            recorder?.start()
            ct_time.start()
        } catch (e: Exception) {
            Log.e("Test", e.message, e)
        }
    }

以上就是Camera+MediaRecord錄製視頻的方法!打完收工!有問題大家提出來討論一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章