4、格式转换实战:常见容器格式互转(MP4/MKV/AVI/FLV)、编码器选择策略
格式转换,说白了就是给视频「换包装」。
很多人以为转格式就是改个后缀名。我见过不少新手直接把 .mkv 改成 .mp4,然后问我为什么播放器还是打不开。嗯,这里要说明白:容器格式和编码格式是两码事。
核心概念:容器(Container)是外壳,编码(Codec)是内核。转容器 ≠ 转编码。
4.1 容器格式的本质差异
我习惯把容器比作「快递箱」。MP4 是标准纸箱,MKV 是多功能收纳箱,AVI 是老式木箱,FLV 是轻便小盒。它们能装的东西不一样。
| 容器 | 常见编码 | 流支持 | 适用场景 |
|---|---|---|---|
| MP4 | H.264/H.265 + AAC | 1 视频 + 1 音频 + 字幕(有限) | 网页、移动端、通用播放 |
| MKV | 几乎任何编码 | 多视频/多音频/多字幕/章节 | 本地收藏、蓝光原盘、多轨需求 |
| AVI | MPEG-4 Visual / DivX / XviD | 1 视频 + 1~2 音频 | 老旧设备、兼容性兜底 |
| FLV | H.264 + MP3/AAC | 1 视频 + 1 音频 | 直播、Flash 遗留系统 |
你看,MP4 对字幕支持很弱。我曾经想把一个带 ass 特效字幕的 MKV 直接转 MP4,结果字幕全丢了。后来才知道,MP4 只支持内嵌字幕或 timed text,ass 这种高级格式根本塞不进去。
4.2 纯容器转换(不重新编码)
如果源文件的编码格式目标容器也支持,我们可以只换壳,不伤画质。速度极快,几秒搞定。
举个例子,一个 H.264 + AAC 的 MKV 文件,想转成 MP4:
ffmpeg -i input.mkv -c copy output.mp4
-c copy 就是「直接复制流,不重新编码」。我项目里经常用这招给客户交付 MP4 版本,省时省力。
小技巧:如果只想换容器,先查一下源文件的编码信息:ffmpeg -i input.mkv。确认视频和音频编码目标容器都支持,再用 -c copy。
但有些情况不能直接 copy。比如 AVI 不支持 AAC 音频,你硬 copy 过去,播放器会直接罢工。
注意:AVI 容器对音频编码有限制。常见兼容组合是 MP3 或 PCM。如果源文件是 AAC,转 AVI 时必须重编码音频。
4.3 常见互转场景与命令
下面是我工作中最常用的几个转换场景,直接贴命令,你拿去就能用。
4.3.1 MKV → MP4(H.264 + AAC)
ffmpeg -i input.mkv -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k output.mp4
这个命令会重新编码视频和音频。为什么不用 copy?因为 MKV 里可能装了 H.265 或 DTS 音频,MP4 不认。重编码是保险做法。
4.3.2 MP4 → MKV(保留多音轨)
ffmpeg -i input.mp4 -c copy -map 0 output.mkv
-map 0 的意思是「把输入文件的所有流都映射到输出」。MP4 转 MKV 通常可以直接 copy,因为 MKV 什么都能装。
4.3.3 AVI → MP4(老旧视频现代化)
ffmpeg -i input.avi -c:v libx264 -preset slow -crf 22 -c:a aac -b:a 128k output.mp4
AVI 里的视频编码通常是 MPEG-4 Visual,压缩效率低,画质差。我建议重编码成 H.264,体积能缩小 50% 以上。
4.3.4 FLV → MP4(直播录播转通用)
ffmpeg -i input.flv -c:v libx264 -preset fast -crf 24 -c:a aac -b:a 96k output.mp4
FLV 的封装比较老,很多现代播放器不支持。转成 MP4 是标准做法。
4.4 编码器选择策略
选编码器,说白了就是平衡三个东西:画质、体积、速度。你不可能全都要。
我个人习惯按场景选:
- 最终交付给客户:H.264 + AAC,兼容性最好。用
libx264,CRF 设 18~23。 - 自己收藏:H.265(HEVC),体积小画质高。用
libx265,CRF 设 22~28。 - 快速预览:H.264 的
ultrafastpreset,牺牲一点画质换速度。 - 直播推流:硬件编码器,比如
h264_nvenc(NVIDIA)或h264_amf(AMD)。
| 编码器 | 画质 | 体积 | 速度 | 适用场景 |
|---|---|---|---|---|
| libx264 | 高 | 中等 | 中等 | 通用、兼容性优先 |
| libx265 | 更高 | 小 | 慢 | 本地收藏、高压缩比需求 |
| h264_nvenc | 中等 | 较大 | 极快 | 直播、实时转码 |
| libvpx-vp9 | 高 | 极小 | 极慢 | Web 分发、YouTube 标准 |
我的经验:CRF 值不是玄学。18 以下基本看不出区别,但文件大得离谱。23 是视觉无损的起点。我一般用 22 做存档,24 做网络分发。
4.5 避坑指南:我踩过的几个坑
做格式转换这么多年,有些坑我至今记忆犹新。
- 坑一:我曾经把一个 DTS 音轨的 MKV 直接 copy 成 MP4,结果播放器没声音。DTS 需要重编码成 AAC 或 AC3。
- 坑二:AVI 文件超过 2GB 会出问题。老格式的索引机制有限制。解决方案是转成 MKV 或 MP4。
- 坑三:FLV 转 MP4 时,如果源文件是 Sorenson Spark 编码(老 Flash 专用),libx264 不认。需要先解码成原始帧再编码。
- 坑四:硬件编码器(NVENC)虽然快,但同码率下画质不如软件编码器。交付给客户时我从来不用硬件编码。
4.6 知识体系总览
下面这张图帮你理清本章的核心逻辑:
你看,整个流程其实就两个分支:编码兼容就换壳,不兼容就重编码。别把事情想复杂了。
4.7 实战建议
最后给你几条实在的建议:
- 先查再转:每次转格式前,先用
ffmpeg -i看一眼源文件的编码信息。我吃过亏才知道这步不能省。 - 批量转换用脚本:写个 for 循环,别一个个敲命令。比如把所有 MKV 转 MP4:
for f in *.mkv; do ffmpeg -i "$f" -c copy "${f%.mkv}.mp4"; done - 保留原始文件:转码有损,别删源文件。等确认输出没问题了再清理。
- 测试播放兼容性:转完的文件,至少用两个播放器打开看看。VLC 能播不代表手机也能播。
格式转换这事,说难不难,说简单也不简单。你只要记住「容器是壳,编码是核」,再配合我上面给的命令和策略,基本不会翻车。