first
This commit is contained in:
1 parent
af2f967059
commit
754c24615c
166 files changed
+81865
-2
No files matched your search
@@ -0,0 +1,218 @@
|
||||
var rtspPlayer={
|
||||
active:false,
|
||||
type:'live',
|
||||
hls:null,
|
||||
ws:null,
|
||||
mseSourceBuffer:null,
|
||||
mse:null,
|
||||
mseQueue:[],
|
||||
mseStreamingStarted:false,
|
||||
webrtc:null,
|
||||
webrtcSendChannel:null,
|
||||
webrtcSendChannelInterval:null,
|
||||
uuid:null,
|
||||
|
||||
clearPlayer:function(){
|
||||
if(this.active){
|
||||
|
||||
if(this.hls!=null){
|
||||
this.hls.destroy();
|
||||
this.hls=null;
|
||||
}
|
||||
if(this.ws!=null){
|
||||
//close WebSocket connection if opened
|
||||
this.ws.close(1000);
|
||||
this.ws=null;
|
||||
}
|
||||
if(this.webrtc!=null){
|
||||
clearInterval(this.webrtcSendChannelInterval);
|
||||
|
||||
this.webrtc=null;
|
||||
}
|
||||
$('#videoPlayer')[0].src = '';
|
||||
$('#videoPlayer')[0].load();
|
||||
|
||||
|
||||
this.active=false;
|
||||
}
|
||||
},
|
||||
livePlayer:function(type,uuid){
|
||||
this.clearPlayer();
|
||||
this.uuid=uuid;
|
||||
this.active=true;
|
||||
|
||||
$('.streams-vs-player').addClass('active-player');
|
||||
if(type==0){
|
||||
type=$('input[name=defaultPlayer]:checked').val()
|
||||
}
|
||||
switch (type) {
|
||||
case 'hls':
|
||||
this.playHls();
|
||||
break;
|
||||
case 'mse':
|
||||
this.playMse();
|
||||
break;
|
||||
case 'webrtc':
|
||||
this.playWebrtc();
|
||||
break;
|
||||
default:
|
||||
Swal.fire(
|
||||
'Sorry',
|
||||
'This option is still under development',
|
||||
'question'
|
||||
)
|
||||
return;
|
||||
}
|
||||
|
||||
},
|
||||
playHls:function(){
|
||||
if(this.hls==null && Hls.isSupported()){
|
||||
this.hls = new Hls();
|
||||
}
|
||||
if ($("#videoPlayer")[0].canPlayType('application/vnd.apple.mpegurl')) {
|
||||
$("#videoPlayer")[0].src = this.streamPlayUrl('hls');
|
||||
$("#videoPlayer")[0].load();
|
||||
} else {
|
||||
if (this.hls != null) {
|
||||
this.hls.loadSource(this.streamPlayUrl('hls'));
|
||||
this.hls.attachMedia($("#videoPlayer")[0]);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Oops...',
|
||||
text: 'Your browser don`t support hls '
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
playWebrtc:function(){
|
||||
var _this=this;
|
||||
this.webrtc=new RTCPeerConnection({
|
||||
iceServers: [{
|
||||
urls: ["stun:stun.l.google.com:19302"]
|
||||
}]
|
||||
});
|
||||
this.webrtc.onnegotiationneeded = this.handleNegotiationNeeded;
|
||||
this.webrtc.ontrack = function(event) {
|
||||
console.log(event.streams.length + ' track is delivered');
|
||||
$("#videoPlayer")[0].srcObject = event.streams[0];
|
||||
$("#videoPlayer")[0].play();
|
||||
}
|
||||
this.webrtc.addTransceiver('video', {
|
||||
'direction': 'sendrecv'
|
||||
});
|
||||
this.webrtcSendChannel = this.webrtc.createDataChannel('foo');
|
||||
this.webrtcSendChannel.onclose = () => console.log('sendChannel has closed');
|
||||
this.webrtcSendChannel.onopen = () => {
|
||||
console.log('sendChannel has opened');
|
||||
this.webrtcSendChannel.send('ping');
|
||||
this.webrtcSendChannelInterval = setInterval(() => {
|
||||
this.webrtcSendChannel.send('ping');
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
this.webrtcSendChannel.onmessage = e => console.log(e.data);
|
||||
},
|
||||
handleNegotiationNeeded: async function(){
|
||||
var _this=rtspPlayer;
|
||||
|
||||
offer = await _this.webrtc.createOffer();
|
||||
await _this.webrtc.setLocalDescription(offer);
|
||||
$.post(_this.streamPlayUrl('webrtc'), {
|
||||
data: btoa(_this.webrtc.localDescription.sdp)
|
||||
}, function(data) {
|
||||
//console.log(data)
|
||||
try {
|
||||
|
||||
_this.webrtc.setRemoteDescription(new RTCSessionDescription({
|
||||
type: 'answer',
|
||||
sdp: atob(data)
|
||||
}))
|
||||
|
||||
|
||||
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
playMse:function(){
|
||||
//console.log(this.streamPlayUrl('mse'));
|
||||
var _this=this;
|
||||
this.mse = new MediaSource();
|
||||
$("#videoPlayer")[0].src=window.URL.createObjectURL(this.mse);
|
||||
this.mse.addEventListener('sourceopen', function(){
|
||||
_this.ws=new WebSocket(_this.streamPlayUrl('mse'));
|
||||
_this.ws.binaryType = "arraybuffer";
|
||||
_this.ws.onopen = function(event) {
|
||||
console.log('Connect to ws');
|
||||
}
|
||||
|
||||
_this.ws.onmessage = function(event) {
|
||||
var data = new Uint8Array(event.data);
|
||||
if (data[0] == 9) {
|
||||
decoded_arr=data.slice(1);
|
||||
if (window.TextDecoder) {
|
||||
mimeCodec = new TextDecoder("utf-8").decode(decoded_arr);
|
||||
} else {
|
||||
mimeCodec = Utf8ArrayToStr(decoded_arr);
|
||||
}
|
||||
console.log(mimeCodec);
|
||||
_this.mseSourceBuffer = _this.mse.addSourceBuffer('video/mp4; codecs="' + mimeCodec + '"');
|
||||
_this.mseSourceBuffer.mode = "segments"
|
||||
_this.mseSourceBuffer.addEventListener("updateend", _this.pushPacket);
|
||||
|
||||
} else {
|
||||
_this.readPacket(event.data);
|
||||
}
|
||||
};
|
||||
}, false);
|
||||
|
||||
},
|
||||
readPacket:function(packet){
|
||||
if (!this.mseStreamingStarted) {
|
||||
this.mseSourceBuffer.appendBuffer(packet);
|
||||
this.mseStreamingStarted = true;
|
||||
return;
|
||||
}
|
||||
this.mseQueue.push(packet);
|
||||
|
||||
if (!this.mseSourceBuffer.updating) {
|
||||
this.pushPacket();
|
||||
}
|
||||
},
|
||||
pushPacket:function(){
|
||||
var _this=rtspPlayer;
|
||||
if (!_this.mseSourceBuffer.updating) {
|
||||
if (_this.mseQueue.length > 0) {
|
||||
packet = _this.mseQueue.shift();
|
||||
var view = new Uint8Array(packet);
|
||||
_this.mseSourceBuffer.appendBuffer(packet);
|
||||
} else {
|
||||
_this.mseStreamingStarted = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
streamPlayUrl:function(type){
|
||||
switch (type) {
|
||||
case 'hls':
|
||||
return '/stream/' + this.uuid + '/hls/live/index.m3u8';
|
||||
break;
|
||||
case 'mse':
|
||||
var potocol = 'ws';
|
||||
if (location.protocol == 'https:') {
|
||||
potocol = 'wss';
|
||||
}
|
||||
return potocol+'://'+location.host+'/stream/' + this.uuid +'/mse?uuid='+this.uuid;
|
||||
//return 'ws://sr4.ipeye.ru/ws/mp4/live?name=d4ee855e40874ef7b7149357a42f18f0';
|
||||
break;
|
||||
case 'webrtc':
|
||||
return "/stream/"+this.uuid+"/webrtc?uuid=" + this.uuid;
|
||||
break;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/*!
|
||||
* AdminLTE v3.0.5 (https://adminlte.io)
|
||||
* Copyright 2014-2020 Colorlib <http://colorlib.com>
|
||||
* Licensed under MIT (https://github.com/ColorlibHQ/AdminLTE/blob/master/LICENSE)
|
||||
*/
|
||||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).adminlte={})}(this,(function(t){"use strict";var e=function(t){var e="ControlSidebar",i="lte.controlsidebar",n=t.fn[e],s={COLLAPSED:"collapsed.lte.controlsidebar",EXPANDED:"expanded.lte.controlsidebar"},o=".control-sidebar",a=".control-sidebar-content",r='[data-widget="control-sidebar"]',l=".main-header",c=".main-footer",d="control-sidebar-animate",h="control-sidebar-open",f="control-sidebar-slide-open",u="layout-fixed",g="layout-navbar-fixed",p="layout-sm-navbar-fixed",_="layout-md-navbar-fixed",m="layout-lg-navbar-fixed",v="layout-xl-navbar-fixed",C="layout-footer-fixed",y="layout-sm-footer-fixed",b="layout-md-footer-fixed",w="layout-lg-footer-fixed",x="layout-xl-footer-fixed",E={controlsidebarSlide:!0,scrollbarTheme:"os-theme-light",scrollbarAutoHide:"l"},A=function(){function e(t,e){this._element=t,this._config=e,this._init()}var n=e.prototype;return n.collapse=function(){this._config.controlsidebarSlide?(t("html").addClass(d),t("body").removeClass(f).delay(300).queue((function(){t(o).hide(),t("html").removeClass(d),t(this).dequeue()}))):t("body").removeClass(h);var e=t.Event(s.COLLAPSED);t(this._element).trigger(e)},n.show=function(){this._config.controlsidebarSlide?(t("html").addClass(d),t(o).show().delay(10).queue((function(){t("body").addClass(f).delay(300).queue((function(){t("html").removeClass(d),t(this).dequeue()})),t(this).dequeue()}))):t("body").addClass(h);var e=t.Event(s.EXPANDED);t(this._element).trigger(e)},n.toggle=function(){t("body").hasClass(h)||t("body").hasClass(f)?this.collapse():this.show()},n._init=function(){var e=this;this._fixHeight(),this._fixScrollHeight(),t(window).resize((function(){e._fixHeight(),e._fixScrollHeight()})),t(window).scroll((function(){(t("body").hasClass(h)||t("body").hasClass(f))&&e._fixScrollHeight()}))},n._fixScrollHeight=function(){var e={scroll:t(document).height(),window:t(window).height(),header:t(l).outerHeight(),footer:t(c).outerHeight()},i=Math.abs(e.window+t(window).scrollTop()-e.scroll),n=t(window).scrollTop(),s=!1,r=!1;t("body").hasClass(u)&&((t("body").hasClass(g)||t("body").hasClass(p)||t("body").hasClass(_)||t("body").hasClass(m)||t("body").hasClass(v))&&"fixed"===t(l).css("position")&&(s=!0),(t("body").hasClass(C)||t("body").hasClass(y)||t("body").hasClass(b)||t("body").hasClass(w)||t("body").hasClass(x))&&"fixed"===t(c).css("position")&&(r=!0),0===n&&0===i?(t(o).css("bottom",e.footer),t(o).css("top",e.header),t(o+", "+o+" "+a).css("height",e.window-(e.header+e.footer))):i<=e.footer?!1===r?(t(o).css("bottom",e.footer-i),t(o+", "+o+" "+a).css("height",e.window-(e.footer-i))):t(o).css("bottom",e.footer):n<=e.header?!1===s?(t(o).css("top",e.header-n),t(o+", "+o+" "+a).css("height",e.window-(e.header-n))):t(o).css("top",e.header):!1===s?(t(o).css("top",0),t(o+", "+o+" "+a).css("height",e.window)):t(o).css("top",e.header))},n._fixHeight=function(){var e=t(window).height(),i=t(l).outerHeight(),n=t(c).outerHeight();if(t("body").hasClass(u)){var s=e-i;(t("body").hasClass(C)||t("body").hasClass(y)||t("body").hasClass(b)||t("body").hasClass(w)||t("body").hasClass(x))&&"fixed"===t(c).css("position")&&(s=e-i-n),t(o+" "+a).css("height",s),"undefined"!=typeof t.fn.overlayScrollbars&&t(o+" "+a).overlayScrollbars({className:this._config.scrollbarTheme,sizeAutoCapable:!0,scrollbars:{autoHide:this._config.scrollbarAutoHide,clickScrolling:!0}})}},e._jQueryInterface=function(n){return this.each((function(){var s=t(this).data(i),o=t.extend({},E,t(this).data());if(s||(s=new e(this,o),t(this).data(i,s)),"undefined"===s[n])throw new Error(n+" is not a function");s[n]()}))},e}();return t(document).on("click",r,(function(e){e.preventDefault(),A._jQueryInterface.call(t(this),"toggle")})),t.fn[e]=A._jQueryInterface,t.fn[e].Constructor=A,t.fn[e].noConflict=function(){return t.fn[e]=n,A._jQueryInterface},A}(jQuery),i=function(t){var e="Layout",i=t.fn[e],n=".main-header",s=".main-sidebar",o=".main-sidebar .sidebar",a=".content-wrapper",r=".control-sidebar-content",l='[data-widget="control-sidebar"]',c=".main-footer",d='[data-widget="pushmenu"]',h=".login-box",f=".register-box",u="sidebar-focused",g="layout-fixed",p="control-sidebar-slide-open",_="control-sidebar-open",m={scrollbarTheme:"os-theme-light",scrollbarAutoHide:"l",panelAutoHeight:!0,loginRegisterAutoHeight:!0},v=function(){function e(t,e){this._config=e,this._element=t,this._init()}var i=e.prototype;return i.fixLayoutHeight=function(e){void 0===e&&(e=null);var i=0;(t("body").hasClass(p)||t("body").hasClass(_)||"control_sidebar"==e)&&(i=t(r).height());var s={window:t(window).height(),header:0!==t(n).length?t(n).outerHeight():0,footer:0!==t(c).length?t(c).outerHeight():0,sidebar:0!==t(o).length?t(o).height():0,control_sidebar:i},l=this._max(s),d=this._config.panelAutoHeight;!0===d&&(d=0),!1!==d&&(l==s.control_sidebar?t(a).css("min-height",l+d):l==s.window?t(a).cssLine truncated
|
||||
//# sourceMappingURL=adminlte.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../build/js/ControlSidebar.js","../../build/js/Layout.js","../../build/js/PushMenu.js","../../build/js/Treeview.js","../../build/js/DirectChat.js","../../build/js/TodoList.js","../../build/js/CardWidget.js","../../build/js/CardRefresh.js","../../build/js/Dropdown.js","../../build/js/Toasts.js"],"names":["ControlSidebar","$","NAME","DATA_KEY","JQUERY_NO_CONFLICT","fn","Event","COLLAPSED","EXPANDED","Selector","ClassName","Default","controlsidebarSlide","scrollbarTheme","scrollbarAutoHide","element","config","this","_element","_config","_init","_proto","prototype","collapse","addClass","removeClass","delay","queue","hide","dequeue","collapsedEvent","trigger","show","expandedEvent","toggle","hasClass","_this","_fixHeight","_fixScrollHeight","window","resize","scroll","heights","document","height","header","outerHeight","footer","positions","Math","abs","scrollTop","navbarFixed","footerFixed","css","sidebarHeight","overlayScrollbars","className","sizeAutoCapable","scrollbars","autoHide","clickScrolling","_jQueryInterface","operation","each","data","_options","extend","Error","on","event","preventDefault","call","Constructor","noConflict","jQuery","Layout","panelAutoHeight","loginRegisterAutoHeight","fixLayoutHeight","extra","control_sidebar","length","sidebar","max","_max","offset","_isFooterFixed","parseFloat","fixLoginRegisterHeight","box_height","Number","isInteger","setInterval","setTimeout","numbers","Object","keys","forEach","key","PushMenu","EVENT_KEY","SHOWN","autoCollapseSize","enableRemember","noTransitionAfterReload","options","_addOverlay","expand","width","localStorage","setItem","shownEvent","autoCollapse","remember","getItem","_this2","overlay","id","append","match","button","currentTarget","closest","Treeview","SELECTED","LOAD_DATA_API","animationSpeed","accordion","expandSidebar","sidebarButtonSelector","init","_setupListeners","treeviewMenu","parentLi","openMenuLi","siblings","first","openTreeview","find","stop","slideDown","_expandSidebar","slideUp","$relativeTarget","$parent","parent","is","parents","_this3","DirectChat","toggleClass","toggledEvent","TodoList","onCheck","item","onUnCheck","prop","check","unCheck","that","target","CardWidget","MAXIMIZED","MINIMIZED","REMOVED","DATA_REMOVE","DATA_COLLAPSE","DATA_MAXIMIZE","CARD","CARD_HEADER","CARD_BODY","CARD_FOOTER","collapseTrigger","removeTrigger","maximizeTrigger","collapseIcon","expandIcon","maximizeIcon","minimizeIcon","settings","_parent","_settings","children","collapsed","expanded","remove","removed","maximize","transition","maximized","minimize","style","toggleMaximize","card","click","CardRefresh","LOADED","OVERLAY_ADDED","OVERLAY_REMOVED","DATA_REFRESH","source","sourceSelector","params","content","loadInContent","loadOnInit","responseType","overlayTemplate","onLoadStart","onLoadDone","response","_overlay","load","get","html","_removeOverlay","bind","loadedEvent","overlayAddedEvent","overlayRemovedEvent","ready","Dropdown","toggleSubmenu","next","e","fixPosition","elm","visiblePart","left","stopPropagation","Toasts","INIT","CREATED","Position","position","fixed","autohide","autoremove","fade","icon","image","imageAlt","imageHeight","title","subtitle","close","body","class","_prepareContainer","initEvent","create","toast","toast_header","toast_image","attr","toast_close","_getContainerId","prepend","createdEvent","removedEvent","container","replace","option"],"mappings":";;;;;sMAOA,IAAMA,EAAkB,SAACC,GAMvB,IAAMC,EAAqB,iBACrBC,EAAqB,qBAErBC,EAAqBH,EAAEI,GAAGH,GAG1BI,EAAQ,CACZC,UAAS,+BACTC,SAAQ,+BAGJC,EACa,mBADbA,EAEqB,2BAFrBA,EAGS,kCAHTA,EAKI,eALJA,EAMI,eAGJC,EACqB,0BADrBA,EAEkB,uBAFlBA,EAGmB,6BAHnBA,EAIU,eAJVA,EAKU,sBALVA,EAMa,yBANbA,EAOa,yBAPbA,EAQa,yBARbA,EASa,yBATbA,EAUU,sBAVVA,EAWa,yBAXbA,EAYa,yBAZbA,EAaa,yBAbbA,EAca,yBAGbC,EAAU,CACdC,qBAAqB,EACrBC,eAAiB,iBACjBC,kBAAmB,KAQfd,EAtDuB,WAuD3B,SAAAA,EAAYe,EAASC,GACnBC,KAAKC,SAAWH,EAChBE,KAAKE,QAAWH,EAEhBC,KAAKG,QA3DoB,IAAAC,EAAArB,EAAAsB,UAAA,OAAAD,EAgE3BE,SAAA,WAEMN,KAAKE,QAAQP,qBACfX,EAAE,QAAQuB,SAASd,GACnBT,EAAE,QAAQwB,YAAYf,GAAiCgB,MAAM,KAAKC,OAAM,WACtE1B,EAAEQ,GAA0BmB,OAC5B3B,EAAE,QAAQwB,YAAYf,GACtBT,EAAEgB,MAAMY,cAGV5B,EAAE,QAAQwB,YAAYf,GAGxB,IAAMoB,EAAiB7B,EAAEK,MAAMA,EAAMC,WACrCN,EAAEgB,KAAKC,UAAUa,QAAQD,IA9EAT,EAiF3BW,KAAA,WAEMf,KAAKE,QAAQP,qBACfX,EAAE,QAAQuB,SAASd,GACnBT,EAAEQ,GAA0BuB,OAAON,MAAM,IAAIC,OAAM,WACjD1B,EAAE,QAAQuB,SAASd,GAAiCgB,MAAM,KAAKC,OAAM,WACnE1B,EAAE,QAAQwB,YAAYf,GACtBT,EAAEgB,MAAMY,aAEV5B,EAAEgB,MAAMY,cAGV5B,EAAE,QAAQuB,SAASd,GAGrB,IAAMuB,EAAgBhC,EAAEK,MAAMA,EAAME,UACpCP,EAAEgB,KAAKC,UAAUa,QAAQE,IAjGAZ,EAoG3Ba,OAAA,WACsBjC,EAAE,QAAQkC,SAASzB,IAAmCT,EAAE,QACzEkC,SAASzB,GAGVO,KAAKM,WAGLN,KAAKe,QA5GkBX,EAkH3BD,MAAA,WAAQ,IAAAgB,EAAAnB,KACNA,KAAKoB,aACLpB,KAAKqB,mBAELrC,EAAEsC,QAAQC,QAAO,WACfJ,EAAKC,aACLD,EAAKE,sBAGPrC,EAAEsC,QAAQE,QAAO,YACXxC,EAAE,QAAQkC,SAASzB,IAAmCT,EAAE,QAAQkC,SAASzB,KACzE0B,EAAKE,uBA7HcjB,EAkI3BiB,iBAAA,WACE,IAAMI,EAAU,CACdD,OAAQxC,EAAE0C,UAAUC,SACpBL,OAAQtC,EAAEsC,QAAQK,SAClBC,OAAQ5C,EAAEQ,GAAiBqC,cAC3BC,OAAQLine truncated
|
||||
@@ -0,0 +1,531 @@
|
||||
$(document).ready(() => {
|
||||
localImages();
|
||||
if (localStorage.getItem('defaultPlayer') != null) {
|
||||
$('input[name=defaultPlayer]').val([localStorage.getItem('defaultPlayer')]);
|
||||
}
|
||||
})
|
||||
$('input[name=defaultPlayer]').on('change', function() {
|
||||
localStorage.setItem('defaultPlayer', $(this).val());
|
||||
})
|
||||
|
||||
var activeStream = null;
|
||||
|
||||
function showAddStream(streamName, streamUrl) {
|
||||
streamName = streamName || '';
|
||||
streamUrl = streamUrl || '';
|
||||
Swal.fire({
|
||||
title: 'Add stream',
|
||||
html: '<form class="text-left"> ' +
|
||||
'<div class="form-group">' +
|
||||
'<label>Name</label>' +
|
||||
'<input type="text" class="form-control" id="stream-name">' +
|
||||
'<small class="form-text text-muted"></small>' +
|
||||
'</div>' +
|
||||
'<div class="form-group">' +
|
||||
' <label>URL</label>' +
|
||||
' <input type="text" class="form-control" id="stream-url">' +
|
||||
' </div>' +
|
||||
'<div class="form-group form-check">' +
|
||||
'<input type="checkbox" class="form-check-input" id="stream-ondemand">' +
|
||||
'<label class="form-check-label">ondemand</label>' +
|
||||
'</div>' +
|
||||
'</form>',
|
||||
focusConfirm: true,
|
||||
showCancelButton: true,
|
||||
preConfirm: () => {
|
||||
var uuid = randomUuid(),
|
||||
name = $('#stream-name').val(),
|
||||
url = $('#stream-url').val(),
|
||||
ondemand = $('#stream-ondemand').val();
|
||||
if (!validURL(url)) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Oops...',
|
||||
text: 'wrong url',
|
||||
confirmButtonText: 'return back',
|
||||
preConfirm: () => {
|
||||
showAddStream(name, url)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
goRequest('add', uuid, {
|
||||
name: name,
|
||||
url: url,
|
||||
ondemand: ondemand
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function showEditStream(uuid) {
|
||||
console.log(streams[uuid]);
|
||||
}
|
||||
|
||||
function deleteStream(uuid) {
|
||||
activeStream = uuid;
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: "Do you want delete stream " + streams[uuid].name + " ?",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, delete it!'
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
goRequest('delete', uuid)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function renewStreamlist() {
|
||||
goRequest('streams');
|
||||
}
|
||||
|
||||
function goRequest(method, uuid, data) {
|
||||
data = data || null;
|
||||
uuid = uuid || null;
|
||||
var path = '';
|
||||
var type = 'GET';
|
||||
switch (method) {
|
||||
case 'add':
|
||||
path = '/stream/' + uuid + '/add';
|
||||
type = 'POST';
|
||||
break;
|
||||
case 'edit':
|
||||
path = '/stream/' + uuid + '/edit';
|
||||
type = 'POST';
|
||||
break;
|
||||
case 'delete':
|
||||
path = '/stream/' + uuid + '/delete';
|
||||
break;
|
||||
case 'reload':
|
||||
path = '/stream/' + uuid + '/reload';
|
||||
break;
|
||||
case 'info':
|
||||
path = '/stream/' + uuid + '/info';
|
||||
break;
|
||||
case 'streams':
|
||||
path = '/streams';
|
||||
break;
|
||||
default:
|
||||
path = '';
|
||||
type = 'GET';
|
||||
}
|
||||
if (path == '') {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Oops...',
|
||||
text: 'It`s goRequest function mistake',
|
||||
confirmButtonText: 'Close',
|
||||
|
||||
})
|
||||
return;
|
||||
}
|
||||
var ajaxParam = {
|
||||
url: path,
|
||||
type: type,
|
||||
dataType: 'json',
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader("Authorization", "Basic " + btoa("demo:demo"));
|
||||
},
|
||||
success: function(response) {
|
||||
goRequestHandle(method, response, uuid);
|
||||
},
|
||||
error: function(e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
if (data != null) {
|
||||
ajaxParam.data = JSON.stringify(data);
|
||||
}
|
||||
$.ajax(ajaxParam);
|
||||
}
|
||||
|
||||
function goRequestHandle(method, response, uuid) {
|
||||
switch (method) {
|
||||
case 'add':
|
||||
|
||||
if (response.status == 1) {
|
||||
renewStreamlist();
|
||||
Swal.fire(
|
||||
'Added!',
|
||||
'Your stream has been Added.',
|
||||
'success'
|
||||
);
|
||||
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Oops...',
|
||||
text: 'Same mistake issset',
|
||||
})
|
||||
}
|
||||
|
||||
break;
|
||||
case 'edit':
|
||||
if (response.status == 1) {
|
||||
renewStreamlist();
|
||||
Swal.fire(
|
||||
'Success!',
|
||||
'Your stream has been modified.',
|
||||
'success'
|
||||
);
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Oops...',
|
||||
text: 'Same mistake issset',
|
||||
})
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
|
||||
if (response.status == 1) {
|
||||
$('#' + uuid).remove();
|
||||
delete(streams[uuid]);
|
||||
$('#stream-counter').html(Object.keys(streams).length);
|
||||
Swal.fire(
|
||||
'Deleted!',
|
||||
'Your stream has been deleted.',
|
||||
'success'
|
||||
)
|
||||
}
|
||||
|
||||
break;
|
||||
case 'reload':
|
||||
|
||||
break;
|
||||
case 'info':
|
||||
|
||||
break;
|
||||
case 'streams':
|
||||
if (response.status == 1) {
|
||||
streams = response.payload;
|
||||
$('#stream-counter').html(Object.keys(streams).length);
|
||||
if (Object.keys(streams).length > 0) {
|
||||
|
||||
$.each(streams, function(uuid, param) {
|
||||
if ($('#' + uuid).length == 0) {
|
||||
$('.streams').append(streamHtmlTemplate(uuid, param.name));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getImageBase64(videoEl){
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = videoEl.videoWidth;
|
||||
canvas.height = videoEl.videoHeight;
|
||||
canvas.getContext('2d').drawImage(videoEl, 0, 0, canvas.width, canvas.height);
|
||||
const dataURL = canvas.toDataURL();
|
||||
canvas.remove();
|
||||
return dataURL;
|
||||
}
|
||||
|
||||
function downloadBase64Image(base64Data){
|
||||
const a = document.createElement("a");
|
||||
a.href = base64Data;
|
||||
a.download = "screenshot.png";
|
||||
a.click();
|
||||
a.remove();
|
||||
}
|
||||
|
||||
|
||||
function makePic(video_element, uuid, chan) {
|
||||
if (typeof(video_element) === "undefined") {
|
||||
video_element = $("#videoPlayer")[0];
|
||||
}
|
||||
ratio = video_element.videoWidth / video_element.videoHeight;
|
||||
w = 400;
|
||||
h = parseInt(w / ratio, 10);
|
||||
$('#canvas')[0].width = w;
|
||||
$('#canvas')[0].height = h;
|
||||
$('#canvas')[0].getContext('2d').fillRect(0, 0, w, h);
|
||||
$('#canvas')[0].getContext('2d').drawImage(video_element, 0, 0, w, h);
|
||||
var imageData = $('#canvas')[0].toDataURL();
|
||||
var images = localStorage.getItem('imagesNew');
|
||||
if (images != null) {
|
||||
images = JSON.parse(images);
|
||||
} else {
|
||||
images = {};
|
||||
}
|
||||
var uid = $('#uuid').val();
|
||||
if (!!uuid) {
|
||||
uid = uuid;
|
||||
}
|
||||
|
||||
var channel = $('#channel').val() || chan || 0;
|
||||
if (typeof(images[uid]) === "undefined") {
|
||||
images[uid] = {};
|
||||
}
|
||||
images[uid][channel] = imageData;
|
||||
localStorage.setItem('imagesNew', JSON.stringify(images));
|
||||
$('#' + uid).find('.stream-img[channel="' + channel + '"]').attr('src', imageData);
|
||||
}
|
||||
|
||||
function localImages() {
|
||||
var images = localStorage.getItem('imagesNew');
|
||||
if (images != null) {
|
||||
images = JSON.parse(images);
|
||||
$.each(images, function(k, v) {
|
||||
$.each(v, function(channel, img) {
|
||||
$('#' + k).find('.stream-img[channel="' + channel + '"]').attr('src', img);
|
||||
})
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function clearLocalImg() {
|
||||
localStorage.setItem('imagesNew', '{}');
|
||||
}
|
||||
|
||||
function streamHtmlTemplate(uuid, name) {
|
||||
return '<div class="item" id="' + uuid + '">' +
|
||||
'<div class="stream">' +
|
||||
'<div class="thumbs" onclick="rtspPlayer.livePlayer(0, \'' + uuid + '\')">' +
|
||||
'<img src="../static/img/noimage.svg" alt="" class="stream-img">' +
|
||||
'</div>' +
|
||||
'<div class="text">' +
|
||||
'<h5>' + name + '</h5>' +
|
||||
'<p>property</p>' +
|
||||
'<div class="input-group-prepend dropleft text-muted">' +
|
||||
'<a class="btn" data-toggle="dropdown" >' +
|
||||
'<i class="fas fa-ellipsis-v"></i>' +
|
||||
'</a>' +
|
||||
'<div class="dropdown-menu">' +
|
||||
'<a class="dropdown-item" onclick="rtspPlayer.livePlayer(\'hls\', \'' + uuid + '\')" href="#">Play HLS</a>' +
|
||||
'<a class="dropdown-item" onclick="rtspPlayer.livePlayer(\'mse\', \'' + uuid + '\')" href="#">Play MSE</a>' +
|
||||
'<a class="dropdown-item" onclick="rtspPlayer.livePlayer(\'webrtc\', \'' + uuid + '\')" href="#">Play WebRTC</a>' +
|
||||
'<div class="dropdown-divider"></div>' +
|
||||
'<a class="dropdown-item" onclick="showEditStream(\'' + uuid + '\')" href="#">Edit</a>' +
|
||||
'<a class="dropdown-item" onclick="deleteStream(\'' + uuid + '\')" href="#">Delete</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function randomUuid() {
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
|
||||
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
function validURL(url) {
|
||||
//TODO: fix it
|
||||
return true;
|
||||
}
|
||||
|
||||
function Utf8ArrayToStr(array) {
|
||||
var out, i, len, c;
|
||||
var char2, char3;
|
||||
out = "";
|
||||
len = array.length;
|
||||
i = 0;
|
||||
while (i < len) {
|
||||
c = array[i++];
|
||||
switch (c >> 4) {
|
||||
case 7:
|
||||
out += String.fromCharCode(c);
|
||||
break;
|
||||
case 13:
|
||||
char2 = array[i++];
|
||||
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||
break;
|
||||
case 14:
|
||||
char2 = array[i++];
|
||||
char3 = array[i++];
|
||||
out += String.fromCharCode(((c & 0x0F) << 12) |
|
||||
((char2 & 0x3F) << 6) |
|
||||
((char3 & 0x3F) << 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function browserDetector() {
|
||||
var Browser;
|
||||
var ua = self.navigator.userAgent.toLowerCase();
|
||||
var match =
|
||||
/(edge)\/([\w.]+)/.exec(ua) ||
|
||||
/(opr)[\/]([\w.]+)/.exec(ua) ||
|
||||
/(chrome)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(iemobile)[\/]([\w.]+)/.exec(ua) ||
|
||||
/(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(
|
||||
ua
|
||||
) ||
|
||||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(msie) ([\w.]+)/.exec(ua) ||
|
||||
(ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec(ua)) ||
|
||||
(ua.indexOf("compatible") < 0 && /(firefox)[ \/]([\w.]+)/.exec(ua)) || [];
|
||||
var platform_match =
|
||||
/(ipad)/.exec(ua) ||
|
||||
/(ipod)/.exec(ua) ||
|
||||
/(windows phone)/.exec(ua) ||
|
||||
/(iphone)/.exec(ua) ||
|
||||
/(kindle)/.exec(ua) ||
|
||||
/(android)/.exec(ua) ||
|
||||
/(windows)/.exec(ua) ||
|
||||
/(mac)/.exec(ua) ||
|
||||
/(linux)/.exec(ua) ||
|
||||
/(cros)/.exec(ua) || [];
|
||||
var matched = {
|
||||
browser: match[5] || match[3] || match[1] || "",
|
||||
version: match[2] || match[4] || "0",
|
||||
majorVersion: match[4] || match[2] || "0",
|
||||
platform: platform_match[0] || ""
|
||||
};
|
||||
var browser = {};
|
||||
|
||||
if (matched.browser) {
|
||||
browser[matched.browser] = true;
|
||||
var versionArray = matched.majorVersion.split(".");
|
||||
browser.version = {
|
||||
major: parseInt(matched.majorVersion, 10),
|
||||
string: matched.version
|
||||
};
|
||||
|
||||
if (versionArray.length > 1) {
|
||||
browser.version.minor = parseInt(versionArray[1], 10);
|
||||
}
|
||||
|
||||
if (versionArray.length > 2) {
|
||||
browser.version.build = parseInt(versionArray[2], 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (matched.platform) {
|
||||
browser[matched.platform] = true;
|
||||
}
|
||||
|
||||
if (browser.chrome || browser.opr || browser.safari) {
|
||||
browser.webkit = true;
|
||||
} // MSIE. IE11 has 'rv' identifer
|
||||
|
||||
if (browser.rv || browser.iemobile) {
|
||||
if (browser.rv) {
|
||||
delete browser.rv;
|
||||
}
|
||||
|
||||
var msie = "msie";
|
||||
matched.browser = msie;
|
||||
browser[msie] = true;
|
||||
} // Microsoft Edge
|
||||
|
||||
if (browser.edge) {
|
||||
delete browser.edge;
|
||||
var msedge = "msedge";
|
||||
matched.browser = msedge;
|
||||
browser[msedge] = true;
|
||||
} // Opera 15+
|
||||
|
||||
if (browser.opr) {
|
||||
var opera = "opera";
|
||||
matched.browser = opera;
|
||||
browser[opera] = true;
|
||||
} // Stock android browsers are marked as Safari
|
||||
|
||||
if (browser.safari && browser.android) {
|
||||
var android = "android";
|
||||
matched.browser = android;
|
||||
browser[android] = true;
|
||||
}
|
||||
|
||||
browser.name = matched.browser;
|
||||
browser.platform = matched.platform;
|
||||
|
||||
|
||||
return browser;
|
||||
}
|
||||
|
||||
function addChannel() {
|
||||
$('#streams-form-wrapper').append(chanellTemplate());
|
||||
}
|
||||
|
||||
function chanellTemplate() {
|
||||
let random = Math.ceil(Math.random() * 1000);
|
||||
let html = `
|
||||
<div class="col-12">
|
||||
<div class="card card-secondary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Sub channel<small> parameters</small></h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" onclick="removeChannelDiv(this)"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="stream-form">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputPassword1">Substream url</label>
|
||||
<input type="text" name="stream-url" class="form-control" placeholder="Enter stream url" >
|
||||
<small class="form-text text-muted">Enter rtsp address as instructed by your camera. Look like <code>rtsp://<ip>:<port>/path </code> </small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="inputStatus">Substream type</label>
|
||||
<select class="form-control custom-select" name="stream-ondemand" >
|
||||
<option selected disabled><small>Select One</small></option>
|
||||
<option value="1">On demand only</option>
|
||||
<option value="0">Persistent connection</option>
|
||||
</select>
|
||||
<small class="form-text text-muted">On persistent connection, the server get data from the camera continuously. On demand, the server get data from the camera only when you click play button </small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" name="debug" id="substream-debug-switch-` + random + `" >
|
||||
<label class="custom-control-label" for="substream-debug-switch-` + random + `">Enable debug</label>
|
||||
</div>
|
||||
<small class="form-text text-muted">Select this options if you want get more data about the stream </small>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
return html;
|
||||
}
|
||||
|
||||
function removeChannelDiv(element) {
|
||||
$(element).closest('.col-12').remove();
|
||||
}
|
||||
|
||||
function logger() {
|
||||
if (!colordebug) {
|
||||
return;
|
||||
}
|
||||
let colors = {
|
||||
"0": "color:green",
|
||||
"1": "color:#66CDAA",
|
||||
"2": "color:blue",
|
||||
"3": "color:#FF1493",
|
||||
"4": "color:#40E0D0",
|
||||
"5": "color:red",
|
||||
"6": "color:red",
|
||||
"7": "color:red",
|
||||
"8": "color:red",
|
||||
"9": "color:red",
|
||||
"10": "color:red",
|
||||
"11": "color:red",
|
||||
"12": "color:red",
|
||||
"13": "color:red",
|
||||
"14": "color:red",
|
||||
"15": "color:red",
|
||||
}
|
||||
console.log('%c%s', colors[arguments[0]], new Date().toLocaleString() + " " + [].slice.call(arguments).join('|'))
|
||||
}
|
||||
Reference in new issue
Block a user