You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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.widthargs.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_AUDIOCAMERA以及存储权限。

按照上面的步骤调整后,应该能解决“Unsupported set of inputs/outputs provided”的崩溃问题。

内容的提问来源于stack exchange,提问作者Bruno

火山引擎 最新活动