1
0
Fork 0
mirror of https://gitlab.com/Shinobi-Systems/ShinobiCE.git synced 2025-03-09 15:40:15 +00:00

Teenage Turtle

This commit is contained in:
Moe 2018-08-23 14:13:06 -07:00
parent a80c1e4e97
commit 157bf6feb0
14 changed files with 1530 additions and 563 deletions

View file

View file

1162
camera.js

File diff suppressed because it is too large Load diff

View file

@ -23,6 +23,7 @@
"pluginKeys":{
"Motion":"change_this_to_something_very_random____make_sure_to_match__/plugins/motion/conf.json",
"OpenCV":"change_this_to_something_very_random____make_sure_to_match__/plugins/opencv/conf.json",
"OpenALPR":"SomeOpenALPRkeySoPeopleDontMessWithYourShinobi"
"OpenALPR":"SomeOpenALPRkeySoPeopleDontMessWithYourShinobi",
"PythonYolo":"SomeOpenALPRkeySoPeopleDontMessWithYourShinobi"
}
}

View file

@ -248,11 +248,15 @@
"info": [
{
"name": "detail=stream_type",
"field": "Stream Type",
"field": "Stream Type",
"description": "The method that will used to consume the video stream.",
"default": "HLS",
"example": "",
"possible": [
{
"name": "Poseidon",
"info": "Simulates a streaming MP4 file but using the data of a live stream. Includes Audio. Some browsers can play it like a regular MP4 file. Streams over HTTP or WebSocket."
},
{
"name": "MJPEG",
"info": "Standard Motion JPEG image. No audio."

View file

@ -114,6 +114,10 @@
"Saved Filters": "Saved Filters",
"Filter Name": "Filter Name",
"Find Where": "Find Where",
"Reason": "Reason",
"Detection Engine": "Detection Engine",
"X Point": "X Point",
"Y Point": "Y Point",
"Sort By": "Sort By",
"Start Time": "Start Time",
"End Time": "End Time",
@ -128,6 +132,10 @@
"Greater Than": "Greater Than",
"Less Than": "Less Than",
"Less Than or Equal to": "Less Than or Equal to",
"Contains": "Contains",
"Does Not Contain": "Does Not Contain",
"AND": "AND",
"OR": "OR",
"Like": "Like",
"Matches": "Matches",
"Not Matches": "Not Matches",
@ -293,6 +301,8 @@
"Recording Timestamp": "Recording Timestamp",
"Recording Watermark": "Recording Watermark",
"Region Editor": "Region Editor",
"Detector Filters": "Detector Filters",
"Filter for Objects only": "Filter for Objects only",
"Custom": "Custom",
"Detector": "Detector",
"Connected": "Connected",
@ -380,6 +390,7 @@
"Recording Flags": "Recording Flags",
"Output Method": "Output Method",
"Webhook": "Webhook",
"Event Webhook Error": "Event Webhook Error",
"Webhook URL": "Webhook URL",
"Command on Trigger": "Command on Trigger",
"Command": "Command",
@ -388,6 +399,7 @@
"Save Events to SQL": "Save Events to SQL",
"Email on Trigger": "Email on Trigger <small>Emails go to the main account holder's login address.</small>",
"Attach Video Clip": "Attach Video Clip",
"Discord": "Discord",
"Discord Alert on Trigger": "Discord Alert on Trigger",
"Allow Next Email": "Allow Next Email <small>in Minutes</small>",
"Allow Next Discord Alert": "Allow Next Discord Alert <small>in Minutes</small>",
@ -459,6 +471,7 @@
"Audio": "Audio",
"Mute Audio": "Mute Audio",
"No Audio": "No Audio",
"Popout Monitor on Event": "Popout Monitor on Event",
"aac": "aac",
"ac3": "ac3",
"libmp3lame": "libmp3lame",
@ -473,6 +486,7 @@
"Bottom Left": "Bottom Left",
"WebM (libvpx)": "WebM (libvpx)",
"Poseidon": "Poseidon",
"HEVC (H.265)": "HEVC (H.265)",
"MP4 (copy, libx264, libx265)": "MP4 (copy, libx264, libx265)",
"Default": "Default",
"libvpx (Default)": "libvpx (Default)",
@ -517,8 +531,10 @@
"No Videos Found": "No Videos Found",
"FileNotExistText": "Cannot save non existant file. Something went wrong.",
"CameraNotRecordingText": "Settings may be incompatible. Check encoders. Restarting...",
"Camera is not running": "Camera is not running",
"Camera is not recording": "Camera is not recording",
"Camera is not streaming": "Camera is not streaming",
"Process Started": "Process Started",
"Restarting Process": "Restarting Process",
"Restarting": "Restarting",
"Starting": "Starting",
@ -660,6 +676,10 @@
"hevc_qsv": "H.265 (Quick Sync Video)",
"vp8_qsv": "VP8 (Quick Sync Video)",
"mpeg2_qsv": "MPEG2 (Quick Sync Video)",
"h264_mmal": "H.264 (Raspberry Pi)",
"mpeg2_mmal": "MPEG-2 (Raspberry Pi)",
"mpeg4_mmal": "MPEG-4 (Raspberry Pi)",
"h264_omx": "H.264 openMAX (Raspberry Pi)",
"h264_vaapi": "H.264 VA-API (Intel HW Accel)",
"h264_nvenc": "H.264 NVENC (NVIDIA HW Accel)",
"hevc_nvenc": "H.265 NVENC (NVIDIA HW Accel)",

View file

@ -610,6 +610,10 @@
"h264_nvenc": "H. 264 NVENC (NVIDIA HW Accel)",
"h264_qsv": "H. 264 (Quick Sync Video)",
"h264_vaapi": "H. 264 VA-API (Intel HW Accel)",
"h264_mmal": "H.264 (Raspberry Pi)",
"mpeg2_mmal": "MPEG-2 (Raspberry Pi)",
"mpeg4_mmal": "MPEG-4 (Raspberry Pi)",
"h264_omx": "H.264 openMAX (Raspberry Pi)",
"hevc_cuvid": "H. 265 CUVID",
"hevc_nvenc": "H. 265 NVENC (NVIDIA HW Accel)",
"hevc_qsv": "H. 265 (Quick Sync Video)",

View file

@ -287,6 +287,7 @@ form.modal-body{margin:0}
.dropdown-menu.scrollable{max-height:300px}
.upload_file input{display:none}
#video_preview .stream-objects{right:0;margin:auto;display:inline-block;position:relative;width:auto}
.stream-block,.stream-objects{overflow: hidden!important}
.stream-objects{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}
.stream-objects .tag{position:absolute;bottom:100%;left:0;background:red;color:#fff;font-family:monospace;font-size:80%;border-radius:5px 5px 0 0 ;padding:3px 5px;}
.stream-objects .stream-detected-object{position:absolute;top:0;left:0;border:3px solid red;background:transparent;border-radius:5px}

View file

@ -383,6 +383,9 @@ switch($user.details.lang){
case'flv':
streamURL=$.ccio.init('location',user)+user.auth_token+'/flv/'+d.ke+'/'+d.mid+'/s.flv'
break;
case'h265':
streamURL=$.ccio.init('location',user)+user.auth_token+'/h265/'+d.ke+'/'+d.mid+'/s.hevc'
break;
case'mp4':
streamURL=$.ccio.init('location',user)+user.auth_token+'/mp4/'+d.ke+'/'+d.mid+'/s.mp4'
break;
@ -514,7 +517,7 @@ switch($user.details.lang){
$.ccio.mon_groups[b][v.mid]=v;
})
}catch(er){
}
})
return $.ccio.mon_groups;
@ -655,7 +658,7 @@ switch($user.details.lang){
d.fn=function(){
if(!d.speed){d.speed=1000}
switch(d.d.stream_type){
case'b64':case'pam':
case'b64':case'h265':
d.p.resize()
break;
case'hls':case'flv':case'mp4':
@ -770,8 +773,10 @@ switch($user.details.lang){
ctx.drawImage(img, 0, 0,c.width,c.height);
extend(atob(c.toDataURL('image/jpeg').split(',')[1]),c.width,c.height)
break;
case'pam':
alert('Need to add')
case'h265':
var c = $('[mid='+e.mon.mid+'].monitor_item canvas')[0];
var ctx = c.getContext('2d');
extend(atob(c.toDataURL('image/jpeg').split(',')[1]),c.width,c.height)
break;
case'b64':
base64 = e.mon.last_frame.split(',')[1];
@ -779,7 +784,7 @@ switch($user.details.lang){
image_data.src = base64;
extend(atob(base64),image_data.width,image_data.height)
break;
case'jpeg':
case'jpeg':case'h265':
url=e.p.find('.stream-element').attr('src');
image_data = new Image();
image_data.src = url;
@ -1129,7 +1134,7 @@ switch($user.details.lang){
case'jpeg':
tmp+='<img class="stream-element">';
break;
default://base64
default://base64//h265
tmp+='<canvas class="stream-element"></canvas>';
break;
}
@ -1153,6 +1158,63 @@ switch($user.details.lang){
}
$.ccio.init('ls')
break;
case'detector-filters-where':
if(!d)d={};
d.id=$('#filters_where .row').length;
if(!d.p1){d.p1='indifference'}
if(!d.p2){d.p2='='}
if(!d.p3){d.p3=''}
if(!d.p4){d.p4='&&'}
tmp+='<div class="row where-row">'
tmp+=' <div class="form-group col-md-3">'
tmp+=' <label>'
tmp+=' <select class="form-control" where="p1">'
tmp+=' <option value="indifference" selected><%-cleanLang(lang['Indifference'])%></option>'
tmp+=' <option value="name"><%-cleanLang(lang['Region Name'])%></option>'
tmp+=' <option value="reason"><%-cleanLang(lang['Reason'])%></option>'
tmp+=' <option value="plug"><%-cleanLang(lang['Detection Engine'])%></option>'
tmp+=' <optgroup label="Matrix">'
tmp+=' <option value="tag"><%-cleanLang(lang['Object Tag'])%></option>'
tmp+=' <option value="confidence"><%-cleanLang(lang['Confidence'])%></option>'
tmp+=' <option value="x"><%-cleanLang(lang['X Point'])%></option>'
tmp+=' <option value="y"><%-cleanLang(lang['Y Point'])%></option>'
tmp+=' <option value="height"><%-cleanLang(lang['Height'])%></option>'
tmp+=' <option value="width"><%-cleanLang(lang['Width'])%></option>'
tmp+=' </optgroup>'
tmp+=' </select>'
tmp+=' </label>'
tmp+=' </div>'
tmp+=' <div class="form-group col-md-3">'
tmp+=' <label>'
tmp+=' <select class="form-control" where="p2">'
tmp+=' <option value="===" selected><%-cleanLang(lang['Equal to'])%></option>'
tmp+=' <option value="!=="><%-cleanLang(lang['Not Equal to'])%></option>'
tmp+=' <option value="indexOf"><%-cleanLang(lang['Contains'])%></option>'
tmp+=' <option value="!indexOf"><%-cleanLang(lang['Does Not Contain'])%></option>'
tmp+=' <optgroup label="For Numbers">'
tmp+=' <option value=">="><%-cleanLang(lang['Greater Than or Equal to'])%></option>'
tmp+=' <option value=">"><%-cleanLang(lang['Greater Than'])%></option>'
tmp+=' <option value="<"><%-cleanLang(lang['Less Than'])%></option>'
tmp+=' <option value="<="><%-cleanLang(lang['Less Than or Equal to'])%></option>'
tmp+=' </optgroup>'
tmp+=' </select>'
tmp+=' </label>'
tmp+=' </div>'
tmp+=' <div class="form-group col-md-3">'
tmp+=' <label>'
tmp+=' <input class="form-control" placeholder="Value" title="<%-cleanLang(lang.Value)%>" where="p3">'
tmp+=' </label>'
tmp+=' </div>'
tmp+=' <div class="form-group col-md-3">'
tmp+=' <label>'
tmp+=' <select class="form-control" where="p4">'
tmp+=' <option value="&&" selected><%-cleanLang(lang['AND'])%></option>'
tmp+=' <option value="||"><%-cleanLang(lang['OR'])%></option>'
tmp+=' </select>'
tmp+=' </label>'
tmp+=' </div>'
tmp+='</div>'
break;
case'filters-where':
if(!d)d={};
d.id=$('#filters_where .row').length;
@ -1382,9 +1444,12 @@ switch($user.details.lang){
{label:'<%-cleanLang(lang['hevc_cuvid'])%>',value:'hevc_cuvid',group:'NVIDIA'},
{label:'<%-cleanLang(lang['mjpeg_cuvid'])%>',value:'mjpeg_cuvid',group:'NVIDIA'},
{label:'<%-cleanLang(lang['mpeg4_cuvid'])%>',value:'mpeg4_cuvid',group:'NVIDIA'},
{label:'<%-cleanLang(lang['h264_qsv'])%>',value:'h264_qsv',group:'QuickSync Video'},
{label:'<%-cleanLang(lang['hevc_qsv'])%>',value:'hevc_qsv',group:'QuickSync Video'},
{label:'<%-cleanLang(lang['mpeg2_qsv'])%>',value:'mpeg2_qsv',group:'QuickSync Video'},
{label:'<%-cleanLang(lang['h264_qsv'])%>',value:'h264_qsv',group:'Quick Sync Video'},
{label:'<%-cleanLang(lang['hevc_qsv'])%>',value:'hevc_qsv',group:'Quick Sync Video'},
{label:'<%-cleanLang(lang['mpeg2_qsv'])%>',value:'mpeg2_qsv',group:'Quick Sync Video'},
{label:'<%-cleanLang(lang['h264_mmal'])%>',value:'h264_mmal',group:'Raspberry Pi'},
{label:'<%-cleanLang(lang['mpeg2_mmal'])%>',value:'mpeg2_mmal',group:'Raspberry Pi'},
{label:'<%-cleanLang(lang['mpeg4_mmal'])%>',value:'mpeg4_mmal',group:'Raspberry Pi'},
]
},
{
@ -1494,6 +1559,7 @@ switch($user.details.lang){
tmp+=' <option value="h264_qsv"><%-lang["h264_qsv"]%></option>'
tmp+=' <option value="hevc_qsv"><%-lang["hevc_qsv"]%></option>'
tmp+=' <option value="mpeg2_qsv"><%-lang["mpeg2_qsv"]%></option>'
tmp+=' <option value="h264_omx"><%-lang["h264_omx"]%></option>'
tmp+=' </optgroup>'
tmp+=' </select></div>'
tmp+=' </label>'
@ -1654,6 +1720,14 @@ switch($user.details.lang){
k.mon=$.ccio.mon[d.ke+d.mid+user.auth_token]
$.ccio.init('monitorInfo',k)
break;
case'detector-filters-where':
$('#detector_filters_where').append(tmp);
$('#detector_filters_where .row [where="p4"][disabled]').prop('disabled',false)
$('#detector_filters_where .row:last [where="p1"]').val(d.p1)
$('#detector_filters_where .row:last [where="p2"]').val(d.p2)
$('#detector_filters_where .row:last [where="p3"]').val(d.p3)
$('#detector_filters_where .row:last [where="p4"]').val(d.p4).prop('disabled',true)
break;
case'filters-where':
$('#filters_where').append(tmp);
$('#filters_where .row:last [where="p1"]').val(d.p1)
@ -1831,6 +1905,9 @@ $.ccio.globalWebsocket=function(d,user){
},user.details.audio_delay * 1000)
}
}
if(user.details.event_mon_pop === '1' && (!$.ccio.mon[d.ke+d.id+user.auth_token].popOut || $.ccio.mon[d.ke+d.id+user.auth_token].popOut.closed === true)){
d.e.find('[monitor="pop"]').click()
}
}
break;
case'init_success':
@ -1972,7 +2049,14 @@ $.ccio.globalWebsocket=function(d,user){
clearInterval($.ccio.mon[d.ke+d.id+user.auth_token].signal);delete($.ccio.mon[d.ke+d.id+user.auth_token].signal);
$.ccio.mon[d.ke+d.id+user.auth_token].watch=0;
if($.ccio.mon[d.ke+d.id+user.auth_token].hls){$.ccio.mon[d.ke+d.id+user.auth_token].hls.destroy()}
if($.ccio.mon[d.ke+d.id+user.auth_token].Poseidon){$.ccio.mon[d.ke+d.id+user.auth_token].Poseidon.destroy()}
if($.ccio.mon[d.ke+d.id+user.auth_token].Base64){$.ccio.mon[d.ke+d.id+user.auth_token].Base64.disconnect()}
if($.ccio.mon[d.ke+d.id+user.auth_token].h265Socket){$.ccio.mon[d.ke+d.id+user.auth_token].h265Socket.disconnect()}
if($.ccio.mon[d.ke+d.id+user.auth_token].h265Player){$.ccio.mon[d.ke+d.id+user.auth_token].h265Player.stop()}
if($.ccio.mon[d.ke+d.id+user.auth_token].dash){$.ccio.mon[d.ke+d.id+user.auth_token].dash.reset()}
if($.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream && $.ccio.mon[d.ke+d.id+user.auth_token].abort){
$.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream.abort()
}
$.grid.data().removeWidget($('#monitor_live_'+d.id+user.auth_token))
}
break;
@ -2188,6 +2272,47 @@ $.ccio.globalWebsocket=function(d,user){
case'mjpeg':
$('#monitor_live_'+d.id+user.auth_token+' .stream-element').attr('src',$.ccio.init('location',user)+user.auth_token+'/mjpeg/'+d.ke+'/'+d.id+'/?full=true')
break;
case'h265':
var player = $.ccio.mon[d.ke+d.id+user.auth_token].h265Player
var video = $('#monitor_live_'+d.id+user.auth_token+' .stream-element')[0]
if (player) {
player.stop()
}
$.ccio.mon[d.ke+d.id+user.auth_token].h265Player = new libde265.RawPlayer(video)
var player = $.ccio.mon[d.ke+d.id+user.auth_token].h265Player
player.set_status_callback(function(msg, fps) {
})
player.launch()
if($.ccio.mon[d.ke+d.id+user.auth_token].h265Socket && $.ccio.mon[d.ke+d.id+user.auth_token].h265Socket.connected){
$.ccio.mon[d.ke+d.id+user.auth_token].h265Socket.disconnect()
}
if($.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream && $.ccio.mon[d.ke+d.id+user.auth_token].abort){
$.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream.abort()
}
if(d.d.stream_flv_type==='ws'){
$.ccio.mon[d.ke+d.id+user.auth_token].h265Socket = io(url,{transports: ['websocket'], forceNew: false})
var ws = $.ccio.mon[d.ke+d.id+user.auth_token].h265Socket
ws.on('diconnect',function(){
console.log('h265Socket Stream Disconnected')
})
ws.on('connect',function(){
ws.emit('h265',{
url: url,
auth: user.auth_token,
uid: user.uid,
ke: d.ke,
id: d.id,
// channel: channel
})
ws.on('data',function(imageData){
player._handle_onChunk(imageData)
})
})
}else{
var url = $.ccio.init('location',user)+user.auth_token+'/h265/'+d.ke+'/'+d.id+'/s.hevc';
$.ccio.mon[d.ke+d.id+user.auth_token].h265HttpStream = player.createHttpStream(url)
}
break;
}
}
d.signal=parseFloat(d.d.signal_check);
@ -2348,7 +2473,7 @@ $.ccio.globalWebsocket=function(d,user){
}
}
});
var eventsToCheck = Object.assign({},events)
$.each(data,function(m,b){
startTimeFormatted = $.ccio.timeObject(b.time).format('YYYY-MM-DD HH:mm:ss');
@ -2836,7 +2961,7 @@ $.zO.initCanvas=function(){
$.zO.e.find('.cord_name').text(e.val)
$.zO.f.find('[name="sensitivity"]').val(e.cord.sensitivity)
$.zO.e.find('.canvas_holder canvas').remove();
$.zO.initLiveStream()
e.e=$.zO.ca.val(e.ar.join(','))
e.e.canvasAreaDraw({
@ -2916,7 +3041,7 @@ $.zO.e.on('changed','#regions_canvas',function(e){
})
$.zO.f.submit(function(e){
e.preventDefault();e.e=$(this),e.s=e.e.serializeObject();
return false;
});
$('#regions_points')
@ -2950,7 +3075,7 @@ $.pB.f.submit(function(e){
$.pB.o.empty();
$.pB.e.find('.stop').show();
$.pB.e.find('[type="submit"]').hide();
e.preventDefault();e.e=$(this),e.s=e.e.serializeObject();
e.s.url=e.s.url.trim();
var flags = '';
@ -3111,7 +3236,7 @@ $.multimon.e.find('.import_config').click(function(){
newMon.details.auto_host = Monitor.Device
break;
case'remote':
break;
}
newMon.details = JSON.stringify(newMon.details)
@ -3254,9 +3379,9 @@ $.each(<%-JSON.stringify(define["Monitor Settings"].blocks)%>,function(n,v){
}
if(b.name.indexOf('detail=')>-1){
b.name=b.name.replace('detail=','')
v.element=$('[detail="'+b.name+'"]')
v.element=$.aM.e.find('[detail="'+b.name+'"]')
}else{
v.element=$('[name="'+b.name+'"]')
v.element=$.aM.e.find('[name="'+b.name+'"]')
}
v.parent=v.element.parents('.form-group').find('label div:first-child span')
v.parent.find('small').remove()
@ -3692,12 +3817,12 @@ $.aM.f.submit(function(ee){
var copyMonitors = $.aM.monitorsForCopy.val();
var chosenSections = [];
var chosenMonitors = {};
if(!copyMonitors||copyMonitors.length===0){
$.ccio.init('note',{title:'<%-cleanLang(lang['No Monitors Selected'])%>',text:'<%-cleanLang(lang.monSavedButNotCopied)%>'})
return
}
$.aM.e.find('[copy]').each(function(n,v){
var el = $(v)
if(el.val() === '1'){
@ -3767,7 +3892,7 @@ $.aM.f.submit(function(ee){
})
console.log(chosenMonitors)
}
$.aM.e.modal('hide')
return false;
});
@ -4078,16 +4203,152 @@ $.fI.f.submit(function(e){
e.er=[];
$.each(e.s,function(n,v){e.s[n]=v.trim()})
e.s.where=[];
$('.where-row').each(function(n,v){
e.e.find('.where-row').each(function(n,v){
n={};
$(v).find('[where]').each(function(m,b){
b=$(b);
n[b.attr('where')]=b.val();
n[b.attr('where')]=b.val().trim();
})
e.s.where.push(n)
})
$.ccio.cx({f:'settings',ff:'filters',fff:'save',form:e.s})
});
//detector filters window
$.detectorFilters={e:$('#detector_filter')};
$.detectorFilters.f=$.detectorFilters.e.find('form');
$.detectorFilters.md=$.detectorFilters.f.find('[detail]');
$.detectorFilters.getSelected = function(){
return $('#detector_filters').val()
}
$.detectorFilters.drawOptions = function(){
var dFilters = $.detectorFilters.getCurrent()
$('#detector_filters optgroup').empty()
$.each(dFilters,function(n,dFilter){
$.ccio.tm('option',{auth_token:$user.auth_token,id:dFilter.id,name:dFilter.filter_name},'#detector_filters optgroup')
})
}
$.detectorFilters.getCurrent = function(){
try{
return JSON.parse($.aM.e.find('[detail="detector_filters"]').val())
}catch(err){
return {}
}
}
$.detectorFilters.save = function(){
var currentVals = $.detectorFilters.getCurrent()
currentVals[$.detectorFilters.lastSave.id] = $.detectorFilters.lastSave
$.aM.e.find('[detail="detector_filters"]').val(JSON.stringify(currentVals)).change()
}
$.ccio.tm('detector-filters-where');
$.detectorFilters.e.on('change','[where="p1"]',function(e){
var el = $(this)
var p1v = el.val()
var parent = el.parents('.row')
var p3 = parent.find('[where="p3"]')
var options = []
switch(p1v){
case'reason':
options = [
'licensePlate',
'object',
'motion',
]
break;
case'plug':
options = [
'PythonYolo',
'OpenCV',
'built-in',
]
break;
case'tag':
options = [
'car',
'tree',
'pottedplant',
]
break;
}
var msg = 'Value'
if(options.length > 0){
msg = 'Example : '+options.join(', ')
}
p3.attr('placeholder',msg)
})
$.detectorFilters.e.on('shown.bs.modal',function(e){
$.detectorFilters.drawOptions()
})
$.detectorFilters.e.on('click','.where .add',function(e){
$.ccio.tm('detector-filters-where');
})
$.detectorFilters.e.on('click','.where .remove',function(e){
e.e=$('#detector_filters_where .row');
if(e.e.length>1){
e.e.last().remove();
$('#detector_filters_where .row:last [where="p4"]').prop('disabled',true)
}
})
$.detectorFilters.f.find('.delete').click(function(e){
var currentVals = $.detectorFilters.getCurrent()
var newObject = {}
var deleteId = $.detectorFilters.getSelected()
$.each(currentVals,function(id,obj){
if(id === deleteId)return false;
newObject[id] = obj
})
$.aM.e.find('[detail="detector_filters"]').val(JSON.stringify(newObject)).change()
$.detectorFilters.drawOptions()
})
$('#detector_filters').change(function(){
e = {}
e.e=$(this),e.id=e.e.val();
$('#detector_filters_where').empty()
if(e.id&&e.id!==''){
var currentFilter = $.detectorFilters.getCurrent()[e.id]
e.name=currentFilter.name;
$.each(currentFilter.where,function(n,v){
$.ccio.tm('detector-filters-where',v)
});
$.each(currentFilter.actions,function(action,val){
$.detectorFilters.e.find('[actions="'+action+'"]').val(val)
});
$.each(currentFilter,function(n,v){
if(n==='where'){return}
$.detectorFilters.f.find('[name="'+n+'"]').val(v);
});
}else{
e.name='<%-cleanLang(lang['Add New'])%>';
$.detectorFilters.f.find('[name="id"]').val($.ccio.gid(5));
$.ccio.tm('detector-filters-where');
}
$.detectorFilters.e.find('.filter_name').text(e.name)
}).change()
$.detectorFilters.f.submit(function(ee){
ee.preventDefault()
e = {}
e.e=$(this),e.s=e.e.serializeObject();
e.er=[];
$.each(e.s,function(n,v){e.s[n]=v.trim()})
//create conditions object (where)
e.s.where=[];
e.e.find('.where-row').each(function(n,v){
n={};
$(v).find('[where]').each(function(m,b){
b=$(b);
n[b.attr('where')]=b.val().trim();
})
e.s.where.push(n)
})
// create actions object (do)
e.s.actions={};
e.e.find('.actions-row').each(function(n,v){
b=$(v).find('[actions]');
e.s.actions[b.attr('actions')] = b.val()
})
$.detectorFilters.lastSave = e.s
$.detectorFilters.save()
$.detectorFilters.e.modal('hide')
});
//settings window
$.sM={e:$('#settings')};
$.sM.f=$.sM.e.find('form');
@ -4447,7 +4708,7 @@ $.timelapse.play = function(x){
clearInterval($.timelapse.interval)
videoNow.currentTime = videoNow.duration
}else{
videoNow.currentTime += .5
videoNow.currentTime += .5
}
},500 / $.timelapse.playRate)
}
@ -4625,7 +4886,7 @@ $.timelapse.e.on('click','[timelapse]',function(){
var vidTime = e.videoNow.duration * percentage;
e.videoNow.currentTime = vidTime;
});
$.ccio.log('$.timelapse',e.video)
$.timelapse.line.find('.timelapse_video').removeClass('active')
e.videoCurrentNow=$.timelapse.display.find('.videoNow')
@ -4746,7 +5007,7 @@ $.pwrvid.e.on('click','[preview]',function(e){
})
if(e.status==1){
$.get($.ccio.init('videoHrefToRead',e.href),function(d){
})
}
var labels=[]
@ -4877,7 +5138,7 @@ $.pwrvid.drawTimeline=function(getData){
e.eventLimit = $('#pvideo_event_limit').val();
if(e.eventLimit===''||isNaN(e.eventLimit)){e.eventLimit=500}
if(e.videoLimit===''||isNaN(e.videoLimit)){e.videoLimit=0}
var getTheData = function(){
e.live_header.text($.ccio.mon[$user.ke+mid+$user.auth_token].name)
e.live.attr('src',$.ccio.init('location',$user)+$user.auth_token+'/embed/'+$user.ke+'/'+mid+'/fullscreen|jquery|relative|gui')
@ -4996,7 +5257,18 @@ $.grid.e
.on('gsresizestop', $.grid.saveElementPositions);
//open all monitors
$('[class_toggle="list-blocks"][data-target="#left_menu"]').dblclick(function(){
$('#monitors_list [monitor="watch"]').click()
$('#monitors_list .monitor_block').each(function(n,v){
var el = $(v)
var ke = el.attr('ke')
var mid = el.attr('mid')
var auth = el.attr('auth')
var monItem = $('.monitor_item[ke='+ke+'][mid='+mid+'][auth='+auth+']')
if(monItem.length > 0){
monItem.find('[monitor="watch_on"]').click()
}else{
el.find('[monitor="watch"]').click()
}
})
})
//search monitors list
$('#monitors_list_search').keyup(function(){
@ -5123,7 +5395,7 @@ $('body')
$.ccio.op(e.localStorage,e.value)
})
.on('click','[system]',function(e){
var e={};
var e={};
e.e=$(this),
e.a=e.e.attr('system');//the function
switch(e.a){
@ -5207,7 +5479,7 @@ $('body')
})
//monitor functions
.on('click','[monitor]',function(){
var e={};
var e={};
e.e=$(this),
e.a=e.e.attr('monitor'),//the function
e.p=e.e.parents('[mid]'),//the parent element for monitor item
@ -5310,7 +5582,7 @@ $('body')
e.d.detector_scale_x=e.width.val();
e.d.detector_scale_y=e.height.val();
}
$.zO.e.modal('show');
$.zO.o().attr('width',e.d.detector_scale_x).attr('height',e.d.detector_scale_y);
$.zO.c.css({width:e.d.detector_scale_x,height:e.d.detector_scale_y});
@ -5325,6 +5597,9 @@ $('body')
$.zO.regionViewerDetails=e.d;
$.zO.initRegionList()
break;
case'detector_filters':
$.detectorFilters.e.modal('show');
break;
case'snapshot':
$.ccio.snapshot(e,function(url){
$('#temp').html('<a href="'+url+'" download="'+$.ccio.init('tf')+'_'+e.ke+'_'+e.mid+'.jpg">a</a>').find('a')[0].click();
@ -5673,4 +5948,4 @@ function onFullScreenChange() {
$('canvas.stream-element').resize();
},2000)
}
}
}

View file

@ -0,0 +1,249 @@
<!--Detector Filter Window-->
<div class="modal full fade dark" id="detector_filter" tabindex="-1" role="dialog" aria-labelledby="detector_filterLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<form class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title" id="detector_filterLabel"><i class="fa fa-grav"></i> &nbsp; <%-lang['Detector Filters']%></h4>
</div>
<div class="modal-body">
<div class="form-group-group green">
<h4><%- lang['Saved Filters'] %> : <small class="filter_name"></small></h4>
<div class="form-group">
<label>
<div><span><%-lang.Filters%></span></div>
<div><select id="detector_filters" class="form-control">
<option value=""><%-lang['Add New']%></option>
<optgroup label="Saved"></optgroup>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%- lang['Filter Name'] %></span></div>
<div><input class="form-control" name="id" type="hidden">
<input class="form-control" name="filter_name"></div>
</label>
</div>
</div>
<div class="form-group-group blue where">
<h4>Conditions
<div class="pull-right">
<a class="btn btn-success btn-xs add">&nbsp;<i class="fa fa-plus"></i>&nbsp;</a>
<a class="btn btn-danger btn-xs remove">&nbsp;<i class="fa fa-trash-o"></i>&nbsp;</a>
</div>
</h4>
<div id="detector_filters_where"></div>
</div>
<div class="form-group-group red actions">
<h4><%- lang['Action for Selected'] %></h4>
<%
var possibleActions = [
{
"name": "halt",
"field": "Drop Event",
"description": "Make the event do nothing, as if it never happened.",
"default": "No",
"example": "",
"possible": [
{
"name": "No",
"value": "0",
"info": "Allow other functions to continue.",
selected:true
},
{
"name": "Yes",
"value": "1",
"info": "Use Traditional Recording, Hotswap, or Delete Motionless with their currently set options in the Global Detection Settings section."
}
]
},
{
"name": "save",
"field": "Save Events to SQL",
"description": "Save Motion Events in SQL. This will allow display of motion over video during the time motion events occured in the Power Viewer.",
"default": "Yes",
"example": "",
"possible": [
{
"name": "Default",
"value": "",
"info": "Use values set in Global Detector Settings.",
"selected": true
},
{
"name": "No",
"value": "0",
"info": "Finish the current 10 minute order."
},
{
"name": "Yes",
"value": "1",
"info": "Reset the timer"
}
]
},
{
"name": "mail",
"field": "Email on Trigger",
"description": "Recieve an email of an image during a motion event to the master account for the camera group. You must setup SMTP details in conf.json.",
"default": "No",
"example": "1",
"possible": [
{
"name": "Default",
"value": "",
"info": "Use values set in Global Detector Settings.",
"selected": true
},
{
"name": "No",
"value": "0",
"info": "No Email."
},
{
"name": "Yes",
"value": "1",
"info": "Send Email."
}
]
},
{
"name": "webhook",
"field": "Webhook on Trigger",
"description": "Send a GET request during an event to the URL specified. Webhook location can be specified in the Global Detector Settings for the Monitor.",
"default": "No",
"example": "1",
"possible": [
{
"name": "Default",
"value": "",
"info": "Use values set in Global Detector Settings.",
"selected": true
},
{
"name": "No",
"value": "0",
"info": "No Webhook."
},
{
"name": "Yes",
"value": "1",
"info": "Send Webhook."
}
]
},
{
"name": "discord",
"field": "Discord Alert on Trigger",
"description": "Recieve a Discord Notification with an image or video during an event to the Discord channel specified. Discord Bot and Channel settings can be changed in your Account Settings.",
"default": "No",
"example": "1",
"possible": [
{
"name": "Default",
"value": "",
"info": "Use values set in Global Detector Settings.",
"selected": true
},
{
"name": "No",
"value": "0",
"info": "No Alert."
},
{
"name": "Yes",
"value": "1",
"info": "Get a Message to Discord."
}
]
},
{
"name": "command",
"field": "Detector Command",
"description": "You may use this to trigger a script on command.",
"default": "No",
"example": "",
"possible": [
{
"name": "Default",
"value": "",
"info": "Use values set in Global Detector Settings.",
"selected": true
},
{
"name": "No",
"value": "0",
"info": "No script will run."
},
{
"name": "Yes",
"value": "1",
"info": "Trigger the script that is set in the <b>Command</b> option. <b>Command</b> is only visible when selecting this option."
}
]
},
{
"name": "record",
"field": "Use Record Method",
"description": "Use Traditional Recording, Hotswap, or Delete Motionless with their currently set options in the Global Detection Settings section.",
"default": "No",
"example": "",
"possible": [
{
"name": "Default",
"value": "",
"info": "Use values set in Global Detector Settings.",
"selected": true
},
{
"name": "No",
"value": "0",
"info": "No Traditional Recording, Hotswap, or Delete Motionless."
},
{
"name": "Yes",
"value": "1",
"info": "Use Traditional Recording, Hotswap, or Delete Motionless with their currently set options in the Global Detection Settings section."
}
]
},
].forEach(function(item){ %>
<%
var name = 'actions='+item.name
if(item.name.indexOf('=') > -1){
name = item.name
}
%>
<div class="form-group actions-row">
<label>
<div>
<span>
<%-item.field%>
<small><%-item.description%></small>
</span>
</div>
<div>
<select <%- name %> class="form-control">
<% item.possible.forEach(function(option){ %>
<option value="<%-option.value%>"><%-option.name%></option>
<% }) %>
</select>
</div>
</label>
</div>
<% }) %>
</div>
</div>
<div class="modal-footer">
<div class="pull-left">
<button type="button" class="btn btn-default" data-dismiss="modal"><%- lang['Close'] %></button>
<button type="button" class="btn btn-danger delete"><%- lang['Delete'] %></button>
</div>
<button type="submit" class="btn btn-success"><%- lang['Save'] %></button>
</div>
</form>
</div>
</div>

View file

@ -26,7 +26,7 @@
<%-lang.IdentityText2%>
</blockquote>
<div class="form-group">
<label>
<label>
<div><span><%-lang.Mode%></span></div>
<div><select class="form-control" name="mode" selector="h_m">
<option value="stop"><%-lang.Disabled%></option>
@ -124,26 +124,26 @@
<div class="form-group h_p_input h_p_rtsp">
<label><div><span><%-lang['RTSP Transport']%></span></div>
<div><select class="form-control" detail="rtsp_transport">
<option value="no" selected><%-lang['Auto']%></option>
<option value="tcp"><%-lang['TCP']%></option>
<option value="udp"><%-lang['UDP']%></option>
<option value="http"><%-lang['HTTP']%></option>
<option value="no" selected><%-lang['Auto']%></option>
<option value="tcp"><%-lang['TCP']%></option>
<option value="udp"><%-lang['UDP']%></option>
<option value="http"><%-lang['HTTP']%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Username']%></span></div>
<div><input class="form-control" detail="muser" placeholder=""></div>
<div><input class="form-control" detail="muser"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Password']%></span></div>
<div><input class="form-control" type="password" detail="mpass" placeholder=""></div>
<div><input class="form-control" type="password" detail="mpass"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Host']%></span></div>
<div><input class="form-control" name="host" placeholder=""></div>
<div><input class="form-control" name="host"></div>
</label>
</div>
<div class="form-group">
@ -208,7 +208,7 @@
<div><input class="form-control" detail="probesize"></div>
</label>
</div>
<div class="form-group h_t_input h_t_mp4">
<div class="form-group h_t_input h_t_mp4 h_t_local">
<label><div><span><%-lang["Loop Stream"]%></span></div>
<div><select class="form-control" detail="stream_loop">
<option value="0" selected><%-lang.No%></option>
@ -259,6 +259,11 @@
<option value="hevc_qsv"><%-lang['hevc_qsv']%></option>
<option value="mpeg2_qsv"><%-lang['mpeg2_qsv']%></option>
</optgroup>
<optgroup label="Raspberry Pi">
<option value="h264_mmal"><%-lang['h264_mmal']%></option>
<option value="mpeg2_mmal"><%-lang['mpeg2_mmal']%></option>
<option value="mpeg4_mmal"><%-lang['mpeg4_mmal']%></option>
</optgroup>
</select></div>
</label>
</div>
@ -289,9 +294,9 @@
</div>
<div class="form-group">
<label><div><span><%-lang['Stream Type']%></span></div>
<div><select class="form-control" detail="stream_type" selector="h_st" triggerChange="#add_monitor [detail=stream_vcodec]" triggerChangeIgnore="b64,mjpeg">
<div><select class="form-control" detail="stream_type" selector="h_st" triggerChange="#add_monitor [detail=stream_vcodec]" triggerChangeIgnore="b64,mjpeg,jpeg,gif">
<option value="mp4"><%-lang['Poseidon']%></option>
<!-- <option value="pam">PAM</option>-->
<option value="h265"><%-lang['HEVC (H.265)']%></option>
<option value="b64" selected><%-lang['Base64 over Websocket']%></option>
<option value="jpeg"><%-lang['JPEG (Auto Enables JPEG API)']%></option>
<option value="mjpeg"><%-lang['MJPEG']%></option>
@ -300,7 +305,7 @@
</select></div>
</label>
</div>
<div class="form-group h_st_input h_st_flv h_st_mp4">
<div class="form-group h_st_input h_st_flv h_st_mp4 h_st_h265">
<label><div><span><%-lang['Connection Type']%></span></div>
<div><select class="form-control" detail="stream_flv_type" selector="h_st_lat">
<option value="http" selected><%-lang['HTTP']%></option>
@ -318,7 +323,7 @@
<div><input class="form-control" detail="stream_mjpeg_clients" placeholder="20"></div>
</label>
</div>
<div class="h_st_input h_st_hls h_st_flv h_st_mp4">
<div class="h_st_input h_st_hls h_st_flv h_st_mp4 h_st_h265">
<div class="form-group">
<label><div><span><%-lang['HLS Video Encoder']%></span></div>
<div><select class="form-control" detail="stream_vcodec" selector="h_hls_v">
@ -334,6 +339,7 @@
<option value="h264_qsv"><%-lang['h264_qsv']%></option>
<option value="hevc_qsv"><%-lang['hevc_qsv']%></option>
<option value="mpeg2_qsv"><%-lang['mpeg2_qsv']%></option>
<option value="h264_omx"><%-lang['h264_omx']%></option>
</optgroup>
</select></div>
</label>
@ -351,7 +357,7 @@
</label>
</div>
</div>
<div class="h_st_input h_st_mjpeg h_st_b64 h_st_hls h_st_flv h_st_mp4 h_hls_v_input h_hls_v_libx264 h_hls_v_libx265 h_hls_v_h264_nvenc h_hls_v_hevc_nvenc h_hls_v_no">
<div class="h_st_input h_st_mjpeg h_st_b64 h_st_hls h_st_gif h_st_flv h_st_mp4 h_st_h265 h_hls_v_input h_hls_v_libx264 h_hls_v_libx265 h_hls_v_h264_nvenc h_hls_v_hevc_nvenc h_hls_v_no">
<div class="h_st_input h_st_hls">
<div class="form-group">
<label><div><span><%-lang['HLS Segment Length']%></span></div>
@ -364,7 +370,7 @@
</label>
</div>
</div>
<div class="form-group h_st_input h_st_hls h_st_flv h_st_mp4">
<div class="form-group h_st_input h_st_hls h_st_flv h_st_mp4 h_st_h265">
<label><div><span><%-lang['HLS Preset']%></span></div>
<div><input class="form-control" detail="preset_stream" placeholder="ultrafast"></div>
</label>
@ -447,8 +453,8 @@
<div class="form-group">
<label><div><span><%-lang['Enabled']%></span></div>
<div><select class="form-control" detail="stream_timestamp" selector="h_tm">
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
</select></div>
</label>
</div>
@ -545,12 +551,12 @@
</div>
<div class="form-group">
<label><div><span><%-lang['Image Width']%></span></div>
<div><input class="form-control" detail="snap_scale_x" placeholder=""></div>
<div><input class="form-control" detail="snap_scale_x"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Image Height']%></span></div>
<div><input class="form-control" detail="snap_scale_y" placeholder=""></div>
<div><input class="form-control" detail="snap_scale_y"></div>
</label>
</div>
<div class="form-group">
@ -578,8 +584,8 @@
<div class="form-group">
<label><div><span><%-lang['Record File Type']%></span></div>
<div><select class="form-control" name="ext" selector="h_f">
<option value="webm"><%-lang['WebM (libvpx)']%></option>
<option value="mp4"><%-lang['MP4 (copy, libx264, libx265)']%></option>
<option value="webm"><%-lang['WebM (libvpx)']%></option>
<option value="mp4"><%-lang['MP4 (copy, libx264, libx265)']%></option>
<!-- <option value="mkv">MKV</option> -->
</select></div>
</label>
@ -606,6 +612,7 @@
<option value="h264_qsv"><%-lang['h264_qsv']%></option>
<option value="hevc_qsv"><%-lang['hevc_qsv']%></option>
<option value="mpeg2_qsv"><%-lang['mpeg2_qsv']%></option>
<option value="h264_omx"><%-lang['h264_omx']%></option>
</optgroup>
<optgroup label="WebM <%-lang['Hardware Accelerated']%>">
<option value="vp8_cuvid"><%-lang['vp8_cuvid']%></option>
@ -618,12 +625,12 @@
<div class="h_vc_input h_vc_libvpx h_vc_libvpx-vp9 h_vc_libx264 h_vc_libx265 h_vc_hevc_nvenc h_vc_h264_nvenc h_vc_h264_vaapi h_vc_hevc_vaapi h_vc_h264_qsv h_vc_hevc_qsv h_vc_mpeg2_qsv h_vc_default h_vc_none">
<div class="form-group">
<label><div><span><%-lang['Quality']%></span></div>
<div><input class="form-control" detail="crf" placeholder=""></div>
<div><input class="form-control" detail="crf"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Preset']%></span></div>
<div><input class="form-control" detail="preset_record" placeholder=""></div>
<div><input class="form-control" detail="preset_record"></div>
</label>
</div>
</div>
@ -705,8 +712,8 @@
<div class="form-group">
<label><div><span><%-lang['Enabled']%></span></div>
<div><select class="form-control" detail="timestamp" selector="h_tm">
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
</select></div>
</label>
</div>
@ -785,7 +792,7 @@
<h4><%-lang['Custom']%></h4>
<div class="form-group">
<label><div><span><%-lang['Input Flags']%></span></div>
<div><input class="form-control" detail="cust_input" placeholder=""></div>
<div><input class="form-control" detail="cust_input"></div>
</label>
</div>
<div class="form-group h_sn_input h_sn_1" style="display:none">
@ -820,7 +827,7 @@
</div>
<div class="form-group h_m_input h_m_record">
<label><div><span><%-lang['Recording Flags']%></span></div>
<div><input class="form-control" detail="cust_record" placeholder=""></div>
<div><input class="form-control" detail="cust_record"></div>
</label>
</div>
<div class="form-group">
@ -1005,13 +1012,30 @@
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Detector Filters']%></span></div>
<div><select class="form-control" detail="use_detector_filters" selector="h_det_fil">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group h_det_fil_input h_det_fil_1">
<label><div><span><%-lang['Filter for Objects only']%></span></div>
<div><select class="form-control" detail="use_detector_filters_object">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group h_det_discord_input h_det_discord_1">
<label><div><span><%-lang['Allow Next Discord Alert']%></span></div>
<div><input class="form-control" detail="detector_discordbot_timeout" placeholder="10"></div>
</label>
</div>
<div class="hidden">
<div><input detail="cords" placeholder=""></div>
<input detail="cords">
<input detail="detector_filters">
</div>
<div class="form-group">
<a class="btn btn-danger btn-block" monitor="region"><i class="fa fa-grav"></i> &nbsp; <%-lang['Region Editor']%></a>
@ -1090,7 +1114,7 @@
</div>
</div>
</div>
<div class="form-group-group orange shinobi-detector-opencv shinobi-detector-openalpr shinobi-detector_plug" section id="monSectionDetectorObject">
<div class="form-group-group orange shinobi-detector-opencv shinobi-detector-openalpr shinobi-detector-pythonyolo shinobi-detector_plug" section id="monSectionDetectorObject">
<h4><%-lang['Object Detection']%> <small><%-lang['Plugin']%> : <b class="shinobi-detector_name"></b> <b class="shinobi-detector-invert"><%-lang['Not Connected']%></b><b class="shinobi-detector" style="display:none"><%-lang['Connected']%></b></small></h4>
<div class="form-group">
<label><div><span><%-lang['Detect Objects']%></span></div>
@ -1102,12 +1126,31 @@
</div>
<div class="form-group">
<label><div><span><%-lang['Check for Motion First']%></span></div>
<div><select class="form-control" detail="detector_use_motion">
<div><select class="form-control" detail="detector_use_motion" selector="h_det_mot_fir">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="h_det_pam_input h_det_pam_1">
<div class="h_det_mot_fir_input h_det_mot_fir_1">
<div class="form-group">
<label><div><span><%-lang['Frame Rate']%></span></div>
<div><input class="form-control" type="number" min="1" detail="detector_fps_object" placeholder="2"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Width']%></span></div>
<div><input class="form-control" type="number" min="1" detail="detector_scale_x_object" placeholder="320"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Height']%></span></div>
<div><input class="form-control" type="number" min="1" detail="detector_scale_y_object" placeholder="240"></div>
</label>
</div>
</div>
</div>
<div class=" h_casc_input h_casc_1" style="display:none">
<div class="form-group-group orange shinobi-detector-opencv shinobi-detector-openalpr shinobi-detector_plug" style="display:none" section id="monSectionLisencePlateDetector">
<h4><%-lang['Lisence Plate Detector']%></h4>
@ -1222,8 +1265,8 @@
<div class="form-group">
<label><div><span><%-lang['Controllable']%></span></div>
<div><select class="form-control" detail="control" selector="h_c">
<option value="0"><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0"><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
@ -1236,7 +1279,7 @@
<div class="form-group">
<label><div><span><%-lang['Call Method']%></span></div>
<div><select class="form-control" detail="control_url_method" selector="h_control_call">
<option value="GET">GET (<%-lang.Default%>)</option>
<option value="GET">GET (<%-lang.Default%>)</option>
<option value="PUT">PUT</option>
<option value="POST">POST</option>
<option value="ONVIF">ONVIF</option>
@ -1246,7 +1289,7 @@
<div class="form-group h_control_call_input h_control_call_GET h_control_call_PUT h_control_call_POST">
<label><div><span><%-lang['Digest Authentication']%></span></div>
<div><select class="form-control" detail="control_digest_auth">
<option value="0"><%-lang.No%></option>
<option value="0"><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
@ -1254,7 +1297,7 @@
<div class="form-group">
<label><div><span><%-lang['Stop Command']%></span></div>
<div><select class="form-control" detail="control_stop" selector="h_cs">
<option value="0"><%-lang.No%></option>
<option value="0"><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
@ -1355,8 +1398,8 @@
<div class="form-group">
<label><div><span><%-lang['Copy to Settings']%></span></div>
<div><select class="form-control" id="copy_settings" selector="h_copy_settings">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
@ -1364,32 +1407,32 @@
<div class="form-group">
<label><div><span><%-lang['Copy Connection Settings']%></span></div>
<div><select class="form-control" copy="#monSectionConnection">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Copy Input Settings']%></span></div>
<div><select class="form-control" copy="#monSectionInput">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Copy Stream Settings']%></span></div>
<div><select class="form-control" copy="#monSectionStream,#monSectionStreamTimestamp,#monSectionStreamWatermark">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Copy JPEG API Settings']%></span></div>
<div><select class="form-control" copy="#monSectionJPEGAPI">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
@ -1397,8 +1440,8 @@
<div class="form-group">
<label><div><span><%-lang['Copy Stream Channel Settings']%></span></div>
<div><select class="form-control" copy="stream_channel">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
@ -1406,40 +1449,40 @@
<div class="form-group">
<label><div><span><%-lang['Copy Recording Settings']%></span></div>
<div><select class="form-control" copy="#monSectionRecording">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Copy Detector Settings']%></span></div>
<div><select class="form-control" copy="#monSectionDetector,#monSectionDetectorBuffer,#monSectionLisencePlateDetector,#monSectionNoMotionDetector">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Copy Custom Settings']%></span></div>
<div><select class="form-control" copy="#monSectionCustom">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Copy Group Settings']%></span></div>
<div><select class="form-control" copy="#monSectionGrouping">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Copy Logging Settings']%></span></div>
<div><select class="form-control" copy="#monSectionLogging">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
@ -1462,15 +1505,14 @@
<option value="fatal"><%-lang['Fatal']%></option>
<option value="error" selected><%-lang['on Error']%></option>
<option value="warning"><%-lang['All Warnings']%></option>
<option value="debug"><%-lang['Debug']%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Save Log in SQL']%></span></div>
<div><select class="form-control" detail="sqllog">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
@ -1504,16 +1546,19 @@
<li class="mdl-menu__item add_map"><i class="fa fa-rss"></i> <%-lang['Add Input Feed']%></li>
<li class="mdl-menu__item add_channel"><i class="fa fa-puzzle-piece"></i> <%-lang['Add Channel']%></li>
</ul>
<span class="h_det_input h_det_1"><button type="button" style="display:none" class="btn btn-warning shinobi-detector-opencv shinobi-detector-openalpr shinobi-detector-motion shinobi-detector_plug" monitor="region"><i class="fa fa-grav"></i> <%-lang['Region Editor']%></button></span>
<div class="h_det_input h_det_1" style="display:inline-block">
<button type="button" class="btn btn-primary" monitor="region"><i class="fa fa-grav"></i> <%-lang['Region Editor']%></button>
<button type="button" class="btn btn-primary" monitor="detector_filters"><i class="fa fa-grav"></i> <%-lang['Detector Filters']%></button>
</div>
</div>
<div style="display:inline-block;margin-right:5px">
<div><select class="form-control btn-default" dropdown_toggle="monedit_user_type" selector="h_us">
<option value="simple" selected><%-lang['Simple']%></option>
<option value="advanced"><%-lang['Advanced']%></option>
<option value="simple" selected><%-lang['Simple']%></option>
<option value="advanced"><%-lang['Advanced']%></option>
</select></div>
</div>
<button type="submit" class="btn btn-success"><i class="fa fa-check"></i> <%-lang.Save%></button>
</div>
</form>
</div>
</div>
</div>

View file

@ -24,6 +24,33 @@
</label>
</div>
</div>
<div class="form-group-group grey">
<h4><%-lang['2-Factor Authentication']%></h4>
<div class="form-group">
<label><div><span><%-lang['Enabled']%></span></div>
<div><select class="form-control" detail="factorAuth">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang.Email%></span></div>
<div><select class="form-control" detail="factor_mail">
<option value="1" selected><%-lang.Yes%></option>
<option value="0"><%-lang.No%></option>
</select></div>
</label>
</div>
<div class="form-group u_discord_bot_input u_discord_bot_1">
<label><div><span><%-lang.Discord%></span></div>
<div><select class="form-control" detail="factor_discord">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
</div>
<div class="form-group-group grey">
<h4><%-lang.Profile%></h4>
<div class="form-group">
@ -41,14 +68,6 @@
<div><input class="form-control" type="password" name="password_again"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['2-Factor Authentication']%> (<%-lang.Email%>)</span></div>
<div><select class="form-control" detail="factorAuth">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<% if(!details.sub){ %>
<% if(details.edit_size!=='0'){ %>
<div class="form-group">
@ -116,11 +135,19 @@
</div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Alert Sound Delay']%></span></div>
<div><input class="form-control" detail="audio_delay" placeholder="1"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Alert Sound Delay']%></span></div>
<div><input class="form-control" detail="audio_delay" placeholder="1"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Popout Monitor on Event']%></span></div>
<div><select class="form-control" detail="event_mon_pop">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
</div>
<% if(!details.sub){ %>
<div class="form-group-group blue">

View file

@ -20,6 +20,7 @@ if(data.url.charAt(data.url.length - 1) !== '/'){
<script src="<%=data.url%>libs/js/poseidon.js"></script>
<script src="<%=data.url%>libs/js/hls.min.js"></script>
<script src="<%=data.url%>libs/js/flv.min.js"></script>
<script src="<%=data.url%>libs/js/libde265.min.js"></script>
<% if(data.addon){
var ar={}
decodeURI(data.addon).split('|').forEach(function(v){
@ -133,7 +134,7 @@ $(document).ready(function(){
})
</script>
<div class="shinobi_stream" id="<%= data.name %>">
<% switch(mon.details.stream_type){
case'jpeg':
%><img class="stream-element"><%
@ -148,8 +149,8 @@ $(document).ready(function(){
%><canvas class="stream-element"></canvas><%
break;
} %>
<% if(data.addon&&data.addon.indexOf('gui')>-1){ %>
<div class="shinobi_hud">
<div class="shinobi_viewers" title="Current number of viewers"></div>
@ -170,11 +171,30 @@ $(document).ready(function(){
$.shinobi.mon={}
};
$.shinobi.init=function(d){
if($.shinobi.mon[d.id].Base64 && $.shinobi.mon[d.id].Base64.connected){
$.shinobi.mon[d.id].Base64.disconnect()
}
if($.shinobi.mon[d.id].Poseidon){
$.shinobi.mon[d.id].Poseidon.destroy()
}
if ($.shinobi.mon[d.id].h265Player) {
$.shinobi.mon[d.id].h265Player.stop()
}
if($.shinobi.mon[d.id].h265Socket && $.shinobi.mon[d.id].h265Socket.connected){
$.shinobi.mon[d.id].h265Socket.disconnect()
}
if($.shinobi.mon[d.id].h265HttpStream && $.shinobi.mon[d.id].abort){
$.shinobi.mon[d.id].h265HttpStream.abort()
}
if($.shinobi.mon[d.id].flv){
$.shinobi.mon[d.id].flv.destroy()
}
if($.shinobi.mon[d.id].hls){
$.shinobi.mon[d.id].hls.destroy()
}
clearInterval($.shinobi.mon[d.id].jpegInterval);
switch($.shinobi.mon[d.id].details.stream_type){
case'b64':
if($.shinobi.mon[d.id].Base64 && $.shinobi.mon[d.id].Base64.connected){
$.shinobi.mon[d.id].Base64.disconnect()
}
$.shinobi.mon[d.id].Base64 = io('<%=data.url%>',{transports: ['websocket'], forceNew: false})
var ws = $.shinobi.mon[d.id].Base64
ws.on('diconnect',function(){
@ -209,7 +229,7 @@ $(document).ready(function(){
// }
// ctx.getContext("2d").drawImage(image,d.x,d.y,d.width,d.height)
ctx.getContext("2d").drawImage(image,d.x,d.y,ctx.width,ctx.height)
URL.revokeObjectURL($.ccio.mon[d.ke+d.id+user.auth_token].imageUrl)
URL.revokeObjectURL($.shinobi.mon[d.id].imageUrl)
}
ws.on('data',function(imageData){
try{
@ -232,9 +252,6 @@ $(document).ready(function(){
case'mp4':
var stream = $('#SHINOBI_'+d.ke+'_'+d.id+' .stream-element');
if($.shinobi.mon[d.id].details.stream_flv_type==='ws'){
if($.shinobi.mon[d.id].Poseidon){
$.shinobi.mon[d.id].Poseidon.destroy()
}
var createPoseidon = function(){
$.shinobi.mon[d.id].Poseidon = new Poseidon({
video: stream[0],
@ -261,11 +278,38 @@ $(document).ready(function(){
stream.attr('src','<%=data.url%><%=data.auth%>/mp4/'+d.ke+'/'+d.id+'/s.mp4')
}
break;
case'h265':
var player = $.shinobi.mon[d.id].h265Player
var video = $('#SHINOBI_'+d.ke+'_'+d.id+' .stream-element')[0]
player = new libde265.RawPlayer(video)
player.set_status_callback(function(msg, fps) {
})
player.launch()
if($.shinobi.mon[d.id].details.stream_flv_type==='ws'){
$.shinobi.mon[d.id].h265Socket = io(url,{transports: ['websocket'], forceNew: false})
var ws = $.shinobi.mon[d.id].h265Socket
ws.on('diconnect',function(){
console.log('h265Socket Stream Disconnected')
})
ws.on('connect',function(){
ws.emit('h265',{
auth:'<%=data.auth%>',
ke:d.ke,
uid:'<%=data.uid%>',
id:d.id,
url: '<%=data.url%>'
// channel: channel
})
ws.on('data',function(imageData){
player._handle_onChunk(imageData)
})
})
}else{
$.shinobi.mon[d.id].h265HttpStream = player.createHttpStream('<%=data.url%><%=data.auth%>/h265/'+d.ke+'/'+d.id+'/s.hevc')
}
break;
case'flv':
if (flvjs.isSupported()) {
if($.shinobi.mon[d.id].flv){
$.shinobi.mon[d.id].flv.destroy()
}
var options = {};
// if($.shinobi.mon[d.id].details.stream_flv_type==='ws'){
// if($.shinobi.mon[d.id].details.stream_flv_maxLatency&&$.shinobi.mon[d.id].details.stream_flv_maxLatency!==''){
@ -307,9 +351,9 @@ $(document).ready(function(){
k=d.mon.details;
k.jpegInterval=parseFloat(k.jpegInterval);
if(!k.jpegInterval||k.jpegInterval===''||isNaN(k.jpegInterval)){k.jpegInterval=1}
if(!$.shinobi.mon[d.mon.mid].jpegInterval){
clearInterval($.shinobi.mon[d.mon.mid].jpegInterval);
$.shinobi.mon[d.mon.mid].jpegInterval=setInterval(function(){
if(!$.shinobi.mon[d.id].jpegInterval){
clearInterval($.shinobi.mon[d.id].jpegInterval);
$.shinobi.mon[d.id].jpegInterval=setInterval(function(){
$('#SHINOBI_'+d.ke+'_'+d.id+' .stream-element').attr('src','<%=data.url%><%=data.auth%>/jpeg/'+d.mon.ke+'/'+d.mon.mid+'/s.jpg?time='+(new Date()).getTime())
},1000/k.jpegInterval);
}
@ -317,9 +361,6 @@ $(document).ready(function(){
case'hls':
var video = $('#SHINOBI_'+d.ke+'_'+d.id+' .stream-element')[0];
d.url='<%=data.url%><%=data.auth%>/hls/'+d.ke+'/'+d.id+'/s.m3u8';
if($.shinobi.mon[d.id].hls){
$.shinobi.mon[d.id].hls.destroy()
}
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)||(navigator.userAgent.match(/(Safari)/)&&!navigator.userAgent.match('Chrome'))) {
video.src=d.url;
video.play();
@ -386,7 +427,7 @@ $(document).ready(function(){
$(window).resize();
// d.mon.details=JSON.stringify(d.mon.details);
d.mon.id = d.mon.mid
$.shinobi.mon[d.mon.mid]=d.mon;
$.shinobi.mon[d.id] = d.mon;
$.shinobi.init(d.mon);
break;
}
@ -413,4 +454,4 @@ $(document).ready(function(){
$.shinobi.init(monitor);
})
$('.shinobi_ws_http_toggle').show()
</script>
</script>

View file

@ -163,6 +163,7 @@
<% include blocks/monitoredit.ejs %>
<% include blocks/probe.ejs %>
<% include blocks/region.ejs %>
<% include blocks/detectorfilters.ejs %>
<% include blocks/confirm.ejs %>
<% if(config.DropboxAppKey){ %>
<!--Dropbox Library, Change data-app-key to your app key. -->
@ -179,6 +180,7 @@
<script src="<%-originalURL%>libs/js/socket.io.js"></script>
<script src="<%-originalURL%>libs/js/fullcalendar.min.js"></script>
<script src="<%-originalURL%>libs/js/hls.min.js"></script>
<script src="<%-originalURL%>libs/js/libde265.min.js"></script>
<script type="text/javascript" src="<%-originalURL%>libs/js/flv.shinobi.js">;</script>
<script src="<%-originalURL%>libs/js/menu.js"></script>
<script src="<%-originalURL%>libs/js/clock.js"></script>
@ -193,4 +195,4 @@
<script src="<%-originalURL%>libs/js/gridstack.min.js"></script>
<script src="<%-originalURL%>libs/js/gridstack.jQueryUI.min.js"></script>
<script><% include ../libs/js/main.dash2.js %></script>
<% include blocks/help.ejs %>
<% include blocks/help.ejs %>