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();