Skip to content

FFmpeg 常用编码器与参数:深入了解视频压缩的奥秘

WARNING

不要依赖 FFmpeg 的默认设置! 因为我们不知道 FFmpeg 会在哪个版本修改默认设置。 除非你不在意编码细节,否则请明确指定编码器及其参数。 这也是为什么你需要了解编码器参数。

本章介绍一些常用编码器的参数使用方法。 大部分内容来自 FFmpeg 的 trac 百科。

1. libx264 (H.264 视频):视频压缩界的常青树

H.264 是一种非常流行的视频编码格式,libx264 则是最常用的 H.264 编码器。 如果你需要输出 MP4 格式的视频文件,但没有指定编码器,FFmpeg 会自动调用 libx264 并使用默认参数进行编码。

shell
# 以下命令等于 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。
  • -preset 参数: 指导视频压制的质量。 越慢的预案,压缩效果越好,输出相同质量的视频所需的文件体积越小。 预案从快到慢包括:ultrafast, superfast, veryfast, faster, fast, medium (默认), slow, slower, veryslow

    • 建议使用 medium 或更慢的预案。
    • 指定无损 (CRF=0) 时,可以使用 ultrafast
  • -tune 参数: 告知输入视频的风格。

    • animation:动画。 提升去块 (deblocking) 强度与参考帧数量。
    • fastdecode:快速解码。 禁用滤镜来加快解码。
    • film:电影。 降低去块强度。
    • grain:颗粒。 保留旧电影的颗粒感。
    • stillimage:静止图像。 适用于相片幻灯片或类似主题的内容。
    • zerolatency:零延迟。 适用于快速编码,或者低延迟流媒体内容。

例子:

shell
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 参数。

shell
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 的命令行帮助:

shell
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 级去颗粒。
shell
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 音频:

shell
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*320320 (CBR)
-q:a 0245220 ~ 260
-q:a 1225190 ~ 250
-q:a 2190170 ~ 210
-q:a 3175150 ~ 195
-q:a 4165140 ~ 185
-q:a 5130120 ~ 150
-q:a 6115100 ~ 130
-q:a 710080 ~ 120
-q:a 88570 ~ 105
-q:a 96545 ~ 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"):

shell
ffmpeg -i input.wav -c:a libmp3lame -b:a 192k output.mp3

4.3 平均比特率 (ABR):折中的选择

平均比特率 (ABR) 介于固定与可变之间,可以向参数 -abr 赋值 1 来启用。 除此之外,libmp3lame 编码器此时仍需要 -b:a 的码率参数作为指导:

shell
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

shell
ffmpeg -i input.wav -c:a aac -b:a 192k output.m4a