Extract Keyframes with the FFmpeg Select Filter

Extracting keyframes—also known as intra-frames or I-frames—allows you to capture the primary, fully rendered frames of a video without decoding intermediate motion data. This guide demonstrates how to isolate and export only the keyframes from any video file using FFmpeg's built-in select video filter, explaining the command syntax, the parameters required to prevent duplicated frames, and how to customize the output format.

The Keyframe Extraction Command

To extract all keyframes from a video and save them as individual image files, run the following command in your terminal:

ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)'" -vsync vfr keyframe_%04d.jpg

For newer versions of FFmpeg (version 5.0 and later), -fps_mode is preferred over the deprecated -vsync option:

ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)'" -fps_mode vfr keyframe_%04d.jpg

Breakdown of the Command Options

  • -i input.mp4: Specifies the path to your source video file.
  • -vf "select='eq(pict_type,I)'": Applies the video filter (-vf). The select filter evaluates each frame against a condition. In this case, eq(pict_type,I) checks whether the frame's picture type is an I-frame (keyframe). Frames that evaluate to true are passed through; all others are dropped. You can also write this as eq(pict_type,PICT_TYPE_I).
  • -vsync vfr / -fps_mode vfr: Sets the output to variable frame rate (VFR). By default, FFmpeg attempts to maintain a constant frame rate by duplicating the remaining frames to fill the gaps left by dropped frames. Using vfr ensures FFmpeg only outputs the frames that successfully passed through the filter.
  • keyframe_%04d.jpg: Defines the output naming pattern. %04d formats the frame sequence as a zero-padded, four-digit number (e.g., keyframe_0001.jpg, keyframe_0002.jpg).

Outputting to Different Image Formats

You can change the image format simply by modifying the file extension of the output pattern:

  • PNG (lossless):

    ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)'" -fps_mode vfr keyframe_%04d.png
  • High-Quality JPEG:

    ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)'" -fps_mode vfr -q:v 2 keyframe_%04d.jpg

    The -q:v 2 flag sets the JPEG quality scale, where 2 provides high quality (values range from 1 to 31, with 1 being the highest quality).

Saving Keyframes with Timestamps

If you need the filename to reflect the exact presentation timestamp (PTS) of the keyframe rather than a sequential index, use the showinfo filter or the metadata filter to write the frame's timestamp directly into the file or its metadata:

ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)'" -fps_mode vfr -frame_pts true keyframe_%d.jpg

Setting -frame_pts true substitutes the %d token with the frame's presentation timestamp in the sequence, allowing you to trace each keyframe back to its original position on the video timeline.