How to Extract Every 100th Frame with FFmpeg

Extracting specific frames from a video is a common task in video processing, and FFmpeg makes this process highly efficient using its expression evaluation filters. This article provides a straightforward guide on how to use the FFmpeg select filter to extract exactly every 100th frame from a video file, explaining the command-line syntax and key parameters needed to achieve this result.

The FFmpeg Command

To extract every 100th frame from a video, use the following command in your terminal:

ffmpeg -i input.mp4 -vf "select='not(mod(n,100))'" -vsync vfr output_%04d.png

How the Command Works

Each component of the command plays a specific role in selecting and saving the correct frames:

  • -i input.mp4: Specifies the path to your input video file.
  • -vf: Introduces the video filtergraph.
  • select='not(mod(n,100))': This is the core filter configuration.
    • n represents the sequential frame number, starting at 0.
    • mod(n,100) calculates the remainder of the current frame number divided by 100.
    • not(...) negates the result. When mod(n,100) is 0 (which happens at frames 0, 100, 200, 300, etc.), the expression evaluates to true (or 1), telling FFmpeg to select that frame. For all other frames, it evaluates to false (or 0) and discards them.
  • -vsync vfr: Sets the video synchronization method to Variable Frame Rate (VFR). This prevents FFmpeg from duplicating frames to fill in the gaps of the dropped frames, ensuring you only output the selected images. (Note: In newer versions of FFmpeg, you can use -fps_mode vfr instead).
  • output_%04d.png: Defines the output format and naming convention. %04d is a placeholder that outputs sequential, zero-padded numbers (e.g., output_0001.png, output_0002.png).

Selecting Frames Starting From 1

If you want to skip the very first frame (frame 0) and instead start your extraction exactly at frame 100, frame 200, and so on, modify the expression slightly to ensure n is greater than 0:

ffmpeg -i input.mp4 -vf "select='gt(n,0)*not(mod(n,100))'" -vsync vfr output_%04d.png

This adjustments adds gt(n,0)* (greater than zero multiplied by the modulo logic), ensuring that the initial frame index of 0 is ignored.