23

I'm trying to extract key frames from a video clip. I tried the following command, but it extracts all frames.

ffmpeg -vf select="eq(pict_type\,PICT_TYPE_I)" -i 2.flv -vsync 2 -s 73x41 -r 30 -f image2 thumbnails-%%02d.jpeg
slhck
  • 223,558
  • 70
  • 607
  • 592
Rashed Mustafa
  • 231
  • 1
  • 2
  • 3

3 Answers3

34

You can make this simpler using -skip_frame without the need for select video filter:

ffmpeg -skip_frame nokey -i 2.flv -vsync 0 -r 30 -f image2 thumbnails-%02d.jpeg
radoh
  • 1,381
  • 1
  • 12
  • 13
  • 3
    Amazing, takes less than 10s on a 20min video compared to more than 3 minutes with select filter ! – mad Apr 08 '18 at 15:23
  • 1
    Make sure to use `-threads 1`, compared to the default `-threads auto` it makes a `cropdetect` filter graph (`ffmpeg -threads 1 -skip_frame nokey -i input.mkv -filter:v select='not(mod(n\,20))',cropdetect -an -f null /dev/null`) 2x as fast on my system (60s down to 30s)! – genpfault Feb 09 '19 at 03:36
  • I would not use skip_frame nokey. Have you even checked the output? On my files and build (aug 2019) I get improper time stamps, as in nokey gives me the preceding frame before the I frame, while the nonfiltered/all frames show the I frame at a later time stamp. – JasonXA Nov 21 '19 at 04:57
  • The reason @genpfault suggests using `-threads 1` is that otherwise the sequence of the output keyframes can be issued out-of-order. If you have some kind of *post-hoc* way of dealing with this problem, you can retain multi-threading. Also, it seems that it's still possible to get out-of-order keyframes, ***even when using*** `-threads 1`, but now in this case all such occurrences seem to be accompanied/flagged by an h264 decoder error `illegal short term buffer state detected`. – Glenn Slayden Mar 03 '20 at 01:48
  • 1
    Please do add an explanation on why `-vsync 0` is important for this task. I didn't know what it did and I ended up with a lot of duplicate jpegs because the output matched the framerate of the input, and you need the `-vsync 0` option to avoid that – Federico Bonelli Nov 10 '21 at 08:38
14

Example using the select and scale filters:

ffmpeg -i 2.flv -vf "select=eq(pict_type\,I),scale=73x41" \
-vsync vfr -qscale:v 2 thumbnails-%02d.jpeg

A few tips:

  • Filters should not come before the -i option, as they're an output option. I don't know where exactly you got the command from, but PICT_TYPE_I does not exist – it should be I.

  • In the scale filter you can replace 73 or 41 to have the filter automatically calculate the width or height to preserve aspect ratio: such as scale=73:-1 or scale=-1:41. This prevents stretching or squishing that can result from "forced" scaling.

  • Output quality can be controlled with -qscale:v (or the alias -q:v). Effective range is a linear scale of 2 to 31 and a lower value is a higher quality.

  • That your ffmpeg allows a filter before the input tells me it could be outdated. Download a recent static build for your operating system, or build it yourself according to the compilation guides if the above does not work.

llogan
  • 57,139
  • 15
  • 118
  • 145
slhck
  • 223,558
  • 70
  • 607
  • 592
0

if this errors:

Option vf (set video filters) cannot be applied to input url 1508.mp4 -- you are trying to apply an input option to an output file or vice versa. Move this option before the file it belongs to. Error parsing options for input file 1508.mp4. Error opening input files: Invalid argument

you can do this:

ffmpeg -i 263.mp4 -vf select=eq(pict_type\,PICT_TYPE_I)  -vsync 2 -s 480x320 -r 24 -f image2 thumbnails-%05d.jpeg

==--------------------------------------------

“-i” Parameters in advance

Tom
  • 1
  • 1