FFmpeg zscale HDR10 to Rec 709 SDR Conversion
This article explains how to use the zscale filter in
FFmpeg to tone-map and convert High Dynamic Range (HDR10 / Rec. 2020)
video into Standard Dynamic Range (SDR / Rec. 709) video. You will learn
the exact command-line syntax required to perform this conversion using
dynamic peak detection for optimal visual quality.
Converting HDR10 to SDR requires translating high-luminance color
spaces into a narrower range without losing image detail. The
zscale filter (which uses the ZImg library) is highly
recommended for this task because of its superior scaling, dithering,
and color space conversion accuracy compared to the default
scale filter.
The FFmpeg Command
To convert Rec. 2020 HDR10 to Rec. 709 SDR using zscale
and peak detection, run the following command:
ffmpeg -i input_hdr.mp4 -vf "zscale=t=linear,tonemap=tonemap=hable:peak=0,zscale=p=bt709:t=bt709:m=bt709:r=limited,format=yuv420p" -c:v libx264 -crf 20 -c:a copy output_sdr.mp4How the Filter Chain Works
The video filter chain (-vf) is broken down into four
distinct steps to ensure accurate color mapping:
zscale=t=linearThis step converts the input transfer characteristics (typically SMPTE 2084 / PQ for HDR10) into linear light. Tone mapping algorithms require linear light to correctly calculate brightness adjustments.tonemap=tonemap=hable:peak=0This performs the actual tone mapping.tonemap=hable: Uses the Hable (film-like) tone-mapping algorithm, which preserves highlights and shadow details effectively. You can also usereinhardormobius.peak=0: This is the parameter for peak detection. Setting the peak to0instructs FFmpeg to automatically and dynamically detect the peak luminance of the video frames, preventing the image from becoming washed out or overly dark.
zscale=p=bt709:t=bt709:m=bt709:r=limitedOnce tone-mapped, this secondzscalepass converts the linear video into the standard Rec. 709 color space:p=bt709: Sets the color primaries to BT.709.t=bt709: Sets the transfer characteristics (gamma curve) to BT.709.m=bt709: Sets the matrix coefficients to BT.709.r=limited: Forces limited color range, which is the standard for web and television playback.
format=yuv420pHDR10 videos are encoded in 10-bit color (usuallyyuv420p10le). This final filter converts the pixel format down to standard 8-bityuv420pto guarantee compatibility with all standard SDR displays and players.