[MEncoder-users] Ripping dvd to mp4

Erik Slagter erik at slagter.name
Mon Mar 24 13:34:26 CET 2008


Hi,

I want to be able to rip dvd's and play them on my PS3 (and also other 
future, standards-compliant hardware devices, so this rules out ogg, 
matroska etc.)

The nasty thing is that I also want exactly 1 subtitle track included. 
Without subtitling it is actually very simple to rip a dvd...

I also found out that mp4 does support (soft) subtitling but most 
devices do not render them, so I will need to render the subtitles in 
the video stream :-(

Also the audio and video need to remain in sync (of course) wich rules 
out solutions that use elementary streams without a/v sync compensation.

As far as I know there is only one combination of programs and options 
that can do this (see attached script), which works fairly well. It uses 
the command line versions of x264 and faac to achieve maximum 
flexibility. The audio and video frames are passed using named pipes so 
there are no huge intermediate files. The stdin-stdout pipes are only 
there to keep all processes running while there is still input to be 
processed, no data is passed through them. It adds chapter info to the 
mp4 file although the PS3 doesn't use it :-(

I was wondering whether someone knows other (simpler) solutions as well. 
Native subtitling rendering support in ffmpeg and mencoder would the 
best solution of course, but that's not reality.

==============================================

#!/bin/sh

audiolang="en"
sublang="nl"

if [ $# -lt 1 ]
then
         dvd=$PWD
else
         dvd="$1"
fi

if [ ! -d "$dvd" ]
then
         echo "not a directory: $1"
         exit
fi

vpipe1="dvd2avc1.y4m"
apipe1="dvd2avc1.apipe"

title=$(mplayer -identify -frames 0 -dvd-device $dvd dvd:// 2>&1 |
         egrep "ID_DVD_TITLE_[0-9]+_LENGTH=" |
         sort '-t=' -g -r -k 2 |
         head -1 | \
         perl -n -e '($_) = m/ID_DVD_TITLE_([0-9]+)_LENGTH/; print $_')

echo "Main title: $title"

chapters=$(mplayer -identify -frames 0 -dvd-device $dvd dvd://${title} 
2>&1 |
         perl -n -e 'if(/^CHAPTERS: /) { s/^CHAPTERS: //; s/,/ /g; print 
$_; last; }')
echo "Chapters in this title: $chapters"

aid=$(mplayer -identify -frames 0 -dvd-device $dvd dvd://${title} 2>&1 |
         egrep "ID_AID_[0-9]+_LANG=${audiolang}" |
         sort -g |
         head -1 | \
         perl -n -e '($_) = m/ID_AID_([0-9]+)_LANG/; print $_')

echo "Audio id: $aid"

sid=$(mplayer -identify -frames 0 -dvd-device $dvd dvd:// 2>&1 | \
         perl -n -e "if(/ID_SID_[0-9]+_LANG=${sublang}/) { (\$a) = 
m/ID_SID_([0-9])+_LANG/; printf \"%s\n\", \$a; }")

echo "Sub id: $sid"

avc="dvd.264"
aac="dvd.aac"
mp4="dvd.mp4"
chap="dvd.chap"

rm "$vpipe1"  "$apipe1" 2> /dev/null

mknod "$vpipe1" p
mknod "$apipe1" p

rm "$chap" 2> /dev/null

for chapter in $chapters
do
         echo "$chapter $chapter" >> $chap
done

mplayer -noconsolecontrols -nocache -vf-clr -benchmark -slang nl -sid 
"$sid" -aid "$aid" \
                 -vo "yuv4mpeg:interlaced:file=$vpipe1" -ao 
"pcm:waveheader:file=$apipe1:fast" \
                 -dvd-device $dvd dvd://$title 1>&2 /dev/null | \
         x264 --bframes 16 --b-pyramid --ref 4 --interlaced --crf 20 \
                 --trellis 1 --nr 1000 --level 41 \
                 --threads 2 --direct none --subme 5 -o "$avc" "$vpipe1" | \
         (faac --mpeg-vers 4 -b 192 -o "$aac" "$apipe1" 2> /dev/null)

rm "$vpipe1" "$apipe1" 2> /dev/null

MP4Box -lang en -new "$mp4" -add "$avc" -add "$aac" -chap "$chap" -isma


More information about the MEncoder-users mailing list