如何在 ffmpeg 命令行中将 RGB 图像编码为 HDR10 视频?

F.X*_*.X. 9 ffmpeg

如何使用 ffmpeg 命令行以及正确的颜色和亮度元数据对 RGB 图像中的 HDR10 视频进行编码?

在搜索有关如何正确编码 HDR10 流的信息时,有很多 ffmpeg 命令行示例,但我没有找到任何包含使用 RGB 帧作为输入时可以调整的所有参数的完整列表的示例。

例如:

  • 本文包含大量信息,但使用现有视频作为输入。
  • 同样,本文使用现有视频作为输入

F.X*_*.X. 21

传统视频需要具有以下元数据集:

  • 传递函数决定如何将编码的 RGB 或 YUV 值映射到显示亮度(-color_trc在 ffmpeg 选项中,transfer在 x265 选项中)。HDR 视频的常见选项是 HLG ( arib-std-b67) 或 PQ ( smpte2084),正确应用 HDR10需要 PQ
  • 色彩空间原色定义编码的 RGB 值如何映射到真实颜色(-color_primaries对于 ffmpeg,colorprim对于 x265)。对于常见的 HDR 格式(包括 HDR10),您需要bt2020.
  • 颜色矩阵用于在 RGB 值(用于在屏幕上显示数据)和 YUV 值(这使视频编码器更高效,因为它们大致将亮度 (Y) 与色度 (UV) 通道分开)之间进行转换,以及对应于-colorspaceffmpeg和colormatrixx265中。对于常见的 HDR 格式(包括 HDR10),您需要bt2020nc.
  • 信号范围决定 0-100% 之间的 RGB 值是否映射到完整的 0-255(8 位)或 0-1023(10 位)范围,或者是否保留余量供内部使用(-color_range在 ffmpeg 中) ,range以 x265 表示)。传统上,它在视频中是“有限”(或:“电视”、“窄”),在 RGB 图像中是“完整”(或:“pc”)。

HDR10 定义了额外的元数据,旨在供操作系统/播放器使用来调整不支持 HDR 的屏幕上的视频输出,以便它们可以在这些限制下尽可能地显示:

  • MaxFALLMaxCLL分别描述了。视频的平均和最大亮度(max-cllx265 选项)
  • 掌握显示特性描述了视频要显示的“完美”显示(master-displayx265 选项)

现在,有几件事需要特别注意:

  • 传统的元数据可以在视频容器和x265流中设置(因此应该在ffmpeg和x265中都设置,以避免播放时不匹配)。
  • 传统的元数据应该同时设置输入(之前-i)和输出(之后)格式,以便 ffmpeg 在编码时可以进行正确的转换。
  • HDR10 元数据仅存在于 x265 选项中;ffmpeg 对它们一无所知,并且它们不会影响视频像素值。
  • 不幸的是,ffmpeg 用于格式转换的默认过滤器(swscale 或-vf scale在命令行中)在自动应用时存在很多问题。我发现最好总是明确指定至少信号范围,甚至使用zscale它来代替它并且表现得更好。swscale 存在几个 问题,因此很难解决。
  • 传统 SDR (BT709) 视频和 HDR10 (BT2020) 之间的 YUV 到 RGB 转换(这就是我们在这里所做的,因为我们使用 RGB 图像作为输入!)是不同的这是一个非常常见的错误来源,因为如果没有在输入和输出格式中明确指定,许多 ffmpeg 内部会假定默认(可能是错误的)转换!
  • 输入图像-pix_fmt的 应该自动确定,但我将其包含在这里是为了全面;如果您想从原始 RGB 数据流式传输,它也是必需的。
  • 输出视频的指定-pix_fmt我们想要将 10 位 YUV 数据传递给编码器,并且是必需的。HDR10需要 10 位和 4:2:0 子采样,yuv420p10le
  • 此命令行假定您的 TIFF 图像已包含正确的颜色配置文件(它们已经是 Rec.2020 PQ 图像)。如果您想从 sRGB 或其他空间进行转换,您需要为输入文件设置特定格式并zscale正确过滤。

考虑到这一点,我们可以使用以下命令行将 Rec2020 PQ RGB 图像转换为 HDR10 Rec2020 PQ x265/HEVC 视频:

ffmpeg \

  # Some basic options
  -hide_banner \
  -loglevel verbose \

  # Scaling flags for the input
  # The print_info flag is very useful to debug cases when swscale is applied automatically!
  # The other flags ensure ffmpeg favors accuracy over (very limited) performance gains.
  -sws_flags print_info+accurate_rnd+bitexact+full_chroma_int \

  # Traditional metadata for input images (note the "pc" or "full" range)
  -color_range pc \
  -color_trc smpte2084 \
  -color_primaries bt2020 \
  -colorspace bt2020nc \
  -pix_fmt rgb48be \

  # Input frames as 16-bit big-endian RGB TIFF images with pixel values in Rec2020 HLG
  -framerate 30 -start_number 1 -i input-%03d.tif \

  # Explicitly configure the range conversion (so as to avoid using swscale)
  -vf zscale=rangein=full:range=limited \

  # Specify output codec (x265/HEVC)
  -c:v libx265 \

  # Traditional metadata for output video (note the "tv" or "limited" range)
  -color_range tv \
  -color_trc smpte2084 \
  -color_primaries bt2020 \
  -colorspace bt2020nc \
  -pix_fmt yuv420p10le \

  # Scaling flags for the output
  -sws_flags print_info+accurate_rnd+bitexact+full_chroma_int \

  # x265 HDR10 metadata
  -x265-params colorprim=bt2020:transfer=smpte2084:colormatrix=bt2020nc:range=limited:master-display=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1):max-cll=1000,400 \

  # Output file
  output.mov
Run Code Online (Sandbox Code Playgroud)

编辑 2022/08/29:更改了建议的命令行并澄清了正确传递函数的使用;从技术上讲,HDR10格式的正确应用需要 PQ,但之前的答案使用了 HLG 。HLG编码的视频仍然是HDR,但不能真正称为“HDR10”。