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

How can I encode RGB images into HDR10 videos in ffmpeg command-line?

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

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

例如:

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

  • 传递函数决定了你应该如何将编码的 RGB 或 YUV 值映射到显示亮度(-color_trc 在 ffmpeg 选项中,transfer 在 x265 选项中) .常用选项为 HLG (arib-std-b67) 或 PQ (smpte2084)。
  • colorspace primaries 定义编码的 RGB 值如何映射到真实颜色(-color_primaries for ffmpeg,colorprim for x265)。对于 HDR10,最常见的选项是 bt2020.
  • 颜色矩阵用于RGB值(用于在屏幕上显示数据)和YUV值(这使得视频编码器更高效,因为它们粗略地将亮度(Y)与色度(UV)通道分开),对应于 ffmpeg 中的 -colorspacecolormatrix在 x265 中。对于 HDR10,最常见的选项是 bt2020nc.
  • 信号范围 确定 0-100% 之间的 RGB 值是否映射到完整的 0-255(8 位)或 0-1023(10 位) ) 范围,或者是否保留供内部使用的边距(ffmpeg 中的 -color_range,x265 中的 range)。它传统上在视频中是“有限”(或:“电视”、“窄”),在 RGB 图像中是“完整”(或:“pc”)。

HDR10 在此之上定义了额外的元数据,这些元数据旨在供 OS/player 用来调整不支持 HDR 的屏幕上的视频输出,以便它们可以在这些约束:

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

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

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

考虑到这一点,我们可以使用以下命令行将 Rec2020 HLG RGB 图像转换为 HDR10 Rec2020 HLG 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 arib-std-b67 \
  -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 arib-std-b67 \
  -color_primaries bt2020 \
  -colorspace bt2020nc \
  -pix_fmt yuv444p10le \

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

  # x265 HDR10 metadata
  -x265-params colorprim=bt2020:transfer=arib-std-b67: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