Canon Movies and Linux


Here is how I turn the movies taken with my Canon PowerShot A40 digital camera into highly compressed MPEG files suitable for putting up on my website. Some of this, such as the package installation, is highly Debian-dependent, but there should be something here for non-Debian users.

This is my original page detailing how to convert the Canon movies into MPEG1 format. Ben Low has provided information about converting the movies to DIVX which I have put on another page. His method is substantially simpler and probably the way forward for the future, so I recommend you have a look at it.

For how to get your Linux machine to talk to your Canon A40 see my Howto page, and there are also some FAQs.

Feel free to contact me if you have any questions or comments. Any feedback is welcome, and I will do my best to help you out if you need it. However, please be aware that I am very far from being an expert.

Ben Edgington,
5 August 2002

Home


Index


Introduction

It's not pretty, but I've just found a way of converting the .AVI files generated by my Powershot A40 into MPEG1 files suitable for putting up on the web. I just love the free-software community!

The utilities I use are mencoder, from the mplayer suite, and mjpegtools. Sources and installation tips are to be found below.

The main problem is that the frame-rate of the mjpeg .AVI files generated by the A40 is 20.0fps, which is not a standard MPEG frame-rate. I therefore use mencoder to convert to a standard 24.0fps. It does this by inserting duplicate frames from time-to-time. Not ideal, but effective.

After conversion into an .AVI with a useful framerate the mjpegtools utilities can be used to process and compress the movie and the sound independently and then multiplex them together again. Unfortunately, the mpeg files generated by mencoder are not playable by Windows Media Player, or the Quicktime Player, hence the need for mjpegtools.

5/12/2003 An anonymous correspondent reports that Windows Media Player compatibility can be achieved by using the mencoder options -ovc lavc -lavcopts vcodec=msmpeg4v2. I haven't tested this.

If anyone can show me a better way, please contact me.


A typical session

Given a movie file MVI_0033.AVI create a very highly compressed MPEG, foo.mpg.

The Audio

For convenience we treat the audio as a separate stream. We will merge it back later. The sound quality of the A40 is far from Hi-Fi, so we use the minimum bitrate, 32Kbps, and ensure it's mono (-m flag).

$ lav2wav -I +p MVI_0033.AVI | mp2enc -m -b 32 -o foo.mp2

The Video

Now we do the video. As noted above, we first need to convert the frame-rate from 20.0fps to a standard rate. It seems that 24.0fps is the next smallest standard rate, so I use that.

$ mencoder -fps 20 -ofps 24 -nosound -ovc copy MVI_0033.AVI -o foo.avi

This foo.avi file is now in a fit state to be compressed to MPEG. In the following the yuvdenoise filter vastly improves the quality since, especially in low light, the A40's video is a somewhat grainy. The yuvmedianfilter also makes an improvement at the expense of a little fuzziness.

In this example the MPEG encoding is done with a maximum bitrate of 320Kbps. The bitrate has a dramatic affect on quality, but also on the file size, so you will want to find your own compromise value. The -f 0 parameter forces MPEG1 output. The -B 35 parameter is a little obscure. It refers to the bandwidth of the non-video data that will later be included, ie. our audio stream plus a little extra. RTFM for more on that. I have been using the -q parameter with a value of 5. This gives a variable bitrate. Other values may be better; I have not had a chance to experiment yet. The -a 1 parameter preserves the aspect ratio of the movie (as Jens Stark reminded me).

$ lav2yuv +p foo.avi | yuvdenoise | yuvmedianfilter | mpeg2enc -B 35 -f 0 -q 5 -b 320 -a 1 -o foo.m1v

While doing this, lav2yuv will occasionally report that it cannot decode some frames. These are the duplicate frames inserted earlier by mencoder when changing the frame-rate. I'm not sure what it does about this, but the end result seems satisfactory.

Merging Video and Audio

The resulting separate video and audio files can be multiplexed together with mplex

$ mplex -V -r 360 foo.mp2 foo.m1v -o foo.mpg

The -r 360 is the maximum bitrate of the whole stream, ie. 320 + 32 + 1 or 2%. RTFM for more info.

The final foo.mpg is suitable for web use. At least it can be read by Quicktime and Windows media player as well as the linux players such as mplayer. In a typical case with a relatively high 320Kbps, as above, the compression ratio over the original .AVI movie was around seven times. The audio and video may not be completely in sync, and there may be a little jerkiness from time to time, but frankly it's Good Enough for me 8^).

Rotating and Resizing

Sometimes it would be nice to be able to resize images - to save bandwidth, for example - or to rotate images. I have some movies that I took with the camera in "portrait" orientation, and I don't want all the viewers to have to turn their monitors sideways.

