#!/usr/bin/perl use File::Basename; use Getopt::Long my @largeFiles=(); my @files=(); my $largeSize = 2030000000; my $lastLargeFileTime = 0; my $maxSize = 4200; my $file; my $progname; my $pwd; my $vers; my $date; $vers = "1.0"; $date = "Thu Apr 23 2009"; ($progname = $0) =~ s#.*/##; chop($pwd = `pwd`); %options = ( individual => 0, help => 0, version => 0, height => "720", eightGig => 0, ); sub mtime($) { my $file = shift; ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($$file); return $mtime; } &GetOptions( "--individual" => \$options{individual}, "--help" => \$options{help}, "--version" => \$options{version}, "--height" => \$options{height}, "--8gig" => \$options{eightGig}, ); if($options{version}) { print "$progname, version 1.0 -- $date\n"; exit 0 unless $options{help}; } if($options{help}) { print <<"EOF"; Usage: $progname [-i] [-h] [-v] [-h height] [-8] --individual do each file individually. Do not try to be smart about large files. --help print out this help --version print the version of $progname --height xx make the height of the video xx --8gig fit video to 8 GB rather than 4.2GB EOF exit 0; } if($options{individual}) { print STDERR "# encoding each file separately\n"; } if($options{height}) { if($options{height} =~ /^sd$/i || $options{height} =~ /standard/i) { $options{height} = 480; } elsif($options{height} =~ /^hd$/ || $options{height} =~ /\D1080\D/) { $options{height} = 1080; } elsif($options{height} =~ /(\d+)/) { $options{height} = $1; } } if($options{eightGig}) { $maxSize = 7800; } sub catLargeFiles(@) { my @largeFiles = @_; my $name; my $lastfile = $largeFiles[$#largeFiles]; my $firstname; my $firstpath; my $firstsuffix; my $lastname; my $lastpath; my $lastsuffix; if(scalar @largeFiles < 2) { return $largeFiles[0]; } ($firstname,$firstpath,$firstsuffix) = fileparse($largeFiles[0], qw(.MTS .mts .mp4)); ($lastname,$lastpath,$lastsuffix) = fileparse($lastfile, qw(.MTS .mts .mp4)); $lastsuffix =~ tr [A-Z] [a-z]; $name = "$firstname-$lastname$lastsuffix"; if(! -r $name) { print "joining @largeFiles into $name\n"; system("cat \"" . join('" "', @largeFiles) . "\" > $name"); # make sure timestamp is retained system("touch -r \"$lastfile\" \"$name\""); } else { print "Using already-existing $name.\n"; } $name; } foreach $file (@ARGV) { if(! -r $file) { warn "## Cannot read file $file"; warn "## skipping..."; next; } my $size = -s $file; my $soonAfterLastLargeFile = 0; if(mtime($file) - $lastLargeFileTime < 800) { $soonAfterLastLargeFile = 1; } if(!$options{individual} && $size >= $largeSize && $soonAfterLastLargeFile) { # video cameras using FAT32 split large files into roughly 2GB chunks # so we collect those file names and the name of the smaller one right # after them, to be concatenated together before beginning encoding. # This can be fixed if HandBrake adds the ability to encode multiple # source files to one target file. push @largeFiles, $file; $lastLargeFileTime = mtime($file); } else { if(scalar @largeFiles > 0) { # this is the small file after the large ones, so cat them all # together and encode the resulting huge file. Check that if($soonAfterLastLargeFile) { push @largeFiles, $file; } $name = catLargeFiles(@largeFiles); @largeFiles=(); print "# encoding $name\n"; encode($name); if(!$soonAfterLastLargeFile) { # $file wasn't part of the large file, so it must be # encoded seperately encode($file); } } else { # no large files, just encode this one file encode($file); } } } if(scalar @largeFiles > 0) { $name = catLargeFiles(@largeFiles); @largeFiles=(); print "# encoding $name\n"; encode($name); } sub encode($) { my $file = shift @_; my $name; my $path; my $suffix; ($name,$path,$suffix) = fileparse($file,qw(.MTS .mts .mp4)); print "# encoding $file\n"; print "# $path :: $name :: $suffix\n"; # # use --large-file if more than 2 GB # my $size = -s $file; if($size > 2000000000) { $bigFileFlags="--large-file"; if($size > 4000000000) { # make sure it fits onto a DVD! $bigFileFlags .= " --size=${maxSize}"; } } else { $bigFileFlags=""; } # # don't overwrite previous attempts # my $suff=""; my $index=0; my $base=$name; while(-r "$base$suff.mp4") { $index++; $suff="-$index"; } $base .= $suff; # # encode the video! # $start = time(); print scalar localtime(time), " -- starting encoding ${base}.mp4\n"; $cmd = << "EOF"; $ENV{HOME}/bin/Darwin-i386/HandBrakeCLI \\ --cpu=4 \\ --input="${file}" \\ --output "${base}".mp4 \\ $bigFileFlags \\ --two-pass \\ --decomb \\ --denoise \\ --ipod-atom \\ --markers \\ --height=$options{height} \\ --vb 8500 EOF # --vb 5500 # --vb 8500 # --width=853 # --width=1280 # --height=720 print "$cmd\n"; system $cmd; # # preserve the timestamp # system("touch -r \"$file\" \"$base.mp4\""); # free up disk space # unlink(${file}); print scalar localtime(time), " -- finished encoding ${base}.mp4 [", time() - $start, " sec]\n\n\n"; } __END__ ## # ## # make DivX file ## # ## echo "##############################################" ## echo "## making ${base}.avi" ## echo "##############################################" ## date ## ~/bin/Darwin-i386/HandBrakeCLI \ ## --cpu=4 \ ## --input="${file}" \ ## --output "${base}".avi \ ## --size=${maxSize} \ ## --two-pass \ ## --rate=29.97 \ ## --width=1280 \ ## --height=720