Convert RGB to YUV420p with FFmpeg Zscale

This article explains how to convert an RGB video to the widely compatible YUV420p format using FFmpeg’s high-quality zscale filter. While the standard scale filter (swscale) is commonly used for color space conversion, the zscale filter leverages the zimg library to provide superior color accuracy, high-bit-depth precision, and advanced dithering algorithms to prevent color banding.

Why Use Zscale Instead of Scale?

FFmpeg’s default scale filter can sometimes introduce color shifting, ringing artifacts, or banding when converting from RGB to YUV. The zscale filter solves these issues by using floating-point precision for internal calculations and offering superior algorithms for chroma subsampling and color space transformation.

The Basic Command

To convert an RGB video to YUV420p (using the BT.709 color standard, which is standard for HD video), use the following FFmpeg command:

ffmpeg -i input_rgb.mp4 -vf "zscale=matrix=709:primaries=709:transfer=709:range=limited,format=yuv420p" -c:v libx264 -crf 18 -c:a copy output_yuv420p.mp4

Parameter Breakdown

Advanced: Adding Dithering to Prevent Banding

When downsampling from RGB (which often acts as 10-bit or high-precision color internally) to 8-bit YUV420p, color banding can occur in gradients (like skies or shadows). You can enable dithering within zscale to eliminate this:

ffmpeg -i input_rgb.mp4 -vf "zscale=matrix=709:primaries=709:transfer=709:range=limited:dither=ordered,format=yuv420p" -c:v libx264 -crf 18 output_dithered.mp4

By adding :dither=ordered (or :dither=error_diffusion), zscale will apply a high-quality dither pattern to smooth out transitions, resulting in a visually flawless 8-bit YUV420p file.