How to Preserve HDR10 Metadata in FFmpeg HEVC
Transcoding HDR10 video using FFmpeg often results in a loss of dynamic range, causing the output video to look washed out because the essential HDR10 metadata is discarded by default. This guide provides a direct, step-by-step method to extract the original HDR10 metadata—specifically the Mastering Display Color Volume and Content Light Level—and inject it back into your newly transcoded HEVC/x265 video.
Step 1: Extract the Original HDR10 Metadata
Before transcoding, you must extract the metadata from the source
file. Run the following ffprobe command to read the side
data of the first frame:
ffprobe -v error -select_streams v:0 -show_frames -read_intervals "%+#1" -show_entries frame=side_data_list -of default=noprint_wrappers=1 input.mp4Look for two specific blocks in the output:
- Mastering Display Metadata: This looks like
G(x,y) B(x,y) R(x,y) WP(x,y) L(min,max).- Example output:
G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(5,10000000)
- Example output:
- Content Light Level Metadata: This contains the
MaxCLL and MaxFALL values.
- Example output:
max_content=1000, max_average=400
- Example output:
Step 2: Format the Metadata for FFmpeg
You must pass these values to the x265 encoder using the
-x265-params flag. Format the values as follows:
- Mastering Display: Replace the spaces in the
ffprobeoutput with colons.- Formatted:
master-display=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(5,10000000)
- Formatted:
- Content Light Level: Format as
max-cll=MaxCLL,MaxFALL.- Formatted:
max-cll=1000,400
- Formatted:
Step 3: Run the Transcoding Command
To preserve the HDR10 color space and metadata, you must also specify the correct color primaries, transfer characteristics, and matrix coefficients (BT.2020 and PQ).
Use the following complete FFmpeg command, substituting the metadata values you extracted in Step 1:
ffmpeg -i input.mp4 -c:v libx265 -pix_fmt yuv420p10le -color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc -x265-params "colorprim=bt2020:transfer=smpte2084:colormatrix=bt2020nc:master-display=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(5,10000000):max-cll=1000,400:hdr10=1" -c:a copy output.mp4Command Parameter Breakdown
-pix_fmt yuv420p10le: Forces 10-bit color depth, which is strictly required for HDR10.-color_primaries bt2020: Sets the color primaries to BT.2020.-color_trc smpte2084: Sets the transfer characteristics to SMPTE ST 2084 (PQ curve).-colorspace bt2020nc: Sets the color space matrix.hdr10=1: Enables the x265 encoder to write HDR10-compliant metadata and container-level flags.