All pastes #213016 Raw Edit

node_6

public text v1 · immutable
#213016 ·published 2006-10-21 04:47 UTC
rendered paste body
#!/usr/bin/perl -w

# dvd9to5.pl - v0.1.7
# This file is released under the GNU General Public License. All rights 
# reserved. Please check out http://www.gnu.org/copyleft/gpl.html before you 
# use this code. Minimal support may be provided by sending email to 
#     Jason Cooper <dvd9to5@lakedaemon.net>

use strict;
use Getopt::Std;

my $VERSION="v0.1.7";
my @ChapterMarks;
my $ChapList;
my %Options;
my $StartTime;
my $StopTime;

# User changeable vars
my $DVDDir;
my $WorkDir;
my $LogName;
my $HomeDir;
my $DVDRipDev;
my $DVDBrnDev;
my $BurnSpd;
my $TitleNum;
my @AudioCH;
my @SubCH;
my $RequantFactor;
my $MaxISOSize;

# Config file locations.
chdir;
$HomeDir = `pwd`;
$HomeDir =~ s/\n$//;
my $etcConf_Loc  = '/etc/dvd9to5.conf';
my $homeConf_Loc = $HomeDir . '/.dvd9to5.conf';

# Default values for user changeable vars
my $dflt_DVDDir        = 'dvd/VIDEO_TS';
my $dflt_WorkDir       = '/var/tmp';
my $dflt_LogName       = 'dvd9to5.log';
my $dflt_DVDRipDev     = '/dev/dvd';
my $dflt_DVDBrnDev     = '/dev/dvd';
my $dflt_BurnSpd       = 2;
my $dflt_TitleNum      = 1;
my @dflt_AudioCH;
   $dflt_AudioCH[0]    = '0';
my @dflt_SubCH;
my $dflt_RequantFactor = 1.0;
my $dflt_MaxISOSize    = 4706074624; #bytes, according to growisofs

# Grab the Command Line Options
my $CL_Opts = getopts("i:o:w:t:a:s:S:DIh", \%Options);

if(!$CL_Opts || $Options{h}) {
   print("dvd9to5.pl $VERSION                         \n");
   print("Usage: dvd9to5.pl <options>                 \n");
   print("  -i <dev>     Source device.               \n");
   print("  -o <dev>     Destination device.          \n");
   print("  -w <dir>     Working directory.           \n");
   print("  -t <num>     Title # to use.              \n");
   print("  -a <0,1...n> Audio channel #'s to use.    \n");
   print("  -s <0,1...n> Subtitle channel #'s to use. \n");
   print("  -S <num>     Burn Speed.                  \n");
   print("  -D           Delete unneeded files.       \n");
#   print("  -I          Show DVD info and guesses. \n");
#   print("");
#   print("");
#   print("");
   print("  -h          Print this help.\n");
   exit(0);
}

