How to Use the FFmpeg Select Filter
The FFmpeg select filter is a powerful tool used to
discard or keep specific video frames based on custom evaluation
criteria. This article provides a practical guide on how to use the
select filter to extract keyframes, select frames at
specific intervals, filter scenes by visual changes, and output the
results correctly.
Basic Syntax of the Select Filter
The select filter works by evaluating an expression for
each input frame. If the expression evaluates to a non-zero value
(true), the frame is kept; if it evaluates to zero (false), the frame is
discarded.
The basic syntax for the video select filter is:
ffmpeg -i input.mp4 -vf "select='expression'" -vsync vfr output.mp4Note: When discarding frames, you must use
-vsync vfr (or -fps_mode vfr in newer FFmpeg
versions) to enable a variable frame rate. Otherwise, FFmpeg will
duplicate the remaining frames to maintain the original constant frame
rate.
Common Use Cases and Examples
1. Extracting Keyframes (I-frames)
Keyframes contain complete image data and are often used for
thumbnail generation. You can select only I-frames using the
pict_type variable:
ffmpeg -i input.mp4 -vf "select='eq(pict_type\,I)'" -vsync vfr thumbnail_%03d.pngIn this command, eq(pict_type\,I) checks if the
picture type is equal to āIā (Intra-coded).
2. Selecting Frames by Time Range
If you want to keep only the frames that occur within a specific time
range (for example, between 10 and 20 seconds), use the
between function with the time variable t:
ffmpeg -i input.mp4 -vf "select='between(t\,10\,20)'" -vsync vfr output.mp43. Selecting Every Nth Frame
To extract one frame out of every 100 frames, you can use the modulo
operator on the frame number variable n:
ffmpeg -i input.mp4 -vf "select='not(mod(n\,100))'" -vsync vfr output_%03d.pngHere, mod(n\,100) returns 0 for every 100th frame
(0, 100, 200, etc.). The not() function turns that 0 into 1
(true), selecting those specific frames.
4. Selecting Frames Based on Scene Changes
FFmpeg can detect sudden visual changes between consecutive frames
using the scene variable, which outputs a value between 0
and 1 representing the level of change. To capture frames where a scene
change occurs:
ffmpeg -i input.mp4 -vf "select='gt(scene\,0.4)'" -vsync vfr scene_changes_%03d.pngThe gt(scene\,0.4) expression selects frames where
the scene change detection value is greater than 0.4. You can adjust
this threshold value to make the filter more or less sensitive.
Useful Variables for Expressions
When writing your own custom expressions, you can combine these
common variables using logical operators like and
(*) and or (+):
n: The sequential number of the filtered frame, starting from 0.t: The timestamp of the frame expressed in seconds.key: 1 if the frame is a keyframe, 0 otherwise.pict_type: The picture type (e.g.,I,P,B).interlace_type: Indicates if the frame is progressive or interlaced.