How to create a video from images with FFmpeg?

Apple Touch Icon 2

-pattern_type glob

This great option makes it easier to select the images in many cases.

Slideshow video with one image per second

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

Add some music to it, cutoff when the presumably longer audio when the images end:

ffmpeg -framerate 1 -pattern_type glob -i ‘*.png’ -i audio.ogg -c:a copy -shortest -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4

Here are two demos on YouTube:

Be a hippie and use the Theora patent-unencumbered video format:

ffmpeg -framerate 1 -pattern_type glob -i ‘*.png’ -i audio.ogg -c:a copy -shortest -c:v libtheora -r 30 -pix_fmt yuv420p out.ogg

Your images should of course be sorted alphabetically, typically as:

0001-first-thing.jpg 0002-second-thing.jpg 0003-and-third.jpg

and so on.

I would also first ensure that all images to be used have the same aspect ratio, possibly by cropping them with imagemagick or nomacs beforehand, so that ffmpeg will not have to make hard decisions. In particular, the width has to be divisible by 2, otherwise conversion fails with: “width not divisible by 2”.

Normal speed video with one image per frame at 30 FPS

ffmpeg -framerate 30 -pattern_type glob -i ‘*.png’ -c:v libx264 -pix_fmt yuv420p out.mp4

Here’s what it looks like:


GIF generated with:

Add some audio to it:

ffmpeg -framerate 30 -pattern_type glob -i ‘*.png’ -i audio.ogg -c:a copy -shortest -c:v libx264 -pix_fmt yuv420p out.mp4


These are the test media I’ve used:a

wget -O unzip cd opengl-rotating-triangle wget -O audio.ogg

Images generated with: How to use GLUT/OpenGL to render to a file?

It is cool to observe how much the video compresses the image sequence way better than ZIP as it is able to compress across frames with specialized algorithms:

  • opengl-rotating-triangle.mp4: 340K
  • 7.3M

Convert one music file to a video with a fixed image for YouTube upload

Answered at:

Full realistic slideshow case study setup step by step

There’s a bit more to creating slideshows than running a single ffmpeg command, so here goes a more interesting detailed example inspired by this timeline.

Get the input media:

mkdir -p orig cd orig wget -O 1.png wget -O 2.jpg wget -O 3.jpg wget -O 4.png wget -O 5.jpg wget -O audio.ogg cd .. # Convert all to PNG for consistency. # # Hardlink the ones that are already PNG. mkdir -p png mogrify -format png -path png orig/*.jpg ln -P orig/*.png png

Now we have a quick look at all image sizes to decide on the final aspect ratio:

identify png/*

which outputs:

png/1.png PNG 557×495 557×495+0+0 8-bit sRGB 653KB 0.000u 0:00.000 png/2.png PNG 664×800 664×800+0+0 8-bit sRGB 853KB 0.000u 0:00.000 png/3.png PNG 544×680 544×680+0+0 8-bit sRGB 442KB 0.000u 0:00.000 png/4.png PNG 207×238 207×238+0+0 8-bit sRGB 76.8KB 0.000u 0:00.000 png/5.png PNG 450×600 450×600+0+0 8-bit sRGB 627KB 0.000u 0:00.000

so the classic 480p (640×480 == 4/3) aspect ratio seems appropriate.

Do one conversion with minimal resizing to make widths even (TODO automate for any width, here I just manually looked at identify output and reduced width and height by one):

mkdir -p raw convert png/1.png -resize 556×494 raw/1.png ln -P png/2.png png/3.png png/4.png png/5.png raw ffmpeg -framerate 1 -pattern_type glob -i ‘raw/*.png’ -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p raw.mp4


This produces terrible output, because as seen from:

ffprobe raw.mp4

ffmpeg just takes the size of the first image, 556×494, and then converts all others to that exact size, breaking their aspect ratio.

Now let’s convert the images to the target 480p aspect ratio automatically by cropping as per ImageMagick: how to minimally crop an image to a certain aspect ratio?

mkdir -p auto mogrify -path auto -geometry 640×480^ -gravity center -crop 640×480+0+0 png/*.png ffmpeg -framerate 1 -pattern_type glob -i ‘auto/*.png’ -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p auto.mp4


So now, the aspect ratio is good, but inevitably some cropping had to be done, which kind of cut up interesting parts of the images.

The other option is to pad with black background to have the same aspect ratio as shown at: Resize to fit in a box and set background to black on “empty” part

mkdir -p black ffmpeg -framerate 1 -pattern_type glob -i ‘black/*.png’ -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p black.mp4


Generally speaking though, you will ideally be able to select images with the same or similar aspect ratios to avoid those problems in the first place.

About the CLI options

Note however that despite the name, -glob this is not as general as shell Glob patters, e.g.: -i ‘*’ fails: (apparently because filetype is deduced from extension).

-r 30 makes the -framerate 1 video 30 FPS to overcome bugs in players like VLC for low framerates: VLC freezes for low 1 FPS video created from images with ffmpeg Therefore it repeats each frame 30 times to keep the desired 1 image per second effect.

Next steps

You will also want to:

TODO: learn to cut and concatenate multiple audio files into the video without intermediate files, I’m pretty sure it’s possible:

Tested on

ffmpeg 3.4.4, vlc 3.0.3, Ubuntu 18.04.



Leave a Reply