| > |
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.
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:
vcodec=
Employ the specified codec (default: mpeg4).
mjpeg
Motion JPEG
ljpeg
Lossless JPEG
h263
H.263
h263p
H.263+
mpeg4
MPEG-4 (DivX 4/5)
msmpeg4
DivX 3
msmpeg4v2
MS MPEG4v2
wmv1
Windows Media Video, version 1 (AKA WMV7)
wmv2
Windows Media Video, version 2 (AKA WMV8)
rv10
an old RealVideo codec
mpeg1video
MPEG-1 video
mpeg2video
MPEG-2 video
huffyuv
HuffYUV
asv1
ASUS Video v1
asv2
ASUS Video v2
ffv1
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:
ffmpeg -i test.mp4 -f singlejpeg -t 0.001 test.jpg
Check out this file for an example (latex source file is available here). More info about how to do this is avilable from this website.
The movies will play fine under windows using acroread 7.0. Under linux, if you install acrobat reader 7.0 for linux, you can save the embedded movies to disk and play them form there.