Android オーディオとビデオの開発 (6) ビデオを録画する MediaRecorder

序章

Android API は、画像をキャプチャするカメラを制御するための Camera クラスを提供します。api21 以降、Android は Camera2 も提供します。カメラは廃止されましたが、互換性のために、ここでは Camera がまだ使用されています。ビデオを録画するには、 Android 公式 API ドキュメント
に記載されている MediaRecorder を使用できます。

使用

カメラを使用して写真やビデオを撮影する前に、まず許可を申請する必要があります。

<!-- 相机权限 -->
<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) カメラインスタンスの取得
  2. setParameters カメラパラメータを設定します
  3. setDisplayOrientation は正しいプレビューの方向を設定します
  4. SurfaceViewを関連付けてプレビュー画面を表示する
  5. startPreview はプレビューを開始し、stopPreview はプレビューを停止します
  6. release カメラリソースをリリースします

ビデオ録画プロセス:

  1. オーディオとビデオを記録するための MediaRecorder オブジェクトを作成する
  2. MediaRecorder とカメラを関連付けて、カメラから画像をキャプチャします
  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で動画を録画する方法でした!もう終わりにしましょう!ご質問がございましたら、議論の場に上げてください。

おすすめ

転載: blog.csdn.net/gs12software/article/details/105214944