I have been went through this several times. In the early stage, I was using MATLAB for concatenating figures into videos. There are some shortcomings with this method:
- It requires the MATLAB license.
- 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 some searches on the web, I found a neat solution to these kinds of task: ffmpeg. Personally I installed it through Macports, but you can download it directly from the website.
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. I have encountered several issues when using ffmpeg:
- 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.
- 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.
-vf format=yuv420p or
-pix_fmt yuv420p in the command line options.
- 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.
- Order of files are messed up.
The best practice is to pad zeros such that all the file names have the same width.
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