How to extract one frame of a video every N seconds to an image?

208,379

Solution 1

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 -endposoption. For example, for a 147 second video:

mplayer -vo jpeg -sstep 5 -endpos 145 file.avi

Solution 2

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

Solution 3

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

Solution 4

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:

enter image description here

Solution 5

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

Share:
208,379

Related videos on Youtube

TristanK
Author by

TristanK

With over 15 years experience as a Web Developer, I have gained in-depth knowledge of a wide range of web technologies. I have been responsible for the architecture of several key pieces of software for a diverse portfolio of clients, in the Photography, Education, Tourism, and Retail industries. I mostly work with PHP and JavaScript.

Updated on September 17, 2022

Comments

  • TristanK
    TristanK over 1 year

    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.

  • TristanK
    TristanK about 14 years
    This seems to do what I want, but with one problem. It will process the file from the start on each iteration, getting exponentially slow.
  • TristanK
    TristanK about 14 years
    Will this save every frame as an image?
  • Shevek
    Shevek about 14 years
    yes, every frame.
  • TristanK
    TristanK about 14 years
    I got this message: The command line options couldn't be loaded, check that they are valid.
  • TristanK
    TristanK about 14 years
    On Ubuntu, I got this message: unknown option or missing mandatory argument `--image-out-prefix=capname'
  • TristanK
    TristanK about 14 years
    I need to skip most frames, outputting all frames will use up too much storage space. I need just one frame every few seconds.
  • Julian
    Julian about 14 years
    @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
  • quack quixote
    quack quixote about 14 years
    @liam: put the -ss before the -i so that the seek happens before the input video gets decoded. this should speed it up. source
  • quack quixote
    quack quixote about 14 years
    this sounds like an mplayer bug. nice workaround.
  • stib
    stib about 10 years
    There's a better, much faster way to do it with ffmpeg. See my answer below.
  • Tomáš Zato - Reinstate Monica
    Tomáš Zato - Reinstate Monica about 9 years
    Could you at least mention on which operating system are you using this command?
  • Tomáš Zato - Reinstate Monica
    Tomáš Zato - Reinstate Monica about 9 years
    What 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?
  • stib
    stib about 9 years
    Don't use the -r flag at all. Then FFMPEG will use the input file's frame rate.
  • TristanK
    TristanK about 9 years
    It was 5 years ago, but it was probably the latest Ubuntu Desktop at the time, Ubuntu 10.4 .
  • mlissner
    mlissner over 8 years
    Note that you'll really want to use jpegs for this, unless you're sure png's are what you want. In my case, jpegs were about 50kb each, and pngs were about 2MB.
  • fcpenha
    fcpenha about 8 years
    How can I choose steps shorter than 1s. It does only accept integers.
  • stib
    stib about 8 years
    the 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.
  • Nikolay Shmyrev
    Nikolay Shmyrev almost 7 years
    It is worth to add that -q:v 1 is a very useful option here as in superuser.com/questions/318845/…
  • Adam Katz
    Adam Katz over 6 years
    Nowadays, mpv --vo=image --sstep=5 movie.mkv works great without the aforementioned bug (mpv is a fork of mplayer) using mpv 0.27.0 on Debian.
  • Nathan
    Nathan almost 6 years
    I appreciate how on Super User this answer is 2nd even though it's the accepted answer. On SO and SO Meta the accepted answer is showed first
  • Nathan
    Nathan almost 6 years
    This should probably be its own question, but @stib is that why most of the images I find on Google are .jpgs? Because they're smaller?
  • stib
    stib almost 6 years
    Not only its own question, but probably on a different site… But whatevs: to oversimplify, jpegs work better for photographs (or stills from video), where better means smaller file for less perceptible quality loss, pngs are lossless, and deal with text and design elements much better. See this definitive answer: stackoverflow.com/questions/2336522/…
  • looooongname
    looooongname over 4 years
    Tip: make sure the -r 1 goes AFTER the input file, otherwise it doesn't have the intended effect.
  • stib
    stib over 4 years
    Good point Simon.
  • Filip Allberg
    Filip Allberg about 4 years
    @stib for -r > 1 how are those frames distributed? I'm trying to extract 5 frames from every second of video which are evenly distributed across that second.
  • myfirstAnswer
    myfirstAnswer about 3 years
    @mlissner but with jpegs also quality considerably drops in my case in contrast with pngs
  • stib
    stib about 3 years
    @FilipAllberg If r = 5 you'll get five frames at 1/5 second intervals.
  • stib
    stib about 3 years
    Might be worth noting that TIFFs, while larger are much, much faster than pngs. This is important if you're using them as an image sequence.