File Coverage

blib/lib/FFMPEG/Effects.pm
Criterion Covered Total %
statement 24 674 3.5
branch 0 224 0.0
condition 0 15 0.0
subroutine 8 19 42.1
pod 0 11 0.0
total 32 943 3.3


line stmt bran cond sub pod time code
1             package FFMPEG::Effects;
2              
3 1     1   59701 use warnings;
  1         4  
  1         69  
4 1     1   9 use strict;
  1         3  
  1         56  
5 1     1   2091 use MIME::Base64 ();
  1         3358  
  1         52  
6 1     1   3563 use Data::Dumper;
  1         12692  
  1         8435  
7              
8             our $VERSION = '1.0';
9             our $REVISION = '1.0';
10              
11              
12             =head1 NAME
13              
14             FFMPEG::Effects - PERL Routines To Simplify ffmpeg Video Filter Usage.
15              
16             =head1 VERSION
17              
18             Version 1.0 -- For Use With FFMPEG Release Branch 1.0
19              
20             =head1 SYNOPSIS
21              
22             use FFMPEG::Effects;
23              
24             my $effect=FFMPEG::Effects->new('debug=1');
25              
26             $effect->Help('all');
27              
28             $effect->FadeIn('videofile=short.mpg',
29             'size=cif',
30             'framerate=30',
31             'color=cyan',
32             'opacity=70',
33             'fadeinframes=90',
34             'holdframes=31' );
35              
36             $effect->TitleSplash('size=cif',
37             'framerate=30',
38             'color=black',
39             'opacity=100',
40             'fadeinframes=50',
41             'fadeoutframes=50',
42             'holdframes=30',
43             'titleframes=299',
44             'fontcolor=white',
45             'font=Courier',
46             'justify=center' );
47              
48             $effect->FadeOut('videofile=short.mpg',
49             'size=cif',
50             'framerate=30',
51             'color=cyan',
52             'opacity=70',
53             'fadeoutframes=56',
54             'holdframes=31' );
55              
56              
57             =head1 USAGE
58              
59             The Methods Shown Above Are Shown With Their Relevant Arguments.
60              
61             They Can Be Called With No Arguments And Will Attempt To Produce Useful Output.
62              
63             Use This Module As In The Examples Above, Sending A List Of Quoted Arguments
64             To Each Function.
65              
66             Make a Call to Help() To Find Out More.
67              
68             =head1 DEPENDENCIES
69              
70             This Module is Written, and Numbered Against FFMPEG
71             Release Branches. e.g.: FFMPEG::Effects-1.0 Is Written For Use
72             With FFMPEG Release Branch 1.0.
73              
74             The Version Number of This Module Will Always Be The Same As
75             The FFMPEG Release It Is Written For. Check The $REVISION
76             Number or Release Date To Make Sure You Have The Latest Version.
77              
78             This Module Depends On The GhostScript And ImageMagick
79             Programs. They Must Be Installed And In Your $PATH.
80              
81             =head1 EXPLANATION
82              
83             All Functions Listed in the USAGE Section Can Be Called Without
84             Arguments and Will Attempt To Produce Something Meaningful.
85              
86             When Particular Arguments To Functions Are Not Relevant
87             They Will Be Ignored.
88              
89             If A Particular Value Is Needed And It Is Not Specified
90             A Default Value Will Be Used. The Help() Function
91             Will List Default Values For Critical Settings.
92              
93             The TitleSplash() Function Will Create A New Video Based
94             on the 'textfile=' argument. If no textfile is specified it
95             will create a single color video segmnent with the opacity
96             you set, and the pngfile as the background, if any.
97              
98             The FadeIn() and FadeOut() Methods Operate on A Video
99             You Specify. See EXAMPLES Below, For More Info.
100              
101             The Values for The Arguments Listed Below All Apply
102             To The Output Video File, Except 'videofile', and
103             'textfile' Which Name Input Files.
104              
105             =head1 ARGUMENTS
106              
107             The Methods in FFMPEG::Effects Take The Following Arguments Where Relevant:
108              
109             'videofile' The File Name of The Video File To Be Used As Input
110             'size' Video Image Size -- Can Use 'cif', etc, or x
111             'framerate' Output File Frame Rate
112             'fadeinframes' Number of Frames A Fade In Is Spread Over
113             'fadeoutframes' Number of Frames A Fade Out Is Spread Over
114             'holdframes' Number Of Frames Added to Beginning or End of Effect To Increase Its Duration
115             'titleframes' Number of Frames That Title Frame Will Persist
116             'color' The Fade To And Fade From Color
117             'opacity' Final Opacity of Fade Sequence
118             'fontcolor' Text Color Used In Generated Titles
119             'justify' 'Left', 'Center', or 'Right' Justify Text In Generated Titles
120             'textfile' ASCII Text File Containing The Content For Generating Titles
121             'pngfile' PNG Image File Used To Underlay Generated Titles
122             'font' Font For Generated Titles. -- 'Helvetica' or 'Courier'
123              
124             See SIZES, and COLORS below for specifying sizes and colors.
125              
126              
127             =head1 SIZES
128              
129             FFMPEG::Effects understands the following Size Specs:
130              
131             "sqcif" "128x96"
132             "qcif" "176x144"
133             "cif" "352x288"
134             "4cif" "704x576"
135             "16cif" "1408x1152"
136             "qqvga" "160x120"
137             "qvga" "320x240"
138             "vga" "640x480"
139             "svga" "800x600"
140             "xga" "1024x768"
141             "uxga" "1600x1200"
142             "qxga" "2048x1536"
143             "sxga" "1280x1024"
144             "qsxga" "2560x2048"
145             "hsxga" "5120x4096"
146             "wvga" "852x480"
147             "wxga" "1366x768"
148             "wsxga" "1600x1024"
149             "wuxga" "1920x1200"
150             "woxga" "2560x1600"
151             "wqsxga" "3200x2048"
152             "wquxga" "3840x2400"
153             "whsxga" "6400x4096"
154             "whuxga" "7680x4800"
155             "cga" "320x200"
156             "ega" "640x350"
157             "hd480" "852x480"
158             "hd720" "1280x720"
159              
160             Size Can Be Specified either by common name, or
161             by "x", as above.
162              
163             This Module Has been repeatedly tested with the sizes above up to
164             1920x1200.
165              
166              
167             =head1 COLORS
168              
169             Colors are case-insensitive, specified by common name as below:
170              
171             'red' 'blue' 'green' 'cyan' 'magenta' 'yellow' 'white' 'grey' 'black'
172            
173             The 'color' argument to methods can be specied as above or
174             as a Hexadecimal Value like '#RRGGBB' For Red Green And Blue.
175              
176             The 'fontcolor' Argument is specified by color name as above.
177              
178              
179             =head1 CAVEATS
180              
181             1) Unfortunately This Module Nneeds To Convert Videos
182             To PNG Files To Do Some Of Its Effects. This Can Be
183             Slow For Larger Image Sizes.
184              
185             2) Likewise, This Module Currently Outputs Only .mpg
186             Container Format. In FFMPEG This Is The 'mpeg1video' Video Format.
187             It Will By Convention Transcode Whatever Input Format to
188             mpeg1video Output.
189              
190             3) The Duration Of The Video Is A Necessary Parameter.
191             If The Internal Timecode of A File Is Broken, The Duration Can
192             Not Be Obtained Correctly. Using A Video File As Input
193             That Was Concatenated Together From Multiple Files Can
194             Cause This Problem. For Best Results, Use Single MPEG Video
195             Files That Were Generated With FFMPEG.
196              
197             4) Audio Is Not Supported At This Time. FFMPEG::Effects
198             produces a new video, so the audio from your original
199             can be added to it after the fact.
200              
201              
202             =head1 HINTS
203              
204             1) Small Image Sizes Are Processed VERY Fast. Larger
205             Ones Become Considerably Slower. Try Prototyping Your
206             Scenes With Thumbnail Sizes, And When You Have It To
207             Your Liking, Render It Full-Size. Then You Will Have Time
208             For Coffee.
209              
210             2) This Module Uses an Auto-Scaling Algorithm Based on
211             the Number of Lines, and The Longest Line in the
212             'textfile', to Adjust The Font Size In The Video.
213              
214             3) This Module Was Designed For Working With A Video
215             Split Up Into Separate Comparatively Short Scenes.
216             It Is Intended To Be A Useful Tool For Scripting
217             Routine Effects Like Titles And Fades.
218              
219             4) Beacause of The Complexities Involved In Being Able To
220             Specify Video Time In Seconds, This Module Always Deals
221             With Effects On A Frame-by-Frame Basis.
222              
223              
224             =head1 EXAMPLES
225              
226             This Module Ships With The Following Simple Example Scripts:
227              
228             FFMPEG-Effects.titlesplash.pl
229             FFMPEG-Effects.help.pl
230             FFMPEG-Effects.fadeout.pl
231             FFMPEG-Effects.fadein.pl
232              
233              
234             =head1 SUBROUTINES/METHODS
235              
236             This Module Has The Following Methods Available:
237              
238             new() Instantiate The Class, and Set Debug Level.
239              
240             Help() Print Help.
241              
242             SetParams() Set Necessary Parameters To Operate.
243              
244             FadeIn() Fade In From Solid Or Transparent Color To Scene.
245              
246             FadeOut() Fade Out From Scene To Solid Or Transparent Color.
247              
248             GetDuration() Get Duration Seconds Of Video.
249              
250             GetStreamInfo() Get Various Stream Parameters.
251              
252             TitleSplash() Generate A Title From PostScript With Fade In And Out.
253              
254             PSTitleFrame() Returns PostScript Title Frame Template.
255              
256             =cut
257              
258              
259             my $ProcData="";
260             my $FFCommand="";
261              
262             sub new
263             {
264 0     0 0   my( $class, $debugsetting ) = @_;
265 0           my $debug = 0;
266              
267             # Set Useful Values For Those Not Passed In At Runtime
268             # And For Internal Variables.
269 0           my $self = {
270             'videofile' => 'FFMPEG-Effect',
271             'outputfile' => 'FFMPEG-Effect',
272             'size' => '352x288',
273             'framerate' => '30',
274             'fadeinframes' => '75',
275             'fadeoutframes' => '75',
276             'holdframes' => '0',
277             'titleframes' => '90',
278             'color' => 'blue',
279             'opacity' => '100',
280             'width' => '352',
281             'height' => '288',
282             'DurationSecs' => '30',
283             'aspect' => 'NA',
284             'pngfile' => 'none',
285             'textfile' => 'FFMPEG-Effect',
286             'justify' => 'center',
287             'font' => 'Courier',
288             'fontsize' => 'not-set',
289             'fontcolor' => 'white',
290             'debug' => $debug,
291             };
292              
293 0 0         if ( $debugsetting )
294             {
295 0           eval("\$".$debugsetting);
296 0           $self->{'debug'} = $debug;
297              
298             ##### $debugsetting is a string like: 'debug=xxx'
299             ##### Where 'xxx' can be an integer val, or string description.
300              
301 0 0         if ($self->{'debug'} != 0)
302             {
303 0           print("\n");
304 0           print ("new: $debugsetting \n");
305 0           print Dumper($self) . "\n";
306             }
307             }
308              
309 0           bless $self, $class;
310              
311 0           return ($self);
312             }
313              
314              
315             ##### Help() Print Help
316             sub Help
317             {
318 0     0 0   my ( $self, @inputargs) = @_;
319              
320 0           my $helphash = {
321             'videofile' => 'The File Name of The Video File To Be Used As Input',
322             'size' => 'Video Image Size -- Can Use \'cif\', etc, or \'x\' ',
323             'framerate' => 'Output File Frame Rate',
324             'fadeinframes' => 'Number of Frames A \'Fade In\' Is Spread Over',
325             'fadeoutframes' => 'Number of Frames A \'Fade Out\' Is Spread Over',
326             'holdframes' => 'Number Of Frames Added to Beginning or End of Effect To Increase Its Duration',
327             'titleframes' => 'Number of Frames That \'Title\' Frame Will Persist',
328             'color' => 'The \'Fade To\' And \'Fade From\' Color',
329             'opacity' => 'Final Opacity of Fade Sequence',
330             'width' => 'Image Size In Width -- Internal Variable, Derived From \'size\'',
331             'height' => 'Image Size In Height -- Internal Variable Derived From \'size\'',
332             'aspect' => 'Aspect Ratio -- Internal Variable Derived From \'size\'',
333             'DurationSecs' => 'Total Duration Of Video In Seconds',
334             'fontcolor' => 'Text Color Used In Generated Titles',
335             'justify' => 'Left, Center, or Right Justify Text In Generated Titles',
336             'textfile' => 'ASCII Text File Containing The Content For Generating Titles',
337             'pngfile' => 'PNG Image File Used To Underlay Generated Titles',
338             'font' => 'Font For Generated Titles. -- \'Helvetica\' or \'Courier\''
339             };
340              
341              
342 0 0 0       if ( ( ! @inputargs ) || ( $inputargs[0] eq 'all' ) )
343             {
344 0           print("\nHelp for all...\n");
345              
346 0           while( my ($key, $value ) = each(%$helphash) )
347             {
348 0           print("\t$key : $value\n");
349             }
350              
351 0           print("\n");
352 0           print("Defaults: \n");
353 0           while( my ($key, $value ) = each(%$self) )
354             {
355 0           print("\t$key : $value\n");
356             }
357 0           print("\n");
358             }
359             else
360             {
361 0           foreach( @inputargs )
362             {
363 0 0         if ( $helphash->{$_} )
364             {
365 0           print("$_: $helphash->{$_}, \n");
366             }
367             else
368             {
369 0           print("Help -- No Help For: $_ ... Try 'all'\n");
370              
371             }
372             }
373             }
374              
375             }
376              
377             ##### TestReel() Generate Test Reel.
378              
379              
380             sub TestReel
381             {
382 0     0 0   my ( $self, $inputargs) = @_;
383 0           $self->SetParams($inputargs);
384              
385 0 0         if ($self->{'debug'} != 0)
386             {
387 0           print("TestReel:\n");
388 0           print Dumper($self) . "\n";
389             }
390             }
391              
392              
393             ##### SetParams() Set Necessary Parameters To Operate.
394             ##### Called By Effects Functions To Store Input Arguments
395              
396              
397             sub SetParams
398             {
399              
400 0     0 0   my ( $self, @inputargs) = @_;
401 0           my $data="";
402 0 0         if ($self->{'debug'} != 0)
403             {
404 0           print("SetParams:\n");
405 0           print Dumper($self) . "\n";
406             }
407            
408 0           foreach (@inputargs)
409             {
410 0           $data=($_ );
411 0           my @argdata = split( '=', $data);
412 0           my $param = $argdata[0];
413 0           my $val = $argdata[1];
414            
415 0 0         if ( ! $self->{ $param } )
416             {
417             # print("No Such Parameter -- $param \n");
418 0           $self->{$param} = $val;
419             }
420             else
421             {
422             # print("Indata -- $param : $val \n");
423 0           $self->{$param} = $val;
424             }
425             }
426            
427            
428 0           my $size = $self->{ 'size' };
429            
430 0 0         if ( $size eq "sqcif" ) { $size="128x96" };
  0            
431 0 0         if ( $size eq "qcif" ) { $size="176x144" };
  0            
432 0 0         if ( $size eq "cif" ) { $size="352x288" };
  0            
433 0 0         if ( $size eq "4cif" ) { $size="704x576" };
  0            
434 0 0         if ( $size eq "16cif" ) { $size="1408x1152" };
  0            
435 0 0         if ( $size eq "qqvga" ) { $size="160x120" };
  0            
436 0 0         if ( $size eq "qvga" ) { $size="320x240" };
  0            
437 0 0         if ( $size eq "vga" ) { $size="640x480" };
  0            
438 0 0         if ( $size eq "svga" ) { $size="800x600" };
  0            
439 0 0         if ( $size eq "xga" ) { $size="1024x768" };
  0            
440 0 0         if ( $size eq "uxga" ) { $size="1600x1200" };
  0            
441 0 0         if ( $size eq "qxga" ) { $size="2048x1536" };
  0            
442 0 0         if ( $size eq "sxga" ) { $size="1280x1024" };
  0            
443 0 0         if ( $size eq "qsxga" ) { $size="2560x2048" };
  0            
444 0 0         if ( $size eq "hsxga" ) { $size="5120x4096" };
  0            
445 0 0         if ( $size eq "wvga" ) { $size="852x480" };
  0            
446 0 0         if ( $size eq "wxga" ) { $size="1366x768" };
  0            
447 0 0         if ( $size eq "wsxga" ) { $size="1600x1024" };
  0            
448 0 0         if ( $size eq "wuxga" ) { $size="1920x1200" };
  0            
449 0 0         if ( $size eq "woxga" ) { $size="2560x1600" };
  0            
450 0 0         if ( $size eq "wqsxga" ) { $size="3200x2048" };
  0            
451 0 0         if ( $size eq "wquxga" ) { $size="3840x2400" };
  0            
452 0 0         if ( $size eq "whsxga" ) { $size="6400x4096" };
  0            
453 0 0         if ( $size eq "whuxga" ) { $size="7680x4800" };
  0            
454 0 0         if ( $size eq "cga" ) { $size="320x200" };
  0            
455 0 0         if ( $size eq "ega" ) { $size="640x350" };
  0            
456 0 0         if ( $size eq "hd480" ) { $size="852x480" };
  0            
457 0 0         if ( $size eq "hd720" ) { $size="1280x720" };
  0            
458            
459 0           $self->{ 'size' } = $size;
460            
461 0           my @sizedata=split(/[xX]/, $size);
462 0           my $width=$sizedata[0];
463 0           my $height=$sizedata[1];
464            
465 0           $self->{ 'width' } = $width;
466 0           $self->{ 'height' } = $height;
467              
468 0           my $aspect = ($width / $height);
469              
470 0           my $aspectratio = sprintf("%.2f", $aspect);
471              
472 0 0         if ( $aspectratio == 1.78 )
473             {
474 0           $self->{ 'aspect' } = 'HD';
475             }
476              
477 0 0         if ( $aspectratio == 1.33 )
478             {
479 0           $self->{ 'aspect' } = 'TV';
480             }
481              
482 0 0         if ( $aspectratio == 1.50 )
483             {
484 0           $self->{ 'aspect' } = 'NTSC';
485             }
486              
487 0 0 0       if ( ! ( ($aspectratio == 1.33) || ($aspectratio == 1.78) || ($aspectratio == 1.50) ) )
      0        
488             {
489 0           $self->{ 'aspect' } = 'OTHER';
490             }
491              
492 0           $self->{ 'prec1' } = length( $self->{ 'fadeinframes' } );
493 0           $self->{ 'prec2' } = length( $self->{ 'fadeoutframes' });
494            
495            
496 0           return();
497             }
498              
499             ##### FadeIn() Fade In From Solid Or Transparent Color To Scene.
500              
501              
502             sub FadeIn
503             {
504              
505 0     0 0   my ( $self, @inputargs) = @_;
506 0           $self->SetParams(@inputargs);
507              
508 0 0         if ($self->{'debug'} != 0)
509             {
510 0           print("FadeIn:\n");
511 0           print Dumper($self) . "\n";
512             }
513              
514 0           my $videofile=$self->{'videofile'};
515 0           my $outputfile = `basename "$videofile" 2>&1`;
516 0           chomp($outputfile);
517              
518 0           my $size=$self->{'size'};
519 0           my $framerate=$self->{'framerate'};
520 0           my $fadeinframes=$self->{'fadeinframes'};
521 0           my $fadeoutframes=$self->{'fadeoutframes'};
522 0           my $holdframes=$self->{'holdframes'};
523 0           my $titleframes=$self->{'titleframes'};
524 0           my $color=$self->{'color'};
525 0           my $opacity=$self->{'opacity'};
526 0           my $width=$self->{'width'};
527 0           my $height=$self->{'height'};
528 0           my $DurationSecs=$self->{'DurationSecs'};
529 0           my $prec1=$self->{'prec1'};
530 0           my $prec2=$self->{'prec2'};
531 0           my $aspect=$self->{'aspect'};
532              
533 0           my $frameno=0;
534 0           my $fade=($opacity / 100);
535 0           my $fadefactor=( ($fade / $fadeinframes) );
536 0           my $fadeval=sprintf("%.2f", $fade);
537              
538 0           my $skipsecs=0;
539 0           my $skip=sprintf("%.2f", $skipsecs);
540 0           my $next=( 1 / $framerate);
541              
542 0           my $nextval=sprintf("%.3f", $next);
543 0 0         if ($self->{'debug'} != 0)
544             {
545 0           print("Skip Seconds: $skip\n");
546 0           print("Next Frame At: $nextval sec.\n\n");
547             }
548              
549 0           my $frameindex = $frameno;
550              
551 0           print ("Generating $holdframes Hold Frames...\n");
552 0           for ( $frameno = 1; $frameno <= $holdframes; $frameno++)
553             {
554 0           $frameindex = $frameno;
555 0           my $framecount=sprintf("%05d", $frameindex);
556              
557 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -i $videofile -r $framerate -s $size -qmin 1 -qmax 2 -g 0 -vframes 1 $outputfile-holdframe-$framecount.png 2>&1";
558 0           $ProcData=`$FFCommand`;
559 0 0         if ($self->{'debug'} != 0)
560             {
561 0           print ("Executing: $FFCommand\n");
562 0           print ("$ProcData\n");
563             }
564             }
565              
566 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -i $outputfile-holdframe-%05d.png -r $framerate -qmin 1 -qmax 2 -g 0 -vf \"color=color=$color\@$fade:size=$size [layer1]; [in][layer1] overlay=0:0\" $outputfile-hold.mpg 2>&1";
567 0           $ProcData=`$FFCommand`;
568 0 0         if ($self->{'debug'} != 0)
569             {
570 0           print ("Executing: $FFCommand\n");
571 0           print ("$ProcData\n");
572             }
573              
574 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -i $videofile -r $framerate -s $size -qmin 1 -qmax 2 -g 0 -vframes $fadeinframes $outputfile-%05d.png 2>&1";
575 0           $ProcData=`$FFCommand`;
576 0 0         if ($self->{'debug'} != 0)
577             {
578 0           print ("Executing: $FFCommand\n");
579 0           print ("$ProcData\n");
580             }
581              
582 0           print ("Generating FadeIn Frames...\n");
583 0           for ( $frameno = 1; $frameno <= $fadeinframes; $frameno++)
584             {
585 0           my $framecount=sprintf("%05d", $frameno);
586 0           $frameno=sprintf("%0"."$prec2"."d", "$frameno");
587 0           print("Frame No: $frameno\n");
588              
589 0           $fade=($fade - $fadefactor);
590              
591 0 0         if ( $frameno == $fadeinframes)
592             {
593 0           $fade=0;
594             }
595              
596 0           $fadeval=sprintf("%.2f", $fade);
597 0           print("Opacity: $fadeval\n");
598 0           $skip=( $skip + $next );
599 0           $nextval=sprintf("%.3f", $skip);
600 0           print("Next Frame at: $nextval sec.\n\n");
601              
602 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -i $outputfile-$framecount.png -r $framerate -vf \"color=color=$color\@$fade:size=$size [layer1]; [in][layer1] overlay=0:0\" -s $size -qmin 1 -qmax 2 -g 0 -vframes 1 $outputfile-$framecount.effect.png 2>&1";
603 0           $ProcData=`$FFCommand`;
604 0 0         if ($self->{'debug'} != 0)
605             {
606 0           print ("Executing: $FFCommand\n");
607 0           print ("$ProcData\n");
608             }
609             }
610              
611 0           print ("Processing Effect Into Output Video: $outputfile-fadein.mpg\n");
612 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -i $outputfile-%05d.effect.png -r $framerate -qmin 1 -qmax 2 -g 0 $outputfile-effect.mpg 2>&1";
613 0           $ProcData=`$FFCommand`;
614 0 0         if ($self->{'debug'} != 0)
615             {
616 0           print ("Executing: $FFCommand\n");
617 0           print ("$ProcData\n");
618             }
619              
620 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -ss $skip -i $videofile -r $framerate -s $size -qmin 1 -qmax 2 -g 0 $outputfile-remainder.mpg 2>&1";
621 0           $ProcData=`$FFCommand`;
622 0 0         if ($self->{'debug'} != 0)
623             {
624 0           print ("Executing: $FFCommand\n");
625 0           print ("$ProcData\n");
626             }
627              
628 0           $FFCommand="ffmpeg -y -g 0 -qmin 1 -qmax 2 -r $framerate -i \"concat:$outputfile-hold.mpg|$outputfile-effect.mpg|$outputfile-remainder.mpg\" -g 0 -qmin 1 -qmax 2 -r $framerate -s $size $outputfile-fadein.mpg 2>&1";
629 0           $ProcData=`$FFCommand`;
630 0 0         if ($self->{'debug'} != 0)
631             {
632 0           print ("Executing: $FFCommand\n");
633 0           print ("$ProcData\n");
634             }
635              
636 0 0         unless ($self->{'debug'} != 0)
637             {
638 0           $ProcData=`rm $outputfile-holdframe-?????.png $outputfile-hold.mpg $outputfile-?????.png $outputfile-?????.effect.png $outputfile-effect.mpg $outputfile-remainder.mpg`;
639              
640             }
641              
642 0           $self->{'outputfile'} = "$outputfile-fadein.mpg";
643              
644 0           return;
645             }
646              
647              
648             ##### FadeOut() Fade Out From Scene To Solid Or Transparent Color.
649              
650              
651             sub FadeOut
652             {
653 0     0 0   my ( $self, @inputargs) = @_;
654 0           $self->SetParams(@inputargs);
655              
656 0 0         if ($self->{'debug'} != 0)
657             {
658 0           print("FadeOut:\n");
659 0           print Dumper($self) . "\n";
660             }
661              
662 0           my $videofile=$self->{'videofile'};
663 0           my $outputfile = `basename "$videofile" 2>&1`;
664 0           chomp($outputfile);
665            
666 0           my $size=$self->{'size'};
667 0           my $framerate=$self->{'framerate'};
668 0           my $fadeinframes=$self->{'fadeinframes'};
669 0           my $fadeoutframes=$self->{'fadeoutframes'};
670 0           my $holdframes=$self->{'holdframes'};
671 0           my $titleframes=$self->{'titleframes'};
672 0           my $color=$self->{'color'};
673 0           my $opacity=$self->{'opacity'};
674 0           my $width=$self->{'width'};
675 0           my $height=$self->{'height'};
676 0           my $DurationSecs=$self->{'DurationSecs'};
677 0           my $prec1=$self->{'prec1'};
678 0           my $prec2=$self->{'prec2'};
679 0           my $aspect=$self->{'aspect'};
680              
681 0           $self->GetDuration();
682 0           $DurationSecs=$self->{'DurationSecs'};
683            
684 0           my $frameno=0;
685 0           my $fade=0;
686 0           my $fadefactor=( ( ( $opacity / 100 ) / $fadeoutframes) );
687 0           my $fadeval=sprintf("%.2f", $fade);
688            
689            
690 0           my $skipsecs=( (($framerate * $DurationSecs ) - $fadeoutframes) / $framerate );
691 0           my $skip=sprintf("%.2f", $skipsecs);
692 0           my $next=( 1 / $framerate);
693 0           my $nextval=sprintf("%.3f", $skipsecs);
694              
695 0           my $lastframetime=($skip - $next);
696 0           my $holdframe="";
697              
698              
699 0           my $frontframes=($framerate * $skipsecs);
700 0           my $front=sprintf("%d", $frontframes);
701              
702 0           print ("Preparing Input File...\n");
703 0           print("Duration: $DurationSecs sec.\n");
704 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -i $videofile -r $framerate -s $size -g 0 -qmin 1 -qmax 2 -aspect:v $width:$height $outputfile-tmp.mpg 2>&1";
705 0           $ProcData=`$FFCommand`;
706 0 0         if ($self->{'debug'} != 0)
707             {
708 0           print ("Executing: $FFCommand\n");
709 0           print ("$ProcData\n");
710             }
711              
712 0           print ("Extracting Pre-Effect Frames...\n");
713 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -i $outputfile-tmp.mpg -r $framerate -s $size -vframes $front -g 0 -qmin 1 -qmax 2 $outputfile-front.mpg 2>&1";
714 0           $ProcData=`$FFCommand`;
715 0 0         if ($self->{'debug'} != 0)
716             {
717 0           print ("Executing: $FFCommand\n");
718 0           print ("$ProcData\n");
719             }
720              
721 0           print("Skipping To: $skip sec.\n");
722 0           print ("Generating Frames For FadeOut Effect...\n");
723              
724 0           my $frameindex = $frameno;
725 0           my $framecount=sprintf("%05d", $frameindex);
726              
727 0           for ( $frameno = 1; $frameno <= $fadeoutframes; $frameno++)
728             {
729 0           $frameno=sprintf("%0"."$prec2"."d", "$frameno");
730 0           print("Frame No $frameno\n");
731              
732 0           $frameindex = $frameno;
733 0           $framecount=sprintf("%05d", $frameindex);
734              
735 0           $fade=($fade + $fadefactor);
736              
737              
738 0 0         if ( $frameno == $fadeoutframes)
739             {
740 0           $fade=($opacity / 100 );
741              
742 0           print ("Generating Hold Frames... This Frame Repeated $holdframes Times.\n");
743 0           for ( $holdframe = 1; $holdframe <= $holdframes; $holdframe++)
744             {
745 0           $frameindex = $holdframe;
746 0           $framecount=sprintf("%05d", $frameindex);
747 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -ss $skip -i $outputfile-tmp.mpg -r $framerate -vf \"color=color=$color\@$fade:size=$size [layer1]; [in][layer1] overlay=0:0\" -s $size -qmin 1 -qmax 2 -g 0 -vframes 1 $outputfile-holdframe-$framecount.png 2>&1";
748 0           $ProcData=`$FFCommand`;
749 0 0         if ($self->{'debug'} != 0)
750             {
751 0           print ("Executing: $FFCommand\n");
752 0           print ("$ProcData\n");
753             }
754              
755             }
756 0           next;
757              
758             }
759              
760 0           $fadeval=sprintf("%.2f", $fade);
761 0           print("Opacity: $fadeval\n");
762 0           $skip=( $skip + $next );
763 0           $nextval=sprintf("%.3f", $skip);
764 0           print("Next Frame At: $nextval\n\n");
765              
766              
767 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -ss $skip -i $outputfile-tmp.mpg -r $framerate -vf \"color=color=$color\@$fade:size=$size [layer1]; [in][layer1] overlay=0:0\" -s $size -qmin 1 -qmax 2 -g 0 -vframes 1 $outputfile-effect-$framecount.png 2>&1";
768 0           $ProcData=`$FFCommand`;
769 0 0         if ($self->{'debug'} != 0)
770             {
771 0           print ("Executing: $FFCommand\n");
772 0           print ("$ProcData\n");
773             }
774              
775             }
776              
777 0           print ("Transcoding To Output File... $outputfile-fadeout.mpg\n");
778 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -i $outputfile-effect-%05d.png -r $framerate -s $size -qmin 1 -qmax 2 -g 0 $outputfile-effect.mpg 2>&1";
779 0           $ProcData=`$FFCommand`;
780 0 0         if ($self->{'debug'} != 0)
781             {
782 0           print ("Executing: $FFCommand\n");
783 0           print ("$ProcData\n");
784             }
785              
786 0           $FFCommand="ffmpeg -y -qmin 1 -qmax 2 -g 0 -i $outputfile-holdframe-%05d.png -r $framerate -s $size -qmin 1 -qmax 2 -g 0 $outputfile-hold.mpg 2>&1";
787 0           $ProcData=`$FFCommand`;
788 0 0         if ($self->{'debug'} != 0)
789             {
790 0           print ("Executing: $FFCommand\n");
791 0           print ("$ProcData\n");
792             }
793              
794 0           $FFCommand="ffmpeg -y -g 0 -qmin 1 -qmax 2 -r $framerate -i \"concat:$outputfile-front.mpg|$outputfile-effect.mpg|$outputfile-hold.mpg\" -g 0 -qmin 1 -qmax 2 -r $framerate -s $size $outputfile-fadeout.mpg 2>&1";
795 0           $ProcData=`$FFCommand`;
796 0 0         if ($self->{'debug'} != 0)
797             {
798 0           print ("Executing: $FFCommand\n");
799 0           print ("$ProcData\n");
800             }
801              
802 0 0         unless ($self->{'debug'} != 0)
803             {
804 0           $ProcData=`rm $outputfile-holdframe-?????.png $outputfile-hold.mpg $outputfile-tmp.mpg $outputfile-effect-?????.png $outputfile-effect.mpg $outputfile-front.mpg`;
805             }
806              
807 0           $self->{'outputfile'} = "$outputfile-fadeout.mpg";
808 0           return;
809             }
810              
811              
812             ##### Transition() Transition Between Scenes. TBD
813              
814              
815             sub Transition
816             {
817 0     0 0   my ( $self, @inputargs) = @_;
818 0           $self->SetParams(@inputargs);
819              
820 0 0         if ($self->{'debug'} != 0)
821             {
822 0           print("Transition");
823 0           print Dumper($self) . "\n";
824             }
825             }
826              
827              
828             ##### GetDuration() Get Duration Seconds Of Video.
829              
830              
831             sub GetDuration
832             {
833              
834 0     0 0   my ( $self, @inputargs) = @_;
835 0           $self->SetParams(@inputargs);
836              
837 0 0         if ($self->{'debug'} != 0)
838             {
839 0           print("GetDuration:\n");
840 0           print Dumper($self) . "\n";
841             }
842            
843 0           my $videofile=$self->{'videofile'};
844            
845             ## Stream Whole File
846             # my $VideoData=`ffmpeg -i $videofile -f null /dev/null 2>&1`;
847              
848             ## Summary Only
849 0           my $VideoData=`ffmpeg -i $videofile 2>&1`;
850              
851 0 0         if ($self->{'debug'} != 0)
852             {
853 0           print $VideoData;
854             }
855            
856 0           $VideoData =~ s/\r/\n/g;
857 0           $VideoData =~ s/\n */\n/g;
858 0           my @VideoDataArray=split("\n", $VideoData);
859 0           my $DurationData;
860              
861 0           foreach my $i (0..$#VideoDataArray)
862             {
863 0 0         if ( $VideoDataArray[$i] =~ /Duration/ )
864             {
865 0           $DurationData=$VideoDataArray[$i];
866             }
867              
868             }
869              
870 0 0         if ($self->{'debug'} != 0)
871             {
872 0           print("DurationData---> $DurationData \n");
873             }
874            
875 0           $DurationData =~ s/ //g;
876 0           my @DurationArray=split(",", $DurationData);
877            
878 0           my @timearray=split(":", $DurationArray[0]);
879 0           my $DurationHMS=$timearray[1] . ":" . $timearray[2] . ":" . $timearray[3];
880            
881 0           my $DurationSecs=($timearray[1] * 3600) + ($timearray[2] * 60 ) + $timearray[3];
882              
883 0           $self->{'DurationSecs'} = $DurationSecs;
884            
885 0           return($DurationSecs);
886             }
887             ### End GetDuration
888              
889              
890             ##### GetStreamInfo() Get Various Stream Parameters.
891              
892              
893             sub GetStreamInfo
894             {
895 0     0 0   my ( $self, @inputargs) = @_;
896 0           $self->SetParams(@inputargs);
897              
898 0 0         if ($self->{'debug'} != 0)
899             {
900 0           print("GetStreamInfo:\n");
901 0           print Dumper($self) . "\n";
902             }
903              
904              
905 0           my $videofile=$self->{'videofile'};
906            
907 0           my $StreamInfo = {};
908 0           my $ffmpeg = {};
909 0           my $StreamCount = 0;
910            
911 0           my $ProcData=`ffmpeg -i $videofile 2>&1`;
912              
913 0 0         if ($self->{'debug'} != 0)
914             {
915 0           print ("$ProcData\n");
916             }
917              
918              
919 0           $ProcData =~ s/\r/\n/g;
920 0           $ProcData =~ s/\n */\n/g;
921 0           my @ProcDataArray=split("\n", $ProcData);
922              
923 0           foreach my $i (0..$#ProcDataArray)
924             {
925 0 0         if ($self->{'debug'} != 0)
926             {
927 0           print("--->> $ProcDataArray[$i]\n");
928             }
929              
930 0 0         if ( $ProcDataArray[$i] =~ /FFmpeg version/ )
931             {
932 0           $ProcData=$ProcDataArray[$i];
933 0           my @ProcArray=split(", ", $ProcData);
934 0           $ffmpeg->{'version'} = $ProcArray[0];
935 0           $ffmpeg->{'Copyright'} = $ProcArray[1];
936             }
937              
938 0 0         if ( $ProcDataArray[$i] =~ /built on/ )
939             {
940 0           $ProcData=$ProcDataArray[$i];
941 0           my @ProcArray=$ProcData;
942 0           $ffmpeg->{'builton'} = $ProcArray[0];
943             }
944              
945 0 0         if ( $ProcDataArray[$i] =~ /configuration:/ )
946             {
947 0           $ProcData=$ProcDataArray[$i];
948 0           my @ProcArray=$ProcData;
949 0           my @dataline = split(": ", $ProcArray[0]);
950 0           $ffmpeg->{'configuration'} = $dataline[1];
951             }
952              
953 0 0         if ( $ProcDataArray[$i] =~ /libav/ )
954             {
955 0           $ProcData=$ProcDataArray[$i];
956 0           my @ProcArray=$ProcData;
957 0           my ( $foo ) = ( $ProcArray[0] =~ m/(^.*?) /);
958 0           $ProcArray[0] =~ s/(^.*?) /$foo-/;
959 0           $ProcArray[0] =~ s/ //g;
960 0           my @libav=split('-', $ProcArray[0]);
961 0           $ffmpeg->{$libav[0]} = $libav[1];
962             }
963              
964 0 0         if ( $ProcDataArray[$i] =~ /libsw/ )
965             {
966 0           $ProcData=$ProcDataArray[$i];
967 0           my @ProcArray=$ProcData;
968 0           my ( $foo ) = ( $ProcArray[0] =~ m/(^.*?) /);
969 0           $ProcArray[0] =~ s/(^.*?) /$foo-/;
970 0           $ProcArray[0] =~ s/ //g;
971 0           my @libsw=split('-', $ProcArray[0]);
972 0           $ffmpeg->{$libsw[0]} = $libsw[1];
973             }
974              
975 0 0         if ( $ProcDataArray[$i] =~ /Input/ )
976             {
977 0           $ProcData=$ProcDataArray[$i];
978 0           my @ProcArray=split(", ", $ProcData);
979 0           $ProcArray[0] =~ s/ //g;
980 0           $ProcArray[2] =~ s/from //g;
981 0           $ProcArray[2] =~ s/://g;
982 0           $ProcArray[2] =~ s/'//g;
983 0           $StreamInfo->{$ProcArray[0]}->{'container'} = $ProcArray[1];
984 0           $StreamInfo->{$ProcArray[0]}->{'source'} = $ProcArray[2];
985             }
986              
987 0 0         if ( $ProcDataArray[$i] =~ /Duration:/ )
988             {
989 0           my @dataline = ();
990 0           $ProcData=$ProcDataArray[$i];
991 0           my @ProcArray=split(", ", $ProcData);
992              
993 0           @dataline = split(": ", $ProcArray[0]);
994 0           $StreamInfo->{$dataline[0]} = $dataline[1];
995              
996 0           @dataline = split(": ", $ProcArray[1]);
997 0           $StreamInfo->{$dataline[0]} = $dataline[1];
998              
999 0           @dataline = split(": ", $ProcArray[2]);
1000 0           $StreamInfo->{$dataline[0]} = $dataline[1];
1001              
1002 0           my @timearray=split(":", $StreamInfo->{'Duration'});
1003              
1004 0           my $DurationSecs=($timearray[0] * 3600) + ($timearray[1] * 60 ) + $timearray[2];
1005              
1006 0           $StreamInfo->{'DurationSecs'} = $DurationSecs;
1007             }
1008              
1009 0 0         if ( $ProcDataArray[$i] =~ /Stream/ )
1010             {
1011 0           my @dataline = ();
1012 0           $ProcData=$ProcDataArray[$i];
1013 0           my @ProcArray=split(": ", $ProcData);
1014              
1015 0           $ProcArray[0] =~ s/ //g;
1016              
1017 0           @dataline = split("\\[", $ProcArray[0]);
1018 0           my $stream = $dataline[0];
1019              
1020 0           $StreamInfo->{$stream}->{'type'} = $ProcArray[1];
1021              
1022 0 0         if ( $StreamInfo->{$stream}->{'type'} =~ /Video/)
1023             {
1024 0           @dataline = split(", ", $ProcArray[2]);
1025 0           $StreamInfo->{$stream}->{'codec'} = $dataline[0];
1026 0           $StreamInfo->{$stream}->{'colorspace'} = $dataline[1];
1027 0           $StreamInfo->{$stream}->{'aspect'} = $dataline[2];
1028 0           $StreamInfo->{$stream}->{'bitrate'} = $dataline[3];
1029 0           $StreamInfo->{$stream}->{'framerate'} = $dataline[4];
1030 0           $StreamInfo->{$stream}->{'tbr'} = $dataline[5];
1031 0           $StreamInfo->{$stream}->{'tbn'} = $dataline[6];
1032 0           $StreamInfo->{$stream}->{'tbc'} = $dataline[7];
1033              
1034 0           $StreamCount++;
1035             }
1036              
1037 0 0         if ( $StreamInfo->{$stream}->{'type'} =~ /Audio/)
1038             {
1039 0           @dataline = split(", ", $ProcArray[2]);
1040 0           $StreamInfo->{$stream}->{'codec'} = $dataline[0];
1041 0           $StreamInfo->{$stream}->{'samplerate'} = $dataline[1];
1042 0           $StreamInfo->{$stream}->{'channels'} = $dataline[2];
1043 0           $StreamInfo->{$stream}->{'sampletype'} = $dataline[3];
1044 0           $StreamInfo->{$stream}->{'bitrate'} = $dataline[4];
1045              
1046 0           $StreamCount++;
1047             }
1048              
1049             }
1050              
1051             }
1052              
1053 0 0         if ($self->{'debug'} != 0)
1054             {
1055 0           print Dumper($ffmpeg);
1056 0           print Dumper($StreamInfo);
1057             }
1058              
1059 0           my @StreamInfo=($self->{'framerate'}, $self->{'size'});
1060 0           return(@StreamInfo);
1061             }
1062              
1063              
1064             ##### TitleSplash() Generate A Title From PostScript With Fade In And Out.
1065              
1066              
1067             sub TitleSplash
1068             {
1069              
1070 0     0 0   my ( $self, @inputargs) = @_;
1071 0           $self->SetParams(@inputargs);
1072              
1073 0 0         if ($self->{'debug'} != 0)
1074             {
1075 0           print("TitleSplash:\n");
1076 0           print Dumper($self) . "\n";
1077             }
1078            
1079 0           my $textfile=$self->{'textfile'};
1080 0           my $outputfile = `basename "$textfile" 2>&1`;
1081 0           chomp($outputfile);
1082 0           $textfile = `echo $textfile`;
1083 0           chomp($textfile);
1084              
1085 0 0         if ( ! open(FILE, $textfile) )
1086             {
1087 0           $self->{'outputfile'} = 'FFMPEG-Effect';
1088 0           $self->{'textfile'} = 'FFMPEG-Effect';
1089 0           $outputfile = $self->{'outputfile'};
1090             }
1091              
1092 0           my $videofile=$self->{'videofile'};
1093 0           my $size=$self->{'size'};
1094 0           my $framerate=$self->{'framerate'};
1095 0           my $fadeinframes=$self->{'fadeinframes'};
1096 0           my $fadeoutframes=$self->{'fadeoutframes'};
1097 0           my $holdframes=$self->{'holdframes'};
1098 0           my $titleframes=$self->{'titleframes'};
1099 0           my $color=$self->{'color'};
1100 0           my $opacity=$self->{'opacity'};
1101 0           my $width=$self->{'width'};
1102 0           my $height=$self->{'height'};
1103 0           my $DurationSecs=$self->{'DurationSecs'};
1104 0           my $prec1=$self->{'prec1'};
1105 0           my $prec2=$self->{'prec2'};
1106 0           my $aspect=$self->{'aspect'};
1107            
1108 0           my $gsize = $height . 'x' . $width;
1109              
1110 0           my $frameno=0;
1111 0           my $fadefactor=( ($opacity / $fadeinframes) );
1112            
1113 0           my $fade=($opacity / 100);
1114            
1115             ### Here is where the main difficulty is:
1116             ### GhostScript seems to be a bit buggy when generating PNG Images.
1117             ### When a PNG Image is successfully generated, the FFMPEG
1118             ### Functions usually will work just fine.
1119              
1120 0 0 0       if ( ( ! $self->{'pngfile'} ) || ( $self->{'pngfile'} eq 'none' ) )
1121             {
1122 0           $self->PSTitleFrame();
1123 0           $ProcData=`gs -dBATCH -dNOPAUSE -sDEVICE=pngalpha -g"$size" -sOutputFile=title.png Title.ps`;
1124             }
1125             else
1126             {
1127 0           $self->PSTitleFrame();
1128 0           $ProcData=`gs -dBATCH -dNOPAUSE -sDEVICE=pngalpha -g"$size" -sOutputFile=title.png Title.ps`;
1129 0           $ProcData=`convert $self->{'pngfile'} -resize $self->{'size'}! pngfile.png`;
1130 0           $ProcData=`convert pngfile.png title.png -composite -size $size composite.png`;
1131 0           $ProcData=`mv composite.png title.png`;
1132             }
1133              
1134 0           my $skipsecs=0;
1135             # print("skipsecs: $skipsecs\n");
1136 0           my $skip=sprintf("%.2f", $skipsecs);
1137 0           my $next=( 1 / $framerate);
1138             # print("skip: $skip\n");
1139             # print("nextval: $next\n");
1140            
1141 0           system("convert -size $size xc:$color $color.png");
1142              
1143 0           my $runtime = ($titleframes * $next);
1144              
1145 0           $ProcData=`ffmpeg -y -loop 1 -f image2 -i $color.png -t $runtime $outputfile-titlesplash.background.mpg 2>&1 `;
1146 0 0         if ($self->{'debug'} != 0)
1147             {
1148 0           print ("$ProcData\n");
1149             }
1150              
1151 0           $ProcData=`ffmpeg -y -i $outputfile-titlesplash.background.mpg -vf "movie=title.png [title]; [in][title] overlay=0:0" -qmin 1 -qmax 2 -g 0 -s $size titlesplash.mpg 2>&1 `;
1152 0 0         if ($self->{'debug'} != 0)
1153             {
1154 0           print ("$ProcData\n");
1155             }
1156              
1157 0           $self->FadeIn("videofile=titlesplash.mpg", "size=$size", "framerate=$framerate", "color=$color", "opacity=$opacity", "fadeinframes=$fadeinframes", "fadeoutframes=$fadeoutframes", "holdframes=$holdframes", "titleframes=$titleframes" );
1158              
1159 0           $self->FadeOut("videofile=titlesplash.mpg-fadein.mpg", "size=$size", "framerate=$framerate", "color=$color", "opacity=$opacity", "fadeinframes=$fadeinframes", "fadeoutframes=$fadeoutframes", "holdframes=$holdframes", "titleframes=$titleframes" );
1160              
1161              
1162 0           print ("Saving Output As: $outputfile-titlesplash.mpg\n");
1163 0           $ProcData=`cp $self->{'outputfile'} $outputfile-titlesplash.mpg 2>&1`;
1164 0 0         unless ($self->{'debug'} != 0)
1165             {
1166 0           $ProcData=`rm $outputfile-titlesplash.background.mpg $color.png title.png titlesplash.mpg titlesplash.mpg-fadein.mpg titlesplash.mpg-fadein.mpg-fadeout.mpg Title.ps 2>&1`;
1167             }
1168 0           return;
1169             }
1170              
1171              
1172              
1173             ##### PSTitleFrame() Returns PostScript Title Frame Template.
1174              
1175              
1176             sub PSTitleFrame {
1177              
1178 0     0 0   my ( $self, @inputargs) = @_;
1179 0           $self->SetParams(@inputargs);
1180              
1181 0 0         if ($self->{'debug'} != 0)
1182             {
1183 0           print("PSTitleFrame:\n");
1184 0           print Dumper($self) . "\n";
1185             }
1186              
1187 0           my $height = $self->{'height'};
1188 0           my $width = $self->{'width'};
1189 0           my $justify = $self->{'justify'};
1190              
1191              
1192 0           my $hscale = ( $height * 10 );
1193 0           my $wscale = ( $width * 10 );
1194            
1195 0           my $verysmallfontsize = 12;
1196 0           my $smallfontsize = 18;
1197 0           my $mediumfontsize = 28;
1198             # my $largefontsize = 43;
1199             # my $autofontsize = 310;
1200 0           my $fontsize;
1201              
1202 0           my $cyan = '0.7777';
1203 0           my $magenta = '0.7777';
1204 0           my $yellow = '0.7777';
1205 0           my $black = '0.0000';
1206              
1207              
1208 0           my $redline = "0.1111 0.7777 0.7777 0.0000 SET_CMYK \n";
1209 0           my $blueline = "0.7777 0.7777 0.1111 0.0000 SET_CMYK \n";
1210 0           my $greenline = "0.7777 0.1111 0.7777 0.0000 SET_CMYK \n";
1211 0           my $cyanline = "0.7777 0.1111 0.1111 0.0000 SET_CMYK \n";
1212 0           my $magentaline = "0.1111 0.7777 0.1111 0.0000 SET_CMYK \n";
1213 0           my $yellowline = "0.1111 0.1117 0.7777 0.0000 SET_CMYK \n";
1214 0           my $blackline = "0.9999 0.9999 0.9999 0.9999 SET_CMYK \n";
1215 0           my $whiteline = "0.1051 0.1049 0.1051 0.0000 SET_CMYK \n";
1216 0           my $greyline = "0.1111 0.1111 0.1111 0.5000 SET_CMYK \n";
1217              
1218              
1219 0           my $colorline = $redline;
1220 0           my $fontline;
1221              
1222 0 0         if ( lc($self->{'fontcolor'}) eq 'red' )
1223             {
1224 0           $colorline = $redline;
1225             }
1226              
1227 0 0         if ( lc($self->{'fontcolor'}) eq 'blue' )
1228             {
1229 0           $colorline = $blueline;
1230             }
1231              
1232 0 0         if ( lc($self->{'fontcolor'}) eq 'green' )
1233             {
1234 0           $colorline = $greenline;
1235             }
1236              
1237 0 0         if ( lc($self->{'fontcolor'}) eq 'cyan' )
1238             {
1239 0           $colorline = $cyanline;
1240             }
1241              
1242 0 0         if ( lc($self->{'fontcolor'}) eq 'magenta' )
1243             {
1244 0           $colorline = $magentaline;
1245             }
1246              
1247 0 0         if ( lc($self->{'fontcolor'}) eq 'yellow' )
1248             {
1249 0           $colorline = $yellowline;
1250             }
1251              
1252 0 0         if ( lc($self->{'fontcolor'}) eq 'white' )
1253             {
1254 0           $colorline = $whiteline;
1255             }
1256              
1257 0 0         if ( lc($self->{'fontcolor'}) eq 'grey' )
1258             {
1259 0           $colorline = $greyline;
1260             }
1261              
1262 0 0         if ( lc($self->{'fontcolor'}) eq 'black' )
1263             {
1264 0           $colorline = $blackline;
1265             }
1266              
1267 0 0         if ( lc($self->{'font'}) eq 'helvetica' )
1268             {
1269 0           $fontline = 'HelveticaLarge';
1270             }
1271              
1272 0 0         if ( lc($self->{'font'}) eq 'courier' )
1273             {
1274 0           $fontline = 'CourierLarge';
1275             }
1276             else
1277             {
1278 0           $fontline = 'CourierLarge';
1279             }
1280              
1281              
1282 0           my $titletextfile = $self->{'textfile'};
1283 0           $titletextfile = `echo $titletextfile`;
1284 0           chomp($titletextfile);
1285 0           print "Reading Title Content From: $titletextfile\n";
1286              
1287 0 0         if ( ! open(FILE, $titletextfile) )
1288             {
1289 0           $self->{'outputfile'} = 'FFMPEG-Effect';
1290 0           open(FILE, "+>", "$self->{'outputfile'}.titlesplash.txt");
1291 0           print(FILE "This Video\n\nProduced With:\n\nFFMPEG::Effects 1.0\n");
1292 0           close(FILE);
1293 0           $titletextfile = "$self->{'outputfile'}.titlesplash.txt";
1294             }
1295              
1296 0           open(FILE, $titletextfile);
1297 0           my $linecount = scalar(grep{/\n/});
  0            
1298              
1299 0 0         if ($self->{'debug'} != 0)
1300             {
1301 0           print("Line Count in $titletextfile: $linecount \n");
1302             }
1303              
1304 0           my $longestline = 0;
1305 0           seek( FILE, 0, 0);
1306 0           while ()
1307             {
1308 0           my $linelength = length($_);
1309 0 0         if ( $linelength > $longestline )
1310             {
1311 0           $longestline = $linelength;
1312             }
1313             }
1314            
1315 0 0 0       if ( ( ! $self->{'fontsize'} ) || ( $self->{'fontsize'} eq 'not-set' ) )
1316             {
1317 0           $fontsize = ( ( $wscale / 5 ) / $longestline );
1318             }
1319             else
1320             {
1321 0           $fontsize = $self->{'fontsize'};
1322             }
1323              
1324 0           my $pad = ( $fontsize * 2 );
1325              
1326 0           my $letterheight = ( ( 6.7 * $fontsize ) * 1 );
1327 0           my $pct = ( ( $letterheight / $hscale ) * 100 );
1328 0           my $factor = ( ( ( 98 - $pct ) / 100 ) );
1329              
1330              
1331 0           my $linexpos = 0;
1332 0           my $lineypos = ( $hscale * $factor );
1333 0           my $yspace = $lineypos;
1334              
1335 0           my $largefontsize = $fontsize;
1336              
1337 0           my $pngdata = "\n";
1338              
1339 0           my $linespace = 0;
1340 0           my $linenumber = 0;
1341 0           my $line1text = 'foo';
1342 0           my $line1size;
1343 0           my $line1ypos = 0;
1344 0           my $line1xpos = 0;
1345              
1346 0           seek( FILE, 0, 0);
1347 0           while ()
1348             {
1349 0 0         if ( /./ )
1350             {
1351 0           $linenumber++;
1352              
1353 0 0         if ( $linenumber == 1 )
1354             {
1355 0           chomp($_);
1356 0           $line1text = $_;
1357 0           my $linecharcount = length($_);
1358              
1359 1     1   1040 use integer;
  1         12  
  1         5  
1360 0           $largefontsize = $fontsize / 1;
1361 0           $fontsize = $fontsize / 1;
1362 0           $line1size = ( 5 * $fontsize * $linecharcount );
1363 1     1   48 no integer;
  1         1  
  1         5  
1364              
1365 0           $line1ypos = $lineypos;
1366 0           $linespace = ( ( $yspace / $linecount ) * 1 );
1367              
1368 0 0         if ($justify eq 'left')
1369             {
1370 0           $line1xpos = ( 0 );
1371 0           $line1xpos = ( $line1xpos + $pad );
1372             }
1373              
1374 0 0         if ($justify eq 'center')
1375             {
1376 0           my $whitespace = ( ( $wscale ) - ( $line1size ) );
1377 0           $line1xpos = ($whitespace / 2 );
1378             }
1379              
1380 0 0         if ($justify eq 'right')
1381             {
1382 0           $line1xpos = ( 0 );
1383 0           my $whitespace = ( ( $wscale ) - ( $line1size ) );
1384 0           $line1xpos = ( $whitespace - $pad );
1385             }
1386              
1387 0 0         if ($largefontsize < 1)
1388             {
1389 0           $largefontsize = 1;
1390             }
1391              
1392             }
1393              
1394 0           my $line = chomp($_);
1395 0           my $linecharcount = length($_);
1396              
1397 1     1   248 use integer;
  1         1  
  1         4  
1398 0           $largefontsize = $fontsize / 1;
1399 0           $fontsize = $fontsize / 1;
1400 0           my $linesize = ( 5 * $fontsize * $linecharcount );
1401 1     1   40 no integer;
  1         2  
  1         4  
1402              
1403 0 0         if ($justify eq 'left')
1404             {
1405 0           $linexpos = ( 0 );
1406 0           $linexpos = ( $linexpos + $pad );
1407             }
1408              
1409 0 0         if ($justify eq 'center')
1410             {
1411 0           my $whitespace = ( ( $wscale ) - ( $linesize ) );
1412 0           $linexpos = ($whitespace / 2 );
1413             }
1414              
1415 0 0         if ($justify eq 'right')
1416             {
1417 0           $linexpos = ( 0 );
1418 0           my $whitespace = ( ( $wscale ) - ( $linesize ) );
1419 0           $linexpos = ( $whitespace - $pad );
1420             }
1421              
1422              
1423 0           my $psdata = $colorline.
1424             "$fontline SETFONT \n".
1425             "GS \n".
1426             "n \n".
1427             "$linexpos $lineypos M \n".
1428             "($_) $linesize X \n".
1429             "GR \n".
1430             "\n";
1431              
1432              
1433 0           $pngdata = $pngdata . $psdata;
1434              
1435 0           $lineypos = ( $lineypos - $linespace );
1436             }
1437             else
1438             {
1439 0           my $linesize = ( 5 * $fontsize * 1 );
1440              
1441 0           my $psdata = $colorline.
1442             "$fontline SETFONT \n".
1443             "GS \n".
1444             "n \n".
1445             "0 $lineypos M \n".
1446             "( ) $linesize X \n".
1447             "GR \n".
1448             "\n";
1449              
1450 0           $pngdata = $pngdata . $psdata;
1451              
1452 0           $lineypos = ( $lineypos - $linespace );
1453             }
1454              
1455             }
1456              
1457 0           close(FILE);
1458              
1459              
1460              
1461 0           my $titleframe=<
1462             %!PS-Adobe-3.0
1463             %%Creator: FFMPEG::Effects
1464             %%Pages: 1
1465             %%DocumentNeededResources: font Helvetica Times-Roman
1466             %%EndComments
1467             %%BeginProlog
1468             /bd { bind def } bind def
1469             /n { newpath } bd
1470             /L { lineto } bd
1471             /M { moveto } bd
1472             /C { curveto } bd
1473             /RL { rlineto } bd
1474             /MR { rmoveto } bd
1475             /ST { show } bd
1476             /S { stroke } bd
1477             /SP { strokepath } bd
1478             /GS { gsave } bd
1479             /GR { grestore } bd
1480             /GRAY { setgray } bd
1481             /AXscale { 300 3000 div } bd
1482             /DOSETUP {
1483             AXscale dup scale
1484             1 setlinecap
1485             4 setlinewidth
1486             1 setlinejoin
1487             4 setmiterlimit
1488             [] 0 setdash
1489             } bd
1490             /DOCLIPBOX {
1491             n 4 2 roll 2 copy M 4 1 roll exch 2 copy L exch pop 2 copy L pop
1492             exch L closepath clip
1493             } bd
1494             /DOLANDSCAPE {
1495             90 rotate
1496             0 exch -1 mul translate
1497             } bd
1498             /UNDOLANDSCAPE {
1499             0 exch translate
1500             -90 rotate
1501             } bd
1502             /AXredict 14 dict def
1503             /X {
1504             AXredict begin
1505             exch /str exch def
1506             str stringwidth pop sub
1507             str length div 0 str ashow
1508             end
1509             } bd
1510             /FINDFONT {
1511             { findfont } stopped
1512             { /Times-Roman findfont } if
1513             } bd
1514             /POINTSCALEFONT { AXscale div scalefont } bd
1515             /DOTSCALEFONT { scalefont } bd
1516             /SETFONT { setfont } bd
1517             /p01 <000e0e0600e0e060> def
1518             /p02 <0f0f0f0ff0f0f0f0> def
1519             /p03 def
1520             /p10 <040f0f0e40f0f0e0> def
1521             /p12 <0006060000606000> def
1522             /p13 def
1523             /p21 def
1524              
1525              
1526             /DEFINEFONTS {
1527             /HelveticaLarge /Helvetica-Bold FINDFONT $largefontsize POINTSCALEFONT def
1528             /HelveticaMedium /Helvetica-Bold FINDFONT $mediumfontsize POINTSCALEFONT def
1529             /HelveticaSmall /Helvetica-Bold FINDFONT $smallfontsize POINTSCALEFONT def
1530             /HelveticaVerySmall /Helvetica-Bold FINDFONT $verysmallfontsize POINTSCALEFONT def
1531              
1532             /CourierLarge /Courier-Bold FINDFONT $largefontsize POINTSCALEFONT def
1533             /CourierMedium /Courier-Bold FINDFONT $mediumfontsize POINTSCALEFONT def
1534             /CourierSmall /Courier-Bold FINDFONT $smallfontsize POINTSCALEFONT def
1535             /CourierVerySmall /Courier-Bold FINDFONT $verysmallfontsize POINTSCALEFONT def
1536             } def
1537              
1538              
1539             %%EndProlog
1540             %%BeginSetup
1541             %%IncludeResource: font Helvetica
1542             %%IncludeResource: font Times-Roman
1543              
1544             DEFINEFONTS
1545             systemdict /setcmykcolor known
1546             {
1547             /SET_CMYK { setcmykcolor } bd
1548             }
1549             {
1550             /SET_CMYK {
1551             exch .2 mul add
1552             exch .4 mul add
1553             exch .3 mul add
1554             dup 1 gt
1555             {pop 1} {} ifelse
1556             1 exch sub setgray
1557             } bd
1558             }
1559             ifelse
1560             systemdict /colorimage known
1561             {
1562             /GET_CMYK { currentcmykcolor } bd
1563             }
1564             {
1565             /GET_CMYK {
1566             0 0 0
1567             1 currentgray sub
1568             } bd
1569             }
1570             ifelse
1571             systemdict /colorimage known
1572             {
1573             /COLORIMAGE { false 4 colorimage } bd
1574             /SELECTBUF { pop } bd
1575             }
1576             {
1577             /COLORIMAGE { image } bd
1578             /SELECTBUF { exch pop } bd
1579             }
1580             ifelse
1581             %%EndSetup
1582             %%Page: 1 1
1583             %%BeginPageSetup
1584             save /AXPageSave exch def
1585             DOSETUP
1586             $hscale DOLANDSCAPE
1587             $hscale UNDOLANDSCAPE
1588             %%EndPageSetup
1589              
1590             0.9999 0.9960 0.9999 0.0000 SET_CMYK
1591             CourierLarge SETFONT
1592             GS
1593             n
1594             $line1xpos $line1ypos M
1595             ($line1text) $line1size X
1596             GR
1597              
1598             $pngdata
1599              
1600             %%PageTrailer
1601             AXPageSave restore
1602             showpage
1603             %%Trailer
1604             %%EOF
1605             DATA
1606              
1607 0 0         open (TITLEFILE, '>', "Title.ps") or die $!;
1608 0           print(TITLEFILE $titleframe);
1609 0           close (TITLEFILE);
1610              
1611 0 0         if ($self->{'debug'} != 0)
1612             {
1613 0           print $pngdata;
1614             }
1615              
1616              
1617 0           return($titleframe);
1618              
1619             }
1620              
1621              
1622             =head1 AUTHOR
1623              
1624             Piero Bugoni, C<< >>
1625              
1626             =head1 BUGS
1627              
1628             Please Report Problems Using This Module To The ffmpeg-user
1629             mailing list. That is The Only Place That Will Be Checked.
1630              
1631              
1632             =head1 SUPPORT
1633              
1634             You can find documentation for this module with the UNIX `man` Command:
1635              
1636             man FFMPEG::Effects
1637              
1638             Otherwise, Search The ffmpeg-user mailing List for References to
1639             This Module.
1640              
1641             =head1 ACKNOWLEDGEMENTS
1642              
1643             The FFMPEG Development Crew.
1644              
1645             =head1 LICENSE AND COPYRIGHT
1646              
1647             Copyright 2011-Present Piero Bugoni.
1648              
1649             This program is free software; you can redistribute it and/or modify it
1650             under the terms of either: the GNU General Public License as published
1651             by the Free Software Foundation; or the Artistic License.
1652              
1653             See http://dev.perl.org/licenses/ for more information.
1654              
1655              
1656             =cut
1657             1; # End of FFMPEG::Effects