2. 编解码器基础
各位好,我是老张。今天咱们聊聊编解码器的基础。说实话,很多做容器化部署的朋友,最后踩的坑往往不是K8s配置不对,而是对编码器本身的理解不够深。你想想看,如果连H.264和H.265的区别都说不清楚,怎么给容器配参数?
这一节我会从编码原理讲起,然后带大家过一遍FFmpeg的常用命令。嗯,都是我在生产环境里摸爬滚打总结出来的东西。
2.1 H.264/H.265 编码核心原理
先说H.264,也叫AVC。它为什么能压得那么小?说白了就四个字:帧间预测。
视频里相邻帧之间,大部分像素是不动的。比如一个人坐在那里说话,背景墙根本不变。H.264的做法是:只记录变化的部分,不变的部分直接复用前一帧的数据。这就是所谓的「P帧」和「B帧」。
- I帧(关键帧):完整的一帧图像,不依赖其他帧。解码的起点。
- P帧(前向预测帧):只记录与前一帧的差异。
- B帧(双向预测帧):参考前后两帧,压缩率最高。
核心概念:GOP(Group of Pictures)
GOP就是一组连续的帧,以I帧开头。GOP越长,压缩率越高,但seek(跳转播放)越慢。我在做直播项目时,GOP设成了2秒,既保证压缩率,又保证观众拖进度条时不卡太久。
H.265(HEVC)呢?它是在H.264的基础上做了「暴力升级」。最核心的变化是:编码树单元(CTU)替代了宏块。
H.264的宏块最大16x16像素,而H.265的CTU最大64x64。大块适合平坦区域,小块适合纹理复杂区域。H.265会自适应地切分,说白了就是「哪里复杂切哪里,哪里简单就合并」。同样的画质,H.265能比H.264省30%~50%的码率。
我的经验: 在边缘设备上,如果CPU不够强,别硬上H.265。我曾经在树莓派上试过H.265实时编码,结果CPU直接飙到90%,帧率掉到15fps。后来换回H.264,稳如老狗。
下面这张图展示了H.264和H.265在编码块划分上的核心差异:
2.2 FFmpeg 命令行工具实战
FFmpeg这东西,我用了快十年了。它就是个「瑞士军刀」,什么格式都能切,什么参数都能调。但正因为太强大,很多人反而不知道怎么用。
我个人习惯把FFmpeg命令拆成三部分:输入 → 处理 → 输出。你只要记住这个结构,大部分命令都能自己拼出来。
ffmpeg [输入选项] -i input.mp4 [处理选项] [输出选项] output.mp4
2.2.1 常用转码命令
先来几个最常用的。这些命令我在生产环境里天天用:
| 场景 | 命令 | 说明 |
|---|---|---|
| H.264 转码 | ffmpeg -i input.mp4 -c:v libx264 output.mp4 |
软件编码,兼容性最好 |
| H.265 转码 | ffmpeg -i input.mp4 -c:v libx265 output.mp4 |
压缩率更高,但编码慢 |
| 硬件加速(NVIDIA) | ffmpeg -i input.mp4 -c:v h264_nvenc output.mp4 |
GPU编码,速度快,画质略差 |
| 提取音频 | ffmpeg -i input.mp4 -vn -c:a copy audio.aac |
只取音频流,不重新编码 |
| 截取片段 | ffmpeg -i input.mp4 -ss 00:01:00 -t 30 output.mp4 |
从第1分钟开始,截取30秒 |
注意: 用 -ss 时,如果放在 -i 前面,是「关键帧精准」截取,速度快但可能不准。放在 -i 后面,是「帧精准」截取,速度慢但精确。我一般先放前面快速定位,再放后面做精确裁剪。
2.2.2 常用编码参数解析
参数这东西,每个都有它的脾气。我挑几个最关键的说说:
- -crf (Constant Rate Factor):质量控制参数。范围0~51,越小质量越高。H.264一般用18~28,H.265用24~34。我个人习惯:存档用18,在线分发用23。
- -preset:编码速度预设。可选值:ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo。越慢压缩率越高。我一般用medium或slow,placebo就算了,收益太小。
- -profile:v:H.264档次。baseline(低端设备)、main(主流)、high(高清)。直播用baseline,点播用high。
- -tune:调优模式。film(电影)、animation(动画)、grain(胶片)、fastdecode(快速解码)。选对了能明显提升画质。
我的避坑指南: 曾经有个项目,视频在Chrome上播放正常,但在Safari上黑屏。查了半天,发现是用了-profile:v high10,Safari不支持10bit。后来改成-profile:v high,问题解决。所以,兼容性优先于画质。
2.3 编码参数对比表
下面这张表,是我自己整理的。每次做编码方案时,我都会拿出来对照一下:
| 参数 | H.264 (libx264) | H.265 (libx265) | 建议值 |
|---|---|---|---|
| CRF | 18~28 | 24~34 | 存档18,分发23 |
| Preset | medium/slow | medium/slow | 生产用medium |
| Profile | baseline/main/high | main/main10 | 点播用high |
| 码率控制 | ABR/CBR/CRF | ABR/CBR/CRF | 直播用CBR |
| GOP大小 | 10~300帧 | 10~300帧 | 直播2秒,点播5秒 |
2.4 实战:一条完整的转码命令
最后,我给大家一条「生产级」的转码命令。这条命令我在多个项目里验证过,兼顾了画质、兼容性和编码速度:
ffmpeg -i input.mp4 \
-c:v libx264 \
-preset medium \
-crf 23 \
-profile:v high \
-level 4.1 \
-pix_fmt yuv420p \
-c:a aac \
-b:a 128k \
-movflags +faststart \
output.mp4
解释一下几个关键点:
- -level 4.1:限制解码复杂度,保证在大多数设备上都能播放。
- -pix_fmt yuv420p:最通用的像素格式,兼容性最好。
- -movflags +faststart:把moov元数据移到文件头部,这样视频可以边下载边播放。做Web分发时必加。
总结一下: 编码这件事,没有银弹。你得根据场景选参数。直播追求低延迟,点播追求高压缩率,存档追求无损。理解了原理,再配合FFmpeg的参数,你就能做出适合自己业务的编码方案。