How to Convert SDR to HLG Video Using FFmpeg
Converting Standard Dynamic Range (SDR) video to High Dynamic Range
(HDR) using the Hybrid Log-Gamma (HLG) standard is a highly effective
way to upgrade legacy footage for modern HDR displays. This article
provides a direct, step-by-step guide on how to map SDR (Rec. 709) video
to HLG (Rec. 2020) using FFmpeg’s powerful color mapping filters,
specifically focusing on the zscale and native
colorspace filters, while ensuring the output metadata is
correctly flagged for HDR playback.
Method 1: Using
the zscale Filter (Recommended)
The zscale filter (which requires FFmpeg to be compiled
with --enable-libzimg) is the most accurate tool for
scaling and performing color space conversions in FFmpeg. It handles the
expansion of the Rec. 709 color gamut to Rec. 2020 and maps the transfer
characteristics to HLG (ARIB STD-B67).
Use the following command to perform the conversion:
ffmpeg -i input_sdr.mp4 -vf "zscale=pin=bt709:tin=bt709:min=bt709:p=bt2020:t=arib-std-b67:m=bt2020nc" -c:v libx265 -pix_fmt yuv420p10le -color_range tv -colorspace bt2020nc -color_primaries bt2020 -color_trc arib-std-b67 output_hlg.mp4Command Breakdown:
pin,tin,min: Defines the input primaries, transfer characteristics, and matrix as BT.709 (SDR).p=bt2020: Sets the output color primaries to BT.2020.t=arib-std-b67: Sets the output transfer characteristics to HLG (referenced technically as ARIB STD-B67).m=bt2020nc: Sets the output color matrix to BT.2020 non-constant luminance.-pix_fmt yuv420p10le: Converts the pixel format to 10-bit, which is required for HLG distribution.-color_range tv -colorspace bt2020nc -color_primaries bt2020 -color_trc arib-std-b67: Injects the appropriate metadata into the video container so TVs and media players recognize the file as HLG HDR.
Method 2: Using the
Native colorspace Filter
If your FFmpeg build does not have the zscale filter
enabled, you can use the native colorspace filter. While
slightly less configurable than zscale for complex tone
mapping, it is highly efficient for standard Rec. 709 to Rec. 2020
conversions.
Use the following command:
ffmpeg -i input_sdr.mp4 -vf "colorspace=all=bt2020nc:trc=arib-std-b67:primaries=bt2020:irange=tv:orange=tv" -c:v libx265 -pix_fmt yuv420p10le -color_range tv -colorspace bt2020nc -color_primaries bt2020 -color_trc arib-std-b67 output_hlg.mp4Command Breakdown:
all=bt2020nc: Sets the output color matrix.trc=arib-std-b67: Sets the output transfer characteristics to HLG.primaries=bt2020: Sets the output color primaries.irange=tv:orange=tv: Ensures the input and output color ranges remain restricted (TV/limited range), which is standard for broadcast HLG.
Verifying the Output
To ensure your video has been correctly mapped and tagged, you can
inspect the output file metadata using ffprobe:
ffprobe -show_streams output_hlg.mp4Look for the following fields in the video stream output to confirm
success: * color_range=tv *
color_space=bt2020nc *
color_transfer=arib-std-b67 *
color_primaries=bt2020