root/gs2-extensions/video/trunk/perllib/plugins/VideoConverter.pm @ 22486

Revision 22486, 38.4 KB (checked in by max, 9 years ago)

Increased the default resolution to SD quality,
Added options to enable/disable the deinterlacing filter of Handbrake and the extraction of additional metadata with MediaInfo?.
Ignore some useless metadata extracted from the cache folder
Add some more comments

Line 
1###########################################################################
2#
3# VideoConverter - helper plugin that does video (and audio) conversion using ffmpeg
4#
5# A component of the Greenstone digital library software
6# from the New Zealand Digital Library Project at the
7# University of Waikato, New Zealand.
8#
9# Copyright (C) 2008 New Zealand Digital Library Project
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, write to the Free Software
23# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24#
25###########################################################################
26package VideoConverter;
27
28use MultimediaConverter;
29
30
31use strict;
32no strict 'refs'; # allow filehandles to be variables and viceversa
33
34use gsprintf 'gsprintf';
35
36BEGIN {
37    @VideoConverter::ISA = ('MultimediaConverter');
38}
39
40
41my @thumb_arguments = (       
42      { 'name' => "create_thumbnail",
43    'desc' => "{ImageConverter.create_thumbnail}",
44    'type' => "enum",
45    'list' => [{'name' => "true", 'desc' => "{common.true}"},
46           {'name' => "false", 'desc' => "{common.false}"}],
47    'deft' => "true",
48    'reqd' => "no" },
49          { 'name' => "keep_original_video",
50    'desc' => "Copy the original video file in the collection as an associated file.",
51    'type' => "enum",
52    'list' => [{'name' => "true", 'desc' => "Include the original video file in the collection"},
53           {'name' => "false", 'desc' => "Do not copy the original video file in the collection"}],
54    'deft' => "false",
55    'reqd' => "no" },
56      { 'name' => "thumbnailsize",
57    'desc' => "{ImageConverter.thumbnailsize}",
58    'type' => "int",
59    'deft' => "100",
60    'range' => "1,",
61    'reqd' => "no" },
62      { 'name' => "thumbnailtype",
63    'desc' => "{ImageConverter.thumbnailtype}",
64    'type' => "string",
65    'deft' => "jpg",
66    'reqd' => "no" },
67      { 'name' => "noscaleup",
68    'desc' => "{ImageConverter.noscaleup}",
69    'type' => "flag",
70    'reqd' => "no" } );
71
72
73my @screenview_arguments = (
74      { 'name' => "create_screenview",
75    'desc' => "{ImageConverter.create_screenview}",
76    'type' => "enum",
77    'list' => [{'name' => "true", 'desc' => "{common.true}"},
78           {'name' => "false", 'desc' => "{common.false}"}],
79    'deft' => "true",
80    'reqd' => "no" },
81      { 'name' => "screenviewsize",
82    'desc' => "{ImageConverter.screenviewsize}",
83    'type' => "int",
84    'deft' => "720",
85    'range' => "1,",
86    'reqd' => "no" },
87      { 'name' => "screenviewtype",
88    'desc' => "{ImageConverter.screenviewtype}",
89    'type' => "string",
90    'deft' => "jpg",
91    'reqd' => "no" } );
92
93my $arguments = [
94      @thumb_arguments,
95      @screenview_arguments,
96
97      { 'name' => "converttotype",
98    'desc' => "{ImageConverter.converttotype}",
99    'type' => "string",
100    'deft' => "",
101    'reqd' => "no" },
102
103
104      { 'name' => "converttosize",
105    'desc' => "{VideoPlugin.converttosize}",
106    'type' => "int",
107    'deft' => "",
108##  'deft' => "352",
109    'reqd' => "no" },
110      { 'name' => "converttobitrate",
111    'desc' => "{VideoPlugin.converttobitrate}",
112    'type' => "string",
113    'deft' => "200k",
114    'reqd' => "no" },
115      { 'name' => "extract_keyframes",
116    'desc' => "{VideoPlugin.extractkeyframes}",
117    'type' => "flag",
118    'deft' => "0",
119    'reqd' => "no" },
120      { 'name' => "keep_keyframes",
121    'desc' => "{VideoPlugin.keep_keyframes}",
122    'type' => "string",
123    'deft' => "all",
124    'reqd' => "no" },
125      { 'name' => "streamingsize",
126    'desc' => "{VideoPlugin.streamingsize}",
127    'type' => "int",
128    'deft' => "352",
129    'reqd' => "no" },
130      { 'name' => "streamingbitrate",
131    'desc' => "{VideoPlugin.streamingbitrate}",
132    'type' => "string",
133    'deft' => "200k",
134    'reqd' => "no" },
135    { 'name' => "streamingHQsize",
136    'desc' => "{VideoPlugin.streamingsize}",
137    'type' => "int",
138    'deft' => "720",
139    'reqd' => "no" },
140    { 'name' => "streamingHQVideoBitrate",
141    'desc' => "{VideoPlugin.streamingbitrate}",
142    'type' => "int",
143    'deft' => "496",
144    'reqd' => "no" },
145    { 'name' => "streamingHQAudioBitrate",
146    'desc' => "{VideoPlugin.streamingbitrate}",
147    'type' => "int",
148    'deft' => "80",
149    'reqd' => "no" },
150    { 'name' => "videoDeinterlacingFilter",
151    'desc' => "Activate a deinterlacing filter to increase the quality of TV footage",
152    'type' => "enum",
153    'list' => [{'name' => "true", 'desc' => "{common.true}"},
154           {'name' => "false", 'desc' => "{common.false}"}],
155    'deft' => "false",
156    'reqd' => "no" },
157    { 'name' => "getMaximumMetadata",
158    'desc' => "Extract the maximum technical information of each video",
159    'type' => "enum",
160    'list' => [{'name' => "true", 'desc' => "{common.true}"},
161           {'name' => "false", 'desc' => "{common.false}"}],
162    'deft' => "false",
163    'reqd' => "no" },
164
165      { 'name' => "minimumsize",
166    'desc' => "{ImageConverter.minimumsize}",
167    'type' => "int",
168    'deft' => "100",
169    'range' => "1,",
170    'reqd' => "no" },
171
172         ];
173
174my $options = { 'name' => "VideoConverter",
175        'desc' => "{VideoConverter.desc}",
176        'abstract' => "yes",
177        'inherits' => "yes",
178        'args' => $arguments };
179
180sub new {
181    my ($class) = shift (@_);
182    my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
183    push(@$pluginlist, $class);
184
185    push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
186    push(@{$hashArgOptLists->{"OptList"}},$options);
187
188    my $self = new MultimediaConverter($pluginlist, $inputargs, $hashArgOptLists, 1);
189
190
191    return bless $self, $class;
192
193}
194
195
196
197
198# Discover the characteristics of a video file.
199
200#  Equivalent step to that in ImagePlugin that uses ImageMagicks's
201#  'indentify' utility
202
203#  Here we use 'MediaInfo' for video but for consistency keep the Perl
204#  method name the same as before
205
206sub mediaInfo_Inform_Cmd {
207    my ($video, $parameter, $outhandle, $verbosity) = @_;
208   
209    # Use MediaInfo CLI to get the file spec according to the requested parameter
210    my $command = "mediainfo --Inform=\"$parameter\" \"$video\"";
211
212    print $outhandle "  $command\n" if ($verbosity > 2);
213    my $result = '';
214    $result = `$command 2>&1`;
215    chomp $result;
216    print $outhandle "  $result\n" if ($verbosity > 4);
217   
218    # Return the asked spec
219    return ($result);
220}
221
222# Here we use mediaInfo to get all the possible metadata in XML form that could then be parsed
223#the result will vary depending on the file type and how it was encoded
224sub mediaInfo_XML_Cmd {
225    my ($video, $outhandle, $verbosity) = @_;
226   
227    # Use MediaInfo CLI to get the file spec according to the requested parameter
228    my $command = "mediainfo --Output=XML \"$video\"";
229   
230    print $outhandle "  $command\n" if ($verbosity > 2);
231    my $result = '';
232    $result = `$command 2>&1`;
233    print $outhandle "  $result\n" if ($verbosity > 4);
234   
235    # Return the asked spec
236    return ($result);
237}
238
239#Here we parse the video specs contained in the XML text in order to create a metadata entry for each field
240sub mediaInfo_parse_XML {
241    my ($xmlTxt, $outhandle, $verbosity) = @_;
242   
243    my @parts = split(/<track\s+type=\"(.*?)\">/is,$xmlTxt);
244   
245    shift @parts; # Skip preamble
246    my $metadata_table = {};
247   
248    while (@parts) {
249    my $type = shift(@parts);
250    my $vals = shift(@parts);
251    my @fieldlist=();
252    while ($vals =~ s/<(.*?)>(.*?)<\/\1>//) {
253        my $metaname = $1;
254        my $metaval  = $2;
255        my $fullmetaname = "mi.$type\^$metaname";
256        $metadata_table->{$fullmetaname}= $metaval;
257        push(@fieldlist,$fullmetaname);
258    }
259   
260    $metadata_table->{"mi.${type}Fields"}= join(",",@fieldlist);
261    }
262   
263    return $metadata_table;
264
265    while (@parts) {
266        my $type = shift(@parts);
267        my $vals = shift(@parts);
268        my @fieldlist=();
269        while ($vals =~ s/<(.*?)>(.*?)<\/\1>//) {
270          my $metaname = $1;
271          my $metaval  = $2;
272          my $fullmetaname = "mi.$type\^$metaname";
273          if($metaname ne "Complete_name") #ignore this field as it is pointing to the cache directory
274              {
275              $metadata_table->{$fullmetaname}= $metaval;
276              push(@fieldlist,$fullmetaname);
277              }
278        }
279        $metadata_table->{"mi.${type}Fields"}= join(",",@fieldlist);
280    }
281    return $metadata_table;
282
283}
284
285sub identifyMI {
286    my ($video, $outhandle, $verbosity) = @_;
287
288    # Use the ffmpeg command to get the file specs
289    my $command = "ffmpeg -i \"$video\"";
290
291    print $outhandle "  $command\n" if ($verbosity > 2);
292    my $result = '';
293    $result = `$command 2>&1`;
294    print $outhandle "  $result\n" if ($verbosity > 4);
295
296    # Read the type, width, and height etc.
297    # This could be done in a more efficient way by only calling the application mediainfo once and
298    # giving all the parameters then parsing the results, however on most operating system
299    # once the application is called once it is then cached for subsequent calls.
300    my $vtype =  mediaInfo_Inform_Cmd($video,"General;%Format%",$outhandle,0);
301    my $duration = mediaInfo_Inform_Cmd($video,"General;%Duration%",$outhandle,0);
302    my $durationDisplay = mediaInfo_Inform_Cmd($video,"General;%Duration/String1%",$outhandle,0);
303    my $filesize = mediaInfo_Inform_Cmd($video,"General;%FileSize/String%",$outhandle,0);
304    my $vcodec = mediaInfo_Inform_Cmd($video,"Video;%Format%",$outhandle,0);
305    my $vrate = mediaInfo_Inform_Cmd($video,"Video;%BitRate%",$outhandle,0);
306    my $width =  mediaInfo_Inform_Cmd($video,"Video;%Width%",$outhandle,0);
307    my $height = mediaInfo_Inform_Cmd($video,"Video;%Height%",$outhandle,0);
308    my $fps    = mediaInfo_Inform_Cmd($video,"Video;%FrameRate%",$outhandle,0);
309    my $atype =  mediaInfo_Inform_Cmd($video,"Audio;%Format%",$outhandle,0);
310    my $afreq =  mediaInfo_Inform_Cmd($video,"Audio;%SamplingRate/String%",$outhandle,0);
311    my $achan =  mediaInfo_Inform_Cmd($video,"Audio;%Channel(s)%",$outhandle,0);
312    my $arate =  mediaInfo_Inform_Cmd($video,"Audio;%BitRate%",$outhandle,0);
313
314    my $xmlTxt =  mediaInfo_XML_Cmd ($video,$outhandle,0);
315    my $metadata_table = mediaInfo_parse_XML($xmlTxt,$outhandle,0);
316   
317    # Return the specs
318    return ($vtype,$width,$height,$duration,$durationDisplay,$filesize,
319        $vcodec,$vrate,$fps,$atype,$afreq,$achan,$arate,$metadata_table);
320}
321
322
323sub identify {
324    my ($video, $outhandle, $verbosity) = @_;
325
326    # Use the ffmpeg command to get the file specs
327    my $command = "ffmpeg -i \"$video\"";
328
329    print $outhandle "  $command\n" if ($verbosity > 2);
330    my $result = '';
331    $result = `$command 2>&1`;
332    print $outhandle "  $result\n" if ($verbosity > 4);
333
334    # Read the type, width, and height etc.
335    my $vtype =  'unknown';
336    my $vcodec = 'unknown';
337    my $width =  'unknown';
338    my $height = 'unknown';
339    my $fps    = 'unknown';
340
341    my $atype =  'unknown';
342    my $afreq =  'unknown';
343    my $achan =  'unknown';
344    my $arate =  'unknown';
345
346    my $video_safe = quotemeta $video;
347
348    # strip off everything up to filename
349    $result =~ s/^.*\'$video_safe\'://s;
350
351##    if ($result =~ m/Video: (.*?) fps/m) {
352    if ($result =~ m/^\s+Stream.*?Video: (.*?)$/m) {
353    my $video_info = $1;
354    $video_info =~ s/\s*\[.*?\]//g;
355
356    my @video_fields = split(/,\s*/,$video_info);
357   
358    $vtype = shift @video_fields;
359
360    if ($video_fields[0] !~ m/(\d+)x(\d+)/) {
361        $vcodec = shift @video_fields;
362    }
363    my $video_dim = shift @video_fields;
364
365    ($width,$height) = ($video_dim =~ m/(\d+)x(\d+)/);
366   
367    if ($video_fields[0] =~ m/(\d+)\s+tbr$/) {
368        $fps = $1;
369    }
370
371#   if ($video_info =~ m/([^,]+),(?: ([^,]+),)? (\d+)x(\d+),.*?(\d+\.\d+)/)
372#   {
373#       $vtype = $1;
374#       $vcodec = $2 if defined $2;
375#       $width = $3;
376#       $height = $4;
377#       $fps = $5;
378#   }
379    }
380
381    if ($result =~ m/Audio: (\w+), (\d+) Hz, (\w+)(?:, (\d+.*))?/m) {
382    $atype = $1;
383    $afreq = $2;
384    $achan = $3;
385    $arate = $4 if (defined $4);
386    }
387
388    # Read the duration
389    my $duration = "unknown";
390    if ($result =~ m/Duration: (\d+:\d+:\d+\.\d+)/m) {
391    $duration = $1;
392    }
393    print $outhandle "  file: $video:\t $vtype, $width, $height, $duration\n"
394    if ($verbosity > 2);
395
396    if ($verbosity >3) {
397    print $outhandle "\t video codec=$vcodec, fps = $fps\n";
398    print $outhandle "\t audio codec=$atype, freq = $afreq Hz, $achan, $arate\n";
399    }
400
401    # Return the specs
402    return ($vtype, $width, $height, $duration, -s $video,
403        $vcodec,$fps,$atype,$afreq,$achan,$arate);
404}
405
406
407sub vob_durations
408{
409    my ($media_base_dir,$title_num,$outhandle) = @_;
410
411    my $filter_re = sprintf("^VTS_%02d_[1-9]\\.VOB\$",$title_num);
412
413    my $duration_info = {};
414
415    if (opendir(VTSIN,$media_base_dir)) {
416    my @vts_title_vobs = grep { $_ =~ m/$filter_re/ } readdir(VTSIN);
417    closedir(VTSIN);
418
419    foreach my $v (@vts_title_vobs) {
420        my $full_v = &util::filename_cat($media_base_dir,$v);
421
422        my ($vtype, $width, $height, $duration, $durationDisplay, $vsize,
423        $vcodec,$vrate,$fps,$atype,$afreq,$achan,$arate) = identify($full_v,$outhandle,0);
424
425        my ($vob_num) = ($v =~ m/^VTS_\d\d_(\d)\.VOB$/);
426
427        $duration_info->{$vob_num} = $duration;
428        print STDERR "**** $title_num: $title_num, storing {$vob_num} => $duration\n";
429
430    }
431
432    }
433    else {
434    print $outhandle "Warning: unable to read files in directory $media_base_dir\n";
435    }
436   
437    return $duration_info;
438
439}
440
441
442
443sub init_cache_for_file {
444    my $self = shift(@_);
445
446    my ($video_filename) = @_;
447
448    $self->SUPER::init_cache_for_file($video_filename);
449
450                   
451    my @flvtool2_monitor = ( 'monitor_init'   ,"convertutil::monitor_init_unbuffered",
452                 'monitor_line'   , "VideoConverter::flvtool2_monitor_line",
453                 'monitor_deinit' , "convertutil::monitor_deinit_unbuffered" );
454                   
455    $self->{'flvtool2_monitor'} = \@flvtool2_monitor;
456
457
458}
459
460
461
462sub optional_frame_scale
463{
464    my $self = shift (@_);
465    my ($orig_size,$video_width,$video_height) = @_;
466
467    my $s_opt = "";
468
469    if ($video_width > $video_height) {
470    if ($video_width > $orig_size) {
471        my $scale_factor = $orig_size/$video_width;
472        my $scaled_width = int($video_width * $scale_factor);
473        my $scaled_height = int($video_height * $scale_factor);
474
475        # round to be ensure multiple of 2 (needed by some codecs)
476        $scaled_width  = int($scaled_width/2)*2;
477        $scaled_height = int($scaled_height/2)*2;
478
479        $s_opt = "-s ${scaled_width}x${scaled_height}";
480    }
481    # else, video is smaller than requested size, don't scale up
482    }
483    else {
484    if ($video_height > $orig_size) {
485        my $scale_factor = $orig_size/$video_height;
486        my $scaled_width = int($video_width * $scale_factor);
487        my $scaled_height = int($video_height * $scale_factor);
488
489        # round to be ensure multiple of 2 (needed by some codecs)
490        $scaled_width  = int($scaled_width/2)*2;
491        $scaled_height = int($scaled_height/2)*2;
492
493        $s_opt = "-s ${scaled_width}x${scaled_height}";
494    }
495    # else, video is smaller than requested size, don't scale up
496   
497    }
498   
499    return $s_opt;
500}
501
502
503sub keyframe_cmd
504{
505    my $self = shift (@_);
506    my ($ivideo_filename) = @_;
507
508    my $video_ext_dir = &util::filename_cat($ENV{'GSDLHOME'},"ext","video");
509
510    my $output_dir = $self->{'cached_dir'};
511    my $ivideo_root = $self->{'cached_file_root'};
512
513    my $oshot_filename = &util::filename_cat($output_dir,"shots.xml");
514
515    my $exp_duration = $self->{'exp_duration'};
516    my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";
517
518    my $main_opts = "-y $t_opt";
519
520    my $hive = &util::filename_cat($video_ext_dir,"lib","vhook","hive.so");
521
522    my $oflash_filename = &util::filename_cat($output_dir,"$ivideo_root\_keyframe.flv");
523
524    my $vhook_opts = "$hive  -o $oshot_filename -k $output_dir $ivideo_filename";
525
526    my $ivideo_filename_gsdlenv = $self->gsdlhome_independent($ivideo_filename);
527    my $oflash_filename_gsdlenv = $self->gsdlhome_independent($oflash_filename);
528
529    my $ffmpeg_cmd = "ffkeyframe  $main_opts -vhook \"$vhook_opts\"   -i \"$ivideo_filename_gsdlenv\" -an -y \"$oflash_filename_gsdlenv\"";
530
531
532    return ($ffmpeg_cmd,$oflash_filename);
533}
534
535sub get_ovideo_file
536{
537    my $self = shift (@_);
538    my ($stream_type) = @_;
539   
540    my $ivideo_root = $self->{'cached_file_root'};
541    my $ofile;
542   
543    if ($stream_type eq "flv")
544    {
545        $ofile = "${ivideo_root}_vstream.flv";
546    }
547    else
548    {
549        $ofile = "${ivideo_root}_vHQstream.mp4";
550    }
551   
552    return $ofile;
553}
554
555sub get_ovideo_filename
556{
557    my $self = shift (@_);
558    my ($stream_type) = @_;
559   
560    my $output_dir = $self->{'cached_dir'};
561
562    my $ofile = $self->get_ovideo_file($stream_type);
563       
564    my $ofilename = &util::filename_cat($output_dir,$ofile);
565   
566    return $ofilename;
567}
568
569# Generate the command to use with Handbrake to recompress a video using h264/aac compatible with Flash Player 10
570sub stream_mp4_video_cmd
571{
572    my $self = shift (@_);
573    my ($ivideo_filename,$streaming_HQ_size, $streaming_HQ_VideoBitrate,
574     $streaming_HQ_AudioBitrate) = @_;
575
576    my $output_dir = $self->{'cached_dir'};
577    my $ivideo_root = $self->{'cached_file_root'};
578
579    my $omp4_file = "${ivideo_root}_vHQstream.mp4";
580    my $omp4_filename = &util::filename_cat($output_dir,$omp4_file);
581
582
583    #my $exp_duration = $self->{'exp_duration'};
584    #my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";
585
586    my $deinterlace = $self->{'videoDeinterlacingFilter'};
587    my $video_processing_parameters;   
588    # Use specific resizing algorythms depending if we need to downsize the video resolution or not
589    if(!$streaming_HQ_size || $streaming_HQ_size eq "fullsize") {
590        $video_processing_parameters = "--strict-anamorphic";
591    } else {
592        $video_processing_parameters = "-w $streaming_HQ_size --loose-anamorphic";
593    }
594    # Use the deinterlace video filter if enabled in the plugin
595    if ($deinterlace eq "true")
596    {
597        $video_processing_parameters .= " --decomb";
598    }
599
600    my $ivideo_filename_gsdlenv = $self->gsdlhome_independent($ivideo_filename);
601    my $omp4_filename_gsdlenv = $self->gsdlhome_independent($omp4_filename);
602   
603    # Generate the pre and post video parameters for Handbrake v0.9.4
604    my $pre_opts = "-t 1 -c 1";
605    my $post_opts = "-f mp4 -O $video_processing_parameters -e x264 -b $streaming_HQ_VideoBitrate -a 1 -E faac -6 dpl2 -R Auto -B $streaming_HQ_AudioBitrate -D 0.0 -x ref=2:bframes=2:subq=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0";
606
607    my $handbrake_cmd = "HandbrakeCLI.exe -i \"$ivideo_filename_gsdlenv\" $pre_opts -o \"$omp4_filename_gsdlenv\" $post_opts";
608
609    #print STDERR "****\nHandbrake command: $handbrake_cmd\n****\n";
610   
611    return ($handbrake_cmd,$omp4_filename,$omp4_file);
612}
613
614
615
616sub stream_flv_video_cmd
617{
618    my $self = shift (@_);
619    my ($ivideo_filename,$video_width,$video_height,
620    $streaming_quality,
621    $streaming_bitrate,$streaming_size,
622    $opt_streaming_achan, $opt_streaming_arate) = @_;
623
624    my $streaming_achan
625    = (defined $opt_streaming_achan) ? $opt_streaming_achan : 2;
626
627    my $streaming_arate
628    = (defined $opt_streaming_arate) ? $opt_streaming_arate : 22050;
629
630    my $output_dir = $self->{'cached_dir'};
631    my $ivideo_root = $self->{'cached_file_root'};
632
633    my $oflash_file = "${ivideo_root}_vstream.flv";
634    my $oflash_filename = &util::filename_cat($output_dir,$oflash_file);
635
636    my $s_opt = "";
637    my $media_type = $self->{'media_type'};
638    if ($media_type ne "audio") {
639    $s_opt = $self->optional_frame_scale($streaming_size,$video_width,$video_height);
640    }
641
642
643    my $exp_duration = $self->{'exp_duration'};
644    my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";
645
646    my $main_opts = "-y $t_opt";
647
648    my $bitrate_opt = "-b $streaming_bitrate";
649    ### my $stream_opts = "-r 25 $s_opt";
650    my $stream_opts .= " $s_opt -ac $streaming_achan -ar $streaming_arate";
651
652    # -flags +ilme+ildct' and maybe '-flags +alt' for interlaced material, and try '-top 0/1'
653
654    my $all_opts = "$main_opts $stream_opts";
655
656    my $ffmpeg_cmd;
657
658    my $ivideo_filename_gsdlenv = $self->gsdlhome_independent($ivideo_filename);
659    my $oflash_filename_gsdlenv = $self->gsdlhome_independent($oflash_filename);
660
661    if ($streaming_quality eq "high") {
662
663    my $pass_log_file = &util::filename_cat($output_dir,"$ivideo_root-logpass.txt");
664    if (-e $pass_log_file) {
665        &util::rm($pass_log_file);
666    }
667
668    my $pass_log_file_gsdlenv = $self->gsdlhome_independent($pass_log_file);
669
670    $all_opts .= " -passlogfile \"$pass_log_file_gsdlenv\"";
671
672    my $ffmpeg_cmd_pass1 = "ffmpeg -pass 1 -i \"$ivideo_filename_gsdlenv\" $all_opts -y \"$oflash_filename_gsdlenv\"";
673
674    my $ffmpeg_cmd_pass2 = "ffmpeg -pass 2 -i \"$ivideo_filename_gsdlenv\" $all_opts $bitrate_opt -y \"$oflash_filename_gsdlenv\"";
675    $ffmpeg_cmd = "( $ffmpeg_cmd_pass1 && $ffmpeg_cmd_pass2 )";
676    }
677    else {
678    # single pass
679
680    $ffmpeg_cmd = "ffmpeg -i \"$ivideo_filename_gsdlenv\" $all_opts -y \"$oflash_filename_gsdlenv\"";
681    }
682
683    return ($ffmpeg_cmd,$oflash_filename,$oflash_file);
684}
685
686
687
688
689sub stream_flv_audio_cmd
690{
691    # AudioConverter also has a routine for doing this
692    # => merge into one!
693    # **************
694
695    my $self = shift (@_);
696    my ($ivideo_filename, $opt_streaming_achan, $opt_streaming_arate) = @_;
697
698    # Convert either audio or video to streamable audio format
699
700    my $streaming_achan
701    = (defined $opt_streaming_achan) ? $opt_streaming_achan : 2;
702
703    my $streaming_arate
704    = (defined $opt_streaming_arate) ? $opt_streaming_arate : 22050;
705
706    my $output_dir = $self->{'cached_dir'};
707    my $ivideo_root = $self->{'cached_file_root'};
708
709    my $ofla_file = "${ivideo_root}_astream.flv";
710    my $ofla_filename = &util::filename_cat($output_dir,$ofla_file);
711
712    my $exp_duration = $self->{'exp_duration'};
713    my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";
714
715    my $main_opts = "-vn -y $t_opt";
716
717    my $stream_opts .= " -ac $streaming_achan -ar $streaming_arate";
718
719    my $all_opts = "$main_opts $stream_opts";
720
721    my $ffmpeg_cmd;
722
723    my $ivideo_filename_gsdlenv = $self->gsdlhome_independent($ivideo_filename);
724    my $ofla_filename_gsdlenv = $self->gsdlhome_independent($ofla_filename);
725    $ffmpeg_cmd = "ffmpeg -i \"$ivideo_filename_gsdlenv\" $all_opts -y \"$ofla_filename_gsdlenv\"";
726
727    return ($ffmpeg_cmd,$ofla_filename,$ofla_file);
728}
729
730
731
732
733sub audio_excerpt_cmd
734{
735    my $self = shift (@_);
736    my ($ivoa_filename,$hh,$mm,$ss,$opt_excerpt_len) = @_;
737
738    # ivoa = input video or audio
739
740    my $time_encoded = "$hh:$mm:$ss";
741    my $time_encoded_file = "$hh$mm$ss";
742   
743   
744    my $output_dir = $self->{'cached_dir'};
745    my $ivoa_root = $self->{'cached_file_root'};
746
747    my $omp3_file = "${ivoa_root}_$time_encoded_file.mp3";
748    my $omp3_filename = &util::filename_cat($output_dir,$omp3_file);
749
750    my $all_opts = "-y -acodec mp3 -ss $time_encoded ";
751
752    if (defined $opt_excerpt_len) {
753    $all_opts .= "-t $opt_excerpt_len ";
754    }
755
756
757    my $ivoa_filename_gsdlenv = $self->gsdlhome_independent($ivoa_filename);
758    my $omp3_filename_gsdlenv = $self->gsdlhome_independent($omp3_filename);
759
760
761    my $ffmpeg_cmd = "ffmpeg -i \"$ivoa_filename_gsdlenv\" $all_opts  \"$omp3_filename_gsdlenv\"";
762
763    return ($ffmpeg_cmd,$omp3_filename,$omp3_file);
764}
765
766
767
768sub streamseekable_cmd
769{
770    my $self = shift (@_);
771    my ($oflash_filename) = @_;
772
773    my $output_dir = $self->{'cached_dir'};
774    my $ivideo_root = $self->{'cached_file_root'};
775
776    ## my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");
777
778    my $flvtool_cmd = "flvtool2 -vUP \"$oflash_filename\"";
779
780    return ($flvtool_cmd,$oflash_filename);
781}
782
783
784sub streamkeyframes_cmd
785{
786    my $self = shift (@_);
787    my ($oflash_filename,$doc_obj,$section) = @_;
788
789    my $assocfilepath
790    = $doc_obj->get_metadata_element($section,"assocfilepath");
791
792    my $output_dir = $self->{'cached_dir'};
793
794    my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");
795 
796    my $flvtool_cmd = "flvtool2 -vAUtP \"$cue_filename\"  \"$oflash_filename\"";
797
798    return ($flvtool_cmd,$oflash_filename);
799}
800
801
802sub streamkeyframes_cmd_old
803{
804    my $self = shift (@_);
805    my ($oflash_filename,$doc_obj,$section) = @_;
806
807    my $assocfilepath
808    = $doc_obj->get_metadata_element($section,"assocfilepath");
809
810    my $output_dir = $self->{'cached_dir'};
811
812    my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");
813
814    my $video_server = $ENV{'GEXT_VIDEO_SERVER'};
815    my $video_prefix = $ENV{'GEXT_VIDEO_PREFIX'};
816
817    my $collect = $ENV{'GSDLCOLLECTION'};
818 
819    print STDERR "**** Warning: need to remove dependency of GEXT_VIDEO_SERVER and _PREFIX\n";
820
821    my $flvtool_cmd = "flvtool2 -vAUtP \"$cue_filename\" -thumbLocation:$video_server$video_prefix/collect/$collect/index/assoc/$assocfilepath \"$oflash_filename\"";
822
823
824    return ($flvtool_cmd,$oflash_filename);
825}
826
827
828sub streamcuepts_cmd
829{
830    my $self = shift (@_);
831    my ($oflash_filename) = @_;
832
833    my $output_dir = $self->{'cached_dir'};
834
835    my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");
836
837    ##my $video_server = $ENV{'GEXT_VIDEO_SERVER'};
838    ##my $video_prefix = $ENV{'GEXT_VIDEO_PREFIX'};
839
840    ## my $collect = $ENV{'GSDLCOLLECTION'};
841
842    ## my $thumbloc = "$video_server$video_prefix/collect/$collect";
843
844
845#    my $flvtool_cmd = "flvtool2 -vUAtP \"$cue_filename\" -thumbLocation:$thumbloc \"$oflash_filename\"";
846
847#    my $flvtool_cmd = "flvtool2 -vUAt \"$cue_filename\" \"$oflash_filename\"";
848
849
850
851#    my $flvtool_cmd = "flvtool2 -vUAt \"$cue_filename\" \"$oflash_filename\"";
852
853
854##    my $flvtool_cmd = "flvtool2 -vAt \"$cue_filename\" -UP \"$oflash_filename\" \"$output_dir/updated.flv\"";
855
856##    my $flvtool_cmd = "flvtool2 -vAtU \"$cue_filename\" \"$oflash_filename\" \"$output_dir/updated.flv\"";
857
858    my $flvtool_cmd = "flvtool2 -vAtUP \"$cue_filename\" \"$oflash_filename\"";
859
860    return ($flvtool_cmd,$oflash_filename);
861}
862
863
864sub keyframe_thumbnail_cmd
865{
866    my $self = shift (@_);
867    my ($ivideo_filename,$thumbnailfile,$thumbnailwidth,$thumbnailheight) = @_;
868
869    my $output_dir = $self->{'cached_dir'};
870    my $ivideo_root = $self->{'cached_file_root'};
871
872    my $key_filename_prefix = &util::filename_cat($output_dir,$ivideo_root);
873
874
875    # Try for 4th keyframe, but fall back to 1st if doesn't exist
876    my $key_filename = "${key_filename_prefix}_0003.jpg";
877    $key_filename = "${key_filename_prefix}_0000.jpg" if (!-e $key_filename);
878
879    my $key_filename_gsdlenv = $self->gsdlhome_independent($key_filename);
880    my $thumbnailfile_gsdlenv = $self->gsdlhome_independent($thumbnailfile);
881
882    my $command;
883
884    if (-e $key_filename) {
885    $command = "convert -interlace plane -verbose -geometry $thumbnailwidth"
886        . "x$thumbnailheight \"$key_filename_gsdlenv\" \"$thumbnailfile_gsdlenv\"";
887    }
888    else {
889    # extract_keyframe has either not been switched on, or else had
890    # a problem when running
891    # => extract a from
892    # my $frame_rate = 1.0 / 60.0;
893   
894    my $ivideo_filename_gsdlenv = $self->gsdlhome_independent($ivideo_filename);
895
896    $command = "ffmpeg -i \"$ivideo_filename_gsdlenv\"  -ss 3.5 -vframes 1 -f image2 -s ${thumbnailwidth}x${thumbnailheight} -y \"$thumbnailfile_gsdlenv\"";
897
898    # fmpeg -i input.dv -r 1 -f image2 -s 120x96 images%05d.png
899    }
900
901    return ($command,$thumbnailfile);
902}
903
904
905sub keyframe_montage_cmd
906{
907    my $self = shift (@_);
908    my ($ivideo_filename,$montagefile) = @_;
909
910    my $output_dir = $self->{'cached_dir'};
911    my $ivideo_root = $self->{'cached_file_root'};
912
913    my $key_filename_prefix = &util::filename_cat($output_dir,$ivideo_root);
914
915    my $options = "-tile 10  -geometry 75x62+2+2";
916
917    my $command = "montage $options ${key_filename_prefix}_*.jpg \"$montagefile\"";
918
919    return ($command,$montagefile);
920}
921
922
923
924sub parse_shot_xml
925{
926    my ($self) = shift(@_);
927
928    my $outhandle = $self->{'outhandle'};
929    my $output_dir = $self->{'cached_dir'};
930
931    my $shots_filename = &util::filename_cat($output_dir,"shots.xml");
932
933    eval {
934    $self->{'parser'}->parsefile($shots_filename);
935    };
936   
937    if ($@) {
938    print $outhandle "VideoConverter: skipping $shots_filename as not conformant to Hive shot syntax\n" if ($self->{'verbosity'} > 1);
939    print $outhandle "\n Perl Error:\n $@\n" if ($self->{'verbosity'}>2);
940    return 0;
941    }
942
943}
944
945sub associate_keyframes_old
946{
947    my ($self) = shift(@_);
948
949    my ($doc_obj,$section) = @_;
950
951    my $output_dir = $self->{'cached_dir'};
952
953    my $count = 1;
954    foreach my $kframe_file (@{$self->{'keyframe_fnames'}}) {
955
956    my $kframe_filename = &util::filename_cat($output_dir,$kframe_file);
957    $doc_obj->associate_file($kframe_filename,"keyframe$count.jpg","image/jpeg",
958                 $section);
959    $count++;
960    }
961
962    $doc_obj->add_utf8_metadata($section,"NumKeyframes",scalar(@{$self->{'keyframe_fnames'}}));
963
964
965    # *****
966    # $doc_obj->add_metadata ($section, "thumblist", $self->{'flowplayer_thumblist'});
967
968}
969
970sub associate_keyframes
971{
972    my ($self) = shift(@_);
973
974    my ($doc_obj,$topsection,$timeline) = @_;
975
976    my $output_dir = $self->{'cached_dir'};
977   
978    my $count = 1;
979
980    foreach my $t (sort { $timeline->{$a}->{'keyframeindex'} <=> $timeline->{$b}->{'keyframeindex'} } keys %$timeline)
981    {
982    my $kframe_file = $timeline->{$t}->{'thumb'};
983    my $timestamp = $timeline->{$t}->{'timestamp'};
984
985    # create next sub-section to video "document"
986    my $endchild = $doc_obj->insert_section($doc_obj->get_end_child($topsection));
987    $doc_obj->add_utf8_metadata($endchild,"Title","Timestamp $timestamp");
988    $doc_obj->add_utf8_metadata($endchild,"FrameNum",$t);
989
990    my $kframe_filename = &util::filename_cat($output_dir,$kframe_file);
991    $doc_obj->associate_file($kframe_filename,"keyframe$count.jpg",
992                 "image/jpeg",
993                 $endchild);
994
995    $doc_obj->add_utf8_metadata($endchild,"assockeyframe","keyframe$count.jpg");
996
997    $doc_obj->add_utf8_metadata($topsection,"KeyframeTimestamp",$timestamp);
998    $doc_obj->add_utf8_metadata($topsection,"KeyframeFrameNum",$t);
999
1000
1001
1002    $count++;
1003    }
1004
1005    #### $doc_obj->add_utf8_metadata($topsection,"NumKeyframes",scalar(@{$self->{'keyframe_fnames'}}));
1006
1007    $doc_obj->add_utf8_metadata($topsection,"NumKeyframes",scalar(keys %$timeline));
1008
1009
1010    # *****
1011    # $doc_obj->add_metadata ($topsection, "thumblist", $self->{'flowplayer_thumblist'});
1012}
1013
1014
1015
1016sub enable_audio_streaming
1017{
1018    my $self = shift (@_);
1019    my ($doc_obj,$originalfilename,$filename,$convertto_regenerated) = @_;
1020
1021    my $section = $doc_obj->get_top_section();
1022
1023    my $output_dir   = $self->{'cached_dir'};
1024    my $ivideo_root  = $self->{'cached_file_root'};
1025   
1026    # Generate FLV audio-only format for streaming purposes
1027
1028    my $optionally_run_general_cmd = "run_uncached_general_cmd";
1029    if ($self->{'enable_cache'}) {
1030    $optionally_run_general_cmd
1031        = ($convertto_regenerated) ? "regenerate_general_cmd" : "run_cached_general_cmd";
1032    }
1033
1034   
1035    my $ifilename = $originalfilename || $filename;
1036
1037    my ($stream_cmd,$ofla_filename,$ofla_file)
1038    = $self->stream_flv_audio_cmd($ifilename);
1039   
1040   
1041    my $streamable_options = { @{$self->{'ffmpeg_monitor'}},
1042                   'message_prefix' => "Stream",
1043                   'message' => "Generating streamable audio: $ofla_file" };
1044   
1045
1046    my ($streamable_regenerated,$streamable_result,$streamable_had_error)
1047    = $self->$optionally_run_general_cmd($stream_cmd,
1048                         $ifilename,$ofla_filename,
1049                         $streamable_options);
1050
1051
1052    if (!$streamable_had_error) {
1053    my ($streamseekable_cmd,$ostreamseekable_filename) = $self->streamseekable_cmd($ofla_filename);
1054   
1055    my $streamseekable_options = { @{$self->{'flvtool2_monitor'}},
1056                       'message_prefix' => "Stream Seekable",
1057                       'message' => "Reprocessing audio stream to be seekable by timeline: $ofla_file" };
1058   
1059    if ($streamable_regenerated) {
1060        $self->run_general_cmd($streamseekable_cmd,$streamseekable_options);
1061    }
1062   
1063    my $streamable_url = $ofla_file;
1064    my $streamable_url_safe = $self->url_safe($streamable_url);
1065
1066    $doc_obj->add_utf8_metadata ($section, "streamableaudio", $streamable_url_safe);
1067    $doc_obj->associate_file($ofla_filename,$ofla_file,"audio/flash",
1068                 $section);
1069    }
1070
1071    $doc_obj->add_metadata ($section, "audioflashwidth",    400);
1072    $doc_obj->add_metadata ($section, "audioflashheight",   22 + 100);
1073
1074    $self->{'ofla_file'} = $ofla_file;
1075    $self->{'ofla_filename'} = $ofla_filename;
1076
1077    return $streamable_regenerated;
1078}
1079
1080
1081
1082
1083
1084sub enable_video_streaming
1085{
1086    my $self = shift (@_);
1087    my ($doc_obj,$originalfilename,$filename,$convertto_regenerated,
1088    $video_width,$video_height) = @_;
1089
1090    my $section = $doc_obj->get_top_section();
1091
1092    my $output_dir   = $self->{'cached_dir'};
1093    my $ivideo_root  = $self->{'cached_file_root'};
1094   
1095    # Generate the Flash FLV format for streaming purposes
1096
1097    my $optionally_run_general_cmd = "run_uncached_general_cmd";
1098    if ($self->{'enable_cache'}) {
1099    $optionally_run_general_cmd
1100        = ($convertto_regenerated) ? "regenerate_general_cmd" : "run_cached_general_cmd";
1101    }
1102
1103
1104    my $streaming_bitrate = $self->{'streamingbitrate'};
1105    my $streaming_size    = $self->{'streamingsize'};
1106   
1107    my $streaming_quality = "high";
1108   
1109    my $ifilename = $originalfilename || $filename;
1110
1111    my ($stream_cmd,$oflash_filename,$oflash_file)
1112    = $self->stream_flv_video_cmd($ifilename,
1113                     $video_width,$video_height,
1114                     $streaming_quality,
1115                     $streaming_bitrate, $streaming_size);
1116   
1117   
1118    my $streamable_options = { @{$self->{'ffmpeg_monitor'}},
1119                   'message_prefix' => "Stream",
1120                   'message' => "Generating streamable video: $oflash_file" };
1121   
1122
1123    my ($streamable_regenerated,$streamable_result,$streamable_had_error)
1124    = $self->$optionally_run_general_cmd($stream_cmd,
1125                         $ifilename,$oflash_filename,
1126                         $streamable_options);
1127   
1128    if (!$streamable_had_error) {
1129    my ($streamseekable_cmd,$ostreamseekable_filename) = $self->streamseekable_cmd($oflash_filename);
1130   
1131    my $streamseekable_options = { @{$self->{'flvtool2_monitor'}},
1132                       'message_prefix' => "Stream Seekable",
1133                       'message' => "Reprocessing video stream to be seekable by timeline: $oflash_file" };
1134   
1135    if ($streamable_regenerated) {
1136        $self->run_general_cmd($streamseekable_cmd,$streamseekable_options);
1137    }
1138   
1139    my $streamable_url = $oflash_file;
1140    my $streamable_url_safe = $self->url_safe($streamable_url);
1141   
1142    $doc_obj->add_utf8_metadata ($section, "streamablevideo", $streamable_url_safe);
1143    $doc_obj->associate_file($oflash_filename,$oflash_file,"video/flash",
1144                 $section);
1145    }
1146
1147
1148    #
1149    # FlowPlayer.swf       height+22 pixels
1150    # FlowPlayerBlack.swf  height+16 pixels
1151    # FlowPlayerThermo.swf height+16 pixels
1152    # FlowPlayerWhite.swf  height+26 pixels
1153
1154    my $flashwidth = $video_width;
1155    my $flashheight = $video_height + 22;
1156
1157    if ($self->{'extract_keyframes'}) {
1158    $flashheight += 100;
1159    }
1160
1161    $doc_obj->add_metadata ($section, "flashwidth",    $flashwidth);
1162    $doc_obj->add_metadata ($section, "flashheight",   $flashheight);
1163     
1164    $self->{'oflash_file'} = $oflash_file;
1165    $self->{'oflash_filename'} = $oflash_filename;
1166
1167    return $streamable_regenerated;
1168}
1169
1170sub enable_h264_streaming
1171{
1172    my $self = shift (@_);
1173    my ($doc_obj,$originalfilename,$filename,$convertto_regenerated,
1174    $video_width,$video_height) = @_;
1175   
1176
1177    my $section = $doc_obj->get_top_section();
1178
1179    my $output_dir   = $self->{'cached_dir'};
1180    my $ivideo_root  = $self->{'cached_file_root'};
1181   
1182    # Generate the H264 video file format for streaming purposes using the cache feature if used
1183
1184    my $optionally_run_general_cmd = "run_uncached_general_cmd";
1185    if ($self->{'enable_cache'}) {
1186    $optionally_run_general_cmd
1187        = ($convertto_regenerated) ? "regenerate_general_cmd" : "run_cached_general_cmd";
1188    }
1189
1190    my $streaming_HQ_size    = $self->{'streamingHQsize'};
1191    my $streaming_HQ_VideoBitrate    = $self->{'streamingHQVideoBitrate'};
1192    my $streaming_HQ_AudioBitrate    = $self->{'streamingHQAudioBitrate'};
1193
1194    my $ifilename = $originalfilename || $filename;
1195    my ($stream_cmd,$oflash_filename,$oflash_file)
1196    = $self->stream_mp4_video_cmd($ifilename,
1197                     $streaming_HQ_size,
1198                     $streaming_HQ_VideoBitrate,
1199                     $streaming_HQ_AudioBitrate);
1200   
1201   
1202    my $streamable_options = { @{$self->{'handbrake_monitor'}},
1203                   'message_prefix' => "MP4 Stream",
1204                   'message' => "Generating streamable MP4 video: $oflash_file" };
1205   
1206
1207    my ($streamable_regenerated,$streamable_result,$streamable_had_error)
1208    = $self->$optionally_run_general_cmd($stream_cmd,
1209                         $ifilename,$oflash_filename,
1210                         $streamable_options);
1211   
1212    if (!$streamable_had_error) {
1213
1214   
1215    my $streamable_url = $oflash_file;
1216    my $streamable_url_safe = $self->url_safe($streamable_url);
1217   
1218    my $outhandle = $self->{'outhandle'};
1219
1220    my ($vtype, $width, $height, $duration, $durationDisplay, $vsize,
1221        $vcodec,$vrate,$fps,$atype,$afreq,$achan,$arate,$metadata_table) = identifyMI($oflash_filename,$outhandle,0);
1222    #Add the most common metadata extracted by MediaInfo from the streamable video file
1223    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingVideoFormat", $vtype);
1224    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingVideoFileSize", $vsize);
1225    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingWidth", $width);
1226    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingHeight", $height);
1227    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingDuration", $durationDisplay);
1228    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingFPS", $fps);
1229    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingVideoCodec", $vcodec);
1230    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingVideoBitrate", $vrate);
1231    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingAudioCodec", $atype);
1232    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingAudioBitrate", $arate);
1233    $doc_obj->add_utf8_metadata ($section, "tv.HQStreamingFileBitrate", $vrate + $arate);
1234   
1235    my $get_max_metadata = $self->{'getMaximumMetadata'};
1236    if ($get_max_metadata eq "true"){
1237        foreach my $metaname(keys %$metadata_table)
1238        {
1239            my $metaval = $metadata_table->{$metaname};
1240            $doc_obj->add_utf8_metadata ($section, $metaname, $metaval);
1241        }
1242    }
1243   
1244    #add the metadata for the resulting file that should be open inside the flash video player
1245    $doc_obj->add_utf8_metadata ($section, "streamablevideo", $streamable_url_safe);
1246    $doc_obj->associate_file($oflash_filename,$oflash_file,"video/mp4",
1247                 $section);
1248    }
1249
1250
1251
1252
1253    my $flashwidth = $video_width;
1254    my $flashheight = $video_height + 22;
1255
1256    if ($self->{'extract_keyframes'}) {
1257    $flashheight += 100;
1258    }
1259
1260    $doc_obj->add_metadata ($section, "flashwidth",    $flashwidth);
1261    $doc_obj->add_metadata ($section, "flashheight",   $flashheight);
1262     
1263    $self->{'oflash_file'} = $oflash_file;
1264    $self->{'oflash_filename'} = $oflash_filename;
1265
1266    return $streamable_regenerated;
1267   
1268   
1269}
1270
1271sub enable_full_streaming
1272{
1273    my $self = shift (@_);
1274    my ($doc_obj,$originalfilename,$filename,$convertto_regenerated,
1275    $video_width,$video_height) = @_;
1276
1277    my $video_streamable_regenerated
1278    = $self->enable_video_streaming($doc_obj,$originalfilename,$filename,
1279                    $convertto_regenerated,
1280                    $video_width,$video_height);
1281
1282    my $audio_streamable_regenerated
1283    = $self->enable_audio_streaming($doc_obj,$originalfilename,$filename,
1284                    $convertto_regenerated);
1285
1286    return ($video_streamable_regenerated || $audio_streamable_regenerated);
1287}
1288
1289
1290
1291sub flvtool2_monitor_line
1292{
1293    my ($line) = @_;
1294
1295    my $had_error = 0;
1296    my $generate_dot = 1;
1297
1298    if ($line =~ m/\s+\- /) {
1299    # ignore tabulated output printed at end of command
1300    $generate_dot = 0;
1301    }
1302   
1303    if ($line =~ m/^Error:/i) {
1304    $had_error = 1;
1305    }
1306
1307    return ($had_error,$generate_dot);
1308}
1309
1310
1311
1312
1313
13141;
Note: See TracBrowser for help on using the browser.