#!/usr/bin/perl =head1 SYNOPSIS ripdvd [TITLE] =head1 DESCRIPTION ripdvd is a perl script that ties together lower-level utilities to rip a dvd and transcode it into xvid format in an avi wrapper. If no TITLE argument is provided, /dev/dvd will be scanned for a disk and the tracks on it will be ripped and then transcoded into a new subdirectory of ~/Video. If a title argument is provided, already-ripped tracks in an existing subdirectory of ~/Video will be transcoded. In either case, the work files resulting from ripping the dvd will be removed once the transcode is completed successfully. =head1 DEPENDENCIES ripdvd has been tested on ubuntu 10.4 and requires the installation of several dependencies. To install the dependencies on ubuntu: sudo /usr/share/doc/libdvdread4/install-css.sh sudo apt-get install transcode sudo apt-get install libevent-execflow-perl sudo apt-get install dvdrip-utils sudo apt-get install lsdvd =head1 COPYRIGHT Copyright 2010 Julian Haight, all rights reserved. http://www.julianhaight.com/ripdvd This program is free software; you may redistribute it and/or modify it under the GPL v2 license: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html =cut # 9/2/2010 version 1.0: add docstring and more constants, release. use strict; my($WHERE) = $ENV{HOME} . '/Videos'; # where to put output my($MAXLOAD) = 2; # sleep before encode if load higher my($VBR, $ABR) = (1800, 128); # video bitrate, audio bitrate my($VMOD) = 'xvid'; # video export modules doit(); sub doit { my($title, $tracks, $dir, $tno); if ($ARGV[0]) { $title = $ARGV[0]; my(@tracks, $line); foreach $line (`cd $WHERE/$title; ls | grep 'vob'|sed 's/-vob//'`) { chomp($line); push(@tracks, $line); } $tracks = \@tracks; } else { ($title, $tracks) = getTracks(); } $dir = join('/', $WHERE, $title); (-e $WHERE) || mkdir ($WHERE) || die "mkdir $WHERE $!\n"; (-e $dir) || mkdir ($dir) || die "mkdir $dir $!\n"; foreach $tno (@$tracks) { rip($dir, $tno); } system('eject'); if (loadavg() > $MAXLOAD) { print "Waiting for load below $MAXLOAD\n"; while (loadavg() > $MAXLOAD) { sleep(60); } } foreach $tno (@$tracks) { transcode($dir, $tno); } foreach $tno (@$tracks) { cleanup($dir, $tno); } } sub loadavg { open(IN, '/proc/loadavg'); my($load) = ; close(IN); return ($load*1); } sub getTracks { my($lsdvd) = join('', `lsdvd`); my($secs, @tracks, $title); $lsdvd =~ m/Disc Title:\s(.*)/ || die "Can't get disk title"; $title = $1; while ($lsdvd =~ m/Title:\s*(\d+), Length: (\d+):(\d+):([\d\.]+)/msg) { $secs = ($2 * 60 * 60) + ($3 * 60) + $4; if ($secs > (60*5)) { push(@tracks, $1); } } print "disc title: $title tracks: @tracks\n"; return ($title, \@tracks); } sub rip { my($dir, $tno, $vobdir, $file, $cmd); ($dir, $tno) = @_; $file = "$dir/$tno-vob/$tno-001.vob"; $vobdir = "$dir/$tno-vob"; (-e $vobdir) || mkdir ($vobdir) || die "mkdir $vobdir $!\n"; if (-e $file) { print STDERR "$file already exists, skipping rip\n"; } else { $cmd = "execflow -n 19 tccat -t dvd -T $tno,-1,1 -i \/dev\/dvd | " . "dvdrip-splitpipe -f $dir/$tno-nav.log 1024 " . "$dir/$tno-vob/$tno vob 2>/dev/null | " . "tcextract -d 1 -a 0 -x pcm -t vob > $dir/$tno.pcm"; #print $cmd; print "rip $dir $tno\n"; system($cmd); unless (-e $file) { die "rip failed $file"; } } } sub transcode { my($dir, $tno, $file, $d4file, $cmd); ($dir, $tno) = @_; $d4file = "$dir/$tno-divx4.log"; $file = "$dir/$tno-video.avi"; if (-e $d4file) { print STDERR "$d4file already exists, skipping transcode stage 1\n"; } else { $cmd = "execflow -n 19 transcode -H 10 -a 0 -x vob " . "-i $dir/$tno-vob/ -w $VBR,50 -b $ABR,0,2 --a52_drc_off " . "-I 3 -f 30,4 -M 2 -R 1,$d4file -y $VMOD,null --psu_mode " . "--nav_seek $dir/$tno-nav.log --no_split -o /dev/null"; #print $cmd; print "transcode stage 1 $dir $tno\n"; system($cmd); } if (-e $file) { print STDERR "$file already exists, skipping transcode stage 2\n"; } else { $cmd = "execflow -n 19 transcode -H 10 -a 0 -x vob " . "-i $dir/$tno-vob/ -w $VBR,50 -b $ABR,0,2 --a52_drc_off " . "-I 3 -f 30,4 -M 2 -R 2,$d4file -y $VMOD -o $file"; #print $cmd; print "transcode stage 2 $dir $tno\n"; system($cmd); } } sub cleanup { my($dir, $tno, $vobdir, $file, $cmd); ($dir, $tno) = @_; if (-e "$dir/$tno-video.avi") { # made avi ok print "cleanup $dir $tno\n"; unlink("$dir/$tno-nav.log"); unlink(glob("$dir/$tno-vob/*")); rmdir("$dir/$tno-vob"); unlink("$dir/$tno.pcm"); unlink("$dir/$tno-divx4.log"); } }