Apply 3D LUT to HDR Video with FFmpeg
This guide explains how to apply a 3D LUT (.cube) file to an HDR video using FFmpeg. You will learn how to apply the lookup table while preserving the 10-bit HDR color metadata, as well as how to convert HDR footage to SDR using a standard Rec.709 LUT.
Applying a LUT While Preserving HDR (HDR to HDR)
If your 3D LUT is designed for HDR color spaces (such as BT.2020) and you want to output an HDR video, you must apply the LUT and explicitly pass the HDR metadata to the output file. Without specifying the color metadata, FFmpeg may strip the HDR flags, resulting in a washed-out video.
Use the following command to apply the LUT and maintain HDR10 compatibility:
ffmpeg -i input.mp4 -vf "lut3d=file.cube" -c:v libx265 -pix_fmt yuv420p10le -color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc -metadata:s:v:0 master-display="G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)" -c:a copy output.mp4Command Breakdown:
-vf "lut3d=file.cube": Calls the 3D LUT filter and points to your.cubefile.-c:v libx265: Encodes the output video using the H.265/HEVC codec, which is standard for HDR.-pix_fmt yuv420p10le: Sets the pixel format to 10-bit, which is required for HDR10.-color_primaries bt2020: Defines the BT.2020 wide color gamut.-color_trc smpte2084: Sets the transfer characteristics to SMPTE ST 2084 (PQ curve used for HDR10).-colorspace bt2020nc: Sets the color space matrix to BT.2020 non-constant luminance.-metadata:s:v:0 master-display: Optional but recommended; it passes mastering display metadata to ensure proper HDR playback on compatible screens.
Applying a Rec.709 LUT to HDR (HDR to SDR Conversion)
If you have a standard creative LUT designed for Rec.709 (SDR) footage, you cannot apply it directly to HDR footage without mapping the colors first. You must tonemap the HDR video to SDR before applying the 3D LUT.
Use this command to convert the HDR video to SDR and apply a Rec.709 LUT:
ffmpeg -i input.mp4 -vf "zscale=transfer=linear,tonemap=tonemap=hable,zscale=transfer=bt709:matrix=bt709:primaries=bt709,format=yuv420p,lut3d=file.cube" -c:v libx264 -crf 18 -c:a copy output.mp4Command Breakdown:
zscale=transfer=linear: Converts the transfer characteristics to linear light for accurate tonemapping.tonemap=tonemap=hable: Applies the Hable tonemapping algorithm to compress high-dynamic-range highlights into standard dynamic range.zscale=transfer=bt709...: Converts the color space, matrix, and primaries to Rec.709 (SDR).format=yuv420p: Sets the pixel format to 8-bit YUV 4:2:0, standard for SDR H.264 video.lut3d=file.cube: Applies your.cubeLUT to the newly converted SDR video stream.