#!/usr/bin/perl -w # The goal of this script is to rip a DVD to a set of OGG files # I created this script because transcode is not able to rip in 5.1 channels # I tried to keep this script as simple as possible # The script is just a simple frontend to mplayer/oggenc # There is nothing magic, but I spent many hours to find the clever way to do that # I hope this script will help you to save some time in converting DVD to OGG # If you like this script and/or if you have some comments/patches, email me ;) # # TODO: # Using a multithread system to encode while ripping # # (C) 2006 Erwan Velu , under the GNU GPL License use strict; use Getopt::Long; my $dvd_dev = "/dev/dvd"; my $channels = 2; my $input_format = "ac3"; my $ogg_quality = 6; my $verbose = 0; my $version = "0.1"; my $selected_aid = 0; my $selected_format = ""; my $chapters_max = 0; my $first_chapter = 1; my $last_chapter = 1; my $basename = "chapter"; my $mplayer = "mplayer"; my $oggenc = "oggenc"; my $opt_last_chapter; my $help; my $detect; my $keeprip; my $justrip; sub usage { print<] [--channels=] [--detect] [--format=] [--quality=] [--first-chapter=] [--last-chapter=] [--keep-rip] [--just-rip] [--help] Options: --dev Select the dvd device to rip (Default: $dvd_dev) --channels Select the number of channels to encode from 2 to 6 (Default: $channels) --detect Detect the available audio format and exit --format Select the audio format to rip in ogg (Default: $input_format) --quality Select the ogg quality: -1 to 10 (Default: $ogg_quality) --first-chapter Select the first chapter (Default: $first_chapter) --last-chapter Select the first chapter (Default: the last chapter available) --basename Select the basename for the chapter's naming (Default : $basename) --keep-rip Do not delete ripped tracks after encoding --just-rip Don't encode ripped tracks --help This help Example of use: To encode a full dvd in ogg 2.0 using an ogg quality set to 6 $0 To encode a full dvd (/dev/dvd1) in ogg 5.1 using ogg quality set to the max $0 --dev=/dev/dvd1 --channels 6 --quality 10 To encode the chapter 6 and 7 in ogg 5.1 $0 --first-chapter=6 --last-chapter=7 --channels 6 To detect all audio format available $0 --detect EOF } #Removing some white unecessary white spaces sub trim { my $my_string=shift; for ($my_string) { s/^\s+//; s/\s+$//; } return $my_string; } #We try to detect the aid corresponding to the input format the user want #We also find the numbers of chapters available sub scan_dvd { open (MPLAYER,"export LC_LANG=en; echo quit | $mplayer -v -dvd-device $dvd_dev dvd:// -vo null -vc null -ao null -slave 2>/dev/null |"); while () { # We try to find the number of chapters available in the mplayer output if (my ($chapters)= $_ =~ /\s*There\s*are\s*(\d+)\s* chapters.*/) { $chapters_max=$chapters; if (! $opt_last_chapter) { $last_chapter=$chapters_max } else { $last_chapter=$opt_last_chapter; } print "There are $chapters chapters on this DVD\n" } # We try to find an aid description in the mplayer output # It looks like : # [open] audio stream: 2 audio format: ac3 (stereo) language: en aid: 130 # or sometimes like # audio stream: 0 format: ac3 (5.1) language: en aid: 128 if (my ($format,$aid)= $_ =~ /.*audio\s*stream:\s*\d+\s*.*format:\s*(.*)\s*language:.*aid:\s*(\d+)/) { $format = &trim($format); if ($detect) { print "Detected a '$format' audio stream\n"; } else { if ($format =~ /.*$input_format.*/) { print "Found $format track\n"; if ($selected_aid == 0) { $selected_aid=$aid; $selected_format=$format; } } } } } close MPLAYER; } # Rip a chapter to the disk sub rip_chapter { my $chapter=shift; print " |-Ripping\n"; system ("mplayer -dvd-device $dvd_dev dvd://1 -dumpaudio -dumpfile ./$basename-$chapter.rip -aid $selected_aid -vc null -vo null -ao pcm:nowaveheader -channels $channels -chapter $chapter-$chapter >/dev/null 2>&1"); } # Convert a chapter to the pcm format sub convert_chapter { my $chapter=shift; print " |-Converting to wave\n"; system("mplayer -quiet -channels $channels ./$basename-$chapter.rip -rawaudio format=0x2000 -demuxer rawaudio -vo null -vc null -ao pcm:waveheader:file=$basename-$chapter.wav >/dev/null 2>&1"); if (! $keeprip) { system("rm $basename-$chapter.rip >/dev/null 2>&1"); } else { print " |-Keeping ripped track\n"; } } # Encode a chapter to the ogg format sub encode_chapter { my $chapter=shift; print " |-Encoding to ogg\n"; # We don't keep the pcm file as it could be so big system("$oggenc -q$ogg_quality $basename-$chapter.wav >/dev/null 2>&1 && rm -f $basename-$chapter.wav >/dev/null 2>&1"); } # Encode the dvd to ogg sub encode_dvd { print "Starting to rip " . ($last_chapter - $first_chapter +1) . " chapters\n"; for (my $chapter=$first_chapter; $chapter<=$last_chapter;$chapter++) { print "Chapter $chapter\n"; &rip_chapter($chapter); &convert_chapter($chapter); &encode_chapter($chapter) if not $justrip; } } sub check_parameters { open(DVD,"$dvd_dev") or die "Can't access to $dvd_dev\nExiting\n"; close(DVD); die "The number of channels must be set between 2 and 6\nExiting\n" if (($channels < 2) or ($channels >6)); die "The ogg quality must be set between -1 and 10\nExiting\n" if (($ogg_quality < -1) or ($ogg_quality >10)); die "The first chapter must be greater than 0\nExiting\n" if ($first_chapter < 1); } ########## MAIN PROGRAM ############# GetOptions( "verbose" => \$verbose, "dev=s" => \$dvd_dev, "channels=i" => \$channels, "format=s" => \$input_format, "quality=i" => \$ogg_quality, "detect" => \$detect, "help" => \$help, "first-chapter=i" => \$first_chapter, "last-chapter=i" => \$opt_last_chapter, "basename=s" => \$basename, "keep-rip" => \$keeprip, "just-rip" => \$justrip, ); print "dvdtogg version $version\n"; if ($help) { &usage; exit 1; } &check_parameters; if ($justrip) { print "Using $dvd_dev device, converting $input_format tracks to a $channels channels wav file\n"; } else { print "Using $dvd_dev device, converting $input_format tracks to a $channels channels ogg (quality : $ogg_quality/10)\n"; } &scan_dvd; if ($detect) { print "Detection Terminated, Exiting\n"; exit 1; } #Adding some more tests after the detection die "No audio track found for $input_format, please use --detect option to find available formats\nExiting\n" if ($selected_aid == 0); die "The last chapter can't be greater than the number of available chapters" if ($last_chapter > $chapters_max); die "The last chapter must be greater than the first one\nExiting\n" if ($last_chapter < $first_chapter); print "Using $selected_format track (aid n°$selected_aid)\n"; &encode_dvd; print "End of procedure, have a nice listening\n";