#! /usr/bin/perl # rip_movie uses HandBrakeCLI to rip movies, and is released # under the terms of the GPL version 2, or any later version, at your # option. See the file README and COPYING for more information. # Copyright 2011 by Don Armstrong . # $Id: perl_script 1432 2009-04-21 02:42:41Z don $ use warnings; use strict; use Getopt::Long; use Pod::Usage; =head1 NAME rip_movie - Rips Movies using HandBrakeCLI =head1 SYNOPSIS rip_movie Options: --device Device to rip from (default /dev/dvd) --output Output filename --min-duration Minimum duration in minutes for episode --titles Optional titles to rip; overrides title autodetection --debug, -d debugging level (Default 0) --help, -h display this help --man, -m display manual =head1 OPTIONS =over =item B<--device> Device to rip from (default /dev/dvd) =item B<--output> Override the output filename =item B<--min-duration> Minimum duration in minutes for a track to be considered an episode (Default 25 minutes) =item B<--titles> Optional titles to rip; overrides title autodetection =item B<--debug, -d> Debug verbosity. (Default 0) =item B<--help, -h> Display brief usage information. =item B<--man, -m> Display this manual. =back =head1 EXAMPLES rip_movie =cut use List::Util qw(reduce); use vars qw($DEBUG); my %options = (debug => 0, help => 0, man => 0, min_duration => 25, device => '/dev/dvd', ); GetOptions(\%options, 'titles|title|t=i@', 'device|D=s', 'min_duration|min-duration=i', 'debug|d+','help|h|?','man|m'); pod2usage() if $options{help}; pod2usage({verbose=>2}) if $options{man}; $DEBUG = $options{debug}; my @titles_to_rip; my @USAGE_ERRORS; if (exists $options{min_duration}) { $options{min_duration}*=60; } if (exists $options{titles}) { for my $title (@{$options{titles}}) { if ($title < 1) { push @USAGE_ERRORS,"Title '$title' is not a valid title; must be greater than zero."; } push @titles_to_rip,$title; } } pod2usage(join("\n",@USAGE_ERRORS)) if @USAGE_ERRORS; my $result = qx(HandBrakeCLI -i $options{device} -t 0 -o /dev/null 2>&1); #print STDERR $result; my ($title) = $result =~ /^libdvdnav:\s+DVD\s+Title:\s+(.+)/im; die "no title" if not defined $title; my $filename = lc($title); $filename =~ s/[\s_-]+/_/; use Data::Printer; my @titles; for my $title_bit ($result =~ /\n(\+ title \d+:.+?)(?=\n\+ title\s+|$)/gs) { my %title; # title number # $title{bit} = $title_bit; $title_bit =~ /^\+ title (\d+):/; $title{num} = $1; my ($duration) = $title_bit =~ /^\s+\+\s+duration:\s+([\d:]+)$/m; # HH:MM:SS, so (HH*60 + MM) * 60 + SS $duration = reduce {defined $a and defined $b ? $a * 60 + $b : undef } split /:/, $duration; $title{duration} = $duration; # figure out audio tracks # use re qw(debug); $title_bit =~ /(?\ +)\+\ +audio\ +tracks:\s*\n # audio track header (?(?:\g{leadspace}\ +\+\ +\d+\,.+\n){0,}) # audio track information /x; my $at_info = $+{audiotracks}; # $title{at_info} = $at_info; my @at_nums = $at_info =~ /^\s+\+\s+(\d+)\,/mg if defined $at_info; $title{audio_tracks} = [@at_nums]; # figure out subtitle tracks $title_bit =~ /(?\ +)\+\ +subtitle\ +tracks:\s*\n # subtitle track header (?(?:\g{leadspace}\ +\+\ +\d+\,.+(?:\n|$)){0,}) # subtitle track information /x; my $st_info = $+{subtittracks}; # $title{st_info} = $st_info; my @st_nums = $st_info =~ /^\s+\+\s+(\d+)\,/mg if defined $st_info; $title{subtitle_tracks} = [@st_nums]; $title{pos_num} = @titles; push @titles,\%title; } # p @titles; #print STDERR Dumper(\@titles); if (not @titles_to_rip) { my $longest_title; for my $i (0..$#titles) { my $title = $titles[$i]; if (not defined $longest_title or $title->{duration} > $titles[$longest_title]{duration}) { $longest_title = $i; } if ($title->{duration} >= $options{min_duration}) { push @titles_to_rip,$i+1; } } if (not @titles_to_rip) { push @titles_to_rip,$longest_title+1; } } # p @titles_to_rip; my $invalid_titles = 0; for my $i (@titles_to_rip) { if ($i > @titles or $i < 1) { print STDERR "Invalid title $i\n"; $invalid_titles = 1; } } exit 1 if $invalid_titles; my $multiple_titles = @titles_to_rip > 1; #print STDERR Dumper(\@titles_to_rip,[@titles[map {$_} @titles_to_rip]]); #exit; p @titles_to_rip; p @titles; for my $i (@titles_to_rip) { system('HandBrakeCLI','-i',$options{device},'-t',$titles[$i-1]{num}, '-o',$filename.($multiple_titles ? '_'.$titles[$i-1]{num} : '').".mkv", '-e','x264','-2','-q','21', '-a',join(',',@{$titles[$i-1]{audio_tracks}}), '-s',join(',',@{$titles[$i-1]{subtitle_tracks}}), ); } __END__