【问题标题】:Android Camera Video is blank with white linesAndroid 相机视频为空白,带有白线
【发布时间】:2021-04-12 02:45:52
【问题描述】:

我已经使用MediaRecorder 实现了Android 的Camera2 API 来从摄像头录制视频。相机预览工作正常,视频文件也成功创建,没有任何错误。但是,输出的视频是空白的,并且有白色闪烁的线条。

这是我得到的输出视频。

准备MediaRecorder的代码

val surface = MediaCodec.createPersistentInputSurface()
surface.release()

val outputFile = createFile(applicationContext,"mp4")
val mMediaRecorder = MediaRecorder()
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC)
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mMediaRecorder.setOutputFile(outputFile.absolutePath)
mMediaRecorder.setVideoEncodingBitRate(10_000_000)
mMediaRecorder.setVideoFrameRate(30)
mMediaRecorder.setVideoSize(matchedResolution.width, matchedResolution.height)
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
mMediaRecorder.setInputSurface(surface)

创建会话。

val previewSurface = surfaceView2.holder.surface

val captureCallbackVideo =
    object : CameraCaptureSession.StateCallback() {
        override fun onConfigureFailed(session: CameraCaptureSession) {}
        override fun onConfigured(session: CameraCaptureSession) {
            // session configured
            val previewRequestBuilder =
                cameraDevice.createCaptureRequest(TEMPLATE_RECORD)
                    .apply {
                        addTarget(previewSurface)
                        addTarget(surface)
                        set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range(30,30))
                    }
            session.setRepeatingRequest(
                previewRequestBuilder.build(),
                null,
                Handler { true }
            )
        }
    }

cameraDevice.createCaptureSession(mutableListOf(previewSurface, surface), captureCallbackVideo, Handler { true })

开始录制

mMediaRecorder.prepare()
mMediaRecorder.start()

为了停止

mMediaRecorder.stop()
mMediaRecorder.release()

【问题讨论】:

    标签: android kotlin android-camera video-capture android-camera2


    【解决方案1】:

    我想通了。问题出在MediaRecorder 的输入表面上。显然,Google 在 GitHub 上的代码camera2 的方式在正确设置SurfaceMediaRecorder 时是不对的。

    解决方案是我们不应该提供Surface 作为MediaRecorder 的输入,而是提供prepare 不带MediaRecorderSurface,然后将其内部Surface 用于我们的CaptureRequest

    mMediaRecorder = MediaRecorder()
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
    mMediaRecorder.setVideoEncodingBitRate(10_000_000)
    //Uncomment on physical device, comment on emulator
    //mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
    mMediaRecorder.setVideoSize(matchedResolution.width, matchedResolution.height)
    mMediaRecorder.setVideoFrameRate(30)
    mMediaRecorder.setOutputFile(outputFile.absolutePath)
    try {
        mMediaRecorder.prepare()
    } catch (e: java.lang.Exception) {
        e.printStackTrace()
        return
    }
    

    用于创建会话

    val previewSurface = surfaceView2.holder.surface
    
    val captureCallbackVideo =
        object : CameraCaptureSession.StateCallback() {
            override fun onConfigureFailed(session: CameraCaptureSession) {}
            override fun onConfigured(session: CameraCaptureSession) {
                // session configured
                val previewRequestBuilder =
                    cameraDevice.createCaptureRequest(TEMPLATE_RECORD)
                        .apply {
                            addTarget(previewSurface)
                            addTarget(mMediaRecorder.surface)
                            set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range(30,30))
                        }
                session.setRepeatingRequest(
                    previewRequestBuilder.build(),
                    null,
                    Handler { true }
                )
            }
        }
    
    cameraDevice.createCaptureSession(mutableListOf(previewSurface, mMediaRecorder.surface), captureCallbackVideo, Handler { true })
    

    开始录制:

    mMediaRecorder.start()
    

    停止录制:

    mMediaRecorder.stop()
    mMediaRecorder.release()
    

    【讨论】:

      【解决方案2】:

      您可以使用下面的代码,我认为 setVideoEncodingBitRate 可能存在问题

      recorder.setVideoSize(640, 480);
      recorder.setVideoFrameRate(16); //might be auto-determined due to lighting
      recorder.setVideoEncodingBitRate(3000000);
      recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// MPEG_4_SP
      recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
      

      【讨论】:

      • 这不是问题。我已经尝试过不同的比特率。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 1970-01-01
      • 2017-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多