How can I convert a video file to a sequence of images, for example one frame every N seconds. Can mplayer or ffmpeg do this? I have used MPlayer to grab screenshots manually but I would like to automate this for a long video.
8 Answers
It's very simple with ffmpeg, and it can output one frame every N seconds without extra scripting. To export as an image sequence just use myimage_%04d.png
or similar as the output. The %0xd
bit is converted to a zero-padded integer x
digits long - the example I gave gets output as
myimage_0000.png
,myimage_0001.png
,myimage_0002.png
etc..
You can use lots of still image formats, png, jpeg, tga, whatever (see ffmpeg -formats
for a full list).
Ok so now we know how to export the movie as a sequence of images, but say we don't want to export every single frame?
The trick is to simply change the frame rate of the output to whatever we want using the -r n
option where n
is the number of frames per second. 1 frame per second would be -r 1
, one frame every four seconds would be -r 0.25
, one frame every ten seconds would be -r 0.1
and so on.
So to put it all together, this is how it would look to save one frame of input.mov
every four seconds to output_0000.png
, output_0001.png
etc.:
ffmpeg -i input.mov -r 0.25 output_%04d.png
Note that the -r 0.25
option goes after the -i input.mov
part, because it's controlling the frame rate of the output. If you put it before the input it would treat the input file as if it had the specified frame rate.
Change the %xd to however many digits you need, e.g. if the command would create more than 10,000 frames change the %04d
to %05d
. This also works for input files that are image sequence. Read more here.
Windows users:
On the command line use %
example: ffmpeg -i inputFile.mp4 -r 1 outputFile_%02d.png
In CMD and BAT Scripts use %%
example: ffmpeg -i inputFile.mp4 -r 1 outputFile %%02d.png
So double %%
in scripts, and single %
on the interactive command line. Getting it wrong in either situation will generate an error.
Edit Worth checking out the discussion of file types in the comments below. There are advantages and disadvantages with each:
- jpeg much smaller file sizes, lossy, only 8-bit colour, no alpha.
- png lossless, large files, slow. 8-bit colour supports alpha.
- tiff lossless, even larger files, fast, supports up to 16 colour and alpha.
To specify the file format, just use the required extension in the output file, e.g. myimage_%04d.jpg
, myimage_%04d.png
or myimage_%04d.tiff
-
1What should I put into
-r
if I want to export every frame? If I know the video's FPS, I guess I input that, but what if I don't? Apr 23, 2015 at 0:10 -
7Don't use the -r flag at all. Then FFMPEG will use the input file's frame rate.– stibApr 23, 2015 at 0:42
-
3Note that you'll really want to use
jpegs
for this, unless you're surepng
's are what you want. In my case,jpeg
s were about 50kb each, andpng
s were about 2MB.– mlissnerOct 28, 2015 at 2:14 -
10the advantage of pngs is lossless compression, so if you're using the image sequence as an intermediate and don't mind the extra size then that's when you might use png.– stibMay 11, 2016 at 7:43
-
4Tip: make sure the
-r 1
goes AFTER the input file, otherwise it doesn't have the intended effect.– Simon E.Sep 23, 2019 at 9:10
mplayer -vo jpeg -sstep 5 file.avi
will save a frame as a jpeg file every 5 seconds.
However, it will not stop at the end of the file, it will continue producing copies of the last frame. To avoid this, find the duration of the video in seconds, using another player, or with mplayer:
mplayer -vo null -ao null -frames 0 -identify file.avi
and look for a line like "ID_LENGTH=147.00".
Subtract 2 from the length, and use this value for the -endpos
option. For example, for a 147 second video:
mplayer -vo jpeg -sstep 5 -endpos 145 file.avi
-
-
Could you at least mention on which operating system are you using this command? Apr 23, 2015 at 0:06
-
It was 5 years ago, but it was probably the latest Ubuntu Desktop at the time, Ubuntu 10.4 .– LiamApr 23, 2015 at 22:27
-
How can I choose steps shorter than 1s. It does only accept integers.– fcpenhaMar 2, 2016 at 22:52
-
2
With ffmpeg
, you can do the following:
ffmpeg -ss 4 -i input.avi -s 320x240 -frames:v 1 output.jpg
This command generates a 320×240 sized JPG thumbnail at the 4th second in the video. Put this in a script that changes the time and file name and you're done.
More info: Create a thumbnail image every X seconds of the video
-
2This seems to do what I want, but with one problem. It will process the file from the start on each iteration, getting exponentially slow.– LiamApr 27, 2010 at 14:42
-
@Liam - Does it help if you leave the offset time alone (set it at 1) and use the
-ss position
flag to seek further into the file instead?-ss Seek to given time position in seconds. hh:mm:ss[.xxx] syntax is also supported
– NifleApr 29, 2010 at 7:53 -
1@liam: put the
-ss
before the-i
so that the seek happens before the input video gets decoded. this should speed it up. source Apr 29, 2010 at 17:03 -
2There's a better, much faster way to do it with ffmpeg. See my answer below.– stibMar 15, 2014 at 9:47
-
If you are after a kind of contact sheet and if you are working with a Unix-like OS, you can use this elaborate script, called to the point Video Contact Sheet *NIX, short vcs.
In the background it also uses ffmpeg
(by default) or mplayer
, hence can handle a lot of video formats. It automates the process of capturing still images from the movie and compose these to an image with some header and footer. You can choose e.g. how many captures you want or alternatively the time differences between them.
For a interval of 10 minutes, the invocation is like that:
vcs -i 10m input.avi
Check the full list of commandline options for some other tweaks.
Here is an example contact sheet, taken from the homepage:
With VLC 1.1.0 and above, you can use the scene video filter:
vlc C:\video\to\process.mp4 --rate=1 --video-filter=scene --vout=dummy --start-time=10 --stop-time=11 --scene-format=png --scene-ratio=24 --scene-prefix=snap --scene-path=C:\path\for\snapshots\ vlc://quit
The above saves 1 out of every 24 frames (--scene-ratio=24), starting at 00:00:10 and ending at 00:00:11.
Just tested and confirmed this works with VLC 2.0.3 on a fresh Windows 8 installation (I have no additional video plugins or software).
Full documentation: http://wiki.videolan.org/How_to_create_thumbnails
-
-
-
I need to skip most frames, outputting all frames will use up too much storage space. I need just one frame every few seconds.– LiamApr 28, 2010 at 9:56
You could also try this
from the VLC command line...
vlc "C:\YOUR\file\path\file.avi" -V image --image-out-prefix=capname --image-out-ratio=60
file.avi is the video you want to capture from, capname is the prefix of the saved images, you might want to play around with the ratio (60 means that 1 out of 60 images is captured) You can add more commands, for example --image-out-format jpeg will save your caps as jpegs instead of of pngs, --snapshot-path lets you choose where to save your caps.
You can skip frames in VirtualDub. Just use "Decimate By" option located at Video -> Frame Rate menu. For example if you set "Decimate By 100" then use File -> Export -> Image sequence, it will save only every 100th frame.