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.mp4

Note: 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.png

In 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.mp4

3. 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.png

Here, 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.png

The 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 (+):