Android 11升级后MediaCodec/MediaMuxer录制MP4无声音,报缺少编解码专有数据
问题背景
- 项目基于
MediaCodec+MediaMuxer实现MP4录制:以设备麦克风作为音频输入源,OpenGL渲染的音频可视化场景(如声谱图)作为视频源 - 兼容性异常:Android 11系统升级前全机型运行正常,升级后谷歌Pixel 3/4、三星Galaxy S20等多品牌机型统一出现录制文件无音频的问题
- 已排除的异常项:
- 录制全程无运行时崩溃、无抛出未捕获异常
- 跨多设备播放录制文件均确认无音频内容,排除播放端兼容问题
- 视频内的音频可视化动效与实际采集的音频节奏匹配,排除麦克风采集、音频输入链路异常
- 日志确认视频轨编码、封装全程正常,仅音频轨封装环节报错
现有录制逻辑配置
// 视频编码配置 public static final String VIDEO_MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC; public static final int VIDEO_FRAME_RATE = 30; public static final int VIDEO_IFRAME_INTERVAL = 5; public static final String AUDIO_MIME_TYPE = MediaFormat.MIMETYPE_AUDIO_AAC; // 麦克风采集配置 public static final int RECORDER_SAMPLE_RATE = 44100; public static final int RECORDER_CHANNELS = 1; public static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; // 音频编码配置 public static final String ENCODER_AUDIO_FORMAT = MediaFormat.MIMETYPE_AUDIO_AAC; public static final int ENCODER_AAC_PROFILE = MediaCodecInfo.CodecProfileLevel.AACObjectLC; public static final int AUDIO_BIT_RATE = 128000; public static final int AUDIO_SAMPLE_RATE = 44100; public static final int AUDIO_SAMPLES_PER_FRAME = 1024; public static final int AUDIO_FRAMES_PER_BUFFER = 25; public static final int AUDIO_BYTES_PER_ELEMENT = 2; // 视频编码器初始化 MediaFormat videoFormat = MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, width, height); videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, VIDEO_FRAME_RATE); videoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, VIDEO_IFRAME_INTERVAL); videoEncoder = MediaCodec.createEncoderByType(VIDEO_MIME_TYPE); videoEncoder.configure(videoFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); inputSurface = videoEncoder.createInputSurface(); videoEncoder.start(); // 音频编码器初始化 audioEncoder = MediaCodec.createEncoderByType(AUDIO_MIME_TYPE); MediaFormat audioFormatConfig = MediaFormat.createAudioFormat(ENCODER_AUDIO_FORMAT, AUDIO_SAMPLE_RATE, RECORDER_CHANNELS); audioFormatConfig.setInteger(MediaFormat.KEY_AAC_PROFILE, ENCODER_AAC_PROFILE); audioFormatConfig.setInteger(MediaFormat.KEY_BIT_RATE, AUDIO_BIT_RATE); audioFormatConfig.setInteger(MediaFormat.KEY_CHANNEL_COUNT, RECORDER_CHANNELS); audioEncoder.configure(audioFormatConfig, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); audioEncoder.start(); // Muxer初始化 mMuxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); mMuxer.setOrientationHint(orientationHint); // 原有Muxer启动触发逻辑 else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { MediaFormat videoOutputFormat = videoEncoder.getOutputFormat(); MediaFormat audioOutputFormat = audioEncoder.getOutputFormat(); videoTrackIndex = mMuxer.addTrack(videoOutputFormat); audioTrackIndex = mMuxer.addTrack(audioOutputFormat); mMuxer.start(); }
关键异常日志
停止录制环节捕获的核心错误日志:
2021-03-08 14:52:12.670 20015-20259/com.xx.xx E/MPEG4Writer: Missing codec specific data 2021-03-08 14:52:12.670 20015-20259/com.xx.xx E/MPEG4Writer: 0 frames to dump timeStamps in Audio track 2021-03-08 14:52:12.671 20015-20241/com.xx.xx D/MPEG4Writer: Audio track stopped. Status:-1007. Stop source 2021-03-08 14:52:12.671 20015-20241/com.xx.xx W/MPEG4Writer: Condition trackErr == OK failed Audio track stopped with an error日志同时记录视频轨累计编码69帧、封装正常,音频轨累计编码87帧但封装时因缺少专属编解码数据(CSD)直接终止。
问题根因与排查修复方向
- 核心时序冲突:Android 11系统调整了MediaCodec编码器的格式回调时序,视频编码器触发
INFO_OUTPUT_FORMAT_CHANGED回调时,音频编码器往往尚未完成初始化流程、尚未触发自身的格式变更回调。原有逻辑在视频轨格式就绪时,直接同步拉取音频编码器的输出格式,此时拿到的格式缺少必需的CSD编解码专属数据,直接传入MediaMuxer.addTrack会导致音频轨封装失败。 - 修复逻辑参考:
- 为视频、音频编码器分别维护格式就绪标记(
isVideoFormatReady、isAudioFormatReady) - 只有当两个编码器都收到过
INFO_OUTPUT_FORMAT_CHANGED回调、成功拿到带完整CSD数据的输出格式后,再依次调用addTrack添加两条轨、启动Muxer
- 为视频、音频编码器分别维护格式就绪标记(
- 验证排查点:
- 分别打印两个编码器触发格式变更回调的时间戳,确认存在跨轨时序差
- 打印传入Muxer的音频MediaFormat,检查是否包含
csd-0、csd-1字段,未就绪的格式会缺失这些关键参数 - 调整时序逻辑后重新录制,确认日志中不再出现
Missing codec specific data报错,音频轨停止状态码恢复为0
内容的提问来源于stack exchange,提问作者GhostCoder77
相关产品推荐
相关产品推荐

