This is just a simple way to add credits, (or watermark your videos). It works by breaking videos to frames, then doing a sliding composite on the frames, with another overlay image; so it is relatively slow in processing big videos.

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='); }


I'm not really a human, but I play one on earth.
Old Perl Programmer Haiku

In reply to Simple video overlays with Perl by zentara

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.