Sunday, March 7, 2010

Watching a film on your F*CKING telephone

Before we begin, please watch this important safety video. If Mr. Lynch's cautionary tale has not dissuaded you, read on, with the understanding that you should not try this at home, that I am not responsible if your house burns down or you get arrested or sued, and that I offer no warranty, including for merchantability or fitness for a particular purpose.

I have a 45+ minute commute, twice a day. By way of sanity management, I use my phone (typically a Droid or Nexus One these days) to listen to music... and watch some videos. (No, I don't drive, I take transit, but your interest in safety is reassuring.) Specifically, I've been ripping DVDs to watch on my phone.[1]  It took me quite some doing to find a way to rip DVDs so that they'd play on my phone, and I figured I would blog about it for two reasons: so that others may perhaps benefit, but also so that when my computer dies the next time, I'll have a copy in this Cloud all the kids these days are talking about.

So, here is how to use Ubuntu to rip DVDs to MP4 files that will work on an Android device. This approach uses command line programs: no GUI required. Mostly this is because I prefer it this way so that I can rip DVDs from my headless server, but it's also partly because I couldn't find a GUI program that was capable of ripping a file that Android can understand. (I suspect it's because they all use mencoder behind the scenes -- read on.)


The output we're looking for is an MPEG4 SP file, with video and audio encoded in a supported format. Any supported formats will work, but practically speaking we want H264 for video, and AAC for audio. You could use MP3 for audio, but... why would you do that to yourself? Note that many (most? all?) DVDs use AC3 for audio, but we are transcoding that to AAC.

The basic idea here is that you use the mencoder program to do the ripping. However, mencoder has a bug that generates broken MP4 container files, so Android devices don't recognize them as movies and can't play them. So, after you rip a DVD to AVI, you need to repackage it as a legitimate MP4 file.

To begin, you need to install a few packages:
  • libdvdcss2 - for the ability to decrypt DVDs [2]
  • lsdvd - for looking at the contents of a DVD
  • mencoder - to rip DVDs to AVI files (don't bother trying to rip to MP4, it won't work)
  • faac - used by mencoder to rip audio to AAC
  • mplayer - for extracting the audio track from the AVI file 
  • mpeg4ip-server - for its mp4creator tool which can re-merge audio and video into a correct MP4
These can be installed via apt-get or aptitude or whatever floats your boat.

In slightly more detail, here is the actual procedure:
  1. Use 'mencoder dvd://' to rip the DVD to an AVI file containing H264 video and AAC audio
  2. Use 'mplayer -dumpaudio' to extract the AAC data from the AVI
  3. Use 'mencoder -of rawvideo' to extract the H264 video from the AVI
  4. Use 'mp4creator -create' to create an MP4 file from the AAC audio track
  5. Use 'mp4creator -create' again to merge the video in to the new MP4
It's not quite as simple as the above, but since I don't really want to bother getting into the gory command-line details, I have instead included a simple Python script that automates these. You pass it a single integer as a command line argument, which indicates which track on the DVD to rip.


In the script, I set the H264 bitrate to 768. This is too high for first-generation devices like the G1, Magic, and Hero, which don't have the hardware to handle 768kbit. However, Droid and Nexus one can actually handle higher, but I set it at 768kbit as a compromise between quality and file size. A half-hour TV show episode is about 275MB with this configuration. (Wow, my first hard drive was 20MB.)

Notes
[1] - I do not condone ripping DVDs which you do not own. Seriously. I have ripped 800+ CDs to our disk server, but in each case we own the physical disk, or purchased it legitimately if it is digital. The same is true for DVDs I've ripped. I do this as a form of time-shifting (which I believe is fair use, or ought to be), and because I've bought the media in each case I have no moral issues doing this. Don't be evil!


[2] - See [1].


Maybe one day mencoder will get fixed and steps 2 - 5 will become obsolete. Until that day, here is a Python script:



import os, sys
tracknum = int(sys.argv[1])
args = {'tracknum': tracknum}


print 'mencoder...'
s = 'mencoder dvd://%(tracknum)s -dvd-device /dev/dvd -aid 128 -o ripping-%(tracknum)s.avi -ovc x264 -x264encopts bitrate=1024:nocabac:direct_pred=auto:me=umh:frameref=2:level_idc=21:partitions=all:subq=6:threads=auto:trellis=1:vbv_maxrate=768:vbv_bufsize=244:bframes=0 -oac faac -faacopts br=192:mpeg=4:object=2 -channels 2 -srate 48000 -vf harddup' % args
f = os.popen(s)
x = f.read()
while x:
  x = f.read()


print 'dumping audio...'
s = 'mplayer "ripping-%(tracknum)s.avi" -dumpaudio -dumpfile "ripping-%(tracknum)s.aac"' % args
f = os.popen(s)
x = f.read()
while x:
  x = f.read()


print 'dumping video...'
s = 'mencoder ripping-%(tracknum)s.avi -of rawvideo -nosound -ovc copy -o ripping-%(tracknum)s.h264' % args
f = os.popen(s)
x = f.read()
while x:
  x = f.read()


print 'creating mp4 from aac...'
s = 'mp4creator -create ripping-%(tracknum)s.aac ripping-%(tracknum)s.mp4' % args
f = os.popen(s)
x = f.read()
while x:
  x = f.read()


print 'merging h264 to mp4...'
s = 'mp4creator -create ripping-%(tracknum)s.h264 -rate 29.97 ripping-%(tracknum)s.mp4' % args
f = os.popen(s)
x = f.read()
while x:
  x = f.read()


print 'cleaning up...'
os.remove('ripping-%(tracknum)s.avi' % args)
os.remove('ripping-%(tracknum)s.h264' % args)
os.remove('ripping-%(tracknum)s.aac' % args)





4 comments:

Countervail said...

Isn't it just easier to use something like HandBrake and make sure the settings leave a workable file for Android?

MagicFab said...

Wow, that's involved. With Handrbake it's a 5 step operation:
1) Choose Apple > Ipod & Ipod video from pofiles
2) Click Source, load DVD
3) Enqueue
4) Click start
5) Rename resulting file to .mp4

Even the resized videos from the Apple Ipod profiles look very good on the N1.

Handbrake is also command line although I haven't tried it that way,

Dan Morrill said...

Like I said, Handbrake doesn't work; it generates bogus .mp4 files since it's using mencoder. Perhaps this is just on the Ubuntu 8.04 box I have, so maybe it's fixed in a later version.

MagicFab said...

Sorry, I forgot to mention I tested using Ubuntu 9.10.