sub LoadValues {
      # NOTE: Order of preference:
      #        1.) command line opts
      #        2.) ~/.dvd9to5.conf
      #        3.) /etc/dvd9to5.conf
      #        4.) hard coded defaults.

   # Setting hard coded defaults
   $WorkDir    = $dflt_WorkDir;
   $DVDRipDev  = $dflt_DVDRipDev;
   $DVDBrnDev  = $dflt_DVDBrnDev;
   $BurnSpd    = $dflt_BurnSpd;
   $TitleNum   = $dflt_TitleNum;
   @AudioCH    = @dflt_AudioCH;
   @SubCH      = @dflt_SubCH;
   $MaxISOSize = $dflt_MaxISOSize;
   $DVDDir     = $dflt_DVDDir;

   # Overwriting with "etc-config"
   my @args;
   if (-e $etcConf_Loc) {
      open(ETCCONF, "<$etcConf_Loc");
      print("dvd9to5: Reading $etcConf_Loc\n");
      while(<ETCCONF>) {
         if($_ =~ m/^DVDRipDev/i) {
            @args = split;
            $DVDRipDev = $args[1];
         }
         if($_ =~ m/^DVDBurnDev/i) {
            @args = split;
            $DVDBrnDev = $args[1];
         }
         if($_ =~ m/^BurnSpd/i) {
            @args = split;
            $BurnSpd = $args[1];
         }
         if($_ =~ m/^WorkDir/i) {
            @args = split;
            $WorkDir = $args[1];
         }
      }      
      close(ETCCONF);
   }
   else {print("dvd9to5: Config file $etcConf_Loc not found.\n");}

   # Overwriting with "user-config"
   if (-e $homeConf_Loc) {
      open(HOMECONF, "<$homeConf_Loc");
      print("dvd9to5: Reading $homeConf_Loc\n");
      while(<HOMECONF>) {
         if($_ =~ m/^DVDRipDev/i) {
            @args = split;
            $DVDRipDev = $args[1];
         }
         if($_ =~ m/^DVDBurnDev/i) {
            @args = split;
            $DVDBrnDev = $args[1];
         }
         if($_ =~ m/^BurnSpd/i) {
            @args = split;
            $BurnSpd = $args[1];
         }
         if($_ =~ m/^WorkDir/i) {
            @args = split;
            $WorkDir = $args[1];
         }
      }
      close(HOMECONF);
   }
   else {print("dvd9to5: Config file $homeConf_Loc not found.\n");}

   # Overwriting with command line opts   
   $DVDRipDev = $Options{i} if($Options{i});
   $DVDBrnDev = $Options{o} if($Options{o});
   $WorkDir   = $Options{w} if($Options{w});
   $BurnSpd   = $Options{S} if($Options{S});
   $TitleNum  = $Options{t} if($Options{t});
   @AudioCH   = split /\,/, $Options{a} if($Options{a});
   @SubCH     = split /\,/, $Options{s} if($Options{s});

   $WorkDir =~ s/\n$//;
   $WorkDir =~ s/\/$//;

   # Grab the dvd_name 
   my $GetNameCmd = 'isoinfo -d -i ' . $DVDRipDev . ' | egrep "^Volume id"';
   my $name = `$GetNameCmd`;
   my @words = split / /,$name;
   $name = $words[2];
   
   $name =~ s/\n$// if($name);
   $WorkDir = $WorkDir . '/' . $name if($name);
   unless (-d $WorkDir) {
      my $MkDirCmd = 'mkdir -p ' . $WorkDir;
      system("$MkDirCmd");
   }

   $LogName = $WorkDir . '/' . $dflt_LogName;

   if($Options{D}) {
      LogThis("WARNING: You are deleting files as you go. Very Dangerous!!!");
   }
}

sub ExtractData {
   my $VideoCmd   = 'tcextract -i vid.fifo -t vob -x mpeg2 > ofile.m2v &';
   my $ChapsCmd   = 'tcprobe -i ' . $DVDRipDev . 
                    ' -T ' . $TitleNum . 
                    ' -H 500 2>&1' .
                    ' | egrep "\[Chapter ..\] "';
   my $VidFifoCmd = 'mkfifo vid.fifo';
   my $TeeList    = 'vid.fifo ';
   my $RmFifoCmd  = 'rm -f *.fifo';

   chdir("$WorkDir");
   LogThis("Changed to working directory [$WorkDir].");

   LogThis("Grabbing chapter list.");

   my @ChapMarks = `$ChapsCmd`;
   for my $Line (@ChapMarks) {
      my @Items = split(/ /, $Line);
      if($Items[3] =~ /..\:..\:..\..../) {
         $Items[3] =~ s/\n$//;
         $ChapList .= $Items[3] . ',';
      }
   }
   $ChapList =~ s/,$//;

   RunThis("$VidFifoCmd");
   RunThis("$VideoCmd");

   my $fifoname;
   foreach(@AudioCH) {
      $fifoname   = 'aud' . $_ . '.fifo';
      $TeeList      .= $fifoname . ' ';
      my $AudFifoCmd = 'mkfifo ' . $fifoname;
      my $AudioCmd   = 'tcextract -i ' . $fifoname . ' -t vob -x ac3 -a ' . 
                       $_ . ' > ofile' . $_ . '.ac3 &';
      RunThis("$AudFifoCmd");
      RunThis("$AudioCmd");
   }#foreach(@AudioCH)

   foreach(@SubCH) {
      $fifoname   = 'sub' . $_ . '.fifo';
      $TeeList      .= $fifoname . ' ';
      my $SubFifoCmd = 'mkfifo ' . $fifoname;
      my $SubCmd     = 'tcextract -i ' . $fifoname . ' -t vob -x ps1 -a ' .
                       $_ . ' > ofile' . $_ . '.ps1 &';
      RunThis("$SubFifoCmd");
      RunThis("$SubCmd");
   }#foreach(@SubCH)

   my $DumpCmd = 'tccat -i ' . $DVDRipDev . ' -T ' . $TitleNum .
                 ',-1 -L | tee ' . $TeeList . ' >/dev/null';

   RunThis("$DumpCmd");
   LogThis("Done with source DVD, please remove it and insert a blank.");
   LogThis("Done extracting, cleaning up.");
   RunThis("$RmFifoCmd");
 
}

sub RequantVideo {
   my $M2VName  = 'ofile.m2v';
   my $OutName  = 'movie.m2v';
   my $SizeSlop = 1.05; 
   my $ret      = 0;

   # Get file sizes
   my $M2VSize  = GetSize("$M2VName");
   my $AudSize;
   my $SubSize;

   foreach(@AudioCH) {
      my $audname = 'ofile' . $_ . '.ac3';
      $AudSize   += GetSize("$audname");
   }#foreach(@AudioCH)

   foreach(@SubCH) {
      my $subname = 'ofile' . $_ . '.ps1';
      $SubSize   += GetSize("$subname");
   }#foreach(@SubCH)

   #Calc Requant number.
   my $StreamSize = $SubSize + $AudSize;
   my $ReqNum     = (($SizeSlop * $M2VSize) / ($MaxISOSize - $StreamSize));
   my $ReqCmd     = 'tcrequant -i ' . $M2VName . 
                    ' -o ' . $OutName .
                    ' -f ' . $ReqNum;
   my $RmCmd      = 'rm -f ofile.m2v';

   if($ReqNum > 1.00) {
      LogThis("Requantizing with $ReqNum");
      RunThis("$ReqCmd");
      LogThis("Done requantizing.");
      if($Options{D}) {
         LogThis("Cleaning up.");
         RunThis("$RmCmd");
      }
      $ret=1;
   } 
   else {
      LogThis("Requantization not necessary, Continuing.");
      $ret=0;
   }
   return $ret;
}

sub MultiplexData {
   my $MplexCmd;
   my $RmOM2VCmd = 'rm -f ofile.m2v';
   my $RmMM2VCmd = 'rm -f movie.m2v';
   my $AudList;
   my $SubList;

   my $filename;
   foreach(@AudioCH) {
      $filename = 'ofile' . $_ . '.ac3 ';
      $AudList    .= $filename;
   }#foreach(@AudioCH)

   foreach(@SubCH) {
      $filename = 'ofile' . $_ . '.ps1 ';
      $SubList    .= $filename;
   }#foreach(@SubCH)

   my $RmAAC3Cmd   = 'rm -f ' . $AudList;
   my $RmAPS1Cmd   = 'rm -f ' . $SubList;   

   if(RequantVideo()) {
      LogThis("Multiplexing requantized video with audio.");
      $MplexCmd = 'mplex -f 8 -S 0 -o movie.mpeg movie.m2v ' . 
                  $AudList . $SubList;
   }
   else {
      LogThis("Multiplexing original video with audio.");
      $MplexCmd = 'mplex -f 8 -S 0 -o movie.mpeg ofile.m2v ' .
                  $AudList . $SubList;
   }
   RunThis("$MplexCmd");

   if($Options{D}) {
      LogThis("Cleaning up.");
      if(-e 'ofile.m2v') {
         RunThis("$RmOM2VCmd");
      }
      if(-e 'movie.m2v') {
         RunThis("$RmMM2VCmd");
      }
      RunThis("$RmAAC3Cmd");
      RunThis("$RmAPS1Cmd");
   }#if($Options{D})

}

