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.

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.mp4

Command 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.mp4

Command 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.mp4

Look 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