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/921681ef/
作者
Kukmoon谷月
发布于
2024年3月27日
许可协议