#!/usr/local/bin/perl -w ########################################### # video-title-add # 2009, Mike Schilli ########################################### use strict; use Sysadm::Install qw(:all); use Imager; use Imager::Fill; use Log::Log4perl qw(:easy); use Video::FrameGrab; use File::Temp qw(tempdir tempfile); sub shell; my $title_length = 2; # length in seconds my $FONT_FILENAME = "/usr/share/fonts/" . "truetype/ttf-bitstream-vera/VeraSe.ttf"; Log::Log4perl->easy_init($ERROR); my($video_file, $upper, $lower) = @ARGV; die "usage: $0 ", "video_file upper_text lower_text" unless defined $upper; (my $video_out = $video_file) =~ s/(\.[^.]+$)/-withtitle$1/; my $video_mum = throwaway_file(".avi"); my $video_title = throwaway_file(".avi"); my $audio_title = throwaway_file(".wav"); my $audio_total = throwaway_file(".wav"); my $grabber = Video::FrameGrab->new( video => $video_file); my $meta = $grabber->meta_data(); my $height = $meta->{video_height}; my $width = $meta->{video_width}; my $dir = jpeg_dir_create( $width, $height, $upper, $lower, $meta->{video_fps} * $title_length); shell qw(mencoder -nosound), "mf://$dir/*.jpg", qw(-mf fps=30 -o), $video_title, qw(-ovc lavc -lavcopts vcodec=mjpeg); my $sample_size = $meta->{audio_bitrate} / $meta->{audio_rate} / $meta->{audio_nch} / 8; silent_wav( $title_length, $audio_title, $meta->{audio_rate}, $meta->{audio_nch}, $sample_size ); shell qw(mplayer -vc null -vo null -ao pcm), $video_file; shell "sox", $audio_title, "audiodump.wav", "-o", $audio_total; shell "mencoder", "-nosound", $video_title, $video_file, qw(-ovc lavc -lavcopts vcodec=mjpeg -o), $video_mum; # add sound shell "mencoder", $video_mum, qw(-oac copy -audiofile), $audio_total, qw(-ovc copy -o), $video_out; ########################################### sub throwaway_file { ########################################### my($suffix) = @_; my($fh, $file) = tempfile( UNLINK => 1, SUFFIX => $suffix, ); return $file; } ########################################### sub shell { ########################################### my($stdout, $stderr, $rc) = tap @_; if($rc) { die "Command @_ failed: $stderr"; } } ########################################### sub jpeg_dir_create { ########################################### my($w, $h, $upper, $lower, $n) = @_; my $img = Imager->new(xsize => $width, ysize => $height); my $black = Imager::Color->new( 0,0,0 ); $img->box(color=> $black, filled => 1); my $font = Imager::Font->new( file => $FONT_FILENAME) or die Imager->errstr; $font->align(string => $upper, size => 38, color => "white", x => $width/2, y => $height/3, halign => "center", valign => "center", image => $img ); $font->align(string => $lower, size => 38, color => "white", x => $width/2, y => $height*2/3, halign => "center", valign => "center", image => $img ); my($dir) = tempdir( CLEANUP => 1 ); my $img_file = "$dir/c.jpg"; $img->write(file => $img_file) or die "Cannot write ($!)"; for (1..$n-1) { cd $dir; (my $link = $img_file) =~ s/\./$_./; link $img_file, $link or die $!; cdback; } return $dir; } ########################################### sub silent_wav { ########################################### my($secs, $outfile, $rate, $channels, $sample_size) = @_; my($fh, $tempfile) = tempfile( UNLINK => 1, SUFFIX => ".dat" ); print $fh "; SampleRate $rate\n"; my $samples = $secs * $rate; for (my $i = 0; ($i < $samples); $i++) { print $fh $i / $rate, "\t0\n"; } close $fh; shell "sox", $tempfile, "-r", $rate, "-u", "-$sample_size", "-c", $channels, $outfile; }