Video::FrameGrab - Grab a frame or metadata from a video
use Video::FrameGrab; my $grabber = Video::FrameGrab->new( video => "movie.avi" ); my $jpg_data = $grabber->snap( "00:00:10" ); $grabber->jpeg_save("snapshot.jpg"); print "This movie is ", $grabber->meta_data()->{length}, " seconds long\n"; # Snap 10 frames at constant intervals throughout the movie for my $p ( $grabber->equidistant_snap_times(10) ) { $grabber->snap( $p ); $grabber->jpeg_save("frame-at-$p.jpg"); }
Video::FrameGrab grabs a frame at the specified point in time from the specified video file and returns its JPEG data.
It uses mplayer for the heavy lifting behind the scenes and therefore requires it to be installed somewhere in the PATH. If mplayer is somewhere else, its location can be provided to the constructor:
my $grabber = Video::FrameGrab->new( mplayer => "/path/to/mplayer", video => "movie.avi" );
Grabs a frame from the movie at time $time. Time is given as HH::MM::SS, just as mplayer likes it. Returns the raw jpeg data of the captured frame on success and undef if an error occurs.
Save a grabbed frame as a jpeg image in $file on disk.
Runs mplayer's identify() function and returns a reference to a hash containing something like
demuxer => MOV video_format => AVC1 video_bitrate => 0 video_width => 320 video_height => 240 video_fps => 29.970 video_aspect => 0.0000 audio_format => MP4A audio_bitrate => 0 audio_rate => 48000 audio_nch => 2 length => 9515.94
If you want to snap N frames at constant intervals throughout the movie, use equidistant_snap_times( $n ) to get a list of timestamps you can use later pass to snap(). For example, on a two hour movie, equidistant_snap_times( 5 ) will return
00:20:00 00:40:00 01:00:00 01:20:00 01:40:00
as a list of strings. The movie length is determined by a call to meta data, but some formats don't allow retrieving the movie length that way, therefore the optional options hash can set the movie_length entry to the movie length (or the length of the overall interval to perform the snapshots in) in seconds.
my @times = $fg->equidistant_snap_times( $howmany, { movie_length => 3600 } );
If this is a 16:9 movie converted to 4:3 format, the black bars at the bottom and the top of the screen should be cropped out. To help with this task, cropdetect will return a list of ($width, $height, $x, $y) to be passed to mplayer/mencoder in the form -vf crop=w:h:x:y to accomplish the suggested cropping.
cropdetect
-vf crop=w:h:x:y
The default algorithm is a homegrown detection mechanism {algorithm => "schilli"}, which first blurs the image with the Gaussian Blur algorithm with a radius of $opts->{gaussian_blur_radius} (which defaults to 3), and then measures if any of the left, right, upper or lower border pixel lines of the snapped frame average an intensity of less than $opts->{min_intensity_average}, which defaults to 20.
{algorithm => "schilli"}
$opts->{gaussian_blur_radius}
$opts->{min_intensity_average}
Note that this is just a guess and might be incorrect at times. In a dark scene, black pixels might protrude far into the video, making it impossible to detect the border reliably. However, if you overlay a number of frames, obtained at several times during the movie (e.g. by using the equidistant_snap_times method described above), the result is fairly predicatblye and accurate. cropdetect_average, described below, does exactly that.
cropdetect_average
The alternative algorithm, "mplayer", asks mplayer to come up with a recommendation on how to crop the video. This technique delivers incorrect results if there are sporadic white spots within the dark bars.
"mplayer"
Takes $number_of_probes from the movie at equidistant intervals, overlays the frames and performs a border detection on the resulting images, which is almost white in the viewing area.
$number_of_probes
See equidistant_snap_times for setting the movie length in the optional $opts parameter.
equidistant_snap_times
$opts
This function will take the width and height of the video and map it to the best matching aspect ratio given in a reference to an array.
Snaps a frame in the middle of the movie, determines its width and height and returns them in a list:
my($width, $height) = $grabber->dimensions();
Dimensions are usually also available via the meta_data() call. dimensions() works even in absence of meta data.
Note that the mplayer-based frame grabbing mechanism used in this module allows you to snap a picture about every 10 seconds into the movie, on shorter intervals, you'll get the same frame back.
Copyright 2009 by Mike Schilli, all rights reserved. This program is free software, you can redistribute it and/or modify it under the same terms as Perl itself.
2009, Mike Schilli <cpan@perlmeister.com>
2 POD Errors
The following errors were encountered while parsing the POD:
You forgot a '=back' before '=head1'
=back without =over
To install Video::FrameGrab, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Video::FrameGrab
CPAN shell
perl -MCPAN -e shell install Video::FrameGrab
For more information on module installation, please visit the detailed CPAN module installation guide.