Convert 4:4:4 to 4:2:0 in VP9 Encoding

This article provides a direct guide on how to accurately convert YUV 4:4:4 video sources to the YUV 4:2:0 chroma subsampling format during a libvpx-vp9 encode using FFmpeg. Standard conversion methods often introduce color bleeding, blurriness in fine details (like text), or color shifts. By utilizing high-quality scaling algorithms and explicitly defining color matrices, you can achieve a highly accurate downsampling process that preserves visual fidelity.

The Challenge with Standard Conversion

When converting from YUV 4:4:4 (full color resolution) to YUV 4:2:0 (quarter color resolution), half of the horizontal and vertical color information is discarded. If you rely on FFmpeg’s default conversion, it typically uses a bilinear scaler, which causes neighboring colors to bleed into each other. To prevent this, you must use a high-quality resampling algorithm and ensure the color space (such as BT.709) is strictly preserved.

The Accurate Conversion Command

To convert your video accurately, use the following FFmpeg command structure:

ffmpeg -i input_444.mp4 -vf "scale=sws_flags=lanczos+accurate_rnd:sws_dither=a_dither,format=yuv420p" -c:v libvpx-vp9 -crf 30 -b:v 0 -colorspace bt709 -color_primaries bt709 -color_trc bt709 output.webm

Parameter Breakdown

To understand why this command ensures an accurate conversion, here is a breakdown of the critical parameters:

Alternative: Using the zscale Filter

If your FFmpeg build is compiled with --enable-libzimg, you can use the zscale filter, which uses the highly regarded zimg library. It offers even greater precision for color space conversions and downsampling:

ffmpeg -i input_444.mp4 -vf "zscale=matrix=709:filter=lanczos,format=yuv420p" -c:v libvpx-vp9 -crf 30 -b:v 0 -colorspace bt709 -color_primaries bt709 -color_trc bt709 output.webm

The zscale filter performs internal calculations in a higher bit depth, minimizing rounding errors and producing the cleanest possible 4:2:0 output from a 4:4:4 source.