FFmpeg Format Filter: Force Intermediate Pixel Format
When building complex FFmpeg filtergraphs, FFmpeg automatically
negotiates pixel formats between connected filters, which can sometimes
result in unintended chroma subsampling, loss of color depth, or
performance drops. This article explains how to use the
format filter to explicitly force an intermediate pixel
format within a filtergraph, ensuring precise color fidelity,
compatibility, and control over every stage of your video processing
pipeline.
Why Force an Intermediate Pixel Format?
By default, FFmpeg selects the most convenient common pixel format supported by adjacent filters. However, this automatic negotiation can cause issues:
- Precision Loss: Multi-stage filtering might inadvertently convert a 10-bit stream to 8-bit midway through processing.
- Color Degradation: Colorspace shifts (such as YUV to RGB) might occur prematurely, causing conversion artifacts.
- Filter Incompatibility: Some filters, such as certain color grading or drawing filters, work exclusively or yield better precision in RGB or planar YUV spaces.
Inserting the format filter acts as an explicit contract
between stages, forcing FFmpeg to convert the stream to your target
pixel format at that exact point in the pipeline.
Basic Syntax
The format filter accepts a list of one or more pixel
formats separated by |:
format=pix_fmts=<format_name>
Shorthand syntax:
format=<format_name>
To view all available pixel formats supported by your FFmpeg build, run:
ffmpeg -pix_fmtsUsing
format in a Simple Video Filter (-vf)
In a linear filterchain defined with -vf, filters are
separated by commas. You can place format between two
operations to enforce the format passed to the subsequent filter.
Example: Enforcing High Bit-Depth During Scaling
If you are downscaling or applying blur to an 8-bit file, converting to a 10-bit intermediate format minimizes banding artifacts:
ffmpeg -i input.mp4 -vf "format=yuv420p10le,scale=1280:720,format=yuv420p" -c:v libx264 -crf 18 output.mp4In this pipeline:
format=yuv420p10leupgrades the input to 10-bit planar YUV.scale=1280:720executes its resizing algorithms in 10-bit precision.format=yuv420pconverts the stream back to standard 8-bit YUV for maximum playback compatibility before passing frames to the encoder.
Using
format in Complex Filtergraphs
(-filter_complex)
In non-linear workflows with multiple inputs or outputs, place the
format filter directly on named streams.
Example: Forcing an RGB Intermediate Format for Color Curves
Certain visual manipulation filters, like curves or
colorbalance, perform predictably in RGB space:
ffmpeg -i input.mp4 -filter_complex \
"[0:v]format=gbrp,curves=vintage,format=yuv420p[v_out]" \
-map "[v_out]" -c:v libx264 -crf 20 output.mp4Here:
[0:v]takes the primary video stream.format=gbrpforces the video into planar RGB (GBRP).curves=vintageexecutes in RGB without triggering automatic conversion guesses.format=yuv420preturns the stream to standard YUV prior to H.264 encoding.
Allowing Multiple Acceptable Intermediate Formats
If you want to restrict the pipeline to a specific family of formats
without locking it to a single one, pass multiple choices separated by
the pipe (|) character:
ffmpeg -i input.mp4 -vf "format=yuv420p10le|yuv422p10le|yuv444p10le,scale=1920:1080" -c:v libx265 output.mp4FFmpeg will evaluate the list from left to right and choose the first format that the downstream filter natively supports, preventing unnecessary color conversions while maintaining high bit-depth.