HDR 4K H265 批量转 1080p H264 并保留色彩

HDR 4K H265 批量转 1080p H264 并保留色彩

问题的提出

我下载了一部电视剧,每一集的视频流都是 10 bit HDR 4K H265 格式。我想把它们转换为 1080p H264 格式。

但是,无论是用格式工厂、ShanaEncoder、小丸工具箱,转码后自动生成 8bit H264 视频。视频整体颜色发白,尤其是人物皮肤惨白惨白的,整体饱和度偏低。

这是因为在 10 bit HDR 转换到 8 bit SDR 的过程中,丢失了 HDR 元数据。

经过一番摸索,我终于在网上找到了方案:在 ffmpeg 中使用 tonemap 滤镜,将 10 bit HDR 映射到 8 bit SDR。这样可以尽可能地保留颜色信息。

另外,考虑到我的 CPU 是 R5-5600G,所以我启用了 AMD AMF 硬件加速,具体来说是 D3D11 硬件解码器和 AMF 硬件编码器,并且通过设置参数,让转码更加侧重视频质量。

最后,我用 PowerShell 写了个批量转码的脚本,转换结束后自动关机。为了运行方便,我把多个命令用分号分隔符合并成了一行命令,复制到 PowerShell 中粘贴按回车就可以了。

批量转码脚本

脚本内容如下

1
ls *.mp4 | foreach { ffmpeg -hwaccel d3d11va -i $_ -vf scale=1920:1080,zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p -preset slow -c:v h264_amf -profile:v high -quality quality -rc qvbr -c:a copy -crf 22 ($_.Basename+"_x264_HDR2SDR_ffmpeg.mp4") } ; echo "转换完毕,正在关机..." ; start-sleep -seconds 60 ; stop-computer

注意:执行脚本之前需要先安装 FFmpeg for Windows,并且把 FFMpeg.exe 所在的目录添加到系统变量。

脚本内容解释

  • ls *.mp4:列出当前目录下所有的 MP4 文件。
  • |:管道符,把前一条命令的输出,作为后一条命令的输入。
  • foreach {}:分别针对前面 ls *.mp4 输出的每一个文件执行花括号中的命令。
  • ffmpeg:运行 FFmpeg。
  • -hwaccel d3d11va:开启 d3d11va 硬件解码器。
  • -hwaccel_output_format d3d11:正常情况下这个参数可以避免把解码出的数据从显存转移到内存,FFmpeg 官方文档推荐使用这个参数,但是经本人测试,加上这个参数报错,可能是它与 tonemap 滤镜不兼容有关系,所以本人没有加这个参数。
  • -i $_-i 是 FFmpeg 的参数,表示指定源文件;$_ 是 PowerShell 的变量,代表前面 ls *.mp4 输出的每一个文件,此处对应其他 FFmpeg 教程中的 input.mp4
  • -vf scale=1920:1080,zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p-vf 是 FFmpeg 的参数,表示启用滤镜;scale=1920:1080 表示把分辨率设置为 1920x1080,FFmpeg 默认视频缩小的算法是双三次算法(bicubic);后面那一长串是我从网上抄来的设置 HDR to SDR 映射以及启用 tonemap 滤镜的参数,我也不懂啥意思。
  • -preset slow:把预设速度设置为慢速,速度越慢,转码后的视频质量越好。
  • -c:v h264_amf:目标格式为 H264,启用 AMF 硬件编码器。
  • -profile:v high-quality quality-rc qvbr :都是把转码设置为质量优先,当然,速度会比较慢,体积会比较大。
  • -c:a copy:不处理音频流。
  • -crf 22:将 CRF 参数设置为 22。H264 视频的 CRF 设置范围为 18~28,一般以 22~24 为宜,数值越小,视频质量越高,但是体积越大。
  • ($_.Basename+"_x264_HDR2SDR_ffmpeg.mp4"):此处是目标文件的文件名,对应其他 FFmpeg 教程中的 output.mp4$_.Basename 是前面 ls *.mp4 输出的每一个文件的主文件名(例如:C:\Video\episode1.mp4 的主文件名是 episode1);而 +"_x264_HDR2SDR_ffmpeg.mp4" 指的是把主文件名后面加上 _x264_HDR2SDR_ffmpeg.mp4作为目标文件名(例如,把 C:\Video\episode1.mp4 转码后的目标文件命名为 C:\Video\episode1_x264_HDR2SDR_ffmpeg.mp4);外面要加个圆括号括起来,否则会被 FFMpeg 当作它的参数而不是 foreach 的参数,导致报错。
  • ;:分隔符,把两个或多个命令写在同一行,执行完分号前面的命令,再执行分号后面的命令。
  • echo "转换完毕,正在关机..." :显示提示文字 转换完毕,正在关机...
  • start-sleep -seconds 60:等 60 秒。
  • stop-computer:关机。

图片版权

题图:版权归 FFmpeg 开发者所有。

头图:https://pixabay.com/zh/photos/pond-cherry-trees-dusk-6648129/


求扫码打赏
“我这么可爱,请给我钱 o(*^ω^*)o”

HDR 4K H265 批量转 1080p H264 并保留色彩
https://blog.kukmoon.com/95505eb594c3/
作者
Kukmoon谷月
发布于
2024年3月27日
许可协议