Bugs 35, 171 - Revamped to work with CVS ffmpeg and provide better video management.
git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@1503 e3e1d417-86f3-4887-817a-d78f3d33393fpull/27/merge
parent
77b09f46fa
commit
66d4a72570
|
@ -168,7 +168,15 @@ my $event = $sth->fetchrow_hashref();
|
|||
$sth->finish();
|
||||
chdir( ZM_PATH_WEB.'/'.ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.$event->{Id} );
|
||||
( my $video_name = $event->{Name} ) =~ s/\s/_/g;
|
||||
my $video_file = "$video_name.mpg";
|
||||
my $file_rate = $rate;
|
||||
$file_rate =~ s/\./_/;
|
||||
$file_rate =~ s/_00//;
|
||||
$file_rate =~ s/0$//;
|
||||
my $file_scale = $scale;
|
||||
$file_scale =~ s/\./_/;
|
||||
$file_scale =~ s/_00//;
|
||||
$file_scale =~ s/0$//;
|
||||
my $video_file = "$video_name-$file_rate-$file_scale.mpg";
|
||||
|
||||
if ( $overwrite || !-s $video_file )
|
||||
{
|
||||
|
@ -258,7 +266,7 @@ if ( $overwrite || !-s $video_file )
|
|||
$width = int($width*$scale);
|
||||
$height = int($height*$scale);
|
||||
}
|
||||
my $command = ZM_PATH_FFMPEG." -y ".ZM_FFMPEG_OPTIONS." -r $frame_rate -s ${width}x${height} -i %0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg $video_file > mpeg.log";
|
||||
my $command = ZM_PATH_FFMPEG." -y -r $frame_rate -s ${width}x${height} ".ZM_FFMPEG_INPUT_OPTIONS." -i %0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg ".ZM_FFMPEG_OUTPUT_OPTIONS." $video_file > mpeg.log";
|
||||
print( LOG $command."\n" );
|
||||
my $output = qx($command);
|
||||
print( LOG $output."\n" );
|
||||
|
|
|
@ -23,9 +23,19 @@ if ( !canView( 'Events' ) )
|
|||
$view = "error";
|
||||
return;
|
||||
}
|
||||
$result = mysql_query( "select E.*,M.Name as MonitorName, M.Palette from Events as E, Monitors as M where E.Id = '$eid' and E.MonitorId = M.Id" );
|
||||
|
||||
if ( $user['MonitorIds'] )
|
||||
{
|
||||
$mid_sql = " and MonitorId in (".join( ",", preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).")";
|
||||
}
|
||||
else
|
||||
{
|
||||
$mid_sql = '';
|
||||
}
|
||||
$sql = "select E.*,M.Name as MonitorName,M.Width,M.Height from Events as E inner join Monitors as M on E.MonitorId = M.Id where E.Id = '$eid'$mid_sql";
|
||||
$result = mysql_query( $sql );
|
||||
if ( !$result )
|
||||
die( mysql_error() );
|
||||
die( mysql_error() );
|
||||
$event = mysql_fetch_assoc( $result );
|
||||
|
||||
if ( !isset( $rate ) )
|
||||
|
@ -33,23 +43,76 @@ if ( !isset( $rate ) )
|
|||
if ( !isset( $scale ) )
|
||||
$scale = SCALE_SCALE;
|
||||
|
||||
ob_start();
|
||||
$event_dir = ZM_DIR_EVENTS."/".$event['MonitorId']."/".sprintf( "%d", $eid );
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title><?= ZM_WEB_TITLE_PREFIX ?> - <?= $zmSlangVideo ?> - <?= $event['Name'] ?></title>
|
||||
<link rel="stylesheet" href="zm_html_styles.css" type="text/css">
|
||||
<script type="text/javascript">
|
||||
function closeWindow()
|
||||
{
|
||||
window.close();
|
||||
}
|
||||
function viewVideo(Url,Name,Width,Height)
|
||||
{
|
||||
var Win = window.open(Url,Name,"resizable,width="+Width+",height="+Height);
|
||||
}
|
||||
function deleteVideo( index )
|
||||
{
|
||||
location.replace( '<?= $PHP_FILE ?>?view=<?= $view ?>&eid=<?= $eid ?>&delete='+index );
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
if ( !empty($generate) )
|
||||
{
|
||||
?>
|
||||
<table border="0" cellspacing="0" cellpadding="4" width="100%" height="70">
|
||||
<tr>
|
||||
<td align="center" valign="middle" class="head"><?= $zmSlangGeneratingVideo ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php
|
||||
$buffer_string = "<!-- This is some long buffer text to ensure that IE flushes correctly -->";
|
||||
for ( $i = 0; $i < 4096/strlen($buffer_string); $i++ )
|
||||
{
|
||||
echo $buffer_string."\n";
|
||||
}
|
||||
?>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
ob_flush();
|
||||
ob_start();
|
||||
|
||||
if ( $video_file = createVideo( $event, $rate, $scale, $overwrite ) )
|
||||
{
|
||||
$video_path = $event_dir.'/'.$video_file;
|
||||
}
|
||||
?>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
location.replace('<?= $PHP_FILE ?>?view=<?= $view ?>&eid=<?= $eid ?>&generated=<?= $video_file?1:0 ?>');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
}
|
||||
else
|
||||
{
|
||||
?>
|
||||
<form name="video_form" method="post" action="<?= $PHP_SELF ?>">
|
||||
<input type="hidden" name="view" value="<?= $view ?>">
|
||||
<input type="hidden" name="action" value="<?= $action ?>">
|
||||
<input type="hidden" name="eid" value="<?= $eid ?>">
|
||||
<input type="hidden" name="generate" value="1">
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="2" width="96%">
|
||||
<tr><td width="50"> </td><td class="head" align="center"><?= $zmSlangVideoGenParms ?></td><td width="50" class="text" align="right"><a href="javascript: window.close();"><?= $zmSlangClose ?></a></tr>
|
||||
<tr><td width="50"> </td><td class="head" align="center"><?= $zmSlangVideoGenParms ?></td><td width="50" class="text" align="right"><a href="javascript: closeWindow();"><?= $zmSlangClose ?></a></td></tr>
|
||||
</table>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="2" width="96%">
|
||||
<tr><td width="50%"> </td><td width="50%"> </td></tr>
|
||||
|
@ -60,59 +123,101 @@ ob_start();
|
|||
<tr><td colspan="2" align="center"><input type="submit" class="form" value="<?= $zmSlangGenerateVideo ?>"></td></tr>
|
||||
</table>
|
||||
</form>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="8" width="96%">
|
||||
<?php
|
||||
if ( !empty($generate) )
|
||||
{
|
||||
?>
|
||||
<table border="0" cellspacing="0" cellpadding="4" width="100%">
|
||||
<tr><td> </td></tr>
|
||||
<tr>
|
||||
<td align="center" class="head"><?= $zmSlangGeneratingVideo ?></td>
|
||||
</tr>
|
||||
<tr><td> </td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
$buffer_string = "<!-- This is some long buffer text to ensure that IE flushes correctly -->";
|
||||
for ( $i = 0; $i < 4096/strlen($buffer_string); $i++ )
|
||||
if ( isset($generated) )
|
||||
{
|
||||
echo $buffer_string."\n";
|
||||
if ( $generated )
|
||||
{
|
||||
?>
|
||||
<tr><td align="center" valign="middle" class="head"><font color="green"><?= $zmSlangVideoGenSucceeded ?></font></td></tr>
|
||||
<?php
|
||||
}
|
||||
else
|
||||
{
|
||||
?>
|
||||
<tr><td align="center" valign="middle" class="head"><font color="red"><?= $zmSlangVideoGenFailed ?></font></td></tr>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="6" width="96%">
|
||||
<tr><td class="head" align="center"><?= $zmSlangVideoGenFiles ?></td></tr>
|
||||
</table>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="0" width="96%">
|
||||
<tr><td>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="3">
|
||||
<?php
|
||||
ob_end_flush();
|
||||
if ( $video_file = createVideo( $event, $rate, $scale, $overwrite ) )
|
||||
$video_files = array();
|
||||
$video_types = array( "mpg", "mpeg", "asf", "mov", "3gp" );
|
||||
if ( $dir = opendir( $event_dir ) )
|
||||
{
|
||||
while ( ($file = readdir( $dir )) !== false )
|
||||
{
|
||||
$file = $event_dir.'/'.$file;
|
||||
if ( is_file( $file ) )
|
||||
{
|
||||
if ( preg_match( '/\.(?:'.join( '|', $video_types ).')$/', $file ) )
|
||||
{
|
||||
$video_files[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir( $dir );
|
||||
}
|
||||
|
||||
if ( count($video_files) )
|
||||
{
|
||||
$event_dir = ZM_DIR_EVENTS."/".$event['MonitorId']."/".sprintf( "%d", $eid );
|
||||
$video_path = $event_dir.'/'.$video_file;
|
||||
?>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
location.replace('<?= $video_path ?>');
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
||||
<tr>
|
||||
<td class="text" align="center"><?= $zmSlangFormat ?></td>
|
||||
<td class="text" align="center"><?= $zmSlangSize ?></td>
|
||||
<td class="text" align="center"><?= $zmSlangRate ?></td>
|
||||
<td class="text" align="center"><?= $zmSlangScale ?></td>
|
||||
<td class="text" align="center"><?= $zmSlangAction ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
if ( isset($delete) )
|
||||
{
|
||||
unlink( $video_files[$delete] );
|
||||
unset( $video_files[$delete] );
|
||||
}
|
||||
$index = 0;
|
||||
foreach ( $video_files as $file )
|
||||
{
|
||||
preg_match( '/^(.+)-([_\d]+)-([_\d]+)\.([^.]+)$/', $file, $matches );
|
||||
$rate = (int)(100 * preg_replace( '/_/', '.', $matches[2] ) );
|
||||
$scale = (int)(100 * preg_replace( '/_/', '.', $matches[3] ) );
|
||||
$rate_text = isset($rates[$rate])?$rates[$rate]:($rate."x");
|
||||
$scale_text = isset($scales[$scale])?$scales[$scale]:($scale."x");
|
||||
?>
|
||||
<tr>
|
||||
<td class="text" align="center"><?= $matches[4] ?></td>
|
||||
<td class="text" align="center"><?= filesize( $file ) ?></td>
|
||||
<td class="text" align="center"><?= $rate_text ?></td>
|
||||
<td class="text" align="center"><?= $scale_text ?></td>
|
||||
<td class="text" align="center"><a href="javascript:viewVideo( '<?= $file ?>', 'zmVideo<?= $eid ?>-<?= $scale ?>', 12+<?= reScale( $event['Width'], $scale ) ?>, 20+<?= reScale( $event['Height'], $scale ) ?> );"><?= $zmSlangView ?></a> / <a href="<?= $file ?>" target="_blank"><?= $zmSlangDownload ?></a> / <a href="javascript: deleteVideo( <?= $index ?> )"><?= $zmSlangDelete ?></a></td>
|
||||
</tr>
|
||||
<?php
|
||||
$index++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ob_end_flush();
|
||||
?>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="zm_html_styles.css" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<p class="head" align="center"><font color="red"><br><br><?= $zmSlangVideoGenFailed ?><br><br></font></p>
|
||||
<tr><td class="text" align="center"><br><?= $zmSlangVideoGenNoFiles ?></td></tr>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ob_end_flush();
|
||||
?>
|
||||
</table>
|
||||
</td></tr>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
ob_end_flush();
|
||||
?>
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
// Simple String Replacements
|
||||
$zmSlang24BitColour = '24 bit colour';
|
||||
$zmSlang8BitGrey = '8 bit greyscale';
|
||||
$zmSlangAction = 'Action';
|
||||
$zmSlangActual = 'Actual';
|
||||
$zmSlangAddNewControl = 'Add New Control';
|
||||
$zmSlangAddNewMonitor = 'Add New Monitor';
|
||||
|
@ -213,6 +214,7 @@ $zmSlangDonateRemindMonth = 'Not yet, remind again in 1 month';
|
|||
$zmSlangDonateRemindNever = 'No, I don\'t want to donate, never remind';
|
||||
$zmSlangDonateRemindWeek = 'Not yet, remind again in 1 week';
|
||||
$zmSlangDonateYes = 'Yes, I\'d like to donate now';
|
||||
$zmSlangDownload = 'Download';
|
||||
$zmSlangDuration = 'Duration';
|
||||
$zmSlangEdit = 'Edit';
|
||||
$zmSlangEmail = 'Email';
|
||||
|
@ -249,6 +251,7 @@ $zmSlangFlippedHori = 'Flipped Horizontally';
|
|||
$zmSlangFlippedVert = 'Flipped Vertically';
|
||||
$zmSlangFocus = 'Focus';
|
||||
$zmSlangForceAlarm = 'Force Alarm';
|
||||
$zmSlangFormat = 'Format';
|
||||
$zmSlangFPS = 'fps';
|
||||
$zmSlangFPSReportInterval = 'FPS Report Interval';
|
||||
$zmSlangFrame = 'Frame';
|
||||
|
@ -465,6 +468,7 @@ $zmSlangSet = 'Set';
|
|||
$zmSlangSettings = 'Settings';
|
||||
$zmSlangShowFilterWindow = 'ShowFilterWindow';
|
||||
$zmSlangShowTimeline = 'Show Timeline';
|
||||
$zmSlangSize = 'Size';
|
||||
$zmSlangSleep = 'Sleep';
|
||||
$zmSlangSortAsc = 'Asc';
|
||||
$zmSlangSortBy = 'Sort by';
|
||||
|
@ -529,7 +533,10 @@ $zmSlangVersionRemindHour = 'Remind again in 1 hour';
|
|||
$zmSlangVersionRemindNever = 'Don\'t remind about new versions';
|
||||
$zmSlangVersionRemindWeek = 'Remind again in 1 week';
|
||||
$zmSlangVersion = 'Version';
|
||||
$zmSlangVideoGenSucceeded = 'Video Generation Succeeded!';
|
||||
$zmSlangVideoGenFailed = 'Video Generation Failed!';
|
||||
$zmSlangVideoGenFiles = 'Existing Video Files';
|
||||
$zmSlangVideoGenNoFiles = 'No Video Files Found';
|
||||
$zmSlangVideoGenParms = 'Video Generation Parameters';
|
||||
$zmSlangVideoSize = 'Video Size';
|
||||
$zmSlangVideo = 'Video';
|
||||
|
|
|
@ -455,10 +455,19 @@ my @options =
|
|||
category => 'tools',
|
||||
},
|
||||
{
|
||||
name => "ZM_FFMPEG_OPTIONS",
|
||||
default => "-hq -intra",
|
||||
description => "Additional options to ffmpeg",
|
||||
help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set. Check the ffmpeg documentation for the meaning of these and other options.",
|
||||
name => "ZM_FFMPEG_INPUT_OPTIONS",
|
||||
default => "",
|
||||
description => "Additional input options to ffmpeg",
|
||||
help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the input to ffmpeg (options that are given before to the -i option). Check the ffmpeg documentation for a full list of options which may be used here.",
|
||||
requires => [ { name=>"ZM_OPT_MPEG", value=>"ffmpeg" } ],
|
||||
type => $types{string},
|
||||
category => 'tools',
|
||||
},
|
||||
{
|
||||
name => "ZM_FFMPEG_OUTPUT_OPTIONS",
|
||||
default => "-r 25",
|
||||
description => "Additional output options to ffmpeg",
|
||||
help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the output from ffmpeg (options that are given after to the -i option). Check the ffmpeg documentation for a full list of options which may be used here.",
|
||||
requires => [ { name=>"ZM_OPT_MPEG", value=>"ffmpeg" } ],
|
||||
type => $types{string},
|
||||
category => 'tools',
|
||||
|
@ -1030,6 +1039,14 @@ my @options =
|
|||
type => $types{boolean},
|
||||
category => 'web',
|
||||
},
|
||||
{
|
||||
name => "ZM_WEB_DEFAULT_EVENTS_VIEW",
|
||||
default => "events",
|
||||
description => "What the default view of multiple events should be. This can be 'events' or 'timeline'",
|
||||
help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.",
|
||||
type => { db_type=>'string', hint=>'events|timeline', pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? 'events' : 'timeline' ) },
|
||||
category => 'web',
|
||||
},
|
||||
{
|
||||
name => "ZM_WEB_EVENTS_PER_PAGE",
|
||||
default => "25",
|
||||
|
|
Loading…
Reference in New Issue