3

I need to create multiple thumbnails (ex. 12) from a video at equal times using ffmpeg. So for example if the video is 60 seconds - I need to extract a screenshot every 5 seconds.

Im using the following command to get the frame in the 5ths second.

ffmpeg -ss 5 -i video.webm -frames:v 1 -s 120x90 thumbnail.jpeg

Is there a way to get multiple thumbnails with one command?

llogan
  • 121,796
  • 28
  • 232
  • 243
Alexander Vakrilov
  • 1,131
  • 7
  • 12

2 Answers2

9

Get duration (optional)

Get duration using ffprobe. This is an optional step but is helpful if you will be scripting or automating the next commands.

ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4

Example result:

60.000000

Output one frame every 5 seconds

Using the select filter:

ffmpeg -i input.mp4 -vf "select='not(mod(t,5))',setpts=N/FRAME_RATE/TB" output_%04d.jpg

or

ffmpeg -i input.mp4 -vf "select='not(mod(t,5))'" -vsync vfr output_%04d.jpg

Output specific number of equally spaced frames

This will output 12 frames from a 60 second duration input:

ffmpeg -i input.mp4 -vf "select='not(mod(t,60/12))'" -vsync vfr output_%04d.jpg

You must manually enter the duration of the input (shown as 60 in the example above). See an automatic method immediately below.

Using ffprobe to automatically provide duration value

Bash example:

input=input.mp4; ffmpeg -i "$input" -vf "select='not(mod(t,$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $input)/12))'" -vsync vfr output_%04d.jpg

With scale filter

Example using the scale filter:

ffmpeg -i input.mp4 -vf "select='not(mod(t,60/12))',scale=120:-1" -vsync vfr output_%04d.jpg
llogan
  • 121,796
  • 28
  • 232
  • 243
  • Using `ffmpeg -i input.mp4 -vf "ffmpeg -i input.webm -vf "select='not(mod(t,60/12))'" -vsync vfr output_%04d.jpg` seems to produce only one frame - output_0001.jpg. I'm not sure what the `select='not(mod(t,60/12))` part does. I guess it is testing each frame ot figure if it should output it? – Alexander Vakrilov Jun 03 '20 at 12:08
  • @AlexanderVakrilov What is the duration of `input.webm`? – llogan Jun 03 '20 at 17:27
  • It was about 44 seconds. I think the problem is that times of the frames are not on exact seconds. For example one frame might be at time 4.980s and the next may be on 5.020s. Both will not match the `not(mod(t,60/12))` – Alexander Vakrilov Jun 03 '20 at 20:41
  • 1
    I ended up using `select='not(mod(n, 150}))` where 150 is the estimated total number of frames (`duration*framerate`) devided by 12 (the number of thumbnails to generate). For 60 second video with 30 fps -> (60*30)/12 = 150 – Alexander Vakrilov Jun 03 '20 at 20:45
  • @AlexanderVakrilov Are you working with WebRTC inputs? – llogan Jun 03 '20 at 22:53
  • Yes. I actually process the video in browser using WebAssembly build of ffmpeg – Alexander Vakrilov Jun 04 '20 at 05:50
  • @llogan, or anyone out there how to get only 10 frames always irrespective of video duration. let say if a video duration is `120` then i want to capture 10 frames like so `[0 or 12, 24,36,48,60,72,84,96,108,120]`. please help me with that logic – EaBengaluru Aug 14 '22 at 06:55
  • here i have posted a question too https://stackoverflow.com/questions/73349722/how-to-generate-only-10-thumbnails-irrespective-of-video-duration-with-ffmpeg – EaBengaluru Aug 14 '22 at 14:17
  • @llogan This solution also only generates 1 file using the equally spaced frames code. I'm using a normal MOV file that is 118 seconds. – Panama Jack Aug 26 '23 at 08:24
1

$ffmpegPath = exec('which ffmpeg'); $ffprobePath = exec('which ffprobe');

$command = "$ffprobePath -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $input_video"; $video_duration = shell_exec($command);

$thumbnails_output = 'output%02d.png'; $command = "$ffmpegPath -i $input_video -vf fps=3/$video_duration $thumbnails_output"; shell_exec($command);

  • 2
    What language is this? I think they were asking for a list of CLI commands, which your response contains, but not in a clear way – slythfox Aug 11 '22 at 01:36