Encoding DVD media to AVI for portable media players, under Linux
Before we get started let me first tell you what I am running on my little Linux server that is sitting on a shelf downstairs in the basement of my house:
The process and script described here should work on other systems, but if it doesn't I wanted to make sure you understood what I am using.
For my portable media player (the Creative Zen), I decided I wanted to create AVI files, which are based on MPEG-4 encoding. I'm using the xvid video codec and mp3 (lame) audio at a fixed bit rate. If you have a Zen you can do the same. If you have a different media player, it will likely work if your player can handle AVI files -- but you may need to tweak some of the settings for conversion. You can read more about this, below. Even if you want something other than AVI and/or xvid you can dig deeper into the MPlayer/Mencoder documentation to modify the calls to Mencoder accordingly, to suit your needs.
Problem: How to get my DVD movies onto my media player
For my birthday my wife bought me one of these (ok, I ordered it and she gave it to me):
Right after I received it I loaded a bunch of music onto it, and then started playing around with the video capabilites it has. I was a bit disappointed to find that I had to rely on a utility provided by Creative that allowed my video files to be converted to a format that the Zen would be able to play. Sure, it was nice enough for Creative to supply the utility but I really wanted to do my own conversions. So I studied the Zen documentation and started thinking about my little Linux server I have running in my basement. Wouldn't it be really neat to rip DVDs to the Linux box, and have it do the conversion to a format that the Zen could play?
Problem was, I had no idea where to start. So I started Googling for "Linux video conversion" and found a few packages that would run on my OpenSUSE 10.2 system. I installed one called Avidemux-gtk, which was a really excellent program -- except I could never solve a nasty A/V sync problem. My ripped DVDs converted to AVI beautifully -- but with a progressively worsening audio mis-match with video over the course of the movie. I must have spent 20 hours trying to get it to work, even posting questions to the developer forums. No luck.
I did find a utility that worked. It was called QVideoConverter. No A/V sync problems! But, it just didn't have enough dials and knobs for my liking. And I figured that since it was just a GUI front-end utility, I should be able to use Mencoder directly. Mencoder is part of the awesome MPlayer package.
I studied the Mencoder documentation and looked up every example I could find
on the internet showing how to use it. My first (many) attempts gave me the same A/V sync problem.
I also had problems even getting my resultant AVIs to play on the Zen, until I figured out that
the Zen requires the AVI container to be type-2. I finally found that there is a way to call
Mencoder so it creates an OpenDML AVI container, which meets the type-2 spec. Here is an excerpt
from the Creative Zen guide to encoding, which shows the target format needed for the Zen:
After many experiments I found the winning combination. The calls to Mencoder boil down to
three general steps:
My Linux server is headless. It is on my network, primarily performing file serving duties to
the XP machines in the rest of the house. If I need to log into the Linux machine I do so via
a VNC x-window. So my workflow for converting a DVD to an AVI file that will play on my Zen is
As an example, the movie Minority Report converts to a 672 meg file using a video bitrate of 512K and a fixed audio bitrate of 128K. You could probably get away with an even lower audio bitrate, but I like to retain as much of the "movie sound" quality as possible. I did experiment with lower video bitrates, but found that the artifacting (especially with dark scenes) was a bit too much. Of course, you can play around with the settings in this script all you want, or make calls to it with parameters on the command line to set any of the conversion settings you wish.
Widescreen? 4:3? Cropping?
One other issue that I struggled with was how to fit a widescreen movie into the Zen's 4:3 screen. Should I just crop it to 4:3? Should I retain the original aspect ratio? I tried both ways and wasn't happy with either. I found that just cropping to 4:3 caused the movie to be almost unwatchable. Felt like I was viewing it thorugh a door keyhole. Actors that were having a dialog might be completely "off screen" if they were on the far left or right of the scene! Keeping the original widescreen aspect ratio also wasn't too good. The physical size of the Zen made it simply too small.
So, I came up with the idea of including a variable zoom feature in this script. I experimented with various crop settings and found that by telling it to retain at a minimum 85% of the width of the original movie, it was a good compromise between a straight 4:3 crop and no crop at all. If you look at the script, you will see where I calculate a target crop factor by considering the "zlimit" variable that is defaulted to 15% (i.e. retaining 85% of the original width) -- but can be user specified via command line parameter. If you set zlimit to zero it would retain the original widescreen aspect of the movie. You can set it as high as 50%, via the --zoom command line parameter. Any source media that is already in 4:3 format will of course be unaffected by this command.
The Script: encode4me
Ok, before anyone pwns me about the coding style in this script, please keep in mind it was my very first attempt (other than a couple of "hello world" tests) to write a BASH script. If you see anything seriously wrong with it I would appreciate feedback. If you want to use it as a larger program (or even front it with a nice GUI), that would be fine with me.
Here is a list of the key variables. Any of them can be changed to a new default value by editing the script -- or you can pass them in via command line parameter. Here is a list of what you can tweak:
The defaults for all of these can be found by reading the script itself which is shown at the bottom of this page. One note about the framerate: With my Zen, if I used anything but 30fps I ended up with A/V sync issues. YMMV, of course.
If you have a different media player (say for example, an COWON player with a screen size of 480 by 272), you could still use this utility and set the target --screen to 480:272. Here is what a call to the script would look like in this case:
./encode4me /home/chuck/movies/minority_report/VIDEO_TS -s 480:272
As long as the unit can play an AVI file (with video encoded as MPEG-4), you should be fine. You'd also have to make sure you don't exceed the unit's maximum video or audio bitrate -- but all those parameters are changable in the script or via the call on the command line.
Another neat thing you can do is write ANOTHER small script that calls the encode4me script
multiple times. You may want to convert a single movie to multiple formats, or you may have
a whole bunch of VIDEO_TS folders that you want to convert to AVIs.
Anyway, here's the script. I tried to put a lot of comments in so you can see how it works. If you want
to save it to use on your own Linux system you can simply copy and paste it into your favorite
editor. If you'd like to send me feedback, my userid is furtherside and I am at yahoo.com