I can't find an effective way of doing this with mplayer (see below), and have succeeded only by splitting the movies into their component jpeg files, and transforming them in batch mode with the mogrify utility from the ImageMagick package.

Here is a typical session (lines numbered for reference),

  1. mencoder -fps 20 -ofps 24 -oac copy -ovc copy MVI_0181.AVI -o tmp.avi
  2. lav2wav -I +p tmp.avi | mp2enc -m -b 32 -o foo.mp2
  3. mplayer -vo jpeg MVI_0181.AVI
  4. mogrify -rotate 90 *.jpg
  5. ./fps.sh 20 24 new_
  6. jpeg2yuv -I t -L 1 -f 24 -b 1 -j new_%08d.jpg | yuvdenoise | mpeg2enc -B 35 -f 0 -q 5 -b 500 -a 1 -o foo.m1v
  7. mplex -V -r 538 foo.mp2 foo.m1v -o foo.mpg

and some explanation,

  1. We interpolate the movie from 20 to 24fps for the sake of the audio stream which we will be multiplexing back in later on.
  2. Now extract the audio stream at the minimum quality (32kbps).
  3. This is how we extract all the frames of the original movie to jpeg files.
  4. Now we rotate them all by 90 degrees - you could also scale them, or crop them, or enhance them, or any of the awesome number of options mogrify supports.
  5. I use my shell-script to duplicate enough frames to convert the movie from 20fps to 24fps.
  6. Now we can recombine the jpegs and encode them into mpeg format, at 500kbps in this example.
  7. Finally we recombine the audio and the video streams.

Note (5/12/03) Richard Miles has suggested using ppmtoy4m rather than jpeg2yuv:

The man page for jpeg2yuv tells you to use ppmtoy4m instead, and in fact I got much better, brighter results. So instead of using:

jpeg2yuv -I t -L 1 -f 24 -b 1 -j new_%08d.jpg

I did:

# convert jpeg's to PPM files
for f in new*.jpg; do jpegtopnm $f > `basename $f .jpg`.ppm;
done

# Combine PPM frames to YUV stream
cat *.ppm | ppmtoy4m -o 1 -F 30:1 -I t -L

(note I have to use 30fps not 24, since my camera records at 15fps, and converting from 15 to 24 is difficult.)

An easier way?

In principle mplayer has the capability of combining some of these tasks. For example, the following is promising when it comes to rotating movies,

$ mplayer -nosound -vop rotate=1 MVI_0181.AVI -vo yuv4mpeg 
$ cat stream.yuv | mpeg2enc -B 35 -a 1 -F 2 -f 0 -q 5 -b 500 -o foo.m1v

It does the job, but I can find no way to get it to correct the framerate, even if I preprocess the .AVI with mencoder as described above, so the movies run 20% too fast 8^).


Obtaining the Software

The bulk of the software is not available in Debian Woody, so I compiled from source or found .deb files for most of it around the place.

MPlayer

The mplayer package includes mencoder, and is a good movie-viewer by itself, so definitely worth having.

I installed the source from http://www.mplayerhq.hu/homepage/. It comes with very comprehensive documentation, but in summary I just made sure that I had installed all of the supporting libraries I was interested in (png, mpeg, jpeg, lame, etc. etc.). Then I followed the usual procedure, carefully checking the configure output for missing features,

./configure
make
make install

This compiles without the GUI, but GUIs are not really my thing anyway.

There are a squillion features in mplayer/mencoder I haven't investigated yet.

lame

The lame libraries are useful for doing the MPEG audio encoding stuff. I installed the lame_3.91-2_i386.deb file from http://hive.me.gu.edu.au/not_lame/.

mjpegtools

A Debian package for mjpegtools is available from http://download.sourceforge.net/mjpeg/. I downloaded the latest binary version, http://download.sourceforge.net/mjpeg/mjpegtools_1.6.0-1_i386.deb

I needed to install the libsdl1.2debian package to satisfy dependencies, and this brought in a bunch of other packages. All these are from Debian Woody.

I also found that I needed the libquicktime4linux package, although this was not noted in the dependencies. Again it is available from Debian Woody.


Postscript

You can see a couple of movies I took with the A40 here. Don't get too excited: it's just my cute baby 8^), and the pictures are highly compressed for the web so the quality suffers somewhat. No Oscars for these ones.

Although I did the original MPEG versions using some Windows utilities, I, of course, did these ones under Linux with the tools described above. The result is a pleasing improvement in the file-size/image-quality compromise.