--- /dev/null
+#! /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 <don@donarmstrong.com>.
+# $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:
+ --debug, -d debugging level (Default 0)
+ --help, -h display this help
+ --man, -m display manual
+
+=head1 OPTIONS
+
+=over
+
+=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,
+ );
+
+GetOptions(\%options,
+ 'titles|title|t=i@',
+ '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 /dev/dvd -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::Dumper;
+
+my @titles;
+for my $title_bit ($result =~ /\n(\+ title \d+:.+?)(?=\n\+ title\s+|$)/gs) {
+ my %title;
+ # title number
+ $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 {$a * 60 + $b } split /:/, $duration;
+ $title{duration} = $duration;
+ # figure out audio tracks
+ $title_bit =~ /(?<leadspace>\s+)\+\s+audio\s+tracks:\n # audio track header
+ (?<audiotracks>(?:\g{leadspace}\s+\+\s+\d+\,.+\n){1,}) # audio track information
+ /x;
+ my $at_info = $+{audiotracks};
+ my @at_nums = $at_info =~ /^\s+\+\s+(\d+)\,/mg;
+ $title{audio_tracks} = [@at_nums];
+ # figure out subtitle tracks
+ $title_bit =~ /(?<leadspace>\s+)\+\s+subtitle\s+tracks:\n # subtitle track header
+ (?<subtittracks>(?:\g{leadspace}\s+\+\s+\d+\,.+(?:\n|$)){1,}) # subtitle track information
+ /x;
+ my $st_info = $+{subtittracks};
+ my @st_nums = $st_info =~ /^\s+\+\s+(\d+)\,/mg;
+ $title{subtitle_tracks} = [@st_nums];
+ push @titles,\%title;
+}
+
+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;
+ }
+}
+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;
+
+for my $i (@titles_to_rip) {
+ system('HandBrakeCLI','-i','/dev/dvd','-t',$i,
+ '-o',$filename.($multiple_titles ? '_'.$i : '').".mkv",
+ '-e','x264','-2','-q','21',
+ '-a',join(',',@{$titles[$i-1]{audio_tracks}}),
+ '-s',join(',',@{$titles[$i-1]{subtitle_tracks}}),
+ );
+}
+
+
+
+
+
+__END__