How to Change Color Matrix in FFmpeg for SD Video
This article explains how to adjust and set the color matrix coefficients for Standard Definition (SD) video using FFmpeg. You will learn how to convert color spaces (such as from HD BT.709 to SD BT.601) and how to correctly tag video metadata so media players render the colors accurately.
Understanding SD Color Matrices
Standard Definition (SD) video typically utilizes the
BT.601 color matrix (often represented in FFmpeg as
smpte170m or bt470bg). In contrast, High
Definition (HD) video uses BT.709. If you play an SD
video with the wrong color matrix settings, the colors may appear washed
out, overly saturated, or shifted green/magenta.
To fix this, you can either convert the actual pixel values to the correct color space, tag the metadata to tell the player which color space to use, or do both.
Method 1: Converting the Color Space (Filter Method)
If your video was encoded with the wrong color coefficients (for example, an SD video using HD BT.709 colors), you can convert the actual color properties using FFmpeg filters.
Using the colormatrix
Filter
The colormatrix filter allows you to convert directly
from one color space to another. To convert a video from BT.709 to
BT.601 (specifically smpte170m for SD):
ffmpeg -i input.mp4 -vf colormatrix=bt709:smpte170m -c:v libx264 -crf 18 -c:a copy output.mp4Using the scale Filter
Alternatively, you can use the scale filter, which is
highly efficient and handles color space conversion during scaling:
ffmpeg -i input.mp4 -vf scale=out_color_matrix=bt601 -c:v libx264 -crf 18 -c:a copy output.mp4Method 2: Flagging the Metadata (No Re-encoding / Fast Method)
Sometimes the pixels are already correct, but the video file lacks the metadata flags telling the player to use BT.601. You can set these flags without re-encoding the video by using bitstream filters, which is extremely fast and preserves original quality.
For H.264 video, use the h264_metadata bitstream filter
to set the transfer characteristics, color primaries, and color matrix
to BT.601 (smpte170m):
ffmpeg -i input.mp4 -c:v copy -bsf:v h264_metadata=video_full_range_flag=0:colour_primaries=6:transfer_characteristics=6:matrix_coefficients=6 -c:a copy output.mp4(Note: Value 6 corresponds to the BT.601/SMPTE170M
standard in H.264 specifications).
Method 3: Converting and Tagging (Recommended)
To ensure maximum compatibility across all players and devices, it is best to convert the color space and explicitly write the metadata tags at the same time. Use the following command to encode the video with BT.601 colors and inject the correct tags:
ffmpeg -i input.mp4 -vf scale=out_color_matrix=bt601 -c:v libx264 -pix_fmt yuv420p -color_range tv -colorspace smpte170m -color_trc smpte170m -color_primaries smpte170m -crf 18 output.mp4Command Breakdown:
-vf scale=out_color_matrix=bt601: Converts the physical pixel values to BT.601.-pix_fmt yuv420p: Ensures standard YUV chroma subsampling compatibility.-color_range tv: Sets the color range to limited (standard TV range 16-235).-colorspace smpte170m: Tags the matrix coefficients as BT.601.-color_trc smpte170m: Tags the transfer characteristics (gamma curve) as BT.601.-color_primaries smpte170m: Tags the color primaries as BT.601.