首页 > 解决方案 > Android 相机视频为空白,带有白线

问题描述

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

这是我得到的输出视频。

MediaRecorder 的视频输出

准备代码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()

标签: androidkotlinandroid-cameravideo-captureandroid-camera2

解决方案


我已经想通了。问题出在MediaRecorder. 显然,Googlecamera2在 GitHub 上的代码方式在正确设置Surfacefor方面是不MediaRecorder正确的。

解决方案是我们不应该提供Surface作为 MediaRecorder 的输入,而是prepareMediaRecorder没有 a的情况下Surface使用它的内部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()

推荐阅读