如何在 ffmpeg 命令行中将 RGB 图像编码为 HDR10 视频?
How can I encode RGB images into HDR10 videos in ffmpeg command-line?
如何使用 ffmpeg 命令行使用正确的颜色和亮度元数据对 RGB 图像的 HDR10 视频进行编码?
在搜索有关如何正确编码 HDR10 流的信息时,有很多 ffmpeg 命令行示例随处可见,但我没有找到任何具有使用 RGB 时可以调整的所有参数的完整列表的示例帧作为输入。
例如:
- This article 有很多信息,但使用现有视频作为输入。
- 同样,this article 使用现有视频作为输入
传统视频需要具有以下元数据集:
- 传递函数决定了你应该如何将编码的 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 中的
-colorspace
和 colormatrix
在 x265 中。对于 HDR10,最常见的选项是 bt2020nc
.
- 信号范围 确定 0-100% 之间的 RGB 值是否映射到完整的 0-255(8 位)或 0-1023(10 位) ) 范围,或者是否保留供内部使用的边距(ffmpeg 中的
-color_range
,x265 中的 range
)。它传统上在视频中是“有限”(或:“电视”、“窄”),在 RGB 图像中是“完整”(或:“pc”)。
HDR10 在此之上定义了额外的元数据,这些元数据旨在供 OS/player 用来调整不支持 HDR 的屏幕上的视频输出,以便它们可以在这些约束:
- MaxFALL 和 MaxCLL 分别描述。视频的平均和最大亮度(
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
如何使用 ffmpeg 命令行使用正确的颜色和亮度元数据对 RGB 图像的 HDR10 视频进行编码?
在搜索有关如何正确编码 HDR10 流的信息时,有很多 ffmpeg 命令行示例随处可见,但我没有找到任何具有使用 RGB 时可以调整的所有参数的完整列表的示例帧作为输入。
例如:
- This article 有很多信息,但使用现有视频作为输入。
- 同样,this article 使用现有视频作为输入
传统视频需要具有以下元数据集:
- 传递函数决定了你应该如何将编码的 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 中的
-colorspace
和colormatrix
在 x265 中。对于 HDR10,最常见的选项是bt2020nc
. - 信号范围 确定 0-100% 之间的 RGB 值是否映射到完整的 0-255(8 位)或 0-1023(10 位) ) 范围,或者是否保留供内部使用的边距(ffmpeg 中的
-color_range
,x265 中的range
)。它传统上在视频中是“有限”(或:“电视”、“窄”),在 RGB 图像中是“完整”(或:“pc”)。
HDR10 在此之上定义了额外的元数据,这些元数据旨在供 OS/player 用来调整不支持 HDR 的屏幕上的视频输出,以便它们可以在这些约束:
- MaxFALL 和 MaxCLL 分别描述。视频的平均和最大亮度(
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