diff --git a/scripts/zmvideo.pl.in b/scripts/zmvideo.pl.in index 2b6765420..ed88a155c 100644 --- a/scripts/zmvideo.pl.in +++ b/scripts/zmvideo.pl.in @@ -20,10 +20,37 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # ========================================================================== -# -# This script is used to create MPEG videos of events for the web pages -# or as email attachments. -# + +=head1 NAME + +zmvideo.pl - ZoneMinder Video Creation Script + +=head1 SYNOPSIS + + zmvideo.pl -e <event_id>,--event=<event_id> [--format <format>] + [--rate=<rate>] + [--scale=<scale>] + [--fps=<fps>] + [--size=<size>] + [--overwrite] + +=head1 DESCRIPTION + +This script is used to create MPEG videos of events for the web pages +or as email attachments. + +=head1 OPTIONS + + -e<event_id>, --event=<event_id> - What event to create the video for + -f<format>, --format=<format> - What format to create the video in, default is mpg. For ffmpeg only. + -r<rate>, --rate=<rate> - Relative rate, 1 = realtime, 2 = double speed, 0.5 = half speed etc. + -s<scale>, --scale=<scale> - Scale, 1 = normal, 2 = double size, 0.5 = half size etc. + -F<fps>, --fps=<fps> - Absolute frame rate, in frames per second + -S<size>, --size=<size> - Absolute video size, WxH or other specification supported by ffmpeg + -o, --overwrite - Whether to overwrite an existing file, off by default. + -v, --version - Outputs the currently installed version of ZoneMinder + +=cut use strict; use bytes; @@ -39,6 +66,7 @@ use DBI; use Data::Dumper; use POSIX qw(strftime); use Getopt::Long qw(:config no_ignore_case ); +use autouse 'Pod::Usage'=>qw(pod2usage); $| = 1; @@ -60,77 +88,66 @@ my $version = 0; my @formats = split( /\s+/, $Config{ZM_FFMPEG_FORMATS} ); for ( my $i = 0; $i < @formats; $i++ ) { - if ( $i =~ /^(.+)\*$/ ) - { - $format = $formats[$i] = $1; - } + if ( $i =~ /^(.+)\*$/ ) + { + $format = $formats[$i] = $1; + } } -sub Usage -{ - print( " -Usage: zmvideo.pl -e <event_id>,--event=<event_id> [--format <format>] [--rate=<rate>] [--scale=<scale>] [--fps=<fps>] [--size=<size>] [--overwrite] -Parameters are :- --e<event_id>, --event=<event_id> - What event to create the video for --f<format>, --format=<format> - What format to create the video in, default is mpg. For ffmpeg only. --r<rate>, --rate=<rate> - Relative rate , 1 = realtime, 2 = double speed , 0.5 = half speed etc --s<scale>, --scale=<scale> - Scale, 1 = normal, 2 = double size, 0.5 = half size etc --F<fps>, --fps=<fps> - Absolute frame rate, in frames per second --S<size>, --size=<size> - Absolute video size, WxH or other specification supported by ffmpeg --o, --overwrite - Whether to overwrite an existing file, off by default. --v, --version - Outputs the currently installed version of ZoneMinder -"); - exit( -1 ); -} - -if ( !GetOptions( 'event=i'=>\$event_id, 'format|f=s'=>\$format, 'rate|r=f'=>\$rate, 'scale|s=f'=>\$scale, 'fps|F=f'=>\$fps, 'size|S=s'=>\$size, 'overwrite'=>\$overwrite, version=>\$version ) ) -{ - Usage(); -} +GetOptions( + 'event=i' =>\$event_id, + 'format|f=s' =>\$format, + 'rate|r=f' =>\$rate, + 'scale|s=f' =>\$scale, + 'fps|F=f' =>\$fps, + 'size|S=s' =>\$size, + 'overwrite' =>\$overwrite, + 'version' =>\$version +) or pod2usage(-exitstatus => -1); if ( $version ) { - print ZoneMinder::Base::ZM_VERSION . "\n"; - exit(0); + print ZoneMinder::Base::ZM_VERSION . "\n"; + exit(0); } if ( !$event_id || $event_id < 0 ) { - print( STDERR "Please give a valid event id\n" ); - Usage(); + print( STDERR "Please give a valid event id\n" ); + pod2usage(-exitstatus => -1); } if ( ! $Config{ZM_OPT_FFMPEG} ) { - print( STDERR "Mpeg encoding is not currently enabled\n" ); - exit(-1); + print( STDERR "Mpeg encoding is not currently enabled\n" ); + exit(-1); } if ( !$rate && !$fps ) { - $rate = 1; + $rate = 1; } if ( !$scale && !$size ) { - $scale = 1; + $scale = 1; } if ( $rate && ($rate < 0.25 || $rate > 100) ) { - print( STDERR "Rate is out of range, 0.25 >= rate <= 100\n" ); - Usage(); + print( STDERR "Rate is out of range, 0.25 >= rate <= 100\n" ); + pod2usage(-exitstatus => -1); } if ( $scale && ($scale < 0.25 || $scale > 4) ) { - print( STDERR "Scale is out of range, 0.25 >= scale <= 4\n" ); - Usage(); + print( STDERR "Scale is out of range, 0.25 >= scale <= 4\n" ); + pod2usage(-exitstatus => -1); } if ( $fps && ($fps > 30) ) { - print( STDERR "FPS is out of range, <= 30\n" ); - Usage(); + print( STDERR "FPS is out of range, <= 30\n" ); + pod2usage(-exitstatus => -1); } my ( $detaint_format ) = $format =~ /^(\w+)$/; @@ -148,9 +165,23 @@ $size = $detaint_size; my $dbh = zmDbConnect(); my @filters; -my $sql = "select max(F.Delta)-min(F.Delta) as FullLength, E.*, unix_timestamp(E.StartTime) as Time, M.Name as MonitorName, M.Width as MonitorWidth, M.Height as MonitorHeight, M.Palette from Frames as F inner join Events as E on F.EventId = E.Id inner join Monitors as M on E.MonitorId = M.Id where EventId = '$event_id' group by F.EventId"; -my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); -my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); +my $sql = " SELECT max(F.Delta)-min(F.Delta) as FullLength, + E.*, + unix_timestamp(E.StartTime) as Time, + M.Name as MonitorName, + M.Width as MonitorWidth, + M.Height as MonitorHeight, + M.Palette + FROM Frames as F + INNER JOIN Events as E on F.EventId = E.Id + INNER JOIN Monitors as M on E.MonitorId = M.Id + WHERE EventId = '$event_id' + GROUP BY F.EventId" +; +my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); +my $res = $sth->execute() + or Fatal( "Can't execute: ".$sth->errstr() ); my $event = $sth->fetchrow_hashref(); $sth->finish(); my $event_path = getEventPath( $event ); @@ -160,42 +191,42 @@ chdir( $event_path ); my @file_parts; if ( $rate ) { - my $file_rate = $rate; - $file_rate =~ s/\./_/; - $file_rate =~ s/_00//; - $file_rate =~ s/(_\d+)0+$/$1/; - $file_rate = 'r'.$file_rate; - push( @file_parts, $file_rate ); + my $file_rate = $rate; + $file_rate =~ s/\./_/; + $file_rate =~ s/_00//; + $file_rate =~ s/(_\d+)0+$/$1/; + $file_rate = 'r'.$file_rate; + push( @file_parts, $file_rate ); } elsif ( $fps ) { - my $file_fps = $fps; - $file_fps =~ s/\./_/; - $file_fps =~ s/_00//; - $file_fps =~ s/(_\d+)0+$/$1/; - $file_fps = 'R'.$file_fps; - push( @file_parts, $file_fps ); + my $file_fps = $fps; + $file_fps =~ s/\./_/; + $file_fps =~ s/_00//; + $file_fps =~ s/(_\d+)0+$/$1/; + $file_fps = 'R'.$file_fps; + push( @file_parts, $file_fps ); } if ( $scale ) { - my $file_scale = $scale; - $file_scale =~ s/\./_/; - $file_scale =~ s/_00//; - $file_scale =~ s/(_\d+)0+$/$1/; - $file_scale = 's'.$file_scale; - push( @file_parts, $file_scale ); + my $file_scale = $scale; + $file_scale =~ s/\./_/; + $file_scale =~ s/_00//; + $file_scale =~ s/(_\d+)0+$/$1/; + $file_scale = 's'.$file_scale; + push( @file_parts, $file_scale ); } elsif ( $size ) { - my $file_size = 'S'.$size; - push( @file_parts, $file_size ); + my $file_size = 'S'.$size; + push( @file_parts, $file_size ); } my $video_file = "$video_name-".$file_parts[0]."-".$file_parts[1].".$format"; if ( $overwrite || !-s $video_file ) { - Info( "Creating video file $video_file for event $event->{Id}\n" ); + Info( "Creating video file $video_file for event $event->{Id}\n" ); my $frame_rate = sprintf( "%.2f", $event->{Frames}/$event->{FullLength} ); if ( $rate ) @@ -228,22 +259,32 @@ if ( $overwrite || !-s $video_file ) $video_size = $size; } - my $command = $Config{ZM_PATH_FFMPEG}." -y -r $frame_rate ".$Config{ZM_FFMPEG_INPUT_OPTIONS}." -i %0".$Config{ZM_EVENT_IMAGE_DIGITS}."d-capture.jpg -s $video_size ".$Config{ZM_FFMPEG_OUTPUT_OPTIONS}." '$video_file' > ffmpeg.log 2>&1"; + my $command = $Config{ZM_PATH_FFMPEG} + ." -y -r $frame_rate " + .$Config{ZM_FFMPEG_INPUT_OPTIONS} + ." -i %0" + .$Config{ZM_EVENT_IMAGE_DIGITS} + ."d-capture.jpg -s $video_size " + .$Config{ZM_FFMPEG_OUTPUT_OPTIONS} + ." '$video_file' > ffmpeg.log 2>&1" + ; Debug( $command."\n" ); my $output = qx($command); my $status = $? >> 8; if ( $status ) { - Error( "Unable to generate video, check ".$event_path."/ffmpeg.log for details" ); + Error( "Unable to generate video, check " + .$event_path."/ffmpeg.log for details" + ); exit( -1 ); } - - Info( "Finished $video_file\n" ); + + Info( "Finished $video_file\n" ); } else { - Info( "Video file $video_file already exists for event $event->{Id}\n" ); + Info( "Video file $video_file already exists for event $event->{Id}\n" ); } #print( STDOUT $event->{MonitorId}.'/'.$event->{Id}.'/'.$video_file."\n" ); print( STDOUT $video_file."\n" );