An animation is simply frames of figures. It is pretty helpful to be proficient at generating a set of figures and combining them into a video.

Making Figures

Guidelines in making figures from time-series data:

  • Reuse whatever possible. The figure canvas, axis, colorbar can often be reused. Instead of creating and deleting objects, think about the possibilty of modifying the properties of objects or replacing the data. Many practical examples can be found in Vlasiator.jl using Matplotlib.

Concatenating Figures Into Videos

I have encountered the task of combining figures into a video several times. In the early days, I used built-in MATLAB functions for concatenating figures into videos. There are some shortcomings with this method:

  1. It requires a MATLAB license.
  2. The simple brute force algorithm generates large video files, and you cannot control the output resolution.

Then I tried the VideoIO package in Julia, but unfortunately, currently it lacks the support for VGBA encoding format.

After searching more on the web, I found a neat solution to these kinds of task: ffmpeg. I installed it through Macports on Mac, but you can also download it directly from the website for installation on other platforms.

Using FFmpeg

Although it seems easy to make videos from figures, it is actually not. You need to have some basic understandings of how figures are saved and how different video formats are structured. The best tool for video format conversion and filtering is FFmpeg. Here is a nice intro to FFmpeg in Chinese

I have encountered several issues when using ffmpeg:

  1. Image size must be a multiple of 2.

My png files generated from Matplotlib have odd pixel numbers for both width and height.
From one of the answers posted on StackOverFlow

As required by x264, the “divisible by 2 for width and height” is needed for YUV 4:2:0 chroma subsampled outputs. 4:2:2 would need “divisible by 2 for width”, and 4:4:4 does not have these restrictions. However, most non-FFmpeg based players can only properly decode 4:2:0, so that is why you often see ffmpeg commands with the -pix_fmt yuv420p option when outputting H.264 video.

There is an option -2 in specifying the size. For example,

-vf scale=1280:-2 Set width to 1280, and height will automatically be calculated to preserve the aspect ratio, and the height will be divisible by 2
-vf scale=-2:720 Same as above, but with a declared height instead; leaving width to be dealt with by the filter.

  1. movie that is generated by ffmpeg is not playable.

From ffmpeg wiki:

You may need to use -vf format=yuv420p (or the alias -pix_fmt yuv420p) for your output to work in QuickTime and most other players. Some players only support the YUV planar color space with 4:2:0 chroma subsampling for H.264 video. Otherwise, depending on your source, ffmpeg may output to a pixel format that may be incompatible with these players.

Use -vf format=yuv420p or -pix_fmt yuv420p in the command line options.

  1. Missing frames from the input figure list.

If one of your figure file is corrupted (e.g. empty), ffmpeg will stop reading all the subsequent figures.

  1. Order of files are messed up.

The best practice is to pad zeros such that all the file names have the same width.

TL;DR

Finally, the following command works for me:

ffmpeg -r 12 -pattern_type glob -i '*.png' -vcodec libx264 -vf scale=640:-2 -pix_fmt yuv420p pi.mp4

Tags:

Categories:

Updated: