2

I use FFmpeg to extract a keyframe at the 3rd minute. This means that it is the 3*60*25 th frame (assuming 25 FPS). Now, often this frame is not a keyframe.

I want to extract a frame closest to the above frame but ensure that it is a keyframe. This means the frame may occur a few seconds before or after the third minute of the video.

I have looked everywhere without any luck! I am doing this on Linux, so if you are using a FFmpeg with something specially installed or bundled, let me know!

slhck
  • 235,242
cnfcnf
  • 263

2 Answers2

5

Using -ss parameter with select filter would work.

Something similar to:

ffmpeg -ss 180 -i yourvideo.mp4 -vf select="eq(pict_type\,I)" -vframes 1 thumbnails.jpeg
slhck
  • 235,242
d33pika
  • 1,981
2

If you assume that the closest I-frame to 00:03:00 appears before that timestamp, you'll have to do some guessing, since the GOP length (the number of frames between each I-frame) isn't the same for each video. If you know your GOP length, e.g. 125 frames, then start 5 seconds before that, at 00:02:55, for example.

Note that this doesn't have to be a fixed length. Good encoders will place an I-frame at scene cuts rather than fixed points to achieve better compression and reliability.

So, let's shift the input by the amount of time we calculated before, using -itsoffset.

We specify the select filter to get us only I-frames, and -vframes to only receive one frame. Finally, write that to a .jpg file.

ffmpeg -itsoffset -00:02:55 -i in.mp4 -filter:v select='eq(pict_type\,I)' -vframes 1 out.jpg

I tested this with a video that originally has a P-frame at 00:03:00, and I received the 13th frame after that, which is the start of a new scene—an I-frame.

slhck
  • 235,242