Yes, converting High Dynamic Range (HDR) video to Standard Dynamic Range (SDR) is entirely possible using FFmpeg by applying a tone mapping filter. This process compresses the wider color gamut and brightness range of HDR content into the limited range of SDR displays, ensuring accurate colors and preventing washed-out or crushed blacks on standard monitors.
Understanding the Conversion Challenge
HDR videos contain metadata describing their color space and peak brightness, typically using formats like BT.2020 and PQ (Perceptual Quantizer) transfer functions. When played on an SDR display without conversion, these signals are often interpreted incorrectly, resulting in poor visual quality. The goal of conversion is to map the high dynamic range luminance values down to the 0-100 nits range typical of SDR while preserving as much detail as possible.
FFmpeg handles this through its
vapoursynth or native
zscale and
tonemap filters. Unlike simple transcoding tasks discussed in
FFMPEG: Converting MKV to MP4 for Playback in VLC Media Player, HDR conversion requires specific handling of color matrices and transfer characteristics to avoid artifacts.
Required Tools and Setup
To perform this conversion effectively, you need a version of FFmpeg that includes support for the
tonemap filter. Most modern builds include this, but it is crucial to verify that your installation supports the necessary color spaces. You will also need the source HDR file, which usually has a container format like MP4 or MKV containing HEVC or H.265 video streams with HDR metadata.
Ensure your output device supports the target SDR format. While most screens accept H.264 or H.265 encoded SDR video, the key difference lies in the color metadata embedded in the stream. You do not need specialized hardware for the conversion itself, as FFmpeg can utilize CPU-based software tonemapping, though GPU acceleration can speed up the process significantly for large files.
The Tone Mapping Filter Explained
The core of the conversion is the
tonemap filter. This filter remaps the luma values from the HDR range to the SDR range. It uses algorithms to determine how to compress highlights and shadows. Common modes include "linear," "clip," "mobius," and "bt.2390." The choice of algorithm affects the final look; "linear" is often preferred for general use due to its simplicity and lack of visible banding, while "mobius" may preserve more shadow detail.
You must also specify the input and output color spaces. Typically, HDR sources use
bt2020 for color primaries and
pq for transfer characteristics. The output should be set to
bt709 and
bt709 (or
smpte170m) respectively. Failing to specify these correctly can result in colors appearing neon or desaturated. For more details on setting conversion parameters, see
Converting Video Data: Specifying Conversion Settings for FFmpeg Order.
Step-by-Step Conversion Command
Here is a robust command structure for converting an HDR HEVC file to an SDR MP4 file. This example assumes the input is BT.2020/PQ and outputs to BT.709/BT.709 using linear tonemapping.
ffmpeg -i input_hdr.mp4 -vf "zscale=transfer=bt709,colorspace=bt709,tonemap=linear,format=yuv420p" -c:v libx264 -crf 23 -preset fast output_sdr.mp4
Let's break down the components:
- -i input_hdr.mp4: Specifies the source HDR file.
- -vf ...: Applies the video filter chain.
- zscale=transfer=bt709,colorspace=bt709: Converts the color space metadata to SDR standards.
- tonemap=linear: Applies the linear tone mapping algorithm.
- format=yuv420p: Ensures the output pixel format is compatible with most players and devices.
- -c:v libx264: Encodes the video using the H.264 codec, which is widely supported for SDR content.
- -crf 23: Sets the Constant Rate Factor for quality control. Lower values mean higher quality and larger file sizes.
If you encounter issues with color spaces similar to those described in
Issues Converting FFmpeg Video HEVC1 to HVC1, check your FFmpeg version and ensure that the
zscale filter is properly linked. Some older builds may require explicit declaration of input color properties using
-colorspace bt2020nc -color_trc pq before the filter chain.
Troubleshooting Common Issues
One common issue is "clipping," where bright areas turn completely white and lose detail. If this occurs, try changing the tonemap mode from "linear" to "mobius" or "clip." Another issue is incorrect color appearance, often caused by mismatched input metadata. Always verify the input file's properties using
ffprobe to confirm it is indeed BT.2020/PQ.
Additionally, some players may ignore the SDR metadata if the container does not explicitly signal it. Using the MP4 container with H.264 encoding, as shown above, generally ensures broad compatibility. If you are converting from MKV containers, note that while FFmpeg handles the conversion internally, the final output might benefit from re-muxing into MP4 for better player recognition, a topic explored in
Unable to Convert MKV Video File to MP4 Container: Unsupported Codec?.
Frequently Asked Questions
Will the converted video look flat compared to the original HDR?
Yes, the video will likely appear less vibrant because the wide color gamut and high contrast are compressed. However, proper tone mapping preserves perceptual brightness and color accuracy, making it suitable for SDR displays rather than just looking "washed out."
Can I convert HDR to SDR without re-encoding the video stream?
No, tone mapping requires modifying the pixel data to adjust luminance values, which necessitates re-encoding. You cannot simply change metadata tags to achieve true HDR to SDR conversion.
What is the best tonemap mode for movies?
The "linear" mode is generally recommended for most movies as it provides a balanced approach without introducing artificial contrast boosts. "Mobius" may be better for content with very dark scenes, but it can sometimes introduce subtle banding in gradients.
Does this method work for Dolby Vision content?
Standard FFmpeg tonemapping works well for SMPTE ST 2084 (PQ) HDR10 content. Dolby Vision is a proprietary format that often requires specific parsing tools or newer FFmpeg versions with enhanced Dolby Vision support, so results may vary.
How can I reduce the file size after conversion?
Adjust the
-crf value in the encoding command. Increasing the CRF from 23 to 28 will significantly reduce file size at the cost of some quality loss. Additionally, using a slower
-preset like "slow" or "medium" can improve compression efficiency.