Force Intermediate Pixel Format in FFmpeg Filtergraph

This article explains how to use the format filter in FFmpeg to explicitly set intermediate pixel formats within a filtergraph. You will learn why forcing these formats is necessary for maintaining image quality, how the syntax works, and how to implement it in both simple and complex filter chains.

Understanding the Need for Intermediate Pixel Formats

When processing video, FFmpeg automatically negotiates pixel formats between adjacent filters in a filtergraph. While this auto-negotiation is convenient, it can sometimes choose an suboptimal format, leading to unintended color space conversions, loss of chroma information, or compatibility issues with certain filters.

By inserting the format filter as an intermediate step, you take manual control over the pixel format. This is highly useful when you want to force high-bit depth processing (like yuv420p10le) through a specific filter chain before downsampling to a standard format (like yuv420p) for the final output encoder.

The format Filter Syntax

The basic syntax for the format filter is:

format=pix_fmts=pixel_format_name

Or, using the shorthand version:

format=pixel_format_name

To allow FFmpeg to choose from a list of acceptable formats, you can separate multiple formats with a pipe (|) character:

format=yuv420p|yuv422p|yuv444p

How to Apply It in a Filtergraph

To force an intermediate pixel format, place the format filter directly between the filters where you want the conversion to occur.

Example 1: Simple Filterchain

In this example, we scale a video, force an intermediate conversion to yuv444p for precision, and then let the encoder handle the final output.

ffmpeg -i input.mp4 -vf "scale=1920:1080,format=yuv444p" output.mp4

Example 2: Complex Filtergraph with Intermediate Formats

In a complex filtergraph (-filter_complex), you might want to force a specific pixel format before overlaying elements or applying color adjustments to prevent quality degradation.

Here, we force the video into high-precision rgb24 for a custom filtering step, and then convert it back to yuv420p at the end of the graph to ensure maximum playback compatibility:

ffmpeg -i input.mp4 -i logo.png -filter_complex "[0:v]scale=1920:1080,format=rgb24[bg];[bg][1:v]overlay=10:10,format=yuv420p[out]" -map "[out]" output.mp4

In this command: 1. The background video (0:v) is scaled and immediately converted to rgb24 using format=rgb24. 2. The logo is overlaid onto the RGB background. 3. The final combined stream is converted back to yuv420p using format=yuv420p before being sent to the encoder.