In my research, I often generate a sequence of images from either my experiment or from a simulation that I want to put together into a movie. Since I use linux, I wanted to do this using free software in linux, and I wanted to be able to play the movie in linux. This webpage outlines what I've learned about how to do this in linux using mencoder or ffmpeg to create high quality files that are well compressed and the play well under all operating systems.

The movies are going to be non-standard size (usually square, around 200x200 pixels for me), and have a non-standard frame rate: typcially, my movies may only be 10 frames, so I don't want to run it at 30 fps.

The details

We want to encode to some kind of relatively portable movie format. ffmpeg and mencoder both do this using the libavcodec library developed as part of ffmpeg. The codec options from the mencoder man page include:

              Employ the specified codec (default: mpeg4).
                      Motion JPEG
                      Lossless JPEG
                      MPEG-4 (DivX 4/5)
                      DivX 3
                      MS MPEG4v2
                      Windows Media Video, version 1 (AKA WMV7)
                      Windows Media Video, version 2 (AKA WMV8)
                      an old RealVideo codec
                      MPEG-1 video
                      MPEG-2 video
                      ASUS Video v1
                      ASUS Video v2
                      FFmpeg's lossless video codec

ffmpeg supports an even larger list of output codecs and container formats.

MPEG-1 and MPEG-2 streams are no good, since the frame rate is locked to 29.97 or 25 FPS. For an excellent overview of some of the common open-standard compression methods, see this page.

(Note: "open" standard only means that the specifications aren't some undocumented industry secret. It does not mean, however, that the formats are not entrenched with patent issues, which mpeg4, and even mpeg1 and mpeg2, most certainly are...You take what you can get, though.)

MJPEG would seem to be a good option, except that the files that we get seem to be incompatible with windows media player for some reason (at least with files encoded with mencoder). MJPEG supports arbitrary frame rates, but the movies files could get large if you have a lot of frames since it doesn't use temporal coding.

MPEG-4 is the best option. The mpeg4 stream can be stored in either in the .avi or .mp4 (quicktime) container file: it can support high levels of lossy compression to keep file sizes small and also supports arbitrary frame rates. It is also translates much more easily to other platforms than wmv1 or wmv2.

mencoder only supports avi file containers, which is a pity since the quicktime widgets looks nicer, and the .mp4 container format has fewer issues with compatibility (there are some fourcc issues with .avi: this container file format issue is the only reason why the mpeg4 streams inside avi files from DiVX, xvid, ..., codecs are incompatible! How stupid is that?)

Note also that mencoder (at least version 1.0pre6-3.3.3 does) will barf if we use anything other than jpeg files as our input, so we should convert all our images to jpeg's with 100% quality to avoid any quantization loss at this stage:

 $ for f in *ppm ; do convert -quality 100 $f `basename $f ppm`jpg; done 

With mencoder, we can use the vbitrate option to set the degree of lossy compression. Note that the default mpeg4 option will add a "DivX" logo to the movie when playin in windows media player, so we prefer to use one of the other mpeg4 encoders, such as msmpeg4 or msmpeg4v2. The commmand line I've used is:

mencoder "mf://*.jpg" -mf fps=10 -o test.avi -ovc lavc -lavcopts vcodec=msmpeg4v2:vbitrate=800 

We can also use ffmpeg directly to encode the images files into a movie. If we start with files name 001.jpg, 002.jpg, ..., we can use:

ffmpeg -r 10 -b 1800 -i %03d.jpg test1800.mp4

This works very well, and is nice because ffmpeg is included in debian! My only complaint is that with ffmpeg is that you have to be careful that all the files are named sequentially. For example, for a long time, I was missing 015.jpg, which caused it to encode only 15 frames. To get it to work, I had to rename the files so that there were no gaps in the file numbers. The .mp4 files encoded this way will play fine with quicktime under windows, which I peronally prefer over media player, and which will never show the stupid DiVX logo, since it's doesn't use the braindead avi container. (see rant above...)

How do the file sizes compare?

Image files:

Initial ppms: 6.9 MB
Initial jpgs: 8.0 MB (100% quality)

Movies (10 frames per second): avi files are encoded using mspeg4v2, mp4 files are done using the ffmpeg default (mpeg4).

1500 test1800.avi
 900 test800.avi
 528 test400.avi

1748 test1800.mp4
 860 test800.mp4
 504 test400.mp4
 324 test200.mp4
 264 test100.mp4

At 1800 kbits/sec, the quality is excellent, with no noticeable motion artifacts. 800 is very good, but at 400, the motion artifacts become quite noticeable.

Other useful stuff: