Mac 上传上来一个 iPhone 拍的视频,4 分钟,2.3 GB,后缀是 .MOV。发给同事被拒收,云盘上传提示文件过大。想压缩,但打开"照片"app 找一圈,只找到一个叫"视频压缩"的按钮,点了之后没反应。
先弄清楚 .MOV 是什么。MOV 是容器,里面装的是视频流和音频流。决定文件大小的是里面装的编解码器,容器后缀只是包的外衣。iPhone 从 XS 之后默认用 H.265 拍,老一点的用 H.264。H.264 就是这篇文章要讲的东西。
H.264 编码器在做什么
H.264 的思路非常朴素。视频相邻帧之间几乎全是一模一样的东西,只有一小块在动,所以不需要每一帧都完整存,只存变化部分,同时告诉播放器"这里相对上一帧往左挪了 3 个像素"。
一个典型编码器做四件事。
第一步是宏块分割。把 1080p 一帧拆成 16x16 像素的小块,一整帧大概三千多个。每个块独立处理。
第二步是运动估计。拿当前块去和参考帧对比,找一个最匹配的位移量。位移最小时算出残差,也就是两帧之间的差异。运动预测精确到四分之一像素,这一步决定了压缩率的地基。
第三步是块内预测。同一个 16x16 块里,内部还可以再切成 8x8 或 4x4 的小块,因为一个宏块里的物体可能不是齐步走的。天空整体不动,一只鸟从中间飞过。编码器得识别这种局部运动。
第四步是 DCT 变换和量化。残差送进离散余弦变换,把空间域信号转成频率域信号。低频信息(画面里的主体、大范围色块)留得多,高频信息(细节、噪点、纹理)留得少。然后按量化步长(QP)舍入,小的高频值直接归零。这一步是唯一有损的部分,也是最关键的一步。QP 越小,保留的高频越多,画质越好,文件越大。QP 越大反过来。整个压缩里,量化是唯一真正动画质的地方。
最后还有熵编码。H.264 里用 CABAC,是 CAVLC 的升级版,比上一代省 5-10% 空间。
这四步走完,就是一份合规的 H.264 码流。编码器还会决定 GOP 结构,把帧排成 I 帧、P 帧、B 帧的组合。I 帧完整存一帧,P 帧只存和 I 的差异,B 帧双向参考前后帧,编码效率高但播放延迟更高。
用 ffmpeg 压一个视频
Mac 上装工具,两条命令搞定。
brew install ffmpeg
brew install --cask handbrakeffmpeg 是命令行,HandBrake 是 GUI,都是同一批人维护的。GUI 用户走 HandBrake,命令行用户走 ffmpeg。
换容器不重编码
如果只是想改个后缀,不想动视频流,一条命令就完事。
ffmpeg -i input.mkv -c:v copy -c:a copy output.mp4-c:v copy 表示视频流直接复制。文件秒完,画质完全不变。但前提是目标容器支持原编解码器。MOV 换成 MP4,通常能无缝过。MKV 换成 AVI,可能会报错。
从 iPhone MOV 压成通用 MP4
iPhone 用 HEVC 拍的视频,兼容性最差。老电脑、Windows 版浏览器、很多剪辑软件都读不动。压成 H.264 兼容性最好。
ffmpeg -i input.mov -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 192k output.mp4libx264 是软件编码,速度一般但兼容性最好。-c:a aac 是音频也要转,因为 HEVC 视频的音频可能是 HE-AAC 或 ALAC,直接放 mp4 有些平台不认。
用 Mac 硬件加速
M 系列芯片有 VideoToolbox 硬件编码器,速度快很多,画质略输软件编码,但差距在 CRF 20 以上时几乎看不出。
ffmpeg -i input.mov -c:v h264_videotoolbox -b:v 6M -c:a aac output.mp4注意硬件编码不支持 CRF,只能用固定码率 -b:v。想调质量只能改这个数。
HandBrake 走图形界面
不想敲命令的话,HandBrake 里有个"Fast 1080p30"预设,直接选,导出。命令行版本是 HandBrakeCLI,同样在 Homebrew 里。
HandBrakeCLI -i input.mov -o output.mp4 -f mp4 -p "Fast 1080p30" -e 1 -E aac -q:a 20 -B 192CRF 和 preset
CRF 是码率控制模式,从 0 到 51,数字越小画质越好、文件越大。x264 默认 23,实际用得比较多的区间在 18 到 28。
- 22-24 是日常备份和分享够用的区间
- 18-20 是可以反复剪辑的余量
- 15 以下肉眼已经看不出差别了,但文件翻几倍
-preset 控制编码速度。fast 快但文件大,slow 慢但文件小,同一个 CRF 下,veryslow 比 fast 大约省 15-20% 的空间。日常用 medium 平衡速度和质量。
常见坑
第一个是 -crf 和 -b:v 混用。两个是不同码率控制模式,混用会让 CRF 失效。要么定死码率,要么定死质量,二选一。
第二个是忽略音频 codec。不指定 -c:a,ffmpeg 会保留原格式。iPhone 的 mov 里可能是 HE-AAC,mp4 通常是 aac,虽然都是 AAC 家族但不同版本。想稳一点就显式指定 -c:a aac -b:a 192k。
第三个是可变帧率。iPhone 录屏、120fps 慢动作、HEVC 视频基本都是 VFR。转码时不指定 -vsync vfr 或 -r 30,某些播放器会跳帧卡顿。iPhone 视频转码建议加 -vsync vfr。
第四个是给剪辑用。有些教程说要先用 ProRes 做代理再转回 H.264。ProRes 体积大得多,但编辑流畅。个人用户压完 CRF 20 的 H.264 直接扔给剪映或 DaVinci 用就够了。
什么时候不用 H.264
H.265 压缩率高 30-50%,但编解码专利要交钱,硬件解码发热大,M 系列芯片上播放 H.265 明显比 H.264 热。
AV1 开源,压缩率比 H.265 再好 10-20%,但编码极慢,软件编码基本不可用。硬件解码目前只在少数新芯片上有。
VP9 是 Google 的开源方案,压得比 H.264 好但比 H.265 差,Chrome 原生支持,其他平台要装解码器。
个人用户想压手机视频、发朋友圈、云盘备份,H.264 + CRF 码率控制仍然是最省事的选择。
一条可以直接用的命令
想省事的,记下面这条就够。
ffmpeg -i input.mov \
-c:v libx264 -preset medium -crf 23 \
-c:a aac -b:a 192k \
-vsync vfr \
output.mp4跑完得到一个体积合理、画质够看、兼容性最好的 H.264 MP4。
H.264 的压缩能力来自运动估计、量化和熵编码这三步。Mac 上压视频只需要一行命令,关键是 CRF 和 preset 怎么选,以及音频 codec 别忘。CRF 23 加 medium preset 是日常用的最佳起点,其他都是在这个基础上做微调。