支持,zscale滤镜可实现hdr→sdr动态范围映射,需配合t=linear、p=bt2020、m=smpte2084等参数精确处理pq/hlg信号,并依赖libzimg和ffmpeg≥5.1。

FFmpeg 的 zscale 滤镜是否支持 HDR 到 SDR 的动态范围映射?
支持,但必须用 zscale(而非 scale 或 tonemap)配合正确参数才能可靠完成 HDR→SDR 映射。关键在于它能处理 PQ/HLG 信号、保留 BT.2020/BT.709 色域信息,并支持 t=linear + m=smpte2084 等精确传递函数。常见错误是直接套用 tonemap=tonemap=hable,结果亮度发灰、高光细节全丢——那只是简单压缩,不是标准动态范围映射。
-
zscale需要 FFmpeg ≥ 4.3(推荐 ≥ 5.1),且编译时启用了libzimg - 输入视频必须带正确元数据:可通过
ffprobe -v quiet -show_entries stream=color_transfer,color_space,color_primaries video.mp4验证是否为smpte2084/bt2020nc - 若元数据缺失,需手动补全,否则
zscale会按默认 SDR 处理,输出仍是 HDR 感观
PHP 中调用 FFmpeg 命令做 HDR→SDR 转码的最小可行命令是什么?
以下命令可作为 PHP exec() 或 shell_exec() 的基础模板,已验证对 H.265 HDR10 MP4 输入有效:
ffmpeg -i input.mp4 \ -vf "zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv" \ -c:v libx264 -crf 23 -preset medium \ -c:a aac -b:a 128k \ output_sdr.mp4
说明:
-
zscale=t=linear:npl=100:将 PQ 曲线转为线性光,npl=100表示参考白点 100 nits(SDR 标准),这是映射基准 -
format=gbrpf32le:强制 32 位浮点中间格式,避免整数截断导致 banding -
tonemap=tonemap=hable是可选但推荐的色调映射器,比mobius更稳,desat=0防止自动去饱和 - 最后
zscale把信号转回 gamma-corrected BT.709,否则播放器可能误判为线性信号而过曝
PHP 执行时常见失败原因和绕过方法
不是命令写错,而是环境与权限卡住。最常触发的错误是:Unknown encoder 'libx264' 或 Filter 'zscale' has an unconnected output。
- 确认 PHP 进程使用的 FFmpeg 是你本地编译/安装的版本,而非系统自带旧版(如 Ubuntu 20.04 自带的 4.2.7 不支持
zscale的完整 HDR 流程) - 用
exec('which ffmpeg', $out); var_dump($out);和exec('ffmpeg -version', $out); var_dump($out);双重校验路径与版本 -
zscale报 unconnected output 多因滤镜链中漏了format或前后 color space 不匹配,务必保持gbrpf32le → gbrpf32le或显式加format=yuv420p收尾 - 权限问题:Web 服务器用户(如 www-data)可能无权读取输入文件或写入输出目录,建议用绝对路径并
chown www-data:www-data /path/to/videos
为什么输出视频在浏览器里看起来还是“HDR 感”?
因为浏览器不读取或忽略 colormatrix 和 transfer 元数据,即使 FFmpeg 已正确写入 -colorspace bt709 -color_trc bt709 -color_primaries bt709,Chrome/Safari 仍可能按 HDR profile 渲染。这不是转码失败,而是播放端限制。
- 验证是否真失败:用
ffprobe -v quiet -show_entries stream=color_transfer,color_space output_sdr.mp4查看输出是否为bt709—— 若是,问题在播放器 - 临时对策:加
-movflags +write_colr强制写入 ISO/IEC 23001-8 兼容的色彩描述符(对 MP4 有效) - 长期方案:前端用
<video></video>加playsinline+ Media Source Extensions(MSE)注入自定义色彩配置,但需 JS 解析并重封装帧
真正难的不是跑通命令,而是确认每一帧的 luminance 值落在 0–100 nits 区间内,且 peak white 没被硬 clipped。这需要靠 ffprobe -select_streams v -show_entries frame=pkt_pts_time,pict_type,tag:lavfi.pixelutils.signalstats.YAVG 抽样分析,而不是只看预览图。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











