Extracting the index of key frames from a video using ffmpeg
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.
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.