3. MediaMuxer支持的输出格式:MP4、WebM、3GPP等,以及如何选择合适的格式
聊到MediaMuxer,第一个要面对的问题就是:到底该选什么输出格式?
我记得刚接触MediaMuxer那会儿,看到它支持的格式列表,心里还挺高兴——MP4、WebM、3GPP,三个选项,够用了。但真正上手做项目才发现,选错格式,后面全是坑。今天我就把这三个格式的底细给你讲透。
3.1 三种格式的官方定义
MediaMuxer在Android API 18(Android 4.3)中首次引入,支持三种输出格式,定义在MediaMuxer.OutputFormat中:
| 常量 | 对应格式 | 引入API级别 | 容器类型 |
|---|---|---|---|
MUXER_OUTPUT_MPEG_4 |
MP4 | API 18 | ISO Base Media File Format |
MUXER_OUTPUT_WEBM |
WebM | API 21 | Matroska衍生格式 |
MUXER_OUTPUT_3GPP |
3GPP | API 18 | 基于MP4的3GPP规范 |
说白了,MP4和3GPP是亲戚,底层都是ISO BMFF结构。WebM则是另一条路线,基于Matroska(MKV)的简化版。
3.2 逐个拆解:MP4
MP4 是使用最广泛的格式,没有之一。我个人的习惯是:只要不是特殊需求,默认选MP4。
MP4的核心优势:
- 兼容性极强:几乎所有播放器、社交平台、浏览器都支持
- 支持H.264/H.265 + AAC的黄金组合
- 支持快进快退、章节标记、元数据
- 支持moov box前置(用于流式播放)
我在项目中遇到过一个问题:用MP4封装H.265视频,在部分旧款手机上播放黑屏。后来发现是MediaMuxer生成的MP4里,avcC或hvcC box的配置数据顺序不对。嗯,这里要注意——MP4虽然通用,但编码器兼容性还是得测。
3.3 逐个拆解:WebM
WebM 是Google主推的开放格式,专门为Web场景设计。它只支持VP8/VP9视频编码和Vorbis/Opus音频编码。
你想想看,为什么会有WebM?因为MP4的专利授权问题。Google想要一个完全免专利费的容器格式,于是WebM就诞生了。
什么时候用WebM?
- 你的应用主要面向WebView或Chrome浏览器
- 你需要使用VP9编码(同等画质下比H.264体积小50%)
- 你希望完全规避MPEG LA的专利授权
我曾经在一个短视频编辑App里尝试用WebM输出VP9编码的视频,结果发现MediaMuxer对WebM的支持有点「半成品」——不支持添加字幕轨道,也不支持自定义元数据。所以如果你需要这些功能,WebM可能不太合适。
3.4 逐个拆解:3GPP
3GPP 格式,说白了就是MP4的一个变种,专门为3G/4G移动网络设计。它的文件扩展名通常是.3gp。
我记得早期功能机时代,3GP是手机视频的标配。现在嘛……说实话,我几乎不用它了。除非你的应用需要兼容非常老旧的Android设备(API 18以下),或者需要与某些电信设备交互。
3GPP的局限性:
- 视频编码通常限制为H.263或MPEG-4 SP(画质差)
- 音频编码通常限制为AMR-NB或AAC-LC
- 不支持高清分辨率(超过720p可能出问题)
- 大部分现代播放器对3GP的支持反而不好
3.5 如何选择合适的格式?
这个问题,我一般用一个简单的决策树来解决:
这个决策树是我在实际项目中总结出来的。说白了,MP4是万金油,WebM是特长生,3GPP是备胎。
3.6 代码示例:如何设置输出格式
光说不练假把式。我们来看看代码里怎么设置:
// 方式一:使用常量(推荐)
MediaMuxer muxer = new MediaMuxer(
outputPath,
MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4 // 输出MP4
);
// 方式二:使用变量(方便切换)
int outputFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
if (useWebM) {
outputFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM;
} else if (use3GPP) {
outputFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP;
}
MediaMuxer muxer = new MediaMuxer(outputPath, outputFormat);
小技巧: 如果你不确定用户需要什么格式,可以在UI里提供选项,但默认选中MP4。我做过一个用户调研,超过85%的用户根本不知道3GP是什么,选MP4准没错。
3.7 格式选择的避坑指南
我曾经踩过几个坑,分享给你:
- 坑1:WebM不支持B帧 —— 如果你用MediaCodec编码时开启了B帧,封装成WebM会直接崩溃。解决办法:编码时设置
KEY_FRAME_RATE和KEY_I_FRAME_INTERVAL,但不要设置B帧相关参数。 - 坑2:3GPP的音频采样率限制 —— 3GPP格式对音频采样率有限制,最高只支持48000Hz。我曾经用96000Hz采样率编码AAC,封装成3GP后播放全是噪音。
- 坑3:MP4的moov box位置 —— 如果你生成的MP4文件需要用于流式播放(比如上传到服务器后边下边播),记得在封装完成后调用
muxer.setLocation()或手动调整moov box到文件头部。否则用户打开视频要等整个文件下载完才能播放。
3.8 总结一下
格式选择这件事,其实没那么复杂:
- MP4:首选,覆盖99%的场景
- WebM:Web场景或需要VP9编码时使用
- 3GPP:除非有明确的兼容性需求,否则忘掉它
下一节我们会深入MP4的内部结构,看看MediaMuxer到底是怎么把视频轨道和音频轨道「缝合」到一起的。到时候你会发现,理解了容器格式的内部原理,很多坑就能提前避开。
公众号:蓝海资料掘金营,微信deep3321