How to Select Keyframes with FFmpeg Select Filter
Filtering specific video frames, such as I-frames (keyframes), is a
common task in video processing, editing, and analysis. This article
explains how to use the FFmpeg select filter to isolate
frames based on criteria like picture type, providing clear command-line
examples to extract and save those select frames efficiently.
Selecting Frames by Picture Type (I-Frames)
To select only I-frames (keyframes) from a video, you use the
pict_type evaluation option within the select
filter. The command compares the picture type of each frame to the
character representation of the frame type (I for
intra-frames, P for predicted frames, and B
for bi-directional predicted frames).
Here is the standard command to extract all I-frames as images:
ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)'" -fps_mode vfr output_%03d.pngBreakdown of the Command:
-vf "select='eq(pict_type,I)'": This applies the video filter (-vf) calledselect. The expressioneq(pict_type,I)checks if the picture type of the current frame is equal (eq) toI.-fps_mode vfr: This tells FFmpeg to use a Variable Frame Rate (VFR) output. Without this option (or the older-vsync vfr), FFmpeg may duplicate the selected I-frames to maintain the original constant frame rate of the input video.output_%03d.png: Specifies the output format, saving each selected frame as a sequentially numbered PNG image (e.g.,output_001.png,output_002.png).
Other Common Selection Criteria
The select filter is highly versatile and accepts
various expressions to match different criteria.
1. Select Keyframes (Alternative Method)
While checking the picture type works well, FFmpeg also has a dedicated boolean flag for keyframes:
ffmpeg -i input.mp4 -vf "select='key'" -fps_mode vfr output_%03d.png2. Select Every Nth Frame
If you want to sample a video by selecting every 30th frame:
ffmpeg -i input.mp4 -vf "select='not(mod(n,30))'" -fps_mode vfr output_%03d.pngn: The sequential frame number, starting from 0.mod(n,30): Computes the remainder of the frame number divided by 30. Usingnot()selects the frame when the remainder is 0.
3. Select Scene Changes
You can select frames that represent the start of a new scene using
the scene option, which detects changes in visual
content:
ffmpeg -i input.mp4 -vf "select='gt(scene,0.4)'" -fps_mode vfr output_%03d.pngscene: A value between 0 and 1 indicating how different the current frame is from the previous one.gt(scene,0.4): Selects the frame if the scene change value is greater than (gt) 0.4 (40% difference).