File Coverage

blib/lib/FFmpeg/Command.pm
Criterion Covered Total %
statement 24 73 32.8
branch 2 22 9.0
condition 2 14 14.2
subroutine 6 10 60.0
pod 4 4 100.0
total 38 123 30.8


line stmt bran cond sub pod time code
1             package FFmpeg::Command;
2              
3 7     7   12129 use warnings;
  7         12  
  7         235  
4 7     7   35 use strict;
  7         12  
  7         348  
5             our $VERSION = '0.19';
6              
7 7     7   34 use base qw( Class::Accessor::Fast Class::ErrorHandler );
  7         79  
  7         9847  
8             __PACKAGE__->mk_accessors(qw/
9             input_file
10             output_file
11             ffmpeg
12             options
13             global_options
14             infile_options
15             outfile_options
16             timeout
17             stdin
18             stdout
19             stderr
20             command
21             /);
22              
23 7     7   126692 use IPC::Run qw( start );
  7         556589  
  7         535  
24 7     7   72 use Carp qw( carp );
  7         15  
  7         6896  
25              
26             our %option = (
27             format => '-f',
28             video_codec => '-vcodec',
29             bitrate => '-b',
30             frame_rate => '-r',
31             frame_size => '-s',
32             audio_codec => '-acodec',
33             audio_sampling_rate => '-ar',
34             audio_bit_rate => '-ab',
35             size => '-s',
36             );
37              
38             our %metadata = (
39             title => 'title=',
40             author => 'author=',
41             comment => 'comment=',
42             );
43              
44             sub new {
45 7     7 1 307 my $class = shift;
46              
47 7         18 my $command;
48              
49 7   50     69 for my $cmd ( shift || 'ffmpeg', 'avconv' ) {
50 14         103884 system("$cmd -version > /dev/null 2>&1");
51 14         637 my $ret = $? >> 8;
52 14 50 33     1098 if ( $ret == 0 || $ret == 1 ) {
53 0         0 $command = $cmd;
54 0         0 last;
55             }
56             }
57 7 50       250 unless ( $command ) {
58 7         5086 carp "Can't find ffmpeg/avconv command.";
59 7         1816 exit 0;
60             }
61              
62 0           my $self = {
63             ffmpeg => $command,
64             options => [],
65             global_options => [],
66             infile_options => [],
67             outfile_options => [],
68             input_file => [],
69             output_file => '',
70             timeout => 0,
71             };
72              
73 0           bless $self, $class;
74             }
75              
76             sub input_options {
77 0     0 1   my ( $self, $args ) = @_;
78 0   0       $self->input_file($args->{file} || $args->{'files'});
79 0           return;
80             }
81              
82             sub output_options {
83 0     0 1   my ( $self, $args ) = @_;
84 0           $self->output_file(delete $args->{file});
85 0           my $device = delete $args->{device};
86              
87 0           my %device_option = (
88             ipod => {
89             format => 'mp4',
90             video_codec => 'mpeg4',
91             bitrate => 600,
92             frame_size => '320x240',
93             audio_codec => 'libfaac',
94             audio_sampling_rate => 48000,
95             audio_bit_rate => 64,
96             },
97             psp => {
98             format => 'psp',
99             video_codec => 'mpeg4',
100             bitrate => 600,
101             frame_size => '320x240',
102             audio_codec => 'libfaac',
103             audio_sampling_rate => 48000,
104             audio_bit_rate => 64,
105             },
106             );
107              
108 0           my %output_option = (
109             %$args,
110             );
111              
112             # if a device name was supplied, add its output options
113 0 0         if( $device ) {
114 0           %output_option = (
115             %output_option,
116 0           %{ $device_option{$device} },
117             );
118             }
119              
120 0           for ( keys %output_option ){
121 0 0 0       if( defined $option{$_} and defined $output_option{$_} ){
    0 0        
122 0           push @{ $self->outfile_options }, $option{$_}, $output_option{$_};
  0            
123             }
124             elsif( defined $metadata{$_} and defined $output_option{$_} ){
125 0           push @{ $self->outfile_options }, '-metadata', $metadata{$_} . $output_option{$_};
  0            
126             }
127             else {
128 0           carp "$_ is not defined and ignored.";
129             }
130             }
131              
132 0           return;
133             }
134              
135             sub execute {
136 0     0 1   my $self = shift;
137              
138 0 0         my @opts = map { $self->{$_} ? $self->{$_} : \$self->{$_} } qw/stdin stdout stderr/;
  0            
139 0 0         push @opts, IPC::Run::timeout($self->timeout) if $self->timeout;
140              
141 0           my $cmd = $self->_compose_command;
142              
143             # store the command line so we can debug it
144 0           $self->command( join( ' ', @$cmd ) );
145              
146 0           my $h = eval {
147 0           start( $cmd, @opts )
148             };
149              
150 0 0         if( $@ ){
151 0           $self->error($@);
152 0           return;
153             }
154             else {
155 0 0         finish $h or do {
156 0           $self->error($self->stderr);
157 0           return;
158             };
159             }
160              
161 0           return 1;
162             }
163              
164             *exec = \&execute;
165              
166             sub _compose_command {
167 0     0     my $self = shift;
168              
169 0           my $files = $self->input_file;
170 0 0         $files = [ $files ] unless ref $files eq 'ARRAY';
171              
172 0           my $cmd = [
173             $self->ffmpeg,
174             '-y',
175 0           @{ $self->global_options },
176 0           map ( { @{ $self->infile_options }, ( '-i', $_ ) } @$files ),
  0            
177 0           @{ $self->options },
178 0           @{ $self->outfile_options },
179             ];
180              
181             # add output file only if we have one
182 0 0         push @$cmd, $self->output_file
183             if $self->output_file;
184              
185 0           return $cmd;
186             }
187              
188             __END__
189              
190             =head1 NAME
191              
192             FFmpeg::Command - A wrapper class for ffmpeg/avconv command line utility.
193              
194             =head1 DESCRIPTION
195              
196             A simple interface for using ffmpeg command line utility with fallback to use
197             the newer avconv utility if ffmpeg is not installed.
198              
199             =head1 SYNOPSIS
200              
201             use FFmpeg::Command;
202              
203             my $ffmpeg = FFmpeg::Command->new('/usr/local/bin/ffmpeg');
204              
205             # Set timeout
206             $ffmpeg->timeout(300);
207              
208             # ga: global option a, gb: global option b
209             # ia: infile option a, ib: infile option b
210             # oa: outfile option a, ob: outfile option b
211              
212             # ffmpeg -y -ga -gb -ia -ib -i filename1 -oa -ob output_file
213             $ffmpeg->global_options(qw/-ga -gb/);
214             $ffmpeg->infile_options(qw/-ia -ib/);
215             $ffmpeg->outfile_options(qw/-oa -ob/);
216             $ffmpeg->input_file('filename1');
217             $ffmpeg->output_file('output_file');
218              
219             my $result = $ffmpeg->exec();
220             croak $ffmpeg->errstr unless $result;
221              
222             # ffmpeg -y -i filename1 -ga -gb -ia -ib -oa -ob output_file
223             $ffmpeg->options(qw/-ga -gb -ia -ib -oa -ob/);
224             $ffmpeg->input_file('filename1');
225             $ffmpeg->output_file('output_file');
226              
227             $ffmpeg->exec();
228              
229             # ffmpeg -y -ga -gb -ia -ib -i filename1 -ia -ib -i filename2 -oa -ob output_file
230             # Infile options are adopted for every input files
231             $ffmpeg->global_options(qw/-ga -gb/);
232             $ffmpeg->infile_options(qw/-ia -ib/);
233             $ffmpeg->outfile_options(qw/-oa -ob/);
234             $ffmpeg->input_file(['filename1','filename2']);
235             $ffmpeg->output_file('output_file');
236              
237             $ffmpeg->exec()
238              
239             # ffmpeg -y -ga -gb -ia1 -ib1 -i filename1 -ia2 -ib2 -i filename2 -oa -ob output_file
240             # Each input file has different infile options
241             $ffmpeg->options(qw/-ga -gb -ia1 -ib1 -i filename1 -ia2 -ib2 -i filename2 -oa -ob output_file/);
242              
243             $ffmpeg->exec()
244              
245             # This sample code takes a screen shot.
246             $ffmpeg->input_file($input_file);
247             $ffmpeg->output_file($output_file);
248              
249             $ffmpeg->options(
250             '-f' => 'image2',
251             '-pix_fmt' => 'jpg',
252             '-vframes' => 1,
253             '-ss' => 30,
254             '-s' => '320x240',
255             '-an',
256             );
257              
258             $ffmpeg->exec()
259              
260             # Below are old style example(may be obsoleted at future release)
261             $ffmpeg->input_options({
262             file => $input_file,
263             });
264              
265             # Convert a video file into iPod playable format.
266             $ffmpeg->output_options({
267             file => $output_file,
268             device => 'ipod',
269             });
270              
271             # This is same as above.
272             $ffmpeg->output_options({
273             file => $output_file,
274             format => 'mp4',
275             video_codec => 'mpeg4',
276             bitrate => 600,
277             frame_size => '320x240',
278             audio_codec => 'libaac',
279             audio_sampling_rate => 48000,
280             audio_bit_rate => 64,
281             });
282              
283             # Convert a video file into PSP playable format.
284             $ffmpeg->output_options({
285             file => $output_file,
286             device => 'psp',
287             });
288              
289             # This is same as above.
290             $ffmpeg->output_options({
291             file => $output_file,
292             format => 'psp',
293             video_codec => 'mpeg4',
294             bitrate => 600,
295             frame_size => '320x240',
296             audio_codec => 'libaac',
297             audio_sampling_rate => 48000,
298             audio_bit_rate => 64,
299             });
300              
301              
302              
303             =head1 METHODS
304              
305             =head2 new('/usr/bin/ffmpeg')
306              
307             Contructs FFmpeg::Command object.It takes a path of ffmpeg command.
308             You can omit this argument and this module searches ffmpeg command within PATH environment variable.
309              
310             =head2 timeout()
311              
312             Set command timeout.Default is 0.
313              
314             =head2 input_file( @files );
315              
316             Specify names of input file(s).
317              
318             =head2 output_file('/path/to/output_file')
319              
320             Specify output file name.
321              
322             =head2 global_options( @options )
323              
324             Specify ffmpeg global options.
325              
326             =head2 infile_options( @options )
327              
328             Specify ffmpeg infile options.
329              
330             =head2 outfile_options( @options )
331              
332             Specify ffmpeg outfile options.
333              
334              
335             =head2 options( @options )
336              
337             Specify ffmpeg command options directly including input files and and output file.
338              
339             =head2 execute()
340              
341             Executes ffmpeg command with specified options.
342              
343             =head2 exec()
344              
345             An alias of execute()
346              
347             =head2 stdout()
348              
349             Get ffmpeg command output to stdout.
350              
351             =head2 stderr()
352              
353             Get ffmpeg command output to stderr.
354              
355             =head2 input_options({ %options })
356              
357             Specify input file name and input options.(Now no options are available.)
358              
359             =over
360              
361             =item file
362              
363             a file name of input file or an anonymous list of multiple input files
364             (useful for merging audio and video files together).
365              
366             =back
367              
368             =head2 output_options({ %options })
369              
370             Specify output file name and output options.
371              
372             Avaiable options are:
373              
374             =over
375              
376             =item file
377              
378             a file name of output file.
379              
380             =item format
381              
382             Output video format.
383              
384             =item video_codec
385              
386             Output video codec.
387              
388             =item bitrate
389              
390             Output video bitrate.
391              
392             =item frame_size
393              
394             Output video screen size.
395              
396             =item audio_codec
397              
398             Output audio code.
399              
400             =item audio_sampling_rate
401              
402             Output audio sampling rate.
403              
404             =item audio_bit_rate
405              
406             Output audio bit rate.
407              
408             =item title
409              
410             Set the title.
411              
412             =item author
413              
414             Set the author.
415              
416             =item comment
417              
418             Set the comment.
419              
420             =back
421              
422             =head1 AUTHORS
423              
424             Gosuke Miyashita, C<< <gosukenator at gmail.com> >>
425              
426             Munechika Sumikawa, C<< <sumikawa at sumikawa.jp> >>
427              
428             =head1 BUGS
429              
430             Please report any bugs or feature requests to
431             C<bug-ffmpeg-command at rt.cpan.org>, or through the web interface at
432             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=FFmpeg-Command>.
433             I will be notified, and then you'll automatically be notified of progress on
434             your bug as I make changes.
435              
436             =head1 SUPPORT
437              
438             You can find documentation for this module with the perldoc command.
439              
440             perldoc FFmpeg::Command
441              
442             You can also look for information at:
443              
444             =over 4
445              
446             =item * AnnoCPAN: Annotated CPAN documentation
447              
448             L<http://annocpan.org/dist/FFmpeg-Command>
449              
450             =item * CPAN Ratings
451              
452             L<http://cpanratings.perl.org/d/FFmpeg-Command>
453              
454             =item * RT: CPAN's request tracker
455              
456             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=FFmpeg-Command>
457              
458             =item * Search CPAN
459              
460             L<http://search.cpan.org/dist/FFmpeg-Command>
461              
462             =back
463              
464             =head1 ACKNOWLEDGEMENTS
465              
466             =head1 COPYRIGHT & LICENSE
467              
468             Copyright 2006 Gosuke Miyashita, all rights reserved.
469              
470             This program is free software; you can redistribute it and/or modify it
471             under the same terms as Perl itself.
472              
473             =cut