FFmpeg 常用编码器与参数:深入了解视频压缩的奥秘
WARNING
不要依赖 FFmpeg 的默认设置! 因为我们不知道 FFmpeg 会在哪个版本修改默认设置。 除非你不在意编码细节,否则请明确指定编码器及其参数。 这也是为什么你需要了解编码器参数。
本章介绍一些常用编码器的参数使用方法。 大部分内容来自 FFmpeg 的 trac 百科。
1. libx264 (H.264 视频):视频压缩界的常青树
H.264
是一种非常流行的视频编码格式,libx264
则是最常用的 H.264 编码器。 如果你需要输出 MP4 格式的视频文件,但没有指定编码器,FFmpeg 会自动调用 libx264
并使用默认参数进行编码。
# 以下命令等于 ffmpeg -i input.mkv -c:v libx264 output.mp4
ffmpeg -i input.mkv output.mp4
1.1 恒定率系数 (CRF):质量与体积的平衡
CRF 是一种控制视频质量的方法。 CRF 值越小,画面质量越好,但文件体积也越大。
-crf
参数:- 对于常见的 8-bit H.264 视频,
-crf
参数可以从 0 (无损) 到 51 (最差压缩) 取值。 - 默认值是 23。
- 建议选择 17~28 之间的数值。
- 17 已经非常接近无压缩的结果,更小的 CRF 值只会增加文件体积。
- 对于 10-bit H.264 视频,
-crf
参数的取值范围是 0~63。
- 对于常见的 8-bit H.264 视频,
-preset
参数: 指导视频压制的质量。 越慢的预案,压缩效果越好,输出相同质量的视频所需的文件体积越小。 预案从快到慢包括:ultrafast
,superfast
,veryfast
,faster
,fast
,medium
(默认),slow
,slower
,veryslow
。- 建议使用
medium
或更慢的预案。 - 指定无损 (CRF=0) 时,可以使用
ultrafast
。
- 建议使用
-tune
参数: 告知输入视频的风格。animation
:动画。 提升去块 (deblocking) 强度与参考帧数量。fastdecode
:快速解码。 禁用滤镜来加快解码。film
:电影。 降低去块强度。grain
:颗粒。 保留旧电影的颗粒感。stillimage
:静止图像。 适用于相片幻灯片或类似主题的内容。zerolatency
:零延迟。 适用于快速编码,或者低延迟流媒体内容。
例子:
ffmpeg -i video.mp4 -c:v libx264 -preset slow -tune film -crf 20 -c:a copy out.mp4
1.2 定限码率压制:为网络传输而生
适用于强制要求码率的场合,例如直播。
1.3 二压 (2Pass):精确控制文件大小
适用于强制要求文件大小的场合。
2. libx265 (H.265/HEVC 视频):更高效的压缩
H.265
的许多参数与 H.264
相同 (但取值含义可能不同),只是使用 libx265
编码器代替 libx264
。
2.1 恒定率系数 (CRF):新一代的平衡艺术
H.265 的默认 CRF 取值是 28,这不同于 H.264 的默认 CRF 取值 23;它们两者对应的视觉画面质量相同。
H.265 的视觉上的无损 CRF 值 (从经验上) 大约在 20~22,这不同于 H.264 中的 17。
H.265 的取值范围始终为 0 (无损) 到 51 (最差压缩),这不同于 H.264 的 CRF 取值范围 (8bit 0~51; 10bit 0~63)。
DANGER
libx264 与 libx265 的 CRF 取值无法对应
libx264 与 libx265 的 CRF 取值没有一一对应的公式。 除了上文所述的无损参数均为 CRF=0、libx264 CRF=23 对应 libx265 CRF=28,其余 CRF 值并不存在对应关系。
-preset
参数: 指导视频压制的质量。 其取值与libx264
相同,默认为medium
。- 与
libx264
类似,建议使用medium/slow
或更慢的预案。 - 指定无损 (CRF=0) 时,可以使用
ultrafast
。 - 较慢的预案在同等的 CRF 值上有更好的表现。 建议在选用更快速的预案时,适当降低 CRF 值以保持相近的质量。
- 与
-tune
参数: 告知输入视频的风格。libx265
支持的风格不如libx264
多,只包括:fastdecode
:快速解码。 禁用滤镜来加快解码。zerolatency
:零延迟。 适用于快速编码,或者低延迟流媒体内容。
2.2 定限码率压制:为带宽而生
用法与 libx264
类似,适用于强制要求码率的场合,例如直播。 请参考 码率限制 一节的内容。
2.3 二压 (2Pass):精确控制文件大小
用法与 libx264
类似,适用于强制要求文件大小的场合。 但请注意,编码器 libx265
需要额外在两步中指定 -x265-params
参数。 具体的用法,请参考 两遍编码 一节的内容。
2.4 10-bit 色深:更丰富的色彩
如果要以 10-bit 色深编码 H.265 视频,使用 -x265-params
下的 profile
参数。
ffmpeg -i video.mp4 -c:v libx265 -crf 21 -preset faster -tune fastdecode -x265-params profile=main10 -c:a aac -b:a 192k out.mp4
如果输入视频是 8-bit 的,那么需要使用
-pix_fmt
参数将其转为 10-bit:shell... -i video.mp4 -pix_fmt yuv420p10le -c:v libx265 ...
3. libsvtav1 (AV1 视频):未来之星
INFO
libsvtav1
编码器在 FFmpeg 5.1 版本后加入到了官方编译版本中。 推荐使用它,而不是较老的 libaom
编码器。 本节也只介绍 libsvtav1
的使用。
DANGER
libsvtav1
是一个较新的编码器,其参数可能发生变化。 因此本小节中的内容 (基于 FFmpeg 7.0) 可能与您所安装版本的不同。 具体请参考所安装的 FFmpeg 的命令行帮助:
ffmpeg -h encoder=libsvtav1
也可以参考 SVT-AV1 官方针对 FFmpeg 撰写的 使用指南。
AV1
可以视作是 H.265
的继任者,不仅提供了更好的压缩率,在使用权利上的约束也更少。 当然,转码的开销也更大;用户需要较新的硬件支持,否则转码速度将会极慢。
libsvtav1
编码器使用的许多参数都类似 libx264/libx265
,常用的有:
恒定率系数 (CRF): CRF 越小,画面质量越好,但文件体积越大。
- AV1 的取值范围始终为 1 (最好压缩) 到 63 (最差压缩),这不同于 H.264 的 CRF 取值范围 (8bit 0~51; 10bit 0~63)。
- AV1 中的 CRF 默认值为 35。
-preset
参数: 指导视频压制的质量。 数字越大,编码越快,同时质量越差。- 取值范围为 -1 到 13 (默认为 -1)。
- SVT-AV1 在 官方问答 中建议一般用户使用 预案 4-6 作为一般选择,以平衡存储效率与压制时间。 预案 1-3 压缩质量上佳,但是编码极度缓慢;预案 7-12 用于希望进行快速编码的场合;预案 13 通常只用于开发者测试。
关键帧间隔帧数量
-g
: 这实际上是 FFmpeg 的通用参数。 一般根据视频帧率,取 5 到 10 秒 (但不应超过 300)。 一个较通用的 g 值是 240,它对应 24 帧视频的 10 秒,或者 30 帧视频的 8 秒。 该参数也可以在编码器参数中用keyint
直接指定时长。常用编码器参数
-svtav1-params
: 使用键等于值 (key=value
) 的格式书写,并用冒号分隔。主观质量模式
tune
: 采用值tune=0
可以切换到主观质量模式 (VQ),这将稍微锐化图像并提供更好的“心理视觉效果”。 默认值为1
,即峰值信噪比 (PSNR) 模式。关键帧间隔时长
keyint
: 一般取 5-10 秒,请注意带单位s
,例如keyint=8s
。 默认值为 -2 (约 5 秒)。快速解码等级
fast-decode
: 取值从 0 (关闭) 到 2 (最高)。 默认值 0。 尽管该参数可以用于主观质量模式,但它是在tune=1
(默认) 模式下开发测试的,因此不推荐与主观质量模式共用。WARNING
我很少用到 fast-decode 参数,也不推荐在没有 AV1 解码能力的硬件上播放 AV1 编码的视频。 因为 AV1 解码的开销较大,即使使用了快速解码模式,在旧硬件上播放也非常容易卡顿。 这时候应该放弃文件体积优化,使用硬件支持较好的方式 (H.265 甚至 H.264) 进行编码,优先保证播放的流畅性。
去颗粒等级
file-grain
: 取值从 0 (关闭) 到 50 (最高)。 默认值 0。去颗粒等级并不是越高越好,过高可能会损害原有图像质量。 根据官方问答,这里提供以下建议:
- 如果原视频具有通常级别的颗粒数量,建议使用 8 左右的数值;如果颗粒比较明显,考虑使用 10-15 之间的数值。
- 如果原视频是平面动画类,建议使用较低的去颗粒等级 (4 左右),或者不使用。
- 如果原视频没有颗粒/热噪,建议不使用该参数,以提高编码速度与避免质量损失。
官方同样在问答中建议总是使用 10-bit 编码输出;即使源是 8-bit 视频,也可以通过 -pix_fmt yuv420p10le
参数来强制转 10-bit。 这样能以较小的开销 (约 5% 的文件体积增长) 降低运算时的损失。
下面给出一个针对 8-bit 视频的 AV1 转码示例,主要参数释义如下:
- 预案
-preset 5
,采用了官方建议的一般用户预案 4-6 的中间数。 - CRF 参数 32 是官方示例中的值
- 关键帧间隔参数
-g 240
。 对 30 帧视频而言,即 8 秒一个关键帧。 - 色深度
-pix_fmt yuv420p10le
,强制指定输出编码为 10-bit;如果原视频是 10-bit,则可省略该项。 - 在编码器参数中,此处使用了主观质量模式与 8 级去颗粒。
ffmpeg -i video.mp4 -c:v libsvtav1 -preset 5 -crf 32 -g 240 -pix_fmt yuv420p10le -svtav1-params tune=0:film-grain=8 -c:a copy out.mp4
4. libmp3lame (MP3 音频):经典的音频压缩格式
MP3
曾经是最为流行的压缩音乐格式。 FFmpeg 通过 libmp3lame 编码器对 MP3 编码提供支持,一般有可变比特率、固定比特率、平均比特率三种质量控制方式。
4.1 可变比特率 (VBR):灵活的质量控制
一般地,推荐利用可变比特率 (VBR) 来编码 MP3 音频:
ffmpeg -i input.wav -c:a libmp3lame -q:a 2 output.mp3
- 质量参数
-q:a
(或者其全称-qscale:a
) 用于控制 MP3 品质。 - 编码器
libmp3lame
支持 0~9 的质量参数,其中 0 表示最高质量 (最高比特率,245 kbps 左右),而默认值是 4。 - 一般认为 0~3 的取值可以达到令人满意的质量。
FFmpeg 比特率参数与实际比特率范围 (kbps) 有如下对应关系:
参数 | 平均比特率 | 比特率范围 |
---|---|---|
-b:a 320k* | 320 | 320 (CBR) |
-q:a 0 | 245 | 220 ~ 260 |
-q:a 1 | 225 | 190 ~ 250 |
-q:a 2 | 190 | 170 ~ 210 |
-q:a 3 | 175 | 150 ~ 195 |
-q:a 4 | 165 | 140 ~ 185 |
-q:a 5 | 130 | 120 ~ 150 |
-q:a 6 | 115 | 100 ~ 130 |
-q:a 7 | 100 | 80 ~ 120 |
-q:a 8 | 85 | 70 ~ 105 |
-q:a 9 | 65 | 45 ~ 85 |
此为 MP3 所支持的最高码率,但在实际应用中并不推荐。 详情请参考下文中关于固定比特率 (CBR) 部分的内容。
4.2 固定比特率 (CBR):简单粗暴的质量控制
除了可变比特率,在网络上分享的 MP3 文件也常常采用固定比特率 (CBR) 编码,如 128, 192, 256 kbps。 编码器 libmp3lame
通过 -b:a
参数支持一系列固定比特率,分别是 8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 160, 192, 224, 256, 以及 320 kbps。
WARNING
一般认为在 MP3 (或者其他压缩格式上) 追求高码率 (如 320 kbps) 是没有意义的,因为 VBR 0~3 的质量对压缩格式已经足够好。 毕竟无论如何,MP3 都是有损压缩;想要更高的质量,建议转向 FLAC 等无损格式。
下例将音频以 192 kbps 的固定码率输出为 MP3 (不要忘记码率数字后面的字母 "k"):
ffmpeg -i input.wav -c:a libmp3lame -b:a 192k output.mp3
4.3 平均比特率 (ABR):折中的选择
平均比特率 (ABR) 介于固定与可变之间,可以向参数 -abr
赋值 1
来启用。 除此之外,libmp3lame
编码器此时仍需要 -b:a
的码率参数作为指导:
ffmpeg -i input.wav -c:a libmp3lame -abr 1 -b:a 192k output.mp3
5. aac (AAC 音频):新一代的音频压缩格式
AAC
是另一种常见的有损音频编码。 AAC 普遍在 MP4 视频容器中被使用,它也常用作独立的音频 m4a 文件。
FFmpeg 原生支持 aac
编码器,声称是仅次于 libfdk_aac
的 AAC 编码器。 官方提供的编译版本不使用 libfdk_aac
编码器,用户使用则需要重新编译 FFmpeg 。
建议在原生的 FFmpeg aac 编码器上使用固定比特率 (CBR) 参数 -b:a
:
ffmpeg -i input.wav -c:a aac -b:a 192k output.m4a