]> git.donarmstrong.com Git - bin.git/blob - rip_movie
add --device support
[bin.git] / rip_movie
1 #! /usr/bin/perl
2 # rip_movie uses HandBrakeCLI to rip movies, and is released
3 # under the terms of the GPL version 2, or any later version, at your
4 # option. See the file README and COPYING for more information.
5 # Copyright 2011 by Don Armstrong <don@donarmstrong.com>.
6 # $Id: perl_script 1432 2009-04-21 02:42:41Z don $
7
8
9 use warnings;
10 use strict;
11
12 use Getopt::Long;
13 use Pod::Usage;
14
15 =head1 NAME
16
17 rip_movie - Rips Movies using HandBrakeCLI
18
19 =head1 SYNOPSIS
20
21  rip_movie
22
23  Options:
24   --debug, -d debugging level (Default 0)
25   --help, -h display this help
26   --man, -m display manual
27
28 =head1 OPTIONS
29
30 =over
31
32 =item B<--device>
33
34 Device to rip from (default /dev/dvd)
35
36 =item B<--output>
37
38 Override the output filename
39
40 =item B<--min-duration>
41
42 Minimum duration in minutes for a track to be considered an episode
43 (Default 25 minutes)
44
45 =item B<--titles>
46
47 Optional titles to rip; overrides title autodetection
48
49 =item B<--debug, -d>
50
51 Debug verbosity. (Default 0)
52
53 =item B<--help, -h>
54
55 Display brief usage information.
56
57 =item B<--man, -m>
58
59 Display this manual.
60
61 =back
62
63 =head1 EXAMPLES
64
65 rip_movie
66
67 =cut
68
69 use List::Util qw(reduce);
70
71 use vars qw($DEBUG);
72
73 my %options = (debug           => 0,
74                help            => 0,
75                man             => 0,
76                min_duration    => 25,
77                device          => '/dev/dvd',
78                );
79
80 GetOptions(\%options,
81            'titles|title|t=i@',
82            'device|D=s',
83            'min_duration|min-duration=i',
84            'debug|d+','help|h|?','man|m');
85
86 pod2usage() if $options{help};
87 pod2usage({verbose=>2}) if $options{man};
88
89 $DEBUG = $options{debug};
90
91 my @titles_to_rip;
92
93 my @USAGE_ERRORS;
94 if (exists $options{min_duration}) {
95     $options{min_duration}*=60;
96 }
97 if (exists $options{titles}) {
98     for my $title (@{$options{titles}}) {
99         if ($title < 1) {
100             push @USAGE_ERRORS,"Title '$title' is not a valid title; must be greater than zero.";
101         }
102         push @titles_to_rip,$title;
103     }
104 }
105
106 pod2usage(join("\n",@USAGE_ERRORS)) if @USAGE_ERRORS;
107
108
109 my $result = qx(HandBrakeCLI -i $options{device} -t 0 -o /dev/null 2>&1);
110
111 #print STDERR $result;
112 my ($title) = $result =~ /^libdvdnav:\s+DVD\s+Title:\s+(.+)/im;
113 die "no title" if not defined $title;
114 my $filename = lc($title);
115 $filename =~ s/[\s_-]+/_/;
116
117 use Data::Dumper;
118
119 my @titles;
120 for my $title_bit ($result =~ /\n(\+ title \d+:.+?)(?=\n\+ title\s+|$)/gs) {
121     my %title;
122     # title number
123 #    $title{bit} = $title_bit;
124     $title_bit =~ /^\+ title (\d+):/;
125     $title{num} = $1;
126     my ($duration) = $title_bit =~ /^\s+\+\s+duration:\s+([\d:]+)$/m;
127     # HH:MM:SS, so (HH*60 + MM) * 60 + SS
128     $duration = reduce {defined $a and defined $b ? $a * 60 + $b : undef } split /:/, $duration;
129     $title{duration} = $duration;
130     # figure out audio tracks
131 #    use re qw(debug);
132     $title_bit =~ /(?<leadspace>\ +)\+\ +audio\ +tracks:\s*\n # audio track header
133                    (?<audiotracks>(?:\g{leadspace}\ +\+\ +\d+\,.+\n){0,}) # audio track information
134                   /x;
135     my $at_info = $+{audiotracks};
136 #    $title{at_info} = $at_info;
137     my @at_nums = $at_info =~ /^\s+\+\s+(\d+)\,/mg if defined $at_info;
138     $title{audio_tracks} = [@at_nums];
139     # figure out subtitle tracks
140     $title_bit =~ /(?<leadspace>\ +)\+\ +subtitle\ +tracks:\s*\n # subtitle track header
141                    (?<subtittracks>(?:\g{leadspace}\ +\+\ +\d+\,.+(?:\n|$)){0,}) # subtitle track information
142                   /x;
143     my $st_info = $+{subtittracks};
144 #    $title{st_info} = $st_info;
145     my @st_nums = $st_info =~ /^\s+\+\s+(\d+)\,/mg if defined $st_info;
146     $title{subtitle_tracks} = [@st_nums];
147     $title{pos_num} = @titles;
148     push @titles,\%title;
149 }
150
151 #print STDERR Dumper(\@titles);
152
153
154 if (not @titles_to_rip) {
155     my $longest_title;
156     for my $i (0..$#titles) {
157         my $title = $titles[$i];
158         if (not defined $longest_title or
159             $title->{duration} > $titles[$longest_title]{duration}) {
160             $longest_title = $i;
161         }
162         if ($title->{duration} >= $options{min_duration}) {
163             push @titles_to_rip,$i;
164         }
165     }
166     if (not @titles_to_rip) {
167         push @titles_to_rip,$longest_title;
168     }
169     print STDERR Dumper({longest_title => $longest_title});
170 }
171 my $invalid_titles = 0;
172 for my $i (@titles_to_rip) {
173     if ($i > @titles or $i < 1) {
174         print STDERR "Invalid title $i\n";
175         $invalid_titles = 1;
176     }
177 }
178 exit 1 if $invalid_titles;
179
180 my $multiple_titles = @titles_to_rip > 1;
181
182 #print STDERR Dumper(\@titles_to_rip,[@titles[map {$_} @titles_to_rip]]);
183 #exit;
184
185 for my $i (@titles_to_rip) {
186     system('HandBrakeCLI','-i',$options{device},'-t',$titles[$i]{num},
187            '-o',$filename.($multiple_titles ? '_'.$titles[$i]{num} : '').".mkv",
188            '-e','x264','-2','-q','21',
189            '-a',join(',',@{$titles[$i-1]{audio_tracks}}),
190            '-s',join(',',@{$titles[$i-1]{subtitle_tracks}}),
191           );
192 }
193
194
195
196
197
198 __END__