#!/usr/bin/perl use warnings; use strict; use Data::Dumper; use Gearman::Client; use Getopt::Long; use Log::Handler; use Pod::Usage; use Storable qw/freeze thaw/; # Handle interrupts, and term signals $SIG{'INT'} = 'INT_handler'; $SIG{'TERM'} = 'TERM_handler'; # Globals our %options = ( verbose => 0, quiet => 0, log_file => '/tmp/handbrake-cluster-client.log', silent => 0, help => 0, pretend => 0, job_servers => ['build0.sihnon.net', 'build1.sihnon.net', 'build2.sihnon.net'], ); our %rip_options = ( nice => 15, input_filename => '/dev/sr0', output_filename => 'rip-output.mkv', title => -1, format => 'mkv', video_codec => 'x264', video_width => 720, # DVD resolution video_height => 576, # DVD resolution quantizer => 0.61,# x264 quantizer = 20 deinterlace => 0, # 0 = off, 1 = on, 2 = selective audio_tracks => 1, audio_codec => 'ac3', audio_names => 'English', subtitle_tracks => 1, ); Getopt::Long::Configure( qw(bundling no_getopt_compat) ); GetOptions( 'verbose|v+' => \$options{verbose}, 'debug|d' => \$options{debug}, 'quiet|q' => \$options{quiet}, 'silent|s' => \$options{silent}, 'log|l=s' => \$options{log_file}, 'help|h' => \$options{help}, 'pretend|n' => \$options{pretend}, 'job-servers|j=s@' => \$options{job_servers}, 'nice|N=i' => \$rip_options{nice}, 'input|i=s' => \$rip_options{input_filename}, 'output|o=s' => \$rip_options{output_filename}, 'title|t=s' => \$rip_options{title}, 'format|f=s' => \$rip_options{format}, 'video-encoder|e=s' => \$rip_options{video_codec}, 'width|w=i' => \$rip_options{video_width}, 'height|l=i' => \$rip_options{video_height}, 'quantizer|Q=f' => \$rip_options{quantizer}, 'deinterlate|D=i' => \$rip_options{deinterlace}, 'audio-tracks|a=s' => \$rip_options{audio_tracks}, 'audio-encoder|E=s' => \$rip_options{audio_codec}, 'audio-name|A=s' => \$rip_options{audio_names}, 'subtitle-tracks|S=s' => \$rip_options{subtitle_tracks}, ) or pod2usage(-verbose => 0); pod2usage(-verbose => 1) if ($options{help}); # Setup logging my $log = Log::Handler->new(); my $maxLogLevel = ($options{debug} ? 'debug' : ($options{quiet} ? 3 : $options{verbose} + 4)); # default to logging warning+, unless quiet in which case log error+, or debug in which case log everything my $maxFileLogLevel = ($options{debug} ? 'debug' : 'info'); if ( ! $options{silent}) { $log->add( screen => { log_to => 'STDOUT', minlevel => 'emergency', maxlevel => $maxLogLevel, }, ); } if ( $options{log_file}) { $log->add( file => { filename => $options{log_file}, minlevel => 'emergency', maxlevel => $maxFileLogLevel, }, ); } # Setup the distribution client my $client = Gearman::Client->new; $client->job_servers($options{job_servers}); # Add new ripping task my $taskset = $client->new_task_set; $taskset->add_task("rip", freeze(\%rip_options), { on_complete => \&on_complete_handler, on_fail => \&on_fail_handler, } ); $taskset->wait; sub on_complete_handler { my $result_ref = shift or die; $log->notice("Completed rip to $$result_ref"); } sub on_fail_handler { $log->error("Rip failed"); } sub INT_handler { $log->error("Caught interrupt, exiting."); exit 0; } sub TERM_handler { $log->error("Caught SIGTERM, exiting."); exit 0; } __END__; =head1 NAME handbrake-cluster-client - Sets up DVD ripping tasks to be distributed =head1 SYNOPSIS handbrake-cluster-client.pl -h handbrake-cluster-client.pl [-v [-d]|-q|-s] [-l logfile] [-n] =head1 DESCRIPTION Sets up one or more DVD ripping tasks, and hands them off to gearman for distribution. Logging and ripping configuration can be controlled with command line arguments. =head1 OPTIONS =cut