The results can be seen at an overlayed video
The original video I used is available at sample video to play with
I use mp3lame in my options, so if your mencoder install dosn't have the codecs, you can modify it to use whatever is safe for you, like avi or mov
The base64 encoded image, is just the Republic of Perl logo
The same idea can be extended to embedding smaller videos within another video, by extracting, resizing, and overlaying the frames in the proper order, and at the proper coordinates.
#!/usr/bin/perl use warnings; use strict; use Image::Magick; use MIME::Base64; # Usage: $0 myneat.flv/mpg/avi OR $0 r # The r option will skip ripping and recombine # the contents of the riptemp-$base subdir. # This allows you to manually edit individual files. # If more than 2 riptemp dirs are present, the first # in a dirlist will be used. So.... work on 1 at a time # in their own directories. This is just a snippet. :-) # I admit, that the Lives (Linux Video Editing System) # at http://lives.sourceforge.net/ # is much more powerful than this. Check it out, and # it's "smogrify" perl script.... which is it's workhorse. $|++; my $video = shift || 'z-men.mpg'; my $base; if($video eq 'r'){ recombine(); }else{ $video =~ /^(.+)(\.\w+)$/; $base = $1; } # only 2 IM objects reused in overlay, so they are global my $bimage = Image::Magick->new; #reused objects my $oimage = Image::Magick->new; #reused objects rip(); make_overlay_graphic(); overlay(); recombine(); exit; #######################################################3 sub rip{ #rip to jpg's and audio #will make it's own temp dir my @moptions =( 'mplayer', '-osdlevel', 0, '-vo', "jpeg:quality=100:outdir=riptemp-$base:maxfiles +=2000", '-noframedrop', #important for quality '-ao', "pcm:file=$base.wav", $video, ); system(@moptions); } #########################################################3 sub make_overlay_graphic{ # enter lines of text as array elements my @tarray; foreach (1..1500){ push @tarray , "$_ blah blah blah" } # get logo from base64encoded text my $wimage = Image::Magick->new(magick=>'png'); my $stamp = get_stamp(); $wimage->BlobToImage($stamp); #$wimage->Write('stamp.png'); #if you want to examine it #setup overlay $oimage->Set(size=>'150x1500'); #convenient for my tests #but could be calculated based on the base video frame sizes #this is just a crude demo my $rc = $oimage->Read("xc:green"); $oimage->Transparent('color' => 'green'); #not neccessary to use green here, other than to show # how green screened overlays are made =head1 IM's Annotate methods text=>string, font=>string, family=>string, style=>{Normal, Italic, Oblique, Any}, stretch=>{Normal, UltraCondensed, ExtraCondensed, Condensed, SemiCondensed, SemiExpanded, Expanded, ExtraExpanded, UltraE +xpanded}, weight=>integer, pointsize=>integer, density=>geometry, stroke=>color name, strokewidth=>integer, fill=>color name, undercolor=>color name, geometry=>geometry, gravity=>{NorthWest, North, NorthEast, West, Center, East, SouthWest, +South, SouthEast}, antialias=>{true, false}, x=>integer, y=>integer, affine=>array of float values, translate=>float, float, scale=>float, float, rotate=>float. skewX=>float, skewY=> float, align=>{Left, Center, Right}, encoding=>{UTF-8} =cut # create overlay image my $pos = 0; foreach (@tarray){ $pos+=50; $oimage->Annotate( pointsize => 12, fill => '#ffeeffff', #last 2 digits transparency in hex +ff=max text => $_, #gravity => $pos x=> 1, y=> $pos, ); # add logo every 300 if ($pos % 300 == 0){ $rc = $oimage->Composite( #gravity => "Center", compose=>'Plus', image => $wimage, #opacity => '50%', #how much transparency #tile => 0, x=> 50, y=> $pos ); } } #print "$pos\n"; $oimage->Write("$base-overlay.png"); } ##############################################3 sub overlay{ my @files = <riptemp-$base/*.jpg>; #print join "\n", @files; my $max = scalar @files; #reload $oimage undef @$oimage; $oimage->read("$base-overlay.png"); my $count = 0; my $x = 0; my $y = 0; foreach my $file ( @files ) { # operate on jpgs for effects $count++; print "\rprocessing file $file $count/$max"; $y += 2; $bimage->Read($file); $bimage->Sharpen(10); my $geom_string = '-'.$x.'-'.$y; print "\n$geom_string\n"; my $rc = $bimage->Composite( geometry => $geom_string, #'-0-500', compose=>'ATop', image => $oimage, # opacity => '100%', # tile => 0, ); $bimage->Write($file); undef @$bimage; #clear out object data # for quick testing # last if $count == 10; } print "\n\nDone effects processing\n\n"; } ##################################################################### sub recombine{ opendir my $dh, '.' or die "Error: $!\n"; my @files = grep !/^\.\.?$/, readdir $dh; @files = grep /^riptemp-(.*)$/, @files; closedir $dh; my $dir = $files[0]; $dir =~ /^riptemp-(.*)$/; my $base = $1; my @moptions =( 'mencoder', "mf://$dir/*.jpg", '-mf', 'fps=29.97', #NTSC tv video rate in '-audiofile', "$base.wav", '-srate', 22050, '-o', "$base-overlayed.mpg", '-ovc', 'lavc', '-lavcopts', 'vcodec=mpeg4:vbitrate=100', '-oac', 'mp3lame', '-audio-delay', 2, #adjust for audio syncing problems ); system(@moptions); } ###################################################################### +3 sub get_stamp{ return decode_base64( 'iVBORw0KGgoAAAANSUhEUgAAAGEAAABhBAMAAAA0KNKQAAAAG1BMVEX///8AAAAhISFCQ +kJSUlJ7 e3ucnJzw8PD////JTe+VAAAAAXRSTlMAQObYZgAACJ5JREFUeF7FmEuPuzoSxWdzb6/LMg +lbe0yH 9UjzAWyZhOWAcMLyJsqDZacVHltQCPWxxw6kn//HXYw0R62WOuHHOVXGXU7+8b/RS32yql +/+LlBe JLvrn+ZvQU+G873mXGu9VuxQ//b6UgZKnNBpMFwk4vQboOYqKAaUDTJioVoF5NfJSi5XQ9 +P6kLcA lrg1V0o2L79y4AUmYesl8dZHqxbynvDNT4mK8OLcbP0WZJgsA0sk4GFPxc+Qp1TmCGE7vw +KEMnWp oKT43Huzn+TKWNzmbH6lPYAvTwRxIN2sh3lHfozUYo7gSRjgRpmfxJa4ArMRAc9p/cNMZM +AzADSA 5DxvgbjCIU/CGgse/MCkYjkULQALZQydTUYRz8SzttiRnmy+WygPwcaSZ7/1Ja5wv0KUkS +0DmgT8 RHwzuchbLgGZ6aHL91oLk4ll1nvtvETYeQNZfbWI/DORELY+eje1rNGqztRxlcyw9Vr766 +tJJV2Z QK8EL7TBh9IwgVB6tmMFPX1plN8MAB4U5OrhB70+yxMAoGU+t+tPViBuvcXW7y3wCVm11D +035UA+ maigXeAVsDsJ/KJ0HSKCv/XTxae6Q4DYWmPS4FcpxDP0EHfqQ6yK4RYgb2kX4zfdQoQ48R +A/ruLr DHuSwBB7+APJAa5Q9LQL3kPREFEqmLcFOpW0+ABswWfgDwAX/RarZFhgCzocLQYA0ryHYp +TtACVJ QvKft1BRC24vdTk6dZwGi/dMJEpDPIOX+Nlbt3Y+AMHW14hDXaV0I5/ZA+iAp5T08AyQvy +3iE1nD AHlf+4gyUIqsUiEeTWsJByY30MMKezURNbvCHMBrEa8kUgY2mi82j1AMiNK+hDnefPrXVI +Z2q6H8 CPEs1OqkOE1nk8cNGCc8IB3BC3iPQlIfMYHV4CNCUWMlySJj3qMMYIQRWeDrvZBpa8S5Q7 +oGMVtm zXDgEQcYTaw5cM61f3Yd77KXO8Er6BsMOkTsgXiXsM+IgHCyAGqJVXCmLqO8E3/wbt7CCu +doddiD CPBCpb4TAAyIECLate7tht/XsNLt7AwQ+1M7I12kCoL4nmm5J5xyJV6rEC9slp0ccTY9LJ +GZfKo1 0AfOFTT3TMZwxanWJiwZwHy/uDd3gQw4dDjqLIgB6oiBEa6NkYoZs/YBvAZf70QaokW8B8 +FIdIGA pIW1IKkO1txh62VSYFV0gWvVLjzkWKMZgQGoVs86sAQjy5QeyyBaH8wxwwsAXJeuWbMTAC +xxMRJX 0JxsoizIb+BxE2eoN3VpzPYGICBSziO40AwgDh9PHtNeJjIPX8kzO+Vls1sfomy96wAxWS +cvd8JD 3IYTkZDIZCmTAUpQ8lQM8TVIdXRIL9RlVo5wA4awRTy1iqZHKbiKB0a5WDdFf0qV1kYWuS +OkJf7k uGMAgyOGAreRPjDNIe6BLKPVrRzMQehMJ+Nyqb+sB3Fs1ed4m28tkQZaacqKK4A6zrGsTJ +UZrtWY gY0ehwi3lTUF4E3CtFGpNs0rLK65h1VtbrrebZKR4M6DXsHKEgxolicky1Y2N7YQZ2aNZd +5Xerhp mV+idTN6iJZu4bnPh4iCq3zJi5TsijNZaFnUdT2c9mazT3OwykcPN8Az6zE05wY7knqbAz +9lCoKU Ns2xNPXRdXdPDpr5cvRwdByj7KklgAVRpvLyADwTzTBUvF7vzXG3pwOefTXWQSNjhtjt0I +X1YF7Q 6fWxElwGVWlOl/xiTHUpwCp0Hk9i+g9uraKZJUBEg9ZlTwmblUN/0rNM6ygreg6A6k40V4 +AGw1IW YYw9JyK9CX3aaMGZzvvIpGuTGdkX7r53wssZYX6xwjWmIdaSMFObCI9aM9BNlm42e1MtZQ +sQnG6J mzpBDMUWqEHE1sdhx/jiFh1OVaQlRJssLZb7Y2bolbv9cX/asxAUgPc6EtiCJ9a3Td0vtW +JircRy 2M+jbIYog2lHvYYJkBxbxIFB4TZhltVNvuYRA51zFpz2ggvfEgV00z4/b9zmy1ECzGws4G +k++Gul t8RruI6iTHIeIt6QXoJx3uBdM2OOR2NMKe1VdXGQwIDe2PJQMhaoAp3GmfNHOhJBVVsd67 +0h9r63 BCgHuub6YBtFpgkk/hoHzkiccVLBvEN0AKIZI4E22YonIhgJPhJidOzyyqo+1X1GdPBKBC +cMGI1O kei0j069HIfUv8PHpJ9045JeCQAnAISf0uVlKqPLRmLrTyGHetQp2IPI3NUECIvWx1ROQ3 +HxmGrT 3/iuqEHgnGgmUqHWzXTPYD7NWjaF8fGjQBxYdFCayqDJR4I8pjOfXlBD/UGMEKibHRFpsB +uBXj2I dDJtLdlg4+AGb25iIqaguPDfy/hcCHr4rhtwRREZcM5wlJ4/iD/cS+fBdyZv6jnnHg6Mk2 +yO28G1 /v3c9xSE1hJiRKiOD11AAq1KxkFOb344xD1tZ9bDEV14L2JwqZiEABE4C92bBWL6/PEoam +MDQUT5 XgfjzpVwgdgDUERvMwGPWPR+HX1DgJMYr8AKiw/egK3b4++xBOJicMj7Afl+3+102vAR1e +zTmZoV OOl1QgbGLcEsMK0PqT8R+zk+dIXAbcU1W4q9c5i0Xb58Oel/OEuqyJEsourNGQd30v9kou +f4efUU 0Q32b2nP2lp80uXd5OZNftd897Ae6MoCPzPpgPYivvBw6w/4ZvEVcJW8Hz+hhZkEr/XfYr +oqvpns +COyzzqv2BrSzR4Et436rjKYLtjG0M5xm0NPJyBJncV3nWWIThJIC34rYICpMDFtjO+5xq +ENMHcE eDgSV+/5Z98d1EQWiAMc3Fi4E9C4h1P9/AN6LViOPSC2s6b1ACUU2BP+q68aKiGf8Yh4ts +HmEL4W uKfcRvqFSp6KxkZX/jW82URc/BpwLv8Sii8bdNpzkQob6Teq11wYrRRX2ii++ltfytQHxo +n7Yccp 0e+Zp7qsqkv9Yg3+P/ovrxusJ+JGDQIAAAAASUVORK5CYII='); }
|
|---|