android - Android 相机视频为空白,带有白线
问题描述
我已经实现了 Android 的 Camera2 API,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()
解决方案
我已经想通了。问题出在MediaRecorder
. 显然,Googlecamera2
在 GitHub 上的代码方式在正确设置Surface
for方面是不MediaRecorder
正确的。
解决方案是我们不应该提供Surface
作为 MediaRecorder 的输入,而是prepare
在MediaRecorder
没有 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()
推荐阅读
- javascript - TypeError: this.props.nextStep 不是函数 React 错误
- c++ - 从 Arduino 上的多个模拟引脚读取输入的代码不会显示值
- c# - 如何用accord.net实现人脸识别?
- mysql - 如何通过Node JS在mysql数据库中存储和检索utf8字符
- java - Surefire 实际上并没有运行测试
- android - 更新 Android SDK 包列表失败 - Unity 2019.2.10f1
- r - R:如何创建基于 ggplot 的时间线
- django - 如何定义 django 应用程序特定的异常处理程序
- mysql - MySQL:在 WHERE 子句中,除了逻辑运算符之外,AND / OR / XOR 在哪里可以使用?
- python - 如何在updateview中将参数传递给表单?