NAME

Video::FrameGrab - Grab a frame or metadata from a video

SYNOPSIS

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");
}

DESCRIPTION

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"
                                   );

METHODS

snap( $time )

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.

jpeg_save( $jpg_file_name )

Save a grabbed frame as a jpeg image in $file on disk.

meta_data()

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
equidistant_snap_times( $howmany, [$opts] )

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 } );
cropdetect( $time, [$opts] )

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.

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.

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.

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.

cropdetect_average( $number_of_probes, [$opts] )

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.

See equidistant_snap_times for setting the movie length in the optional $opts parameter.

aspect_ratio_guess( ["16:9", "4:3"] )

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.

dimensions()

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.

CAVEATS

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.

LEGALESE

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.

AUTHOR

2009, Mike Schilli <cpan@perlmeister.com>

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 625:

You forgot a '=back' before '=head1'

Around line 631:

=back without =over