20

I have video frames in PNG format at 1 FPS and I'm trying to convert them into a video using ffmpeg.

If I do something like this:

ffmpeg -i data/input-%4d.png data/output.mp4

I get a video at 25FPS which is basically a very fast-forward of the input (which is captured at 1FPS).

If I try:

ffmpeg -i data/input-%4d.png -r 1 data/output.mp4

I get something that VLC doesn't want to play :)

Now, if I take the first video (the FF one) and apply a filter to slow it down (e.g. -filter:v 'setpts=24.0*PTS'), I can get it to play like a 1 FPS video, but of course the price is file size. It's generating a bunch of repeated frames I guess.

So, the question is how do I create a video that has exactly 1 FPS and actually plays at that speed? The output format, btw, isn't that important for me.

  • I'm not sure ffmpeg is smart enough to figure out the video codec just from the container format file extension, .mp4. Try adding -vcodec libx264 -vpre hq to the command line, to tell it the codec and encoding parameters. – Warren Young Mar 22 '13 at 7:09
  • It actually figured it out ok, and I as mentioned it worked well and only produced weird results when I added -r 1. – Assaf Lavie Mar 22 '13 at 7:43
  • I think you may have better luck at a ffmpeg answer on stackoverflow.com or superuser.com. – Damien May 4 '13 at 18:21
18

If you want a one-liner for FFMPEG that generates a video that plays at 1 frame per second, what you want to do is specify framerates for both input and output, like this:

ffmpeg -r 1 -i data/input-%4d.png -pix_fmt yuv420p -r 10 data/output.mp4

The -r 1 means the video will play at 1 of the original images per second.
The -r 10 means the video will play at 10 frames per second.

(The -pix_fmt yuv420p is just there to ensure compatibility with a wide range of playback programs. It is required here, for example, for the video to be playable by Windows Media Player.)

I tested many different output framerates, and 10 seems to be the lowest number you can use that will still produce a video that VLC will play.

Of course, the command above means each original image is being multiplied, but it is a simpler method than the "slow it down" one you mentioned, and depending on the codec it may not produce a video much larger than a true 1-FPS video.

To test this, I just produced a true 1-FPS video, which came out to 2.24 kiB. I then produced a video with the same input images but output at 24 FPS, and it came out to 5.76 kiB. That's just over double the size, and nowhere near 24 times the size. :)

  • +1 on -pix_fmt. Easy to forget some people insist on using WMP :-) – Smalltown2k Jul 14 '14 at 14:37
  • why would you want the output format to be 10 fps while the input is only 1? Wouldn't it create 90% redundant frames that are exactly the same? – Herbert Jul 8 at 12:30
  • @Herbert it creates redundant frames so that you can get the frame rate up to 10, which is done just so VLC doesn't complain, and it visually doesn't change the video. The encoder is smart enough to see that the frames are all identical so you don't end up with a much larger file – chiliNUT Oct 16 at 18:14
  • @chiliNUT clear, the keyframe thing, which not all formats, but most sane formats will do. Thanks! – Herbert Oct 18 at 9:36
5

Use both -framerate and -r

E.g., to have a final video that looks like 1FPS:

ffmpeg -framerate 1 -pattern_type glob -i '*.png' \
    -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4

This is similar to what Converting PNG frames to video at 1 FPS | Unix & Linux Stack Exchange says, but I needed -framerate instead of -r for it to work.

This is mentioned on the wiki at: http://trac.ffmpeg.org/wiki/Slideshow#Framerates

It sets the output framerate to 30, which VLC can handle, and copies each images 30 times, so that the output video appears to be at 1 FPS. See also: Playback issues in VLC with low fps video from images using ffmpeg | Stack Overflow

VLC is then able to play the video normally.

Tested on Ubuntu 16.10, VLC 2.2.4, ffmpeg 3.0.5, in a directory with 10 PNGs.

See also: https://stackoverflow.com/questions/19267443/vlc-freezes-for-low-1-fps-video-created-from-images-with-ffmpeg

  • What's the difference between -r and -framerate? – Royi Mar 17 '17 at 12:10
  • @Royi I don't really know, except that it is the only thing that worked for me :-) But if you managed to extract it from from the man pages, let me know ;-) A meaningful quote is "-r As an input option, ignore any timestamps stored in the file and instead generate timestamps assuming constant frame rate fps. This is not the same as the -framerate option used for some input formats like image2 or v4l2 (it used to be the same in older versions of FFmpeg). If in doubt use -framerate instead of the input option -r." – Ciro Santilli 新疆改造中心法轮功六四事件 Mar 17 '17 at 13:45
3

What if you augment your second example slightly as follows:

$ ffmpeg -r 1 -i data/input-%4d.png -c:v libx264 out.mp4

The -r 1 needs to come before the .png files, not after.

From the FFmpeg documentation:

As a general rule, options are applied to the next specified file. Therefore, order is important, and you can have the same option on the command line multiple times. Each occurrence is then applied to the next input or output file.

  • Unfortunately this does not work. However, mentioning that the order is important saved me a lot of time. Thanks. – Mohammed Noureldin Apr 24 at 7:57
0

This is a bug in VLC (which still exists in version 3.0.6). After some experiments I realized that VLC crashes for videos with FPS less than 10. So all videos with 10 FPS or more shouldn't be a problem. So there is currently no clean way to get a video with 1 FPS which is playable in VLC (don't give up, keep reading).

One workaround is -as shown in the answer above- to fake the effect of 1 FPS by duplicating the images (when we actually have an FPS equals to 10 or more, which is ok for VLC).

Example: if you have a folder with 12 images, and you would like to generate a video with 1 FPS (which is playable in VLC), then you need to duplicate each image multiple times (let's say 10 times), and then tell FFMPEG to generate a 10 FPS video. In this way we will get a video with a total frames of 120, where each image will be played for 1 seconds (as it is duplicated 10 times), which is simply a fake for 1 FPS.

I prefer to use fps parameter rather than -r (which is shown in another answer) which may in some case be problematic (according to the official documentation).

ffmpeg -framerate 1 -i "img (%d).jpg" -c:v libvpx-vp9 -vf "fps=10,format=yuv420p" out.mkv

As the input -framerate is lower than the output fps, FFMPEG will duplicate frames to reach your desired output frame rate (which is 10 according to the command above).

It is also important to notice that the order of -framerate and -vf fps is important, as this configuration will be applied to the next mentioned video (in- or output). That is according to the official docs:

options are applied to the next specified file. Therefore, order is important...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.