FFmpeg Seek to Frame Number Instead of Time

FFmpeg natively seeks using time duration rather than frame numbers. However, you can easily target a specific frame by either calculating the timestamp using the video’s frame rate (FPS) or by using FFmpeg’s video filters to select the exact frame number. This article provides straightforward methods to achieve both, allowing you to seek and extract specific frames efficiently.

Method 1: The Calculation Method (Fastest)

The fastest way to seek to a specific frame is to convert the frame number into a time value. Because FFmpeg can seek instantly using the -ss parameter, calculating the time is highly efficient.

Use this formula to find the time in seconds: Time (seconds) = Target Frame Number / Frame Rate (FPS)

For example, if you want to seek to frame 300 in a video that runs at 30 FPS: 300 / 30 = 10 seconds.

You can then run the following command to seek to that position and extract a single frame:

ffmpeg -ss 10 -i input.mp4 -vframes 1 output.png

Method 2: The Select Filter Method (Most Accurate)

If you do not know the frame rate, or if the video has a variable frame rate (VFR), calculating the time might not be accurate. In this case, you can use the select filter to target the exact frame number by index (where the first frame is 0).

To extract frame 300 using the filter method, run:

ffmpeg -i input.mp4 -vf "select=eq(n\,300)" -vframes 1 output.png

Note: This method is slower than the calculation method because FFmpeg must decode the video from the very beginning to count the frames accurately.

Method 3: Combined Method for Large Videos (Fast & Accurate)

For very long videos, using the select filter alone can take a long time. You can combine both methods by using -ss to seek close to your target frame, and then using the select filter to land on the exact frame.

If you want to seek to frame 9000 in a 30 FPS video (which is roughly 300 seconds):

ffmpeg -ss 295 -i input.mp4 -vf "select=eq(n\,150)" -vframes 1 output.png

In this command: 1. -ss 295 fast-forwards the video to 295 seconds (frame 8850). 2. The select=eq(n\,150) filter tells FFmpeg to find the 150th frame after the seek point (8850 + 150 = 9000).