音视频开发系列(6)——深入解析Android MediaFormat关键参数与实战配置
1. MediaFormat基础概念与核心参数MediaFormat是Android多媒体框架中描述音视频格式的核心类相当于音视频数据的身份证。在实际开发中我经常把它比作快递包裹上的面单——没有正确的面单信息包裹就无法准确送达。让我们先看一个创建视频格式的典型示例// 创建1080P H.264视频格式 MediaFormat videoFormat MediaFormat.createVideoFormat(video/avc, 1920, 1080); videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, 4000000); // 4Mbps码率 videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30); // 30fps帧率必须设置的视频参数包括KEY_MIME媒体类型如video/avcKEY_WIDTH/KEY_HEIGHT分辨率KEY_BIT_RATE码率bpsKEY_FRAME_RATE帧率fpsKEY_COLOR_FORMAT颜色格式音频格式的创建也类似MediaFormat audioFormat MediaFormat.createAudioFormat(audio/mp4a-latm, 44100, 2); audioFormat.setInteger(KEY_BIT_RATE, 128000); // 128kbps1.1 关键参数详解**码率KEY_BIT_RATE**直接影响视频质量和文件大小。在直播场景中我通常会根据分辨率设置以下经验值720P1.5-2.5 Mbps1080P3-5 Mbps4K12-20 Mbps但要注意过高的码率会导致网络传输压力增大而过低则会出现马赛克。实测发现将码率设置为分辨率乘积的0.1倍是个不错的起点。**帧率KEY_FRAME_RATE**控制视频流畅度。人眼能感知的流畅帧率至少为24fps游戏直播通常需要60fps。但要注意设备性能限制——在低端设备上设置高帧率可能导致编码超时。2. 视频编码高级参数配置2.1 关键帧间隔KEY_I_FRAME_INTERVAL这个参数决定了GOP画面组长度直接影响视频的随机访问能力和压缩效率。在视频会议中我通常设置为1秒format.setInteger(KEY_I_FRAME_INTERVAL, 1); // 每秒一个关键帧常见误区设置为-1会使用编码器默认值通常是10秒不利于视频seek操作直播场景下建议1-2秒点播场景可适当增大到5-10秒不同编码器实现可能有差异华为设备上实测发现实际间隔可能比设置值大1-2帧2.2 颜色格式KEY_COLOR_FORMAT这是最容易出问题的参数之一。Android设备支持的颜色格式差异很大必须通过CodecCapabilities检查MediaCodecInfo.CodecCapabilities caps codecInfo.getCapabilitiesForType(mime); int[] colorFormats caps.colorFormats; for (int format : colorFormats) { if (format CodecCapabilities.COLOR_FormatYUV420Flexible) { // 优先选择Flexible格式 videoFormat.setInteger(KEY_COLOR_FORMAT, format); break; } }颜色格式选择优先级COLOR_FormatYUV420FlexibleAPI 21COLOR_FormatYUV420SemiPlanarNV12COLOR_FormatYUV420PlanarI420如果使用Surface输入编码Camera数据则不需要设置此参数系统会自动处理。3. 音频参数特殊处理音频参数配置相对简单但有几个坑需要注意MediaFormat audioFormat MediaFormat.createAudioFormat(audio/mp4a-latm, 44100, 2); audioFormat.setInteger(KEY_BIT_RATE, 128000); audioFormat.setInteger(KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);音频特有参数KEY_CHANNEL_COUNT声道数1-8KEY_IS_ADTSADTS头标识用于流式传输KEY_AAC_PROFILEAAC编码配置LC/HE/ELD在语音直播中我发现将采样率降到16kHz、使用单声道就能满足需求可以显著降低带宽消耗。4. 编解码器兼容性处理不同Android设备对MediaFormat参数的支持差异很大必须做好兼容性检查4.1 分辨率对齐要求大多数设备要求视频宽高是16的倍数否则编码会失败。处理用户自定义分辨率时一定要做对齐int align16(int value) { return (value 15) ~15; } width align16(width); height align16(height);4.2 码率模式选择Android支持三种码率控制模式通过KEY_BITRATE_MODE设置模式常量值特点适用场景CQ0质量优先本地存储VBR1动态码率点播视频CBR2固定码率实时直播在短视频录制项目中我使用VBR模式获得了更好的质量/体积比format.setInteger(KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR);4.3 编码等级设置对于H.264编码建议明确设置Profile和Levelformat.setInteger(KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh); format.setInteger(KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel31);Profile选择建议Baseline兼容性最好旧设备Main平衡选择High高质量支持B帧5. 实战中的参数优化技巧经过多个项目的积累我总结出以下优化经验直播推流优化使用CBR模式确保网络稳定性适当降低帧率24fps足够开启KEY_LOW_LATENCY标志API 26if (Build.VERSION.SDK_INT Build.VERSION_CODES.O) { format.setInteger(MediaFormat.KEY_LOW_LATENCY, 1); }视频编辑优化使用VBR模式获得更好质量增大关键帧间隔减少文件体积设置KEY_MAX_B_FRAMES为0加快编辑处理低端设备适配检测设备性能等级API 31动态调整分辨率和码率使用CodecCapabilities.getMaxSupportedInstances()检查并发编码能力最后提醒大家MediaFormat参数设置后一定要检查MediaCodec.configure()的返回值有些参数错误不会立即抛出异常但在运行时会导致编码失败。