sub AuthorDVD {
   my $AuthorChapCmd = 'dvdauthor -t -a ac3+en -c ' . $ChapList . 
                       ' -o dvd movie.mpeg';
   my $AuthorTOCCmd  = 'dvdauthor -T -o dvd';
   my $MkDirCmd      = 'mkdir -p ' . $DVDDir;
   my $RmMpegCmd     = 'rm -f movie.mpeg';

   RunThis("$MkDirCmd");
   RunThis("$AuthorChapCmd");
   RunThis("$AuthorTOCCmd");
   if($Options{D}) {
      LogThis("Cleaning up.");
      RunThis("$RmMpegCmd");
   }
}

sub MakeISO {
   my $STATE       = "NO_JOY";
   my $GrowISOCmd  = 'growisofs -speed=' . $BurnSpd . 
                     ' -Z ' . $DVDBrnDev . ' -dvd-video dvd';
   my $DVDReadyCmd = 'tcprobe -i ' . $DVDBrnDev . ' -H 500 2>&1';
   my $RmDirCmd    = 'rm -rf dvd';

   my @Response = `$DVDReadyCmd`;
   for my $line (@Response) {
      if($line =~ /Can't open file VIDEO_TS/) {
         $STATE = "READY";
      }
   }

   if($STATE eq "READY") {
      LogThis("Detected Blank DVD.");
      RunThis("$GrowISOCmd");
      LogThis("Burned the Image to disc.");
      if($Options{D}) {
        LogThis("Cleaning up.");
        RunThis("$RmDirCmd");
     }
   }
   else {
      LogThis("No blank in DVD drive, cannot continue.");
      LogThis("Use \'$GrowISOCmd\' to burn.");
   }
}

sub GetSize {
   my ($Filename) = @_;

   my $SizeCmd = 'du -sb ' . $Filename;

   my $String = `$SizeCmd`;
   my ($Size) = split(/\t/, $String);

   LogThis("$Filename is $Size bytes.");

   return $Size;
}

sub LogThis {
   my ($String) = @_;

   my @Date = localtime(time);
   my $LogStr = sprintf("%04d-%02d-%02d %02d:%02d:%02d LOGGING-> $String\n",
                        $Date[5] + 1900, $Date[4] + 1, $Date[3], 
                        $Date[2], $Date[1], $Date[0]);
   if(-e $LogName) {
      open(CMDLOG, ">>$LogName");
   }
   else {
      open(CMDLOG, ">$LogName");
   }
   print("dvd9to5: $LogStr");
   print(CMDLOG $LogStr);
   close(CMDLOG);
}

sub RunThis {
   my ($Command) = @_;

   my @Date = localtime(time);
   my $LogStr = sprintf("%04d-%02d-%02d %02d:%02d:%02d RUNNING-> $Command\n",
                        $Date[5] + 1900, $Date[4] + 1, $Date[3], 
                        $Date[2], $Date[1], $Date[0]);
   if(-e $LogName) {
      open(CMDLOG, ">>$LogName");
   }
   else {
      open(CMDLOG, ">$LogName");
   }
   print("dvd9to5: $LogStr");
   print(CMDLOG $LogStr);
   system("$Command") == 0
      or die "dvd9to5: system $Command failed: $?";
   if ($? == -1) {
       print "dvd9to5: failed to execute: $!\n";
   }
   elsif ($? & 127) {
       printf "dvd9to5: child died with signal %d, %s coredump\n",
           ($? & 127),  ($? & 128) ? 'with' : 'without';
   }

   close(CMDLOG);
}


LoadValues();
ExtractData();
MultiplexData();
print ("\nDIR AFTER MULTIPLEXING STAGE:\n");
RunThis ("ls -lA /downloads/tmp/");
print ("-----------------------------\n\n");
{
  my $junk = <stdin>;
}
AuthorDVD();
#MakeISO();