Brendan Dawes
The Art of Form and Code

Using FFmpeg to convert image sequences to video

Often times my workflow involves converting a series of images into a video. I've always used Quicktime Player 7 Pro as the app I use to do this. Yet I read the other day that Mac OS Mojave will be the last version of the OS which will allow this version of Quicktime to run. That got me thinking about an alternative way to convert images to video, which led me to FFmpeg.

FFmpeg is a command line tool that can do many things with images and video, one of which is to convert an image sequence into a video such as an mp4. I'll detail how I use this now, but more importantly I'll show how I wrote a bash function that simplifies this process.

Install ffmpeg

The first thing to do is to install ffmpeg. This is easiest using Homebrew, a Mac package manager. If you don't have Homebrew first open up a terminal and paste this in the terminal window then press return

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Homebrew will then install. Next we can install FFmpeg using Homebrew. Again paste or type the following into the terminal and press return.

brew install FFmpeg

All being well FFmpeg should now be installed.

Converting a bunch of images into a video

FFmpeg has a whole host of options to convert a sequence of images to a video, but I'll show you what works for me.

Let's say we have a load of images that are named something like frame0001.png, frame0002.png etc etc. It's important to use padded numbers such as ones with leading zeroes otherwise it can get confused about which number is the correct one in the sequence.

To convert such a list into an mp4, at 24 frames per second we can navigate in the terminal to the directory containing our images and then write:

ffmpeg -r 24 -f image2 -pattern_type glob -i "*?png" -vcodec libx264 -crf 20 -pix_fmt yuv420p output.mp4

This will find all the png images and compile them into a video file called output.mp4 at 24 frames per second.

Simplifying Further

Whilst this is indeed fantastic it's a bit of a pain to have to remember this every time we want to make a video from images. So instead I wrote a little bash function (with the help of Stackoverflow) to simplify everything — I can just type the word mpeg in the terminal and it will do its thing. Here's how to do that.

To add a function to the Bash terminal we need to edit the .bash_profile text file that defines various things for the terminal. This is a normally hidden file that sits in your home directory. The best way to edit it is via Vim, so we'll use that, but you can use another test editor if you prefer.

In the terminal type:

vim ~/.bash_profile

This will either open up the current .bash_profile or create a new one if it doesn't exist.

Copy the function below:


mpeg () {

local fps=24;
local filename=output.mp4;
local quality=20;
local ext=png;

while test $# -gt 0; do
           case "$1" in
                -fps)
                    shift
                    fps=$1
                    shift
                    ;;
                -filename)
                    shift
            filename=$1
                    shift
                    ;;
                -quality)
                    shift
            quality=$1
                    shift
                    ;;
                *)
                   echo "$1 is not a recognized flag!"
                   return 0;
                   ;;
          esac
  done  

    ffmpeg -r $fps -f image2 -pattern_type glob -i "*?$ext" -vcodec libx264 -crf $quality -pix_fmt yuv420p $filename
}

Back in vim, press G which will take you to the end of the file (if there is already something there that is) press o which will insert a line and put you into insert mode. Then paste the function you copied from above. Next press esc to come out of insert mode, press : and then type w followed by return to write the changes to the file. Next type : and then q and press enter to quit vim. All done!

Next quit the terminal and then open it again which will load in your new .bash_profile which now contains out little mpeg function. Navigate to the same folder as your previous png's in the terminal and then type:

mpeg

All being well this should trigger our special function and convert those images to a video, without having to type all the stuff we did before. Much more convenient.

We can pass a few options into our function if we want to change framerate or the type of images, or the outputted filename. Here's an example of changing the framerate, the quality (lower numbers better) the extension to search for and the filename for the video:

mpeg -fps 15 -quality 10 -ext jpg -filename mymovie.mp4

You can see how easy it is to pass in these arguments to suit your requirements.

I'm now using this as my default way to to convert a series of images into a video. You could even add this as an Automator action which you could run on any selected folder without even having to open a Terminal.

If you like this you might also like my Automator and Handbrake solution for converting movie formats.