Navigation

Videojs navigation now uses ajax.  Feels and is faster.  Some improvements, namely if zms ever crashes we can still navigate.  Both zms and videojs update the address bar so refreshing a page doesn't return you to the first event.
pull/3122/head
digital-gnome 2017-10-21 22:08:18 -04:00
parent ff8d067639
commit ecb980c66f
3 changed files with 49 additions and 21 deletions

View File

@ -283,6 +283,17 @@ function convertLabelFormat(LabelFormat, monitorName){
}
function addVideoTimingTrack(video, LabelFormat, monitorName, duration, startTime){
//This is a hacky way to handle changing the texttrack. If we ever upgrade vjs in a revamp replace this. Old method preserved because it's the right way.
let cues = vid.textTracks()[0].cues();
let labelFormat = convertLabelFormat(LabelFormat, monitorName);
startTime = moment(startTime);
for (let i = 0; i <= duration; i++) {
cues[i] = {id: i, index: i, startTime: i, Ca: i+1, text: startTime.format(labelFormat)};
startTime.add(1, 's');
}
}
/*
var labelFormat = convertLabelFormat(LabelFormat, monitorName);
var webvttformat = 'HH:mm:ss.SSS', webvttdata="WEBVTT\n\n";
@ -304,6 +315,7 @@ function addVideoTimingTrack(video, LabelFormat, monitorName, duration, startTim
track.src = 'data:plain/text;charset=utf-8,'+encodeURIComponent(webvttdata);
video.appendChild(track);
}
*/
function changeGroup( e, depth ) {
var group_id = $('group'+depth).get('value');

View File

@ -154,20 +154,11 @@ if ( $Event->DefaultVideo() ) {
<div id="videoFeed">
<video id="videoobj" class="video-js vjs-default-skin" width="<?php echo reScale( $Event->Width(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $scale ) ?>" data-setup='{ "controls": true, "playbackRates": [0.5, 1, 1.5, 2, 4, 8, 16, 32, 64, 128, 256], "autoplay": true, "preload": "auto", "plugins": { "zoomrotate": { "zoom": "<?php echo $Zoom ?>"}}}'>
<source src="<?php echo $Event->getStreamSrc( array( 'mode'=>'mpeg','format'=>'h264' ) ); ?>" type="video/mp4">
<track id="monitorCaption" kind="captions" label="English" srclang="en" src='data:plain/text;charset=utf-8,"WEBVTT\n\n 00:00:00.000 --> 00:00:01.000 ZoneMinder"' default>
Your browser does not support the video tag.
</video>
</div>
<!--script>includeVideoJs();</script-->
<script type="text/javascript">
var LabelFormat = "<?php echo validJsStr($Monitor->LabelFormat())?>";
var monitorName = "<?php echo validJsStr($Monitor->Name())?>";
var duration = <?php echo $Event->Length() ?>, startTime = '<?php echo $Event->StartTime() ?>';
addVideoTimingTrack(document.getElementById('videoobj'), LabelFormat, monitorName, duration, startTime);
nearEventsQuery( eventData.Id );
vjsReplay(<?php echo (strtotime($Event->StartTime()) + $Event->Length())*1000 ?>);
</script>
<p id="dvrControls" class="dvrControls">
<input type="button" value="&lt;+" id="prevBtn" title="<?php echo translate('Prev') ?>" class="inactive" onclick="streamPrev( true );"/>

View File

@ -177,7 +177,7 @@ var zmsBroke = false; //Use alternate navigation if zms has crashed
function getCmdResponse( respObj, respText ) {
if ( checkStreamForErrors( "getCmdResponse", respObj ) ) {
console.log('Got an error from getCmdResponse');
var zmsBroke = true;
zmsBroke = true;
return;
}
@ -302,7 +302,11 @@ function streamFastRev( action ) {
function streamPrev(action) {
if (action) {
if (vid || PrevEventDefVideoPath.indexOf("view_video") >=0 || $j("#vjsMessage").length || zmsBroke) { //handles this or prev being video.js, or end of events
$j(".vjsMessage").remove();
if (vid && PrevEventDefVideoPath.indexOf("view_video") > 0) {
CurEventDefVideoPath = PrevEventDefVideoPath;
eventQuery(prevEventId);
} else if (zmsBroke || (vid && PrevEventDefVideoPath.indexOf("view_video") < 0) || $j("#vjsMessage").length || PrevEventDefVideoPath.indexOf("view_video") > 0) {//zms broke, leaving videojs, last event, moving to videojs
location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery);
} else {
streamReq.send(streamParms+"&command="+CMD_PREV);
@ -312,13 +316,22 @@ function streamPrev(action) {
function streamNext(action) {
if (action) {
$j(".vjsMessage").remove();//This shouldn't happen
if (nextEventId == 0) { //handles deleting last event.
let replaceStream = $j(vid ? "#videoobj" : "#evtStream");
replaceStream.replaceWith('<p class="vjsMessage" style="width:' + replaceStream.css("width") + '; height: ' + replaceStream.css("height") + ';line-height: ' + replaceStream.css("height") + ';">No more events</p>');
} else if (vid || NextEventDefVideoPath.indexOf("view_video") >=0 || zmsBroke) { //handles current or next switch to video.js
vid ? vid.pause() : streamPause();
let hideContainer = $j( vid ? "#eventVideo" : "#imageFeed");
let hideStream = $j(vid ? "#videoobj" : "#evtStream").height() + (vid ? 0 :$j("#progressBar").height());
hideContainer.prepend('<p class="vjsMessage" style="height: ' + hideStream + 'px; line-height: ' + hideStream + 'px;">No more events</p>');
if (vid == null) zmsBroke = true;
return;
}
if (vid && NextEventDefVideoPath.indexOf("view_video") > 0) { //on and staying with videojs
CurEventDefVideoPath = NextEventDefVideoPath;
eventQuery(nextEventId);
} else if (zmsBroke || (vid && NextEventDefVideoPath.indexOf("view_video") < 0) || NextEventDefVideoPath.indexOf("view_video") > 0) {//reload zms, leaving vjs, moving to vjs
location.replace(thisUrl + '?view=event&eid=' + nextEventId + filterQuery + sortQuery);
} else {
streamReq.send( streamParms+"&command="+CMD_NEXT );
streamReq.send(streamParms+"&command="+CMD_NEXT);
}
}
}
@ -349,6 +362,7 @@ function streamQuery() {
var slider = null;
var scroll = null;
var CurEventDefVideoPath = null;
function getEventResponse( respObj, respText ) {
if ( checkStreamForErrors( "getEventResponse", respObj ) ) {
@ -376,6 +390,7 @@ function getEventResponse( respObj, respText ) {
$('dataScore').set( 'text', eventData.TotScore+"/"+eventData.AvgScore+"/"+eventData.MaxScore );
$('eventName').setProperty( 'value', eventData.Name );
history.replaceState(null, null, '?view=event&eid=' + eventData.Id + filterQuery + sortQuery);//if popup removed, check if this allows forward
if ( canEditEvents ) {
if ( parseInt(eventData.Archived) ) {
$('archiveEvent').addClass( 'hidden' );
@ -388,7 +403,13 @@ function getEventResponse( respObj, respText ) {
// Technically, events can be different sizes, so may need to update the size of the image, but it might be better to have it stay scaled...
//var eventImg = $('eventImage');
//eventImg.setStyles( { 'width': eventData.width, 'height': eventData.height } );
drawProgressBar();
if (vid) {
vid.src({type: 'video/mp4', src: CurEventDefVideoPath}); //Currently mp4 is all we use
initialAlarmCues(eventData.Id);//ajax and render, new event
addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime);
} else {
drawProgressBar();
}
nearEventsQuery( eventData.Id );
}
@ -794,7 +815,7 @@ function videoEvent() {
// Called on each event load because each event can be a different width
function drawProgressBar() {
var barWidth = (eventData.Width * $j('#scale').val()) / SCALE_BASE;
let barWidth = $j('#evtStream').width();
$j('#progressBar').css( 'width', barWidth );
}
@ -808,7 +829,7 @@ function updateProgressBar() {
} // end function updateProgressBar()
// Handles seeking when clicking on the progress bar.
function progressBarSeek (){
function progressBarNav (){
$j('#progressBar').click(function(e){
var x = e.pageX - $j(this).offset().left;
var seekTime = (x / $j('#progressBar').width()) * parseFloat(eventData.Length);
@ -927,7 +948,10 @@ function initPage() {
//FIXME prevent blocking...not sure what is happening or best way to unblock
if ($j('#videoobj').length) {
vid = videojs("videoobj");
initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues after videojs is. should be only call to initialAlarmCues on vjs streams
addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime);
$j(".vjs-progress-control").append('<div class="alarmCue"></div>');//add a place for videojs only on first load
nearEventsQuery(eventData.Id);
initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues after videojs is initialized
vjsReplay();
}
if (vid) {
@ -949,9 +973,10 @@ function initPage() {
window.videoobj.load();
streamPlay(); */
} else {
progressBarSeek ();
progressBarNav ();
streamCmdTimer = streamQuery.delay( 250 );
eventQuery.pass( eventData.Id ).delay( 500 );
initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues for zms.
if ( canStreamNative ) {
var streamImg = $('imageFeed').getElement('img');