Home-AssistantConfig/config/www/community/frigate-hass-card/live-go2rtc-0795a62f.js

2 lines
10 KiB
JavaScript

import{dj as e,dk as t,dl as s,dm as i,s as n,di as o,cL as a,l as c,y as r,bj as h,bk as d,bl as l,bn as p}from"./card-555679fd.js";import{g as m}from"./endpoint-aa68fc9e.js";import{s as u,h as v,M as y}from"./lazyload-c2d6254a.js";import"./image-0b99ab11.js";import{m as b}from"./audio-557099cb.js";import"./media-layout-8e0c974f.js";class g extends HTMLElement{constructor(){super(),this.DISCONNECT_TIMEOUT=5e3,this.RECONNECT_TIMEOUT=3e4,this.CODECS=["avc1.640029","avc1.64002A","avc1.640033","hvc1.1.6.L153.B0","mp4a.40.2","mp4a.40.5","flac","opus"],this.mode="webrtc,mse,mp4,mjpeg",this.background=!1,this.visibilityThreshold=0,this.visibilityCheck=!0,this.pcConfig={iceServers:[{urls:"stun:stun.l.google.com:19302"}],sdpSemantics:"unified-plan"},this.wsState=WebSocket.CLOSED,this.pcState=WebSocket.CLOSED,this.video=null,this.ws=null,this.wsURL="",this.pc=null,this.connectTS=0,this.mseCodecs="",this.disconnectTID=0,this.reconnectTID=0,this.ondata=null,this.onmessage=null,this.microphoneStream=null,this.containingPlayer=null,this.controls=!0}reconnect(){this.wsState!==WebSocket.CLOSED?(this.ws?.addEventListener("close",(()=>this.onconnect())),this.ondisconnect()):(this.ondisconnect(),this.onconnect())}set src(e){"string"!=typeof e&&(e=e.toString()),e.startsWith("http")?e="ws"+e.substring(4):e.startsWith("/")&&(e="ws"+location.origin.substring(4)+e),this.wsURL=e,this.onconnect()}play(){}send(e){this.ws&&this.ws.send(JSON.stringify(e))}codecs(e){const t="mse"===e?e=>MediaSource.isTypeSupported(`video/mp4; codecs="${e}"`):e=>this.video.canPlayType(`video/mp4; codecs="${e}"`);return this.CODECS.filter(t).join()}connectedCallback(){if(this.disconnectTID&&(clearTimeout(this.disconnectTID),this.disconnectTID=0),this.video){const e=this.video.seekable;e.length>0&&(this.video.currentTime=e.end(e.length-1)),this.play()}else this.oninit();this.onconnect()}disconnectedCallback(){this.background||this.disconnectTID||this.wsState===WebSocket.CLOSED&&this.pcState===WebSocket.CLOSED||(this.disconnectTID=setTimeout((()=>{this.reconnectTID&&(clearTimeout(this.reconnectTID),this.reconnectTID=0),this.disconnectTID=0,this.ondisconnect()}),this.DISCONNECT_TIMEOUT))}oninit(){if(this.video=document.createElement("video"),u(this.video,this.controls),this.video.playsInline=!0,this.video.preload="auto",this.video.style.display="block",this.video.style.width="100%",this.video.style.height="100%",this.appendChild(this.video),!this.background){if("hidden"in document&&this.visibilityCheck&&document.addEventListener("visibilitychange",(()=>{document.hidden?this.disconnectedCallback():this.isConnected&&this.connectedCallback()})),"IntersectionObserver"in window&&this.visibilityThreshold){new IntersectionObserver((e=>{e.forEach((e=>{e.isIntersecting?this.isConnected&&this.connectedCallback():this.disconnectedCallback()}))}),{threshold:this.visibilityThreshold}).observe(this)}this.video.onloadeddata=()=>{this.controls&&v(this.video,y),e(this,this.video,{player:this.containingPlayer,capabilities:{supports2WayAudio:!!this.pc,supportsPause:!0,hasAudio:b(this.video)}})},this.video.onvolumechange=()=>t(this),this.video.onplay=()=>s(this),this.video.onpause=()=>i(this),this.video.muted=!0}}onconnect(){return!(!this.isConnected||!this.wsURL||this.ws||this.pc)&&(this.wsState=WebSocket.CONNECTING,this.connectTS=Date.now(),this.ws=new WebSocket(this.wsURL),this.ws.binaryType="arraybuffer",this.ws.addEventListener("open",(e=>this.onopen(e))),this.ws.addEventListener("close",(e=>this.onclose(e))),!0)}ondisconnect(){this.wsState=WebSocket.CLOSED,this.ws&&(this.ws.close(),this.ws=null),this.pcState=WebSocket.CLOSED,this.pc&&(this.pc.close(),this.pc=null)}onopen(){this.wsState=WebSocket.OPEN,this.ws.addEventListener("message",(e=>{if("string"==typeof e.data){const t=JSON.parse(e.data);for(const e in this.onmessage)this.onmessage[e](t)}else this.ondata(e.data)})),this.ondata=null,this.onmessage={};const e=[];return this.mode.indexOf("mse")>=0&&"MediaSource"in window?(e.push("mse"),this.onmse()):this.mode.indexOf("mp4")>=0&&(e.push("mp4"),this.onmp4()),this.mode.indexOf("webrtc")>=0&&"RTCPeerConnection"in window&&(e.push("webrtc"),this.onwebrtc()),this.mode.indexOf("mjpeg")>=0&&(e.length?this.onmessage.mjpeg=t=>{"error"===t.type&&0===t.value.indexOf(e[0])&&this.onmjpeg()}:(e.push("mjpeg"),this.onmjpeg())),e}onclose(){if(this.wsState===WebSocket.CLOSED)return!1;this.wsState=WebSocket.CONNECTING,this.ws=null;const e=Math.max(this.RECONNECT_TIMEOUT-(Date.now()-this.connectTS),0);return this.reconnectTID=setTimeout((()=>{this.reconnectTID=0,this.onconnect()}),e),!0}onmse(){const e=new MediaSource;e.addEventListener("sourceopen",(()=>{URL.revokeObjectURL(this.video.src),this.send({type:"mse",value:this.codecs("mse")})}),{once:!0}),this.video.src=URL.createObjectURL(e),this.video.srcObject=null,this.play(),this.mseCodecs="",this.onmessage.mse=t=>{if("mse"!==t.type)return;this.mseCodecs=t.value;const s=e.addSourceBuffer(t.value);s.mode="segments",s.addEventListener("updateend",(()=>{if(!s.updating)try{if(n>0){const e=i.slice(0,n);n=0,s.appendBuffer(e)}else if(s.buffered&&s.buffered.length){const t=s.buffered.end(s.buffered.length-1)-15,i=s.buffered.start(0);t>i&&(s.remove(i,t),e.setLiveSeekableRange(t,t+15))}}catch(e){}}));const i=new Uint8Array(2097152);let n=0;this.ondata=e=>{if(s.updating||n>0){const t=new Uint8Array(e);i.set(t,n),n+=t.byteLength}else try{s.appendBuffer(e)}catch(e){}}}}onwebrtc(){const e=new RTCPeerConnection(this.pcConfig),t=document.createElement("video");t.addEventListener("loadeddata",(e=>this.onpcvideo(e)),{once:!0}),e.addEventListener("icecandidate",(e=>{const t=e.candidate?e.candidate.toJSON().candidate:"";this.send({type:"webrtc/candidate",value:t})})),e.addEventListener("track",(e=>{null===t.srcObject&&0!==e.streams.length&&"{"!==e.streams[0].id[0]&&"video"===e.track.kind&&(t.srcObject=e.streams[0])})),e.addEventListener("connectionstatechange",(()=>{"failed"!==e.connectionState&&"disconnected"!==e.connectionState||(e.close(),this.pcState=WebSocket.CLOSED,this.pc=null,this.onconnect())})),this.onmessage.webrtc=t=>{switch(t.type){case"webrtc/candidate":e.addIceCandidate({candidate:t.value,sdpMid:"0"}).catch((()=>console.debug));break;case"webrtc/answer":e.setRemoteDescription({type:"answer",sdp:t.value}).catch((()=>console.debug));break;case"error":if(t.value.indexOf("webrtc/offer")<0)return;e.close()}},e.addTransceiver("video",{direction:"recvonly"}),e.addTransceiver("audio",{direction:"recvonly"}),this.microphoneStream?.getTracks().forEach((t=>{e.addTransceiver(t,{direction:"sendonly"})})),e.createOffer().then((t=>{e.setLocalDescription(t).then((()=>{this.send({type:"webrtc/offer",value:t.sdp})}))})),this.pcState=WebSocket.CONNECTING,this.pc=e}onpcvideo(e){if(!this.pc)return;const t=e.target,s=this.pc.connectionState;if("connected"===s||"connecting"===s||!s){let e=0,s=0;const i=t.srcObject;i.getVideoTracks().length>0&&(e+=544),i.getAudioTracks().length>0&&(e+=258),this.mseCodecs.indexOf("hvc1.")>=0&&(s+=560),this.mseCodecs.indexOf("avc1.")>=0&&(s+=528),this.mseCodecs.indexOf("mp4a.")>=0&&(s+=257),e>=s?(this.video.srcObject=i,this.play(),this.pcState=WebSocket.OPEN,this.wsState=WebSocket.CLOSED,this.ws.close(),this.ws=null):(this.pcState=WebSocket.CLOSED,this.pc.close(),this.pc=null)}t.srcObject=null}onmjpeg(){let t=!1;this.ondata=s=>{u(this.video,!1),this.video.poster="data:image/jpeg;base64,"+g.btoa(s),t||(t=!0,e(this,this.video,{player:this.containingPlayer}))},this.send({type:"mjpeg"})}onmp4(){const t=document.createElement("canvas");let s;const i=document.createElement("video");i.autoplay=!0,i.playsInline=!0,i.muted=!0,i.addEventListener("loadeddata",(n=>{s||(t.width=i.videoWidth,t.height=i.videoHeight,s=t.getContext("2d"),e(this,i,{player:this.containingPlayer})),s.drawImage(i,0,0,t.width,t.height),u(this.video,!1),this.video.poster=t.toDataURL("image/jpeg")})),this.ondata=e=>{i.src="data:video/mp4;base64,"+g.btoa(e)},this.send({type:"mp4",value:this.codecs("mp4")})}static btoa(e){const t=new Uint8Array(e),s=t.byteLength;let i="";for(let e=0;e<s;e++)i+=String.fromCharCode(t[e]);return window.btoa(i)}}customElements.define("frigate-card-live-go2rtc-player",g);let f=class extends n{constructor(){super(...arguments),this.controls=!1}async play(){return this._player?.video?.play()}async pause(){this._player?.video?.pause()}async mute(){this._player?.video&&(this._player.video.muted=!0)}async unmute(){this._player?.video&&(this._player.video.muted=!1)}isMuted(){return this._player?.video.muted??!0}async seek(e){this._player?.video&&(this._player.video.currentTime=e)}async setControls(e){this._player?.video&&u(this._player.video,e??this.controls)}isPaused(){return this._player?.video.paused??!0}async getScreenshotURL(){return this._player?o(this._player.video):null}disconnectedCallback(){this._player=void 0}connectedCallback(){super.connectedCallback(),this.requestUpdate()}async _createPlayer(){if(!this.hass)return;const e=this.cameraEndpoints?.go2rtc;if(!e)return a(this,c("error.live_camera_no_endpoint"),{context:this.cameraConfig});const t=await m(this,this.hass,e,86400);t&&(this._player=new g,this._player.containingPlayer=this,this._player.microphoneStream=this.microphoneStream??null,this._player.src=t,this._player.visibilityCheck=!1,this._player.controls=this.controls,this.cameraConfig?.go2rtc?.modes&&this.cameraConfig.go2rtc.modes.length&&(this._player.mode=this.cameraConfig.go2rtc.modes.join(",")),this.requestUpdate())}willUpdate(e){this._player&&!e.has("cameraEndpoints")||this._createPlayer(),e.has("controls")&&this._player&&(this._player.controls=this.controls),this._player&&e.has("microphoneStream")&&this._player?.microphoneStream!==this.microphoneStream&&(this._player.microphoneStream=this.microphoneStream??null,this._player.reconnect())}render(){return r`${this._player}`}static get styles(){return h(":host {\n width: 100%;\n height: 100%;\n display: block;\n}\n\nvideo {\n object-fit: var(--frigate-card-media-layout-fit, contain);\n object-position: var(--frigate-card-media-layout-position-x, 50%) var(--frigate-card-media-layout-position-y, 50%);\n width: 100%;\n height: 100%;\n display: block;\n}")}};d([l({attribute:!1})],f.prototype,"cameraConfig",void 0),d([l({attribute:!1})],f.prototype,"cameraEndpoints",void 0),d([l({attribute:!1})],f.prototype,"microphoneStream",void 0),d([l({attribute:!1})],f.prototype,"microphoneConfig",void 0),d([l({attribute:!0,type:Boolean})],f.prototype,"controls",void 0),f=d([p("frigate-card-live-go2rtc")],f);export{f as FrigateCardGo2RTC};