Camera2+MediaRecorder录制WebM格式报错,求可行配置方案
解决Camera2 + MediaRecorder录制WebM格式的配置问题
我来帮你搞定这个Camera2录制WebM时的崩溃问题,核心原因是MediaRecorder的WebM配置和相机设备的支持能力不匹配,或者配置逻辑里有冲突点,下面一步步帮你排查解决:
一、先确认设备对WebM编码的支持性
不是所有Android设备都原生支持VP8视频+Vorbis音频的WebM组合,尤其是Vorbis音频编码器,不少中低端设备可能不支持。你可以先通过代码验证设备是否支持目标编码组合:
private fun isWebMSupported(): Boolean { val mediaCodecList = MediaCodecList(MediaCodecList.REGULAR_CODECS) // 检查VP8视频编码器支持 val hasVP8 = mediaCodecList.codecInfos.any { codecInfo -> codecInfo.isEncoder && codecInfo.supportedTypes.contains("video/x-vnd.on2.vp8") } // 检查Vorbis音频编码器支持 val hasVorbis = mediaCodecList.codecInfos.any { codecInfo -> codecInfo.isEncoder && codecInfo.supportedTypes.contains("audio/vorbis") } return hasVP8 && hasVorbis }
如果设备不支持Vorbis,你可以试试换成Opus音频编码器(很多设备对Opus+VP8的WebM组合支持更好),把MediaRecorder.AudioEncoder.VORBIS替换成MediaRecorder.AudioEncoder.OPUS即可。
二、修正MediaRecorder的配置顺序与参数
MediaRecorder的配置有严格的顺序要求,而且部分参数必须匹配相机设备的支持范围,下面给你两个可行的配置方案:
方案1:仅录制视频(无音频)
如果不需要音频,一定要彻底移除所有音频相关配置,避免残留配置导致冲突:
private fun createRecorder(surface: Surface) = MediaRecorder().apply { // 仅设置视频源 setVideoSource(MediaRecorder.VideoSource.SURFACE) // 设置WebM输出格式 setOutputFormat(MediaRecorder.OutputFormat.WEBM) setOutputFile(outputFile.absolutePath) // 视频参数要匹配相机支持的尺寸/帧率,建议从相机特性中获取,不要硬编码 setVideoSize(args.width, args.height) if (args.fps > 0) setVideoFrameRate(args.fps) setVideoEncodingBitRate(RECORDER_VIDEO_BITRATE) // 使用VP8视频编码器 setVideoEncoder(MediaRecorder.VideoEncoder.VP8) setInputSurface(surface) // 注意:prepare()要在所有配置完成后调用,且必须在子线程执行 }
方案2:带音频的WebM(用Opus替代Vorbis)
如果需要音频,优先尝试Opus编码器,兼容性更好:
private fun createRecorder(surface: Surface) = MediaRecorder().apply { setAudioSource(MediaRecorder.AudioSource.MIC) setVideoSource(MediaRecorder.VideoSource.SURFACE) setOutputFormat(MediaRecorder.OutputFormat.WEBM) setOutputFile(outputFile.absolutePath) setVideoSize(args.width, args.height) if (args.fps > 0) setVideoFrameRate(args.fps) setVideoEncodingBitRate(RECORDER_VIDEO_BITRATE) setVideoEncoder(MediaRecorder.VideoEncoder.VP8) // 替换为Opus音频编码器 setAudioEncoder(MediaRecorder.AudioEncoder.OPUS) setInputSurface(surface) }
三、确保Camera2会话与MediaRecorder兼容
崩溃日志显示CameraDevice-JV-0: Stream configuration failed,说明相机设备无法兼容MediaRecorder提供的Surface,你需要注意两点:
- 确保
args.width和args.height是相机设备支持的录制尺寸,可以通过相机特性获取支持的尺寸列表:
val characteristics = cameraManager.getCameraCharacteristics(cameraId) val configMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!! val supportedVideoSizes = configMap.getOutputSizes(MediaRecorder::class.java) // 从supportedVideoSizes中选择合适的尺寸,不要硬编码
- 如果CameraCaptureSession同时添加了预览Surface和录制Surface,两个Surface的尺寸必须完全匹配,否则会触发配置失败。
四、额外注意事项
- Android版本限制:WebM格式在Android 4.1+支持,但VP8编码器在Android 5.0以下设备可能存在兼容性问题;Opus编码器从Android 6.0开始支持。
- prepare()调用时机:MediaRecorder的
prepare()方法必须在所有配置完成后调用,且要在子线程执行,避免阻塞主线程。 - 权限检查:确保已经申请
RECORD_AUDIO、CAMERA以及存储权限。
按照上面的步骤调整后,应该能解决“Unsupported set of inputs/outputs provided”的崩溃问题。
内容的提问来源于stack exchange,提问作者Bruno




