H.265 Stream Type Added
- Now play H.265 video in almost any browser with the help of libde265.js! + minor bug fixes + preparation for slickslider page (timed switcher)merge-requests/63/head
parent
7f05c62c08
commit
9166d7e8a9
175
camera.js
175
camera.js
|
|
@ -684,9 +684,9 @@ s.systemLog = function(q,w,e){
|
|||
}
|
||||
//system log
|
||||
s.debugLog = function(q,w,e){
|
||||
if(!w){w = ''}
|
||||
if(!e){e = ''}
|
||||
if(config.debugLog === true){
|
||||
if(!w){w = ''}
|
||||
if(!e){e = ''}
|
||||
console.log(s.timeObject().format(),q,w,e)
|
||||
if(config.debugLogVerbose === true){
|
||||
console.log(new Error())
|
||||
|
|
@ -2198,12 +2198,15 @@ s.ffmpeg = function(e){
|
|||
x.pipe+=' -an -c:v mjpeg -f mpjpeg -boundary_tag shinobi'+x.cust_stream+x.stream_video_filters+' pipe:1';
|
||||
}
|
||||
break;
|
||||
case'pam':
|
||||
if(e.coProcessor === false){
|
||||
case'h265':
|
||||
x.cust_stream+=' -movflags +frag_keyframe+empty_moov+default_base_moof -metadata title="Shinobi H.265 Stream" -reset_timestamps 1'
|
||||
if(e.details.stream_vcodec!=='copy'){
|
||||
if(x.dimensions && x.cust_stream.indexOf('-s ')===-1){x.cust_stream+=' -s '+x.dimensions}
|
||||
if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -q:v '+e.details.stream_quality;
|
||||
x.pipe+=' -an -c:v pam -pix_fmt rgba -f image2pipe'+x.cust_stream+x.stream_video_filters+' pipe:1';
|
||||
if(e.details.stream_quality && e.details.stream_quality !== '')x.cust_stream+=' -crf '+e.details.stream_quality;
|
||||
x.cust_stream+=x.preset_stream
|
||||
x.cust_stream+=x.stream_video_filters
|
||||
}
|
||||
x.pipe+=' -f hevc'+x.stream_acodec+x.stream_vcodec+x.cust_stream+' pipe:1';
|
||||
break;
|
||||
case'b64':case'':case undefined:case null://base64
|
||||
if(e.coProcessor === false){
|
||||
|
|
@ -2223,23 +2226,23 @@ s.ffmpeg = function(e){
|
|||
}
|
||||
//detector - plugins, motion
|
||||
if(e.details.detector==='1' && e.details.detector_send_frames==='1' && e.coProcessor === false){
|
||||
if(e.details.input_map_choices&&e.details.input_map_choices.detector){
|
||||
//add input feed map
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector)
|
||||
}
|
||||
if(!e.details.detector_fps||e.details.detector_fps===''){e.details.detector_fps=2}
|
||||
if(e.details.detector_scale_x&&e.details.detector_scale_x!==''&&e.details.detector_scale_y&&e.details.detector_scale_y!==''){x.dratio=' -s '+e.details.detector_scale_x+'x'+e.details.detector_scale_y}else{x.dratio=' -s 320x240'}
|
||||
if(e.details.cust_detect&&e.details.cust_detect!==''){x.cust_detect+=e.details.cust_detect;}
|
||||
if(e.details.detector_pam==='1'){
|
||||
x.pipe+=' -an -c:v pam -pix_fmt gray -f image2pipe -r '+e.details.detector_fps+x.cust_detect+x.dratio+' pipe:3'
|
||||
if(e.details.detector_use_detect_object === '1'){
|
||||
//for object detection
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector)
|
||||
x.pipe += ' -f singlejpeg -vf fps='+e.details.detector_fps+x.cust_detect+x.dratio+' pipe:4';
|
||||
}
|
||||
}else{
|
||||
x.pipe+=' -f singlejpeg -vf fps='+e.details.detector_fps+x.cust_detect+x.dratio+' pipe:3';
|
||||
}
|
||||
if(e.details.input_map_choices&&e.details.input_map_choices.detector){
|
||||
//add input feed map
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector)
|
||||
}
|
||||
if(!e.details.detector_fps||e.details.detector_fps===''){e.details.detector_fps=2}
|
||||
if(e.details.detector_scale_x&&e.details.detector_scale_x!==''&&e.details.detector_scale_y&&e.details.detector_scale_y!==''){x.dratio=' -s '+e.details.detector_scale_x+'x'+e.details.detector_scale_y}else{x.dratio=' -s 320x240'}
|
||||
if(e.details.cust_detect&&e.details.cust_detect!==''){x.cust_detect+=e.details.cust_detect;}
|
||||
if(e.details.detector_pam==='1'){
|
||||
x.pipe+=' -an -c:v pam -pix_fmt gray -f image2pipe -r '+e.details.detector_fps+x.cust_detect+x.dratio+' pipe:3'
|
||||
if(e.details.detector_use_detect_object === '1'){
|
||||
//for object detection
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.detector)
|
||||
x.pipe += ' -f singlejpeg -vf fps='+e.details.detector_fps+x.cust_detect+x.dratio+' pipe:4';
|
||||
}
|
||||
}else{
|
||||
x.pipe+=' -f singlejpeg -vf fps='+e.details.detector_fps+x.cust_detect+x.dratio+' pipe:3';
|
||||
}
|
||||
}
|
||||
//api - snapshot bin/ cgi.bin (JPEG Mode)
|
||||
if(e.details.snap === '1'){
|
||||
|
|
@ -3673,6 +3676,12 @@ s.camera=function(x,e,cn,tx){
|
|||
s.group[e.ke].mon[e.id].emitter.emit('data',d);
|
||||
}
|
||||
break;
|
||||
case'h265':
|
||||
e.frame_to_stream=function(d){
|
||||
resetStreamCheck()
|
||||
s.group[e.ke].mon[e.id].emitter.emit('data',d);
|
||||
}
|
||||
break;
|
||||
// case'pam':
|
||||
// s.group[e.ke].mon[e.id].p2pStream = new P2P();
|
||||
// s.group[e.ke].mon[e.id].spawn.stdout.pipe(s.group[e.ke].mon[e.id].p2pStream)
|
||||
|
|
@ -4032,6 +4041,79 @@ var tx;
|
|||
}
|
||||
})
|
||||
//unique Base64 socket stream
|
||||
cn.on('h265',function(d){
|
||||
if(!s.group[d.ke]||!s.group[d.ke].mon||!s.group[d.ke].mon[d.id]){
|
||||
cn.disconnect();return;
|
||||
}
|
||||
cn.ip=cn.request.connection.remoteAddress;
|
||||
var toUTC = function(){
|
||||
return new Date().toISOString();
|
||||
}
|
||||
var tx=function(z){cn.emit('data',z);}
|
||||
d.failed=function(msg){
|
||||
tx({f:'stop_reconnect',msg:msg,token_used:d.auth,ke:d.ke});
|
||||
cn.disconnect();
|
||||
}
|
||||
d.success=function(r){
|
||||
r=r[0];
|
||||
var Emitter,chunkChannel
|
||||
if(!d.channel){
|
||||
Emitter = s.group[d.ke].mon[d.id].emitter
|
||||
chunkChannel = 'MAIN'
|
||||
}else{
|
||||
Emitter = s.group[d.ke].mon[d.id].emitterChannel[parseInt(d.channel)+config.pipeAddition]
|
||||
chunkChannel = parseInt(d.channel)+config.pipeAddition
|
||||
}
|
||||
if(!Emitter){
|
||||
cn.disconnect();return;
|
||||
}
|
||||
if(!d.channel)d.channel = 'MAIN';
|
||||
cn.ke=d.ke,
|
||||
cn.uid=d.uid,
|
||||
cn.auth=d.auth;
|
||||
cn.channel=d.channel;
|
||||
cn.removeListenerOnDisconnect=true;
|
||||
cn.socketVideoStream=d.id;
|
||||
var contentWriter
|
||||
cn.closeSocketVideoStream = function(){
|
||||
Emitter.removeListener('data', contentWriter);
|
||||
}
|
||||
Emitter.on('data',contentWriter = function(base64){
|
||||
tx(base64)
|
||||
})
|
||||
}
|
||||
//check if auth key is user's temporary session key
|
||||
if(s.group[d.ke]&&s.group[d.ke].users&&s.group[d.ke].users[d.auth]){
|
||||
d.success(s.group[d.ke].users[d.auth]);
|
||||
}else{
|
||||
s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND auth=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) {
|
||||
if(r&&r[0]){
|
||||
d.success(r)
|
||||
}else{
|
||||
s.sqlQuery('SELECT * FROM API WHERE ke=? AND code=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) {
|
||||
if(r&&r[0]){
|
||||
r=r[0]
|
||||
r.details=JSON.parse(r.details)
|
||||
if(r.details.auth_socket==='1'){
|
||||
s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND uid=?',[r.ke,r.uid],function(err,r) {
|
||||
if(r&&r[0]){
|
||||
d.success(r)
|
||||
}else{
|
||||
d.failed('User not found')
|
||||
}
|
||||
})
|
||||
}else{
|
||||
d.failed('Permissions for this key do not allow authentication with Websocket')
|
||||
}
|
||||
}else{
|
||||
d.failed('Not an API key')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
//unique Base64 socket stream
|
||||
cn.on('Base64',function(d){
|
||||
if(!s.group[d.ke]||!s.group[d.ke].mon||!s.group[d.ke].mon[d.id]){
|
||||
cn.disconnect();return;
|
||||
|
|
@ -5442,6 +5524,8 @@ if(config.renderPaths === undefined){config.renderPaths={}}
|
|||
if(config.renderPaths.mjpeg === undefined){config.renderPaths.mjpeg='pages/mjpeg'}
|
||||
//gridstack only page
|
||||
if(config.renderPaths.grid === undefined){config.renderPaths.grid='pages/grid'}
|
||||
//slick.js (cycle) page
|
||||
if(config.renderPaths.cycle === undefined){config.renderPaths.cycle='pages/cycle'}
|
||||
////Pages
|
||||
app.enable('trust proxy');
|
||||
app.use('/libs',express.static(__dirname + '/web/libs'));
|
||||
|
|
@ -5979,8 +6063,42 @@ app.get([config.webPaths.apiPrefix+':auth/flv/:ke/:id/s.flv',config.webPaths.api
|
|||
},res,req)
|
||||
},res,req)
|
||||
})
|
||||
//Get H.265/h265 HEVC stream
|
||||
app.get([config.webPaths.apiPrefix+':auth/h265/:ke/:id/s.hevc',config.webPaths.apiPrefix+':auth/h265/:ke/:id/:channel/s.hevc'], function(req,res) {
|
||||
res.header("Access-Control-Allow-Origin",req.headers.origin);
|
||||
s.auth(req.params,function(user){
|
||||
s.checkChildProxy(req.params,function(){
|
||||
var Emitter,chunkChannel
|
||||
if(!req.params.channel){
|
||||
Emitter = s.group[req.params.ke].mon[req.params.id].emitter
|
||||
chunkChannel = 'MAIN'
|
||||
}else{
|
||||
Emitter = s.group[req.params.ke].mon[req.params.id].emitterChannel[parseInt(req.params.channel)+config.pipeAddition]
|
||||
chunkChannel = parseInt(req.params.channel)+config.pipeAddition
|
||||
}
|
||||
//variable name of contentWriter
|
||||
var contentWriter
|
||||
//set headers
|
||||
res.setHeader('Content-Type', 'video/mp4');
|
||||
res.setHeader('Access-Control-Allow-Origin','*');
|
||||
//write new frames as they happen
|
||||
Emitter.on('data',contentWriter=function(buffer){
|
||||
res.write(buffer)
|
||||
})
|
||||
//remove contentWriter when client leaves
|
||||
res.on('close', function () {
|
||||
Emitter.removeListener('data',contentWriter)
|
||||
})
|
||||
},res,req)
|
||||
},res,req)
|
||||
})
|
||||
//montage - stand alone squished view with gridstackjs
|
||||
app.get([config.webPaths.apiPrefix+':auth/grid/:ke',config.webPaths.apiPrefix+':auth/grid/:ke/:group'], function(req,res) {
|
||||
app.get([
|
||||
config.webPaths.apiPrefix+':auth/grid/:ke',
|
||||
config.webPaths.apiPrefix+':auth/grid/:ke/:group',
|
||||
config.webPaths.apiPrefix+':auth/cycle/:ke',
|
||||
config.webPaths.apiPrefix+':auth/cycle/:ke/:group'
|
||||
], function(req,res) {
|
||||
res.header("Access-Control-Allow-Origin",req.headers.origin);
|
||||
s.auth(req.params,function(user){
|
||||
if(user.permissions.get_monitors==="0"){
|
||||
|
|
@ -6066,14 +6184,19 @@ app.get([config.webPaths.apiPrefix+':auth/grid/:ke',config.webPaths.apiPrefix+':
|
|||
}
|
||||
}
|
||||
})
|
||||
res.render(config.renderPaths.grid,{
|
||||
var page = config.renderPaths.grid
|
||||
if(req.path.indexOf('/cycle/') > -1){
|
||||
page = config.renderPaths.cycle
|
||||
}
|
||||
res.render(page,{
|
||||
data:Object.assign(req.params,req.query),
|
||||
baseUrl:req.protocol+'://'+req.hostname,
|
||||
config:config,
|
||||
lang:user.lang,
|
||||
$user:user,
|
||||
monitors:r,
|
||||
originalURL:s.getOriginalUrl(req)
|
||||
originalURL:s.getOriginalUrl(req),
|
||||
query:req.query
|
||||
});
|
||||
})
|
||||
},res,req)
|
||||
|
|
|
|||
|
|
@ -486,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)",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -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':
|
||||
|
|
@ -779,7 +782,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 +1132,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;
|
||||
}
|
||||
|
|
@ -2260,6 +2263,39 @@ $.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()
|
||||
}
|
||||
player = new libde265.RawPlayer(video)
|
||||
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()
|
||||
}
|
||||
$.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
|
||||
var buffer
|
||||
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)
|
||||
})
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
d.signal=parseFloat(d.d.signal_check);
|
||||
|
|
@ -2420,7 +2456,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');
|
||||
|
|
@ -2908,7 +2944,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({
|
||||
|
|
@ -2988,7 +3024,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')
|
||||
|
|
@ -3022,7 +3058,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 = '';
|
||||
|
|
@ -3183,7 +3219,7 @@ $.multimon.e.find('.import_config').click(function(){
|
|||
newMon.details.auto_host = Monitor.Device
|
||||
break;
|
||||
case'remote':
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
newMon.details = JSON.stringify(newMon.details)
|
||||
|
|
@ -3764,12 +3800,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'){
|
||||
|
|
@ -3839,7 +3875,7 @@ $.aM.f.submit(function(ee){
|
|||
})
|
||||
console.log(chosenMonitors)
|
||||
}
|
||||
|
||||
|
||||
$.aM.e.modal('hide')
|
||||
return false;
|
||||
});
|
||||
|
|
@ -4655,7 +4691,7 @@ $.timelapse.play = function(x){
|
|||
clearInterval($.timelapse.interval)
|
||||
videoNow.currentTime = videoNow.duration
|
||||
}else{
|
||||
videoNow.currentTime += .5
|
||||
videoNow.currentTime += .5
|
||||
}
|
||||
},500 / $.timelapse.playRate)
|
||||
}
|
||||
|
|
@ -4833,7 +4869,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')
|
||||
|
|
@ -4954,7 +4990,7 @@ $.pwrvid.e.on('click','[preview]',function(e){
|
|||
})
|
||||
if(e.status==1){
|
||||
$.get($.ccio.init('videoHrefToRead',e.href),function(d){
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
var labels=[]
|
||||
|
|
@ -5085,7 +5121,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')
|
||||
|
|
@ -5342,7 +5378,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){
|
||||
|
|
@ -5426,7 +5462,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
|
||||
|
|
@ -5529,7 +5565,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});
|
||||
|
|
|
|||
|
|
@ -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,10 +124,10 @@
|
|||
<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>
|
||||
|
|
@ -294,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,jpeg">
|
||||
<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>
|
||||
|
|
@ -305,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>
|
||||
|
|
@ -323,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">
|
||||
|
|
@ -357,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>
|
||||
|
|
@ -370,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>
|
||||
|
|
@ -453,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>
|
||||
|
|
@ -584,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>
|
||||
|
|
@ -712,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>
|
||||
|
|
@ -1265,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>
|
||||
|
|
@ -1279,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>
|
||||
|
|
@ -1289,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>
|
||||
|
|
@ -1297,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>
|
||||
|
|
@ -1398,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>
|
||||
|
|
@ -1407,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>
|
||||
|
|
@ -1440,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>
|
||||
|
|
@ -1449,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>
|
||||
|
|
@ -1511,8 +1511,8 @@
|
|||
<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>
|
||||
|
|
@ -1553,8 +1553,8 @@
|
|||
</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>
|
||||
|
|
|
|||
|
|
@ -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.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>
|
||||
|
|
@ -209,7 +210,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{
|
||||
|
|
@ -261,6 +262,39 @@ $(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]
|
||||
if (player) {
|
||||
player.stop()
|
||||
}
|
||||
player = new libde265.RawPlayer(video)
|
||||
player.set_status_callback(function(msg, fps) {
|
||||
})
|
||||
player.launch()
|
||||
if($.shinobi.mon[d.id].h265Socket && $.shinobi.mon[d.id].h265Socket.connected){
|
||||
$.shinobi.mon[d.id].h265Socket.disconnect()
|
||||
}
|
||||
$.shinobi.mon[d.id].h265Socket = io('<%=data.url%>',{transports: ['websocket'], forceNew: false})
|
||||
var ws = $.shinobi.mon[d.id].h265Socket
|
||||
var buffer
|
||||
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)
|
||||
})
|
||||
})
|
||||
break;
|
||||
case'flv':
|
||||
if (flvjs.isSupported()) {
|
||||
if($.shinobi.mon[d.id].flv){
|
||||
|
|
@ -413,4 +447,4 @@ $(document).ready(function(){
|
|||
$.shinobi.init(monitor);
|
||||
})
|
||||
$('.shinobi_ws_http_toggle').show()
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -180,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.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>
|
||||
|
|
@ -194,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 %>
|
||||
|
|
|
|||
Loading…
Reference in New Issue