- Timestamp:
- 2009-02-20T11:40:23+13:00 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/gsdl-video/trunk/perllib/plugins/MultimediaConverter.pm
r18543 r18556 1 ########################################################################## 2 # 3 # videoconvert.pm -- utility to help convert video file 4 # 5 # Copyright (C) 1999 DigiLib Systems Limited, NZ 1 ########################################################################### 2 # 3 # MultimediaConverter - helper plugin that does audio and video 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 6 10 # 7 11 # This program is free software; you can redistribute it and/or modify … … 20 24 # 21 25 ########################################################################### 22 23 24 package videoconvert; 26 package MultimediaConverter; 27 28 use BaseMediaConverter; 29 25 30 26 31 use strict; 27 32 no strict 'refs'; # allow filehandles to be variables and viceversa 28 33 29 use baseconvert; 30 31 sub BEGIN { 32 @videoconvert::ISA = ('baseconvert'); 33 } 34 35 36 # Discover the characteristics of a video file. 37 # Equivalent step to that in ImagePlugin that uses ImageMagicks's 'indentify' utility 38 # Here we use 'ffmpeg' for video but for consistency keep the Perl method name the same 39 # as before 34 use gsprintf 'gsprintf'; 35 36 BEGIN { 37 @MultimediaConverter::ISA = ('BaseMediaConverter'); 38 } 39 40 my $arguments = [ 41 { 'name' => "converttotype", 42 'desc' => "{ImageConverter.converttotype}", 43 'type' => "string", 44 'deft' => "", 45 'reqd' => "no" }, 46 { 'name' => "minimumsize", 47 'desc' => "{ImageConverter.minimumsize}", 48 'type' => "int", 49 'deft' => "100", 50 'range' => "1,", 51 'reqd' => "no" }, 52 ]; 53 54 my $options = { 'name' => "MultimediaConverter", 55 'desc' => "{MultimediaConverter.desc}", 56 'abstract' => "yes", 57 'inherits' => "yes", 58 'args' => $arguments }; 59 60 sub new { 61 my ($class) = shift (@_); 62 my ($pluginlist,$inputargs,$hashArgOptLists) = @_; 63 push(@$pluginlist, $class); 64 65 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments}); 66 push(@{$hashArgOptLists->{"OptList"}},$options); 67 68 my $self = new BaseMediaConverter($pluginlist, $inputargs, $hashArgOptLists, 1); 69 70 71 return bless $self, $class; 72 73 } 74 75 76 77 # needs to be called after BasePlugin init, so that outhandle is set up. 78 sub init { 79 my $self = shift(@_); 80 81 my $outhandle = $self->{'outhandle'}; 82 83 $self->{'tmp_file_paths'} = (); 84 85 # Check that ffmpeg is installed and available on the path 86 my $multimedia_conversion_available = 1; 87 my $no_multimedia_conversion_reason = ""; 88 89 # None of this works very well on Windows 95/98... 90 if ($ENV{'GSDLOS'} eq "windows" && !Win32::IsWinNT()) { 91 $multimedia_conversion_available = 0; 92 $no_multimedia_conversion_reason = "win95notsupported"; 93 } else { 94 95 my $result = `ffmpeg -h 2>&1`; 96 97 98 if (!defined $result || $result !~ m/^FFmpeg version/) { 99 $self->{'ffmpeg_installed'} = 0; 100 print $outhandle $result; 101 $multimedia_conversion_available = 0; 102 $no_multimedia_conversion_reason = "ffmpegnotinstalled"; 103 } 104 else { 105 $self->{'ffmpeg_installed'} = 1; 106 } 107 } 108 109 $self->{'multimedia_conversion_available'} = $multimedia_conversion_available; 110 $self->{'no_multimedia_conversion_reason'} = $no_multimedia_conversion_reason; 111 112 if ($self->{'multimedia_conversion_available'} == 0) { 113 &gsprintf($outhandle, "MultimediaConverter: {MultimediaConverter.noconversionavailable} ({MultimediaConverter.".$self->{'no_multimedia_conversion_reason'}."})\n"); 114 } 115 116 } 117 118 40 119 41 120 42 121 sub identify { 43 my ($video, $outhandle, $verbosity) = @_; 44 45 # Use the ffmpeg command to get the file specs 46 my $command = "ffmpeg -i \"$video\""; 47 48 print $outhandle " $command\n" if ($verbosity > 2); 49 my $result = ''; 50 $result = `$command 2>&1`; 51 print $outhandle " $result\n" if ($verbosity > 4); 52 53 # Read the type, width, and height etc. 54 my $vtype = 'unknown'; 55 my $vcodec = 'unknown'; 56 my $width = 'unknown'; 57 my $height = 'unknown'; 58 my $fps = 'unknown'; 59 60 my $atype = 'unknown'; 61 my $afreq = 'unknown'; 62 my $achan = 'unknown'; 63 my $arate = 'unknown'; 64 65 my $video_safe = quotemeta $video; 66 67 # strip off everything up to filename 68 $result =~ s/^.*\'$video_safe\'://s; 69 70 if ($result =~ m/Video: (.*?) fps/m) { 71 my $video_info = $1; 72 if ($video_info =~ m/([^,]+),(?: ([^,]+),)? (\d+)x(\d+),.*?(\d+\.\d+)/) 73 { 74 $vtype = $1; 75 $vcodec = $2 if defined $2; 76 $width = $3; 77 $height = $4; 78 $fps = $5; 79 } 80 } 81 82 ## if ($result =~ m/Video: (\w+), (\w+), (\d+)x(\d+),.*?(\d+\.\d+) fps/m) { 83 # if ($result =~ m/Video: ([^,]+),(?: ([^,]+),)? (\d+)x(\d+),.*?(\d+\.\d+) fps/m) { 84 # $vtype = $1; 85 # $vcodec = $2; 86 # $width = $3; 87 # $height = $4; 88 # $fps = $5; 89 # } 90 91 if ($result =~ m/Audio: (\w+), (\d+) Hz, (\w+)(?:, (\d+.*))?/m) { 92 $atype = $1; 93 $afreq = $2; 94 $achan = $3; 95 $arate = $4 if (defined $4); 96 } 97 98 # Read the duration 99 my $duration = "unknown"; 100 if ($result =~ m/Duration: (\d+:\d+:\d+\.\d+)/m) { 101 $duration = $1; 102 } 103 print $outhandle " file: $video:\t $vtype, $width, $height, $duration\n" 104 if ($verbosity > 2); 105 106 if ($verbosity >3) { 107 print $outhandle "\t video codec=$vcodec, fps = $fps\n"; 108 print $outhandle "\t audio codec=$atype, freq = $afreq Hz, $achan, $arate\n"; 109 } 110 111 # Return the specs 112 return ($vtype, $width, $height, $duration, -s $video, 113 $vcodec,$fps,$atype,$afreq,$achan,$arate); 114 } 115 116 117 sub vob_durations 118 { 119 my ($media_base_dir,$title_num,$outhandle) = @_; 120 121 my $filter_re = sprintf("^VTS_%02d_[1-9]\\.VOB\$",$title_num); 122 123 my $duration_info = {}; 124 125 if (opendir(VTSIN,$media_base_dir)) { 126 my @vts_title_vobs = grep { $_ =~ m/$filter_re/ } readdir(VTSIN); 127 closedir(VTSIN); 128 129 foreach my $v (@vts_title_vobs) { 130 my $full_v = &util::filename_cat($media_base_dir,$v); 131 132 my ($vtype, $width, $height, $duration, $vsize, 133 $vcodec,$fps,$atype,$afreq,$achan,$arate) = identify($full_v,$outhandle,0); 134 135 my ($vob_num) = ($v =~ m/^VTS_\d\d_(\d)\.VOB$/); 136 137 $duration_info->{$vob_num} = $duration; 138 print STDERR "**** $title_num: $title_num, storing {$vob_num} => $duration\n"; 139 140 } 141 142 } 143 else { 144 print $outhandle "Warning: unable to read files in directory $media_base_dir\n"; 145 } 146 147 return $duration_info; 148 149 } 150 151 152 153 sub new { 154 my ($class) = shift @_; 155 156 my ($base_dir,$video_filename, $verbosity,$outhandle, 157 $exp_duration,$ascii_only_filenames) = @_; 158 159 my $self = new baseconvert($base_dir,$video_filename,$verbosity,$outhandle); 160 161 $self->{'exp_duration'} = $exp_duration; 122 my ($filename, $outhandle, $verbosity) = @_; 123 124 die "MultimediaConvert::identify() needs to be defined by inheriting plugin"; 125 } 126 127 128 129 sub init_cache_for_file { 130 my $self = shift(@_); 131 132 my ($media_filename) = @_; 133 134 $self->SUPER::init_cache_for_file($media_filename); 135 136 137 # This should probably be replaced with Anu's work that replaced 138 # non-ASCII chars with URL encodings 139 140 my $ascii_only_filenames = $self->{'use_ascii_only_filenams'}; 162 141 163 142 if (defined $ascii_only_filenames && ($ascii_only_filenames)) { 164 my $file_root = $self->{' file_root'};165 $self->{' file_root'} = ascii_only_filename($file_root);143 my $file_root = $self->{'cached_file_root'}; 144 $self->{'cached_file_root'} = ascii_only_filename($file_root); 166 145 } 167 146 168 my @ffmpeg_monitor = ( 'monitor_init' , " videoconvert::ffmpeg_monitor_init",169 'monitor_line' , " videoconvert::ffmpeg_monitor_line",170 'monitor_deinit' , " videoconvert::ffmpeg_monitor_deinit" );147 my @ffmpeg_monitor = ( 'monitor_init' , "MultimediaConverter::ffmpeg_monitor_init", 148 'monitor_line' , "MultimediaConverter::ffmpeg_monitor_line", 149 'monitor_deinit' , "MultimediaConverter::ffmpeg_monitor_deinit" ); 171 150 172 my @flvtool2_monitor = ( 'monitor_init' ,"monitor_init_unbuffered",173 'monitor_line' , "videoconvert::flvtool2_monitor_line",174 'monitor_deinit' , "monitor_deinit_unbuffered" );175 151 176 152 $self->{'ffmpeg_monitor'} = \@ffmpeg_monitor; 177 $self->{'flvtool2_monitor'} = \@flvtool2_monitor; 178 179 180 return bless $self, $class; 181 } 153 154 155 } 156 157 182 158 183 159 … … 216 192 217 193 my $url = $file_unicode; 218 $url =~ s/\x{2018}|\x{2019}|\x{201C}|\x{201D}//g; # remove smart quotes as cause problem in URL for videoserver219 $url =~ s/\x{2013}/\-/g; # change en-dash to '-' as again causes problems for videoserver194 $url =~ s/\x{2018}|\x{2019}|\x{201C}|\x{201D}//g; # remove smart quotes as cause problem in URL for streaming web server 195 $url =~ s/\x{2013}/\-/g; # change en-dash to '-' as again causes problems for streaming web server 220 196 221 197 return $url; … … 255 231 256 232 257 258 sub optional_frame_scale259 {260 my $self = shift (@_);261 my ($orig_size,$video_width,$video_height) = @_;262 263 my $s_opt = "";264 if ($video_width > $video_height) {265 if ($video_width > $orig_size) {266 my $scale_factor = $orig_size/$video_width;267 my $scaled_width = int($video_width * $scale_factor);268 my $scaled_height = int($video_height * $scale_factor);269 270 # round to be ensure multiple of 2 (needed by some codecs)271 $scaled_width = int($scaled_width/2)*2;272 $scaled_height = int($scaled_height/2)*2;273 274 $s_opt = "-s ${scaled_width}x${scaled_height}";275 }276 # else, video is smaller than requested size, don't scale up277 }278 else {279 if ($video_height > $orig_size) {280 my $scale_factor = $orig_size/$video_height;281 my $scaled_width = int($video_width * $scale_factor);282 my $scaled_height = int($video_height * $scale_factor);283 284 # round to be ensure multiple of 2 (needed by some codecs)285 $scaled_width = int($scaled_width/2)*2;286 $scaled_height = int($scaled_height/2)*2;287 288 $s_opt = "-s ${scaled_width}x${scaled_height}";289 }290 # else, video is smaller than requested size, don't scale up291 292 }293 294 return $s_opt;295 }296 297 298 sub keyframe_cmd299 {300 my $self = shift (@_);301 my ($ivideo_filename) = @_;302 303 my $video_ext_dir = &util::filename_cat($ENV{'GSDLHOME'},"ext","video");304 305 my $output_dir = $self->{'cached_dir'};306 my $ivideo_root = $self->{'file_root'};307 308 my $oshot_filename = &util::filename_cat($output_dir,"shots.xml");309 310 my $exp_duration = $self->{'exp_duration'};311 my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";312 313 my $main_opts = "-y $t_opt";314 315 my $hive = &util::filename_cat($video_ext_dir,"lib","vhook","hive.so");316 317 my $oflash_filename = &util::filename_cat($output_dir,"$ivideo_root\_keyframe.flv");318 319 my $vhook_opts = "$hive -o $oshot_filename -k $output_dir $ivideo_filename";320 321 my $ivideo_filename_gsdlenv = $self->gsdlhome_independent($ivideo_filename);322 my $oflash_filename_gsdlenv = $self->gsdlhome_independent($oflash_filename);323 324 my $ffmpeg_cmd = "ffkeyframe $main_opts -vhook \"$vhook_opts\" -i \"$ivideo_filename_gsdlenv\" -an -y \"$oflash_filename_gsdlenv\"";325 326 327 return ($ffmpeg_cmd,$oflash_filename);328 }329 330 331 sub stream_cmd332 {333 my $self = shift (@_);334 my ($ivideo_filename,$video_width,$video_height,335 $streaming_quality,336 $streaming_bitrate,$streaming_size,337 $opt_streaming_achan, $opt_streaming_arate) = @_;338 339 my $streaming_achan340 = (defined $opt_streaming_achan) ? $opt_streaming_achan : 2;341 342 my $streaming_arate343 = (defined $opt_streaming_arate) ? $opt_streaming_arate : 22050;344 345 my $output_dir = $self->{'cached_dir'};346 my $ivideo_root = $self->{'file_root'};347 348 my $oflash_file = "${ivideo_root}_stream.flv";349 my $oflash_filename = &util::filename_cat($output_dir,$oflash_file);350 351 my $s_opt = $self->optional_frame_scale($streaming_size,$video_width,$video_height);352 353 my $exp_duration = $self->{'exp_duration'};354 my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";355 356 my $main_opts = "-y $t_opt";357 358 my $bitrate_opt = "-b $streaming_bitrate";359 ### my $stream_opts = "-r 25 $s_opt";360 my $stream_opts .= " $s_opt -ac $streaming_achan -ar $streaming_arate";361 362 # -flags +ilme+ildct' and maybe '-flags +alt' for interlaced material, and try '-top 0/1'363 364 my $all_opts = "$main_opts $stream_opts";365 366 my $ffmpeg_cmd;367 368 my $ivideo_filename_gsdlenv = $self->gsdlhome_independent($ivideo_filename);369 my $oflash_filename_gsdlenv = $self->gsdlhome_independent($oflash_filename);370 371 if ($streaming_quality eq "high") {372 373 my $pass_log_file = &util::filename_cat($output_dir,"$ivideo_root-logpass.txt");374 if (-e $pass_log_file) {375 &util::rm($pass_log_file);376 }377 378 my $pass_log_file_gsdlenv = $self->gsdlhome_independent($pass_log_file);379 380 $all_opts .= " -passlogfile \"$pass_log_file_gsdlenv\"";381 382 my $ffmpeg_cmd_pass1 = "ffmpeg -pass 1 -i \"$ivideo_filename_gsdlenv\" $all_opts -y \"$oflash_filename_gsdlenv\"";383 384 my $ffmpeg_cmd_pass2 = "ffmpeg -pass 2 -i \"$ivideo_filename_gsdlenv\" $all_opts $bitrate_opt -y \"$oflash_filename_gsdlenv\"";385 $ffmpeg_cmd = "( $ffmpeg_cmd_pass1 ; $ffmpeg_cmd_pass2 )";386 }387 else {388 # single pass389 390 $ffmpeg_cmd = "ffmpeg -i \"$ivideo_filename_gsdlenv\" $all_opts -y \"$oflash_filename_gsdlenv\"";391 }392 393 return ($ffmpeg_cmd,$oflash_filename,$oflash_file);394 }395 396 397 398 sub audio_excerpt_cmd399 {400 my $self = shift (@_);401 my ($ivoa_filename,$hh,$mm,$ss,$opt_excerpt_len) = @_;402 403 # ivoa = input video or audio404 405 my $time_encoded = "$hh:$mm:$ss";406 my $time_encoded_file = "$hh$mm$ss";407 408 409 my $output_dir = $self->{'cached_dir'};410 my $ivoa_root = $self->{'file_root'};411 412 my $omp3_file = "${ivoa_root}_$time_encoded_file.mp3";413 my $omp3_filename = &util::filename_cat($output_dir,$omp3_file);414 415 my $all_opts = "-y -acodec mp3 -ss $time_encoded ";416 417 if (defined $opt_excerpt_len) {418 $all_opts .= "-t $opt_excerpt_len ";419 }420 421 422 my $ivoa_filename_gsdlenv = $self->gsdlhome_independent($ivoa_filename);423 my $omp3_filename_gsdlenv = $self->gsdlhome_independent($omp3_filename);424 425 426 my $ffmpeg_cmd = "ffmpeg -i \"$ivoa_filename_gsdlenv\" $all_opts \"$omp3_filename_gsdlenv\"";427 428 return ($ffmpeg_cmd,$omp3_filename,$omp3_file);429 }430 431 432 433 sub streamseekable_cmd434 {435 my $self = shift (@_);436 my ($oflash_filename) = @_;437 438 my $output_dir = $self->{'cached_dir'};439 my $ivideo_root = $self->{'file_root'};440 441 my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");442 443 my $flvtool_cmd = "flvtool2 -vUP \"$oflash_filename\"";444 445 return ($flvtool_cmd,$oflash_filename);446 }447 448 449 sub streamkeyframes_cmd450 {451 my $self = shift (@_);452 my ($oflash_filename,$doc_obj,$section) = @_;453 454 my $assocfilepath455 = $doc_obj->get_metadata_element($section,"assocfilepath");456 457 my $output_dir = $self->{'cached_dir'};458 459 my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");460 461 my $video_server = $ENV{'GEXT_VIDEO_SERVER'};462 my $video_prefix = $ENV{'GEXT_VIDEO_PREFIX'};463 464 my $collect = $ENV{'GSDLCOLLECTION'};465 466 my $flvtool_cmd = "flvtool2 -vAUtP \"$cue_filename\" -thumbLocation:$video_server$video_prefix/collect/$collect/index/assoc/$assocfilepath \"$oflash_filename\"";467 468 469 return ($flvtool_cmd,$oflash_filename);470 }471 472 473 sub streamcuepts_cmd474 {475 my $self = shift (@_);476 my ($oflash_filename) = @_;477 478 my $output_dir = $self->{'cached_dir'};479 480 my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");481 482 my $video_server = $ENV{'GEXT_VIDEO_SERVER'};483 my $video_prefix = $ENV{'GEXT_VIDEO_PREFIX'};484 485 my $collect = $ENV{'GSDLCOLLECTION'};486 my $thumbloc = "$video_server$video_prefix/collect/$collect";487 488 489 # my $flvtool_cmd = "flvtool2 -vUAtP \"$cue_filename\" -thumbLocation:$thumbloc \"$oflash_filename\"";490 491 # my $flvtool_cmd = "flvtool2 -vUAt \"$cue_filename\" \"$oflash_filename\"";492 493 494 495 # my $flvtool_cmd = "flvtool2 -vUAt \"$cue_filename\" \"$oflash_filename\"";496 497 498 ## my $flvtool_cmd = "flvtool2 -vAt \"$cue_filename\" -UP \"$oflash_filename\" \"$output_dir/updated.flv\"";499 500 ## my $flvtool_cmd = "flvtool2 -vAtU \"$cue_filename\" \"$oflash_filename\" \"$output_dir/updated.flv\"";501 502 my $flvtool_cmd = "flvtool2 -vAtUP \"$cue_filename\" \"$oflash_filename\"";503 504 return ($flvtool_cmd,$oflash_filename);505 }506 507 508 sub keyframe_thumbnail_cmd509 {510 my $self = shift (@_);511 my ($ivideo_filename,$thumbnailfile,$thumbnailwidth,$thumbnailheight) = @_;512 513 my $output_dir = $self->{'cached_dir'};514 my $ivideo_root = $self->{'file_root'};515 516 my $key_filename_prefix = &util::filename_cat($output_dir,$ivideo_root);517 518 519 # Try for 4th keyframe, but fall back to 1st if doesn't exist520 my $key_filename = "${key_filename_prefix}_0003.jpg";521 $key_filename = "${key_filename_prefix}_0000.jpg" if (!-e $key_filename);522 523 my $key_filename_gsdlenv = $self->gsdlhome_independent($key_filename);524 my $thumbnailfile_gsdlenv = $self->gsdlhome_independent($thumbnailfile);525 526 my $command;527 528 if (-e $key_filename) {529 $command = "convert -interlace plane -verbose -geometry $thumbnailwidth"530 . "x$thumbnailheight \"$key_filename_gsdlenv\" \"$thumbnailfile_gsdlenv\"";531 }532 else {533 # extractkeyframe has either not been switched on, or else had534 # a problem when running535 # => extract a from536 # my $frame_rate = 1.0 / 60.0;537 538 my $ivideo_filename_gsdlenv = $self->gsdlhome_independent($ivideo_filename);539 540 541 542 $command = "ffmpeg -i \"$ivideo_filename_gsdlenv\" -ss 12.5 -vframes 1 -f image2 -s ${thumbnailwidth}x${thumbnailheight} -y \"$thumbnailfile_gsdlenv\"";543 544 # fmpeg -i input.dv -r 1 -f image2 -s 120x96 images%05d.png545 }546 547 return ($command,$thumbnailfile);548 }549 550 551 sub keyframe_montage_cmd552 {553 my $self = shift (@_);554 my ($ivideo_filename,$montagefile) = @_;555 556 my $output_dir = $self->{'cached_dir'};557 my $ivideo_root = $self->{'file_root'};558 559 my $key_filename_prefix = &util::filename_cat($output_dir,$ivideo_root);560 561 my $options = "-tile 10 -geometry 75x62+2+2";562 563 my $command = "montage $options ${key_filename_prefix}_*.jpg \"$montagefile\"";564 565 return ($command,$montagefile);566 }567 568 569 570 sub parse_shot_xml571 {572 my ($self) = shift(@_);573 574 my ($plugin) = @_;575 576 my $outhandle = $self->{'outhandle'};577 my $output_dir = $self->{'cached_dir'};578 579 my $shots_filename = &util::filename_cat($output_dir,"shots.xml");580 581 eval {582 $plugin->{'parser'}->parsefile($shots_filename);583 };584 585 if ($@) {586 print $outhandle "videoconvert.pm: skipping $shots_filename as not conformant to Hive shot syntax\n" if ($self->{'verbosity'} > 1);587 print $outhandle "\n Perl Error:\n $@\n" if ($self->{'verbosity'}>2);588 return 0;589 }590 591 }592 593 sub associate_keyframes_old594 {595 my ($self) = shift(@_);596 597 my ($doc_obj,$section,$plugin) = @_;598 599 my $output_dir = $self->{'cached_dir'};600 601 my $count = 1;602 foreach my $kframe_file (@{$plugin->{'keyframe_fnames'}}) {603 604 my $kframe_filename = &util::filename_cat($output_dir,$kframe_file);605 $doc_obj->associate_file($kframe_filename,"keyframe$count.jpg","image/jpeg",606 $section);607 $count++;608 }609 610 $doc_obj->add_utf8_metadata($section,"NumKeyframes",scalar(@{$plugin->{'keyframe_fnames'}}));611 612 613 # *****614 # $doc_obj->add_metadata ($section, "thumblist", $plugin->{'flowplayer_thumblist'});615 616 }617 618 sub associate_keyframes619 {620 my ($self) = shift(@_);621 622 my ($doc_obj,$section,$plugin) = @_;623 624 my $output_dir = $self->{'cached_dir'};625 my $timeline = $plugin->{'keyframe_timeline'};626 627 my $count = 1;628 629 foreach my $t (sort { $timeline->{$a}->{'keyframeindex'} <=> $timeline->{$b}->{'keyframeindex'} } keys %$timeline)630 {631 my $kframe_file = $timeline->{$t}->{'thumb'};632 my $timestamp = $timeline->{$t}->{'timestamp'};633 634 my $kframe_filename = &util::filename_cat($output_dir,$kframe_file);635 $doc_obj->associate_file($kframe_filename,"keyframe$count.jpg","image/jpeg",636 $section);637 $doc_obj->add_utf8_metadata($section,"KeyframeTimestamp",$timestamp);638 639 $count++;640 }641 642 $doc_obj->add_utf8_metadata($section,"NumKeyframes",scalar(@{$plugin->{'keyframe_fnames'}}));643 644 645 # *****646 # $doc_obj->add_metadata ($section, "thumblist", $plugin->{'flowplayer_thumblist'});647 }648 649 650 651 233 sub ffmpeg_monitor_init 652 234 { … … 693 275 694 276 695 sub flvtool2_monitor_line696 {697 my ($line) = @_;698 699 my $had_error = 0;700 my $generate_dot = 1;701 702 if ($line =~ m/\s+\- /) {703 # ignore tabulated output printed at end of command704 $generate_dot = 0;705 }706 707 if ($line =~ m/^Error:/i) {708 $had_error = 1;709 }710 711 return ($had_error,$generate_dot);712 }713 714 715 716 277 717 278
Note:
See TracChangeset
for help on using the changeset viewer.