Extracting all frames from the video:
ffmpeg -i input.avi -f image2 frame-%05d.png
This will create files like frame-00001.png, frame-00002.png, etc.
Extracting a single frame is easy too:
ffmpeg -i input.avi -f image2 -ss 14.342 -vframes 1 frame.png
This will save the frame that is at 14.342s. The fractions in the offset (
-ss
) are good for specifying the frame within a second.
The tricky part comes, when you want to save a set of frames at equal distances from each other. Eg. if your movies is 140s long and you want to save 6 frames (excluding the start and end frames), then you will have to save the frames at 20s, 40s, 60s, 80s, 100s and 140s. The proper options should be:
ffmpeg -i input.avi -f image2 -r 0.05 -vframes 6 frame-%05d.png
The
-r
option specifies the frame rate of the output stream (which is an image sequence in our example). You can calculate the frame rate from the following expression:
(number_of_frames + 1) / input_duration
(in our example: (6 + 1) / 140 = 0.05.
However this does not work as I expected. It's either a bug or I'm not fully understanding how ffmpeg works. Either way ... the output from the above command will not contain the frames that we targeted. The first two images in the saved sequence will always be the first two frames of the input video (strange, isn't it?
) and the other images are not what we wanted. Assuming that the first command (in this article) works OK, we can use its output to compare with the frames in the later examples. Eg. the frame at 20s (the first frame that we wanted to save) is in case of a 24fps video the 480th frame, so the saved image should be the same as the frame-00480.png in the first command's output. However it's not. After some thinking I got to the conclusion that the output is exactly
duration / ((number_of_frames + 1) * 10)
seconds offset backwards from the input video.
To fix this you've to use the following command:
ffmpeg -i input.avi -f image2 -ss 2 -r 0.05 frame-%05d.png
where
-ss
comes from the previous formula substituting the parameters from our example:
140 / ((6 + 1) * 10) = 2
.
In the output the first two images should be discarded and the next 6 images (from 3rd til 8th) will be the ones we were looking for. Most probably there'll be a 9th image as well which can be discarded too. You can also add the
-vframes 8
option (where 8 is
number_of_frames + 2
) to skip the creation of the last image that you won't need anyway.
I tried to find a corresponding thread on the
ffmpeg-devel mailing list, but the closest hit was only the
"Frames outputted on 1 fps do not match the correct frame" thread from September 2006 which did not contain a detailed diagnosis or a solution to the problem.
PS: I've used ffmpeg
fetched from SVN on 4th December 2008. The anomalies with the
-r
option were experienced with FLV videos (created with ffmpeg from other videos using other codecs). It is possible that
-r
works correctly with non-FLV files ... I've never tested it.
Comments
Sometimes I want to take a
ffmpeg -i VIDEO.EXTENSION -f image2 -ss 2 -r 1 IMAGENAME-%05d.png
ffmpeg outputting too many frames from the beginning of the clip
Reducing the Number of Resulting Images
VisiPics: https://www.google.com/search?client=firefox-b-1-d&q=visipics