Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FFMPEG Generate N Evenly Spaced PNG Screenshots

Tags:

ffmpeg

I am trying to generate 8 screenshots for an uploaded video using FFMPEG. I currently have:

ffmpeg -i Trailer-720p.mov -r .2 -vcodec png Preview-%d.png

Which generates a screenshot every 5 seconds. How can I add the ability to generate a screenshot for frames distributed over a percentage of total time. Thanks. Furthermore, is it possible to generate a screenshot at 50% for example? Thanks.

like image 292
Kevin Sylvestre Avatar asked Jul 22 '10 08:07

Kevin Sylvestre


2 Answers

If you run ffmpeg with just the -i parameter, it will provide you with the length of the video on stderr (among lots of other things). You could write something around that, converting the duration and the intended number of frames into the correct -r parameter.

Here is an quick example in python which basically does what I have described. For some reason the first two stills generated by my version of ffmpeg both show frame 0, but Preview-3 to Preview-n are in the correct intervals. Run it with the second parameter set to '1' and it will generate the middle frame as Preview-3.png.

#!/usr/bin/env python

import sys,os,re
from subprocess import *

if len(sys.argv)<=1:
  print("usage: python oneinn.py filename frames")
  sys.exit(0)

try:
  fvideo = sys.argv[1]
  frames = float(sys.argv[2])
except:
  sys.stderr.write("Failed to parse parameters.\n")
  sys.exit(1)

output = Popen(["ffmpeg", "-i", fvideo], stderr=PIPE).communicate()

# searching and parsing "Duration: 00:05:24.13," from ffmpeg stderr, ignoring the centiseconds
re_duration = re.compile("Duration: (.*?)\.")
duration = re_duration.search(output[1]).groups()[0]

seconds = reduce(lambda x,y:x*60+y,map(int,duration.split(":")))
rate = frames/seconds

print("Duration = %s (%i seconds)" % (duration, seconds))
print("Capturing one frame every %.1f seconds" % (1/rate))

output = Popen(["ffmpeg", "-i", fvideo, "-r", str(rate), "-vcodec", "png", 'Preview-%d.png']).communicate()
like image 179
relet Avatar answered Oct 12 '22 00:10

relet


Or just with a shell command:

ffmpeg -i input.m4v -vf fps=1/$(echo 'scale=6;' $(ffprobe -loglevel quiet -of 'compact=nokey=1:print_section=0' -show_format_entry duration input.m4v) ' / 10' | bc) -vframes 10 -qscale:v 2 thumbnail-%d.png

This creates 10 thumbnails with the same dimensions as the source video.

like image 42
Manfred Stienstra Avatar answered Oct 12 '22 00:10

Manfred Stienstra