Programster's Blog

Tutorials focusing on Linux, programming, and open-source

FFmpeg - Extract Keyframe Indexes

FFmpeg also includes the ffprobe tool which allows us to probe the video to find out where the keyframe locations are. When I say "keyframe", I am referring to "I" frames. These frames are frames that don't reference any other frames, and hence are used when you seek to a point in a video. When you do this, the video player has to go backwards to find the nearest keyframe and then work through the subsequent interpolation frames until it gets to the point you desired to play from. This can take some time, so some players have a feature whereby they will play from the nearest keyframe, rather than the precise location you selected. This results in improved "responsiveness" of seeking in the video.

Steps

Update the variables in the commands below as appropriate to the video you are interested in, and a filename you want the keyframe indexes to be output to and then run it.

INPUT_FILE="myVideo.mp4"
OUTPUT_FILE="keyframes.txt"

ffprobe \
  -select_streams v \
  -show_frames \
  -show_entries frame=pict_type \
  -of csv \
  $INPUT_FILE \
  | grep -n I \
  | cut -d ':' -f 1 \
  > $OUTPUT_FILE

echo "Done! Keyframes have been outputted to $OUTPUT_FILE"

The output file will be populated with the indexes of all of your keyframes. It doesn't matter much, but the first frame in the video is 1, and not 0 as developers are used to. Thus, your list should always start with a 1 as the first frame in any video should be a keyframe.

If you change the extension to csv, then your computer will likely open the file in Librecalc if you are using Linux as I am. Then you can add the following equation into the second column in order to get the frames position in the video in seconds:

=(A1-1)/24

This is assuming a 24 FPS video. If your video is 60 FPS or 30 FPS, then change the 24 accordingly.

If you want to convert that into a time format, you then need to further divide that number by the number of seconds in a day (86400), and then convert the style on that column to a time format. The default time format is to a resolution of seconds, so you will likely need to change this in order to show milliseconds as well. Alternatively, just download this template document and paste your keyframe values over the left-most column.

References

Last updated: 4th April 2024
First published: 4th April 2024