16

I'm using ffmpeg for extracting key frames from a video. This is the command:

ffmpeg -i test2.mp4 -vf select='eq(pict_type\,I)' -vsync 2 -s 160x90 -f image2 thumbnails-%02d.jpeg

How can I get the index of each key frame extracted in the video? For example, for the first I-frame, the index would be 0, for the second, it would be 24, etc.

  • possible duplicate of superuser.com/questions/669716/… – user236012 Mar 4 '15 at 16:03
  • Look into using ffprobe then post process the output to get the index? – dstob Mar 4 '15 at 17:36
  • @dstob could you explain more about what you mean ? as I'm new to ffmpeg. – Faten Khalifa Mar 4 '15 at 19:11
  • @LordNeckbeard The frame number in the video frames, ex. the first frame of the video would be at index 0 I want to know the index of each key frame in the video frames. – Faten Khalifa Mar 4 '15 at 19:16
  • You want the frame number to be printed on the thumbnail (on the image itself)? – llogan Mar 4 '15 at 20:30
21

Like @dstob mentioned, you can use ffprobe to get the I-frames and their associated information. ffprobe comes with some of the static builds on the download page and can be built from source as well.

This is assuming you're on Linux/Unix:

Extract frames and frame types

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1

The grep command filters lines with I in them, and counts their index (using the -n option). The cut command selects the first column of the output only (the index). Note that this index is 1-based, not 0-based.

Rename output files based on index

You can actually pipe these indices to a list:

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1 > frame_indices.txt

Then make a list of all the thumbnails too:

ls -1 thumbnails*.jpeg > thumbnails.txt

Then paste those two together:

paste thumbnails.txt frame_indices.txt > combined.txt

The list now contains the name of the thumbnail and the index. Perform a rename based on that:

while read -r thumbnail index; do
  newIndex=$(echo $index - 1 | bc) # subtract 1 from the index
  mv -- "$thumbnail" "thumbnail-$newIndex.jpeg"  # rename file
done < combined.txt

The above will rename thumbnail-01.jpeg to thumbnail-0.jpeg. Note that there is no zero-padding on the output index. If you want to zero-pad it to, say, 5 digits, use printf:

newIndex=$(printf '%05d' $(echo $index - 1 | bc))

On Windows, you'd do the exact same with ffprobe but parse the output differently. No idea how to perform the renaming there though.

  • This error is displayed: 'grep' is not recognized as an internal or external command, operable program or batch file. – Faten Khalifa Mar 5 '15 at 0:23
  • 2
    That's because you're on Windows. Like I said, this answer assumes Linux or Unix. You were not being more specific in your question. You can achieve the same on Windows using Cygwin or similar GNU/Linux layers for Windows. – slhck Mar 5 '15 at 9:29
  • This is a huge help, thanks. One correction: I think the indices in your first command are off by a factor of three, because there is a [FRAME] line and a [/FRAME] line for every pict_type line. – Jack O'Connor Dec 28 '15 at 22:58
  • 2
    @JackO'Connor There is only one line per frame if you use the -of csv option for ffprobe. What you're describing is the default output format, though. – slhck Dec 30 '15 at 10:52
0

If you wish to use FFMPEG as originally stated, You can list all or partial listing as well as create jpg with the following:

ffmpeg.exe \
  -i "C:\Users\UserName\Desktop\jpegs and list\VideoName.mp4" \
  -t 15 \
  -vf select="eq(pict_type\,PICT_TYPE_I)" \
  -vsync 2 \
  -s 160x90 \
  -f image2 thumbnails-%02d.jpeg \
  -loglevel debug 2>&1| for /f "tokens=4,8,9 delims=. " %d in ('findstr "pict_type:I"') do echo %d %e.%f>>"keyframe_list.txt"

Remove -t 15 for no time limit or change to suit. Remove -s 160x90 -f image2 thumbnail-%02d.jpeg or change to suit for thumbnail removal.

  • In Windows 7 CMD, this fails at the \. Changing \ to ^ causes a fail at the :I" . Do you have a version that works on Windows? – ChrisJJ Dec 18 '19 at 9:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.