Socket
Socket
Sign inDemoInstall

@ceeblue/webrtc-client

Package Overview
Dependencies
0
Maintainers
4
Versions
20
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.2.0 to 1.3.0

2

dist/webrtc-client.min.js

@@ -1,1 +0,1 @@

function t(t,e,s,i){return new(s||(s=Promise))((function(r,o){function n(t){try{c(i.next(t))}catch(t){o(t)}}function a(t){try{c(i.throw(t))}catch(t){o(t)}}function c(t){var e;t.done?r(t.value):(e=t.value,e instanceof s?e:new s((function(t){t(e)}))).then(n,a)}c((i=i.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class e{constructor(){this._events=new Map;let t=Object.getPrototypeOf(this);for(;t&&t!==Object.prototype;){for(const e of Object.getOwnPropertyNames(t))if(!(e.length<3)&&e.startsWith("on")&&t[e]instanceof Function){const s=new Set;this._events.set(e.substring(2).toLowerCase(),s);let i=t[e];Object.defineProperties(this,{[e]:{get:()=>(...t)=>{i&&i.call(this,...t);for(const e of s)e(...t)},set:t=>{i=t}}})}t=Object.getPrototypeOf(t)}}on(t,e,s){if(!e)throw Error("event to subscribe cannot be null");const i=this._event(t);i.add(e),s&&s.signal.addEventListener("abort",(()=>{i.delete(e)}))}once(t,e,s){if(!e)throw Error("event to subscribe cannot be null");const i=this._event(t);i.add((()=>{i.delete(e),e()})),s&&s.signal.addEventListener("abort",(()=>{i.delete(e)}))}off(t,e){if(!e)throw Error("event to unsubscribe cannot be null");this._event(t).delete(e)}_event(t){const e=this._events.get(t.toLowerCase());if(!e)throw Error("No event on"+t+" on class "+this.constructor.name);return e}}class s extends e{onOpen(){}onMessage(t){}onClose(t){t&&console.error(t)}get binaryType(){return"arraybuffer"}get url(){var t,e;return null!==(e=null===(t=this._ws)||void 0===t?void 0:t.url)&&void 0!==e?e:""}get extensions(){var t,e;return null!==(e=null===(t=this._ws)||void 0===t?void 0:t.extensions)&&void 0!==e?e:""}get opened(){return this._opened}get readyState(){return this._ws?this._ws.readyState:3}get closed(){return this._closed}get bufferedAmount(){var t;return this._queueingBytes+((null===(t=this._ws)||void 0===t?void 0:t.bufferedAmount)||0)}get queueing(){return this._queueing}constructor(t){super(),this._queueing=[],this._queueingBytes=0,this._opened=!1,this._closed=!0,t&&this.open(t)}open(t){this._closed=!1;const e=this._ws=new WebSocket(t);return e.binaryType=this.binaryType,e.onmessage=t=>this.onMessage(t.data),e.onclose=e=>{this._opened?1e3===e.code||1005===e.code?this.close(t.toString()+" shutdown"):this.close(t.toString()+" disconnection ("+String(e.reason||e.code)+")"):this.close(t.toString()+" connection failed ("+String(e.reason||e.code)+")")},e.onopen=t=>{this._opened=!0,this.flush(),this.onOpen()},this}send(t,e=!1){if(!this._ws)throw Error("Open socket before to send data");return e||!this._opened?(this._queueing.push(t),this._queueingBytes+="string"==typeof t?t.length:t.byteLength):this._ws.send(t),this}flush(){if(this._ws)for(const t of this._queueing)this._ws.send(t);this._queueing.length=0,this._queueingBytes=0}close(t){this._ws&&!this._closed&&(this._closed=!0,this._ws.onopen=this._ws.onclose=this._ws.onmessage=null,this._ws.close(),this._opened=!1,this._queueing.length=0,this._queueingBytes=0,this.onClose(t))}}const i=performance,r={VERSION:"1.2.0",EMPTY_FUNCTION:()=>{},time:()=>Math.floor(i.now()),timeOrigin:()=>Math.floor(i.now()+i.timeOrigin),options(t=("undefined"==typeof location?void 0:location)){if(!t)return{};try{t=new URL(t).searchParams}catch(e){"string"==typeof t&&(t.startsWith("?")&&(t=t.substring(1)),t=new URLSearchParams(t))}return r.objectFrom(t,{withType:!0,noEmptyString:!0})},objectFrom(t,e){e=Object.assign({withType:!1,noEmptyString:!1},e);const s={};if(!t)return s;for(const[i,r]of this.objectEntries(t)){if(t=r,e.withType&&null!=t&&t.substring)if(t){const e=Number(t);if(isNaN(e))switch(t.toLowerCase()){case"true":t=!0;break;case"false":t=!1;break;case"null":t=null;break;case"undefined":t=void 0}else t=e}else e.noEmptyString&&(t=!0);s[i]?(Array.isArray(s[i])||(s[i]=new Array(s[i])),s[i].push(t)):s[i]=t}return s},objectEntries:t=>t.entries?t.entries():Array.from({[Symbol.iterator]:function*(){for(const e in t)yield[e,t[e]]}}),stringify(t,e={}){if(e=Object.assign({space:" ",decimal:2,recursive:!1},e),!t)return String(t);const s=t.error||t.message;s&&(t=s);const i=Number(e.decimal)||0;if(t.toFixed)return t.toFixed(i);if(t.substring)return String(t);const o=e.space||"";let n="{"+o.replace(/[^\S\r\n]+/,""),a=!0;for(const s in t){let c=t[s];if(c){if(c.call)continue;e.recursive&&c===Object(c)&&(c=r.stringify(c,e))}a?a=!1:n+=","+o,n+=s+":"+(c&&c.toFixed?c.toFixed(i):c)}return n+(o.replace(/[^\S\r\n]+$/,"")+"}")}};var o,n;function a(t,e,s){for(let i=0;i<e.length;++i){const r=e[i];s.has(r.codec.toLowerCase())||(t.delete(r.idx),e.splice(i--,1))}}Object.freeze(r),function(t){t.AUDIO="audio",t.VIDEO="video",t.DATA="data"}(o||(o={}));class c{constructor(){this.type="",this.width=0,this.height=0,this.sources=new Map,this.tracks=new Map,this.audios=[],this.videos=[],this.datas=[]}subset(t){const e=Object.assign({},this);if(t){a(e.tracks,e.audios,t),a(e.tracks,e.videos,t);for(const[,t]of e.tracks){for(;t.up&&!e.tracks.has(t.up.idx);)t.up=t.up.up;for(;t.down&&!e.tracks.has(t.down.idx);)t.down=t.down.down}}return e}}class h{static fixProtocol(t,e){const s=e.indexOf("://");return s>=0&&(s>2&&"s"===e.charAt(s-1).toLowerCase()?(t.length<=2||!t.endsWith("s"))&&(t+="s"):t.length>2&&t.endsWith("s")&&(t=t.slice(0,-1)),e=e.substring(s+3)),t+"://"+e}get domain(){return this._domain}get port(){return this._port}toString(){return this._address}valueOf(){return this._address}constructor(t,e){this._address=t;let s=t.indexOf("/");if(s>=0&&(47===t.charCodeAt(s+1)?s>0?58===t.charCodeAt(s-1)&&(t=t.substring(s+2)):t=t.substring(2):s||(t=t.substring(1))),this._domain=t,this._port=e,s=t.lastIndexOf(":"),s>=0){const e=parseInt(t.substring(s+1));e&&e<=65535&&(this._port=e,this._domain=t.substring(0,s))}else s=t.indexOf("/"),s>=0&&(this._domain=t.substring(0,s))}}!function(t){t.WEBRTC="webrtc",t.META="meta",t.DATA="data"}(n||(n={}));const u={buildURL(t,e,s="wss"){const i=new URL(h.fixProtocol(s,e.host));if(i.pathname.length<=1)switch(t){case n.WEBRTC:i.pathname="/webrtc/"+e.streamName;break;case n.META:i.pathname="/json_"+e.streamName+".js";break;case n.DATA:i.pathname="/"+e.streamName+".json";break;default:console.warn("Unknown url type "+t)}e.accessToken&&i.searchParams.set("id",e.accessToken);for(const t in e.query)i.searchParams.set(t,e.query[t]);return i}};Object.freeze(u);const d=(t,e)=>e.maxbps-t.maxbps;class l extends e{onLog(t){}onError(t="unknown"){console.error(t)}onClose(){this.onLog("onClose")}onMetadata(t){this.onLog(r.stringify(t))}get url(){return this._ws.url}get connectParams(){return this._connectParams}get metadata(){return this._metadata}get closed(){return this._ws.closed}constructor(t){super(),this._connectParams=t,this._ws=new s(u.buildURL(n.META,t)),this._ws.onClose=t=>{this._metadata=new c,t&&this.onError(t),this.onClose()},this._ws.onMessage=t=>{try{const e=JSON.parse(t);if(e.error)throw e.error;this._metadata=new c,this._metadata.type=e.type,this._metadata.width=e.width,this._metadata.height=e.height,this._metadata.sources.clear();for(const t of e.source)this._metadata.sources.set(t.hrn,t);const s=[];this._metadata.tracks.clear();for(const[t,i]of r.objectEntries(e.meta.tracks)){switch(i.name=t,i.type=i.type.toLowerCase(),i.type){case"audio":this._metadata.audios.push(i);continue;case"video":this._metadata.videos.push(i);continue;case"meta":i.type=o.DATA,this._metadata.datas.push(i);break;default:this.onLog("Unknown track type"+i.type)}s.push(i)}this._addSortedTrack(this._metadata.audios,this._metadata.tracks),this._addSortedTrack(this._metadata.videos,this._metadata.tracks);for(const t of s)this._metadata.tracks.set(t.idx,t)}catch(t){return void this.onError(r.stringify(t))}this.onMetadata(this._metadata)}}close(t){this._ws.close(t)}_addSortedTrack(t,e){t.sort(d);for(let s=0;s<t.length;++s){const i=t[s];e.set(i.idx,i),s&&(i.up=t[s-1],t[s-1].down=i)}}}function _(t){return"send"in t}const m={fromString(t){if(Array.isArray(t))return t;const e=new Array;let s,i=e;for(let r of t.toString().split("\n")){if(r=r.trim(),!r)continue;let t=r[0];const o=r.substring(r.indexOf("=")+1).trim();switch(t.toLowerCase()){case"a":if(!o)continue;t=this.addAttribute(i,o),e===i&&"fingerprint"===t.toLowerCase()&&(s=i.fingerprint);break;case"m":e.length&&s&&!e[e.length-1].fingerprint&&(i.fingerprint=s),e.push(i={m:o});break;default:i[t]=o}}return e.length&&s&&!e[e.length-1].fingerprint&&(i.fingerprint=s),e},toString(t){if("string"==typeof t)return t;const e=[];let s="v"in t?"v="+t.v+"\n":"";"o"in t&&(s+="o="+t.o+"\n"),"s"in t&&(s+="s="+t.s+"\n");const i=t;for(const r of Object.keys(t)){if("v"===r||"o"===r||"s"===r)continue;const t=i[r];if(null==t)continue;const o=parseInt(r);if(!isNaN(o)){e[o]=t;continue}const n=Array.isArray(t)&&t.length||1;for(let e=0;e<n;++e){const i=Array.isArray(t)&&t.length?t[e]:t;r.length>1?(s+="a="+r,i&&(s+=":")):s+=r+"=",s+=i+"\n"}}for(const t of e)s+=this.toString(t);return s},addAttribute(t,e){var s;const i=m.parseAttribute(e),r=null!==(s=i.value)&&void 0!==s?s:"",o=t,n=o[i.key];return n?Array.isArray(n)?n.push(r):r!==n&&(o[i.key]=[n,r]):o[i.key]=r,i.key},removeAttribute(t,e){const s=m.parseAttribute(e),i=t;if(void 0===s.value)return delete i[e],e;const r=i[e];if(Array.isArray(s.value)){const t=r.findIndex((t=>t===s.value));t>=0&&r.splice(t,1)}else r===s.value&&delete i[e];return s.key},parseAttribute(t){const e=t.indexOf(":");return{key:(e>=0?t.substring(0,e):t).trim(),value:e>=0?t.substring(e+1).trim():void 0}}};Object.freeze(m);class p extends e{onLog(t){}onError(t="unknown"){console.error(t)}onOpen(t){this.onLog("onOpen")}onClose(){this.onLog("onClose")}get opened(){return!(!this._peerConnection||this._peerConnection.ontrack!==r.EMPTY_FUNCTION)}get closed(){return this._closed}get stream(){return this._stream}get streamName(){return this._streamName}get codecs(){return this._codecs}constructor(t,e){super(),this._closed=!1,this._streamName=t.streamName,this._host=t.host,this._stream=e,this._connectionInfosTime=0,this._codecs=new Set}connectionInfos(e=1e3){return t(this,void 0,void 0,(function*(){if(!this._peerConnection)return Promise.reject("Not connected");if(!this._connectionInfos||r.time()-e>this._connectionInfosTime){const t=yield this._peerConnection.getStats(null);this._connectionInfos={inputs:{},outputs:{}};const e=new Map,s=new Map;for(const i of t.values())switch(i.type){case"track":e.set(i.id,i);break;case"outbound-rtp":s.set(i.trackId,i),this._connectionInfos.outputs["audio"===(i.kind||i.mediaType)?"audio":"video"]=i;break;case"inbound-rtp":s.set(i.trackId,i),this._connectionInfos.inputs["audio"===(i.kind||i.mediaType)?"audio":"video"]=i;break;case"candidate-pair":if(null!=i.selected){if(!i.selected)continue}else if(null!=i.nominated&&!i.nominated)continue;this._connectionInfos.candidate=i}for(const[t,i]of e){const e=s.get(t);e&&Object.assign(e,Object.assign(Object.assign({},i),e))}this._connectionInfosTime=r.time()}return this._connectionInfos}))}close(t){if(this._closed)return;this._closed=!0;const e=this._peerConnection;e&&(this._peerConnection=void 0,e.getReceivers().forEach((t=>t.track&&t.track.stop())),e.getSenders().forEach((t=>t.track&&t.track.stop())),e.close()),this._stream&&this._stream.getTracks().forEach((t=>t.stop())),t&&this.onError(t),this.onClose()}_open(t){if(!t){const e=new h(this._host,443).domain;t={urls:["turn:"+e+":3478?transport=tcp","turn:"+e+":3478"],username:"csc_demo",credential:"UtrAFClFFO"}}try{this._peerConnection=new RTCPeerConnection(t?{iceServers:[t]}:void 0)}catch(t){return void this.close("RTCPeerConnection failed, "+r.stringify(t))}if(this._stream)for(const t of this._stream.getTracks())this._peerConnection.addTrack(t);else this._peerConnection.ontrack=t=>{this._stream=t.streams[0],this._tryToOpen()};let e;this._peerConnection.createOffer({offerToReceiveAudio:!this._stream,offerToReceiveVideo:!this._stream}).then((t=>{var s;if(this._peerConnection)return e=null!==(s=t.sdp)&&void 0!==s?s:"",this.onLog("Offer\r\n"+e),this._peerConnection.setLocalDescription(t)})).then((t=>{if(this._peerConnection)return e?this._sip(e):Promise.reject("invalid empty sdp offer")})).then((t=>{if(t&&this._peerConnection){this.onLog("Answer\r\n"+t);for(const e of m.fromString(t)){if(!e.rtpmap)continue;let t=e.rtpmap.indexOf(" ");if(t<0)continue;let s=e.rtpmap.substring(t+1);if(!s)return;t=s.indexOf("/"),s=t<0?s:s.substring(0,t),this._codecs.add(s.toLowerCase())}return this._peerConnection.setRemoteDescription(new RTCSessionDescription({type:"answer",sdp:t}))}})).then((()=>this._tryToOpen())).catch((t=>this.close("SIP failed, "+r.stringify(t))))}_tryToOpen(){this._stream&&this._peerConnection&&this._peerConnection.ontrack!==r.EMPTY_FUNCTION&&(this._peerConnection.ontrack=r.EMPTY_FUNCTION,this.onOpen(this._stream))}}class g extends p{onRTPProps(t){this.onLog("onRTPProps "+r.stringify(t))}onMediaReport(t){console.debug("onMediaReport "+r.stringify(t))}onVideoBitrate(t,e){this.onLog("onVideoBitrate "+r.stringify({video_bitrate:t,video_bitrate_constraint:e}))}onPlaying(t){console.debug("onPlaying "+r.stringify(t))}constructor(t,e){super(t,e),this._ws=new s(u.buildURL(n.WEBRTC,t,"wss")),this._ws.onClose=t=>this.close(t),this._ws.onOpen=()=>{this._open(t.iceServer)},this._ws.onMessage=t=>{try{this._eventHandler(JSON.parse(t))}catch(t){this.onError("Invalid signaling message, "+r.stringify(t))}}}setRTPProps(t,e){this.send("rtp_props",{nack:t,drop:e})}setVideoBitrate(t){this.send("video_bitrate",{video_bitrate:t})}setTracks(t){this.send("tracks",t)}send(t,e){try{this.onLog("Command "+t+" "+r.stringify(e)),this._ws.send(JSON.stringify(Object.assign({type:t},e)))}catch(t){this.onError(r.stringify(t))}}close(t){this._ws.close(t),this._promise&&(this._promise(Error("closing")),this._promise=void 0),super.close(t)}_sip(t){return new Promise(((e,s)=>{this._promise=t=>{t instanceof Error?s(t):e(t)},this._ws.send(JSON.stringify({type:"offer_sdp",offer_sdp:t}))}))}_eventHandler(t){var e,s;switch(t.type){case"on_answer_sdp":this._promise&&this._promise(t.answer_sdp);break;case"on_error":this.opened?this.onError(r.stringify(t)):this.close(r.stringify(t));break;case"on_video_bitrate":this.onVideoBitrate(t.video_bitrate,t.video_bitrate_constraint);break;case"on_stop":this.onLog("on_stop"),this.close();break;case"on_track_drop":{const i=null!==(e=t.mediatype)&&void 0!==e?e:"?",r=null!==(s=t.track)&&void 0!==s?s:"?";this.onError(i+" track #"+r+"dropped");break}case"on_rtp_props":this.onRTPProps(t);break;case"on_media_receive":this.onMediaReport(t);break;case"on_seek":break;case"on_time":this.onPlaying(t);break;default:this.onError("Unhandled event: "+t.type)}}}class f extends p{constructor(t,e){super(t,e),this._url=u.buildURL(n.WEBRTC,t,"https"),this._fetch=new AbortController,setTimeout((()=>{this._open(t.iceServer)}),0)}close(t){this._fetch.abort(),super.close(t)}_sip(e){return t(this,void 0,void 0,(function*(){const t=yield fetch(this._url,{method:"POST",body:e,headers:{"Content-Type":"application/sdp"},signal:this._fetch.signal});return t?t.text():Promise.reject("client rejected")}))}}class v extends e{onLog(t){}onError(t="unknown"){console.error(t)}onClose(){this.onLog("onClose")}onData(t,e,s){this.onLog(`Data received on track ${e} at ${t} : ${r.stringify(s)}`)}get url(){return this._url}get tracks(){return[...this._tracks]}set tracks(t){this._tracks=[...t],this._sendTracks()}get closed(){return!this._ws||this._ws.closed}constructor(t){super(),this._url=u.buildURL(n.DATA,t).toString(),this._tracks=Array(),this._ws=new s,this._ws.onOpen=()=>this._sendTracks(),this._ws.onClose=t=>{t&&this.onError(t),this.onClose()},this._ws.onMessage=t=>{let e;try{e=JSON.parse(t)}catch(t){return this.onError("Invalid signaling message, "+r.stringify(t))}if(e.error)return this.onError(e.error);"time"in e&&"track"in e&&"data"in e?this.onData(e.track,e.time,e.data):"on_time"!==e.type&&console.debug("Internal JSON : ",r.stringify(e))}}close(t){this._ws.close(t)}_sendTracks(){this._tracks.length?this._ws.closed?this._ws.open(this._url):this._ws.opened&&this._ws.send(JSON.stringify({type:"tracks",tracks:this._tracks.join(",")})):this.close()}}class y{onLog(t){}onError(t="unknown"){console.error(t)}get upDelay(){return this._upDelay}get learningUpStep(){return this._learningUpStep}get maximumUpDelay(){return this._maximumUpDelay}constructor(t){const e=Object.assign({learningUpStep:1400,maximumUpDelay:28e3},t);this._learningUpStep=e.learningUpStep,this._maximumUpDelay=e.maximumUpDelay,this._upDelay=0,this._testTime=0,this._enabled=!0}reset(){this._upDelay=0,this._mTrack=void 0}compute(t,e,s){var i;const o=null!==(i=e.video)&&void 0!==i?i:e.audio;if(null==o)return this._mTrack=void 0,!1;const n=r.time();if(!(this._mTrack&&this._mTrack.idx===o||(this._appreciationTime=void 0,this._testTime=n,this._mTrack=t.tracks.get(o),this._mTrack)))return this.onError("Can't find track "+o+" absent from metadata"),!1;const a=o===e.video?s.video:s.audio;if(!a)return this.onError("Can't compute "+this._mTrack.type+" track "+this._mTrack.idx+" without statistics"),!1;const c=this._downBitrate(n-this._testTime,this._mTrack,a);if(c)this._appreciationTime=void 0;else{this._appreciationTime||(this._appreciationTime=n);const t=n-this._appreciationTime;if(!this._upBitrate(t,this._mTrack,a)||t<this._upDelay)return!1}let h=this.updateTrack(e.audio,t,c);if(h)e.audio=h.idx;else{if(h=this.updateTrack(e.video,t,c),!h)return!1;e.video=h.idx}return c&&(this._upDelay=Math.min(this._upDelay+this._learningUpStep,this._maximumUpDelay)),this.onLog((c?"DOWN":"UP")+" from "+this._mTrack.type+" track "+this._mTrack.idx+" ("+this._mTrack.maxbps+"bps) to "+h.type+" track "+h.idx+" ("+h.maxbps+"bps)"),!0}updateTrack(t,e,s){if(null==t)return;const i=s?"down":"up",r=e.tracks.get(t);if(r)return r[i];this.onError("Can't find track "+t+" from metadata")}}class b extends y{constructor(t){super(t),this._keyFramesDecoded=0,this._lost=0,this._nackCount=0}_downBitrate(t,e,s){const i=s.packetsLost,o=s.nackCount;if(null==i)return this.onLog("No packetsLost information in "+r.stringify(s)),!1;const n=t>0&&i>this._lost&&(!o||o>this._nackCount);return this._lost=i,this._nackCount=o||0,n}_upBitrate(t,e,s){if(e.type===o.AUDIO)return!0;if(t>1e4)return!0;const i=s.keyFramesDecoded;if(null==i)return!1;if(t){if(i>this._keyFramesDecoded){if(!this._keyFramesDecoded)return!0;this._keyFramesDecoded=0}}else this._keyFramesDecoded=i;return!1}}const T=1e3;class k extends e{onLog(t){}onError(t="unknown"){console.error(t)}onStart(t){this.onLog("onStart")}onStop(){this.onLog("onStop")}onPlaying(t){console.debug("onPlaying "+r.stringify(t))}onMetadata(t){this.onLog(r.stringify(t))}onData(t,e,s){this.onLog(`Data received on track ${e} at ${t} : ${r.stringify(s)}`)}get streamName(){return this._connector?this._connector.streamName:""}get stream(){return this._connector&&this._connector.stream}get running(){return!!this._connector}get controller(){return this._controller}get connector(){return this._connector}get metadata(){return this._metadata}get playingInfos(){return this._playingInfos}get audioTrack(){return this._audioTrack}set audioTrack(t){if(this._audioTrackFixed=null!=t,this._audioTrackFixed&&this._audioTrack!==t&&(this._audioTrack=t,this._connector)){if(!this._controller)throw Error("Cannot set audioTrack without start a controllable session");this._controller.setTracks({audio:t})}}get videoTrack(){return this._videoTrack}set videoTrack(t){if(this._videoTrackFixed=null!=t,this._videoTrackFixed&&this._videoTrack!==t&&(this._videoTrack=t,this._connector)){if(!this._controller)throw Error("Cannot set videoTrack without start a controllable session");this._controller.setTracks({video:t})}}get dataTracks(){return[...this._dataTracks]}set dataTracks(t){this._dataTracks=[...t],this._streamData&&(this._streamData.tracks=t)}constructor(t){super(),this.Connector=t,this._dataTracks=new Array}connectionInfos(){return this._connector?this._connector.connectionInfos():Promise.reject("Start player before to request connection infos")}start(e,s={}){let i,o,n;this.stop(),"connectParams"in e?(this._initStreamMetadata(Object.assign({},e.connectParams),e),e=e.connectParams):this._initStreamMetadata(Object.assign({},e),new l(e)),null!=this._audioTrack&&(e.query=Object.assign({audio:this._audioTrack.toFixed()},e.query)),null!=this._videoTrack&&(e.query=Object.assign({video:this._videoTrack.toFixed()},e.query)),this._audioTrackFixed=!1,this._videoTrackFixed=!1,this._connector=new(this.Connector||(e.host.startsWith("http")?f:g))(e),this._connector.onLog=t=>this.onLog("Signaling: "+t),this._connector.onError=t=>this.onError("Signaling: "+t),this._connector.onOpen=t=>{var e,s;this.onStart(t),(null===(e=this._streamMetadata)||void 0===e?void 0:e.metadata)&&this._streamMetadata.onMetadata(null===(s=this._streamMetadata)||void 0===s?void 0:s.metadata),o&&this._controller&&this._controller.onPlaying(o)},this._connector.onClose=()=>{null==i||i.reset(),this.stop()},this._newStreamData(Object.assign({},e)),_(this._connector)?(s&&("compute"in s?i=s:(i=new b(s),i.onLog=t=>this.onLog("MultiBitrate: "+t))),this._controller=this._connector,this._controller.onPlaying=e=>t(this,void 0,void 0,(function*(){if(o=e,this._controller&&this._controller.opened&&(this._playingInfos=o,this._updateTracks(),this.onPlaying(o),i))if(this._audioTrackFixed&&this._videoTrackFixed)i.reset();else try{const t=yield this._controller.connectionInfos(1e3);if(t===n)return;const e={audio:this._audioTrackFixed?void 0:this._audioTrack,video:this._videoTrackFixed?void 0:this._videoTrack};this._controller&&this._metadata&&i.compute(this._metadata,e,(n=t).inputs)&&(this._audioTrack=e.audio,this._videoTrack=e.video,this._controller.setTracks(e))}catch(t){this.onError("Can't compute MBR, "+r.stringify(t))}}))):s&&this.onLog("Cannot use a multiple bitrate without a controller: Connector "+this._connector.constructor.name+" doesn't implements IController")}stop(){const t=this._connector;t&&(this._connector=void 0,this._streamMetadata&&(this._streamMetadata.close(),this._streamMetadata=void 0),this._streamData&&(this._streamData.close(),this._streamData=void 0),t.close(),this._audioTrack=void 0,this._videoTrack=void 0,this._dataTracks.length=0,this._playingInfos=void 0,this._metadata=void 0,this.onStop())}_updateTracks(){if(!this._playingInfos||!this._metadata)return;const t=new Array,e=new Array;for(const s of this._playingInfos.tracks){const i=this._metadata.tracks.get(s);i&&(i.type===o.AUDIO?t.push(s):i.type===o.VIDEO&&e.push(s))}1===t.length&&(this._audioTrack=t[0]),1===e.length&&(this._videoTrack=e[0])}_initStreamMetadata(t,e){this._streamMetadata=e,e.onLog=t=>this.onLog("StreamMetadata: "+t),e.onError=t=>this.onError("StreamMetadata: "+t),e.onMetadata=t=>{this._connector&&this._connector.opened&&(this._metadata=t.subset(this._connector.codecs),this._updateTracks(),this.onMetadata(this._metadata))},e.onClose=()=>{this.onLog("StreamMetadata closed, trying to reconnect in 1000ms"),setTimeout((()=>{this._streamMetadata===e&&this._initStreamMetadata(t,new l(t))}),T)}}_newStreamData(t){const e=this._streamData=new v(t);e.onLog=t=>this.onLog("Timed Metadatas: "+t),e.onError=t=>this.onError("Timed Metadatas: "+t),e.onData=(t,e,s)=>this.onData(e,t,s),e.tracks=this._dataTracks,e.onClose=()=>{this.onLog("Timed Metadatas closed, trying to reconnect in 1000ms"),setTimeout((()=>{this._streamData===e&&this._newStreamData(t)}),T)}}}class w extends e{onLog(t){}onError(t="unknown"){console.error(t)}get startup(){return this._startup}set startup(t){this._startup=Math.max(this._minimum,Math.min(Math.round(t),this._maximum))}get minimum(){return this._minimum}set minimum(t){t=Math.round(t),(this._minimum=t)>this._maximum?this._maximum=this._startup=t:this._startup<t&&(this._startup=t)}get maximum(){return this._maximum}set maximum(t){t=Math.round(t),(this._maximum=t)<this._minimum?this._minimum=this._startup=t:this._startup>t&&(this._startup=t)}get constraint(){return this._bitrateConstraint}get value(){return this._bitrate}valueOf(){return this.value}get stream(){return this._stream}constructor(t,e){super();const s=Object.assign({startup:2e6,maximum:3e6,minimum:2e5},t);this._startup=s.startup,this._minimum=s.minimum,this._maximum=s.maximum,this._stream=e,this._enabled=!0}compute(t,e,s){if(null==t)return this._bitrate=t;const i=null==this._bitrate,r=i?this.startup:Math.max(this.minimum,Math.min(this._computeBitrate(t,e,s),this.maximum));return this._bitrate=t,this._bitrateConstraint=e,i?this.onLog("Set startup bitrate to "+r):r>t?this.onLog("Increase bitrate "+t+" => "+r):r<t&&this.onLog("Decrease bitrate "+t+" => "+r),r}reset(){this._bitrate=this._bitrateConstraint=void 0}_updateVideoConstraints(t){const e=this._stream;if(!e)return;const s=e.getVideoTracks()[0];if(!s)return;const i=s.getSettings();if(!i.width||!i.height)return;const r=i.width*i.height;t>=12e5?r<645120&&this._upgradeVideoConstraint(s,2):r>645120&&r<1198080&&this._upgradeVideoConstraint(s,.5)}_upgradeVideoConstraint(t,e){const s={},i=t.getSettings().width;null!=i&&(s.width=i*e);const r=t.getSettings().height;null!=r&&(s.height=r*e),this.onLog("Resolution change "+i+"X"+r+" => "+s.width+"X"+s.height),t.applyConstraints(s)}}let S=class{constructor(){this.stableTime=0,this.stableBitrate=0,this.attempts=1,this.lastLoss=Number.POSITIVE_INFINITY}};class C extends w{constructor(t,e){super(t,e),this._vars=new S}reset(){super.reset(),this._vars=new S}_computeBitrate(t,e,s){const i=s&&s.stats,o=this._vars;if(i&&i.loss_perc)i.loss_perc>=o.lastLoss&&(o.stableTime&&++o.attempts,o.stableTime=0,t=Math.round((1-i.loss_perc/100)*t)),o.lastLoss=i.loss_perc;else{o.lastLoss=Number.POSITIVE_INFINITY;const e=r.time();e>=o.stableTime&&(o.stableTime?(this._updateVideoConstraints(t),t+=Math.ceil((this.maximum-o.stableBitrate)/o.attempts)):o.stableBitrate=t,o.stableTime=e+11)}return t}}class x extends e{onLog(t){}onError(t="unknown"){console.error(t)}onStart(t){this.onLog("onStart")}onStop(){this.onLog("onStop")}onRTPProps(t){this.onLog("onRTPProps "+r.stringify(t))}onMediaReport(t){console.debug("onMediaReport "+r.stringify(t))}onVideoBitrate(t,e){this.onLog("onVideoBitrate "+r.stringify({videoBitrate:t,videoBitrateConstraint:e}))}get streamName(){return this._connector?this._connector.streamName:""}get stream(){return this._connector&&this._connector.stream}get running(){return!!this._connector}get controller(){return this._controller}get connector(){return this._connector}get mediaReport(){return this._mediaReport}get rtpProps(){return this._rtpProps}get videoBitrate(){return this._videoBitrate}set videoBitrate(t){if(!this._controller)throw Error("Cannot set videoBitrate without start a controllable session");this._videoBitrateFixed=null!=t,this._videoBitrateFixed&&t!==this._videoBitrate&&this._controller.setVideoBitrate(t)}get videoBitrateConstraint(){return this._videoBitrateConstraint}constructor(t){super(),this.Connector=t,this._videoBitrate=0,this._videoBitrateConstraint=0}setRTPProps(t,e){if(!this._controller)throw Error("Cannot set rtpProps without start a controllable session");this._controller.setRTPProps(t,e)}connectionInfos(){return this._connector?this._connector.connectionInfos():Promise.reject("Start streamer before to request connection infos")}start(e,s,i={}){let r;this.stop(),this._videoBitrateFixed=!1,this._connector=new(this.Connector||(s.host.startsWith("http")?f:g))(s,e),this._connector.onLog=t=>this.onLog("Signaling: "+t),this._connector.onError=t=>this.onError("Signaling: "+t),this._connector.onOpen=t=>this.onStart(t),this._connector.onClose=()=>{null==r||r.reset(),this.stop()},_(this._connector)?(i&&("compute"in i?r=i:(r=new C(i),r.onLog=t=>this.onLog("AdaptiveBitrate: "+t))),this._controller=this._connector,this._controller.onOpen=t=>{this._computeVideoBitrate(r),this.onStart(t)},this._controller.onRTPProps=t=>{this._rtpProps=t,this.onRTPProps(t)},this._controller.onMediaReport=e=>t(this,void 0,void 0,(function*(){this._mediaReport=e,this._computeVideoBitrate(r),this.onMediaReport(e)})),this._controller.onVideoBitrate=(t,e)=>{this._videoBitrate=t,this._videoBitrateConstraint=e,this.onVideoBitrate(t,e)}):i&&this.onLog("Cannot use an adaptive bitrate without a controller: Connector "+this._connector.constructor.name+" doesn't implements IController")}stop(){const t=this._connector;t&&(this._connector=void 0,t.close(),this._controller=void 0,this._mediaReport=void 0,this._videoBitrate=0,this._videoBitrateConstraint=0,this._rtpProps=void 0,this.onStop())}_computeVideoBitrate(t){var e;if(!this._controller||this._videoBitrateFixed)return;const s=null!==(e=t.compute(this._videoBitrate,this.videoBitrateConstraint,this.mediaReport))&&void 0!==e?e:this._videoBitrate;s!==this._videoBitrate&&this._controller.setVideoBitrate(s)}}class B{get size(){return this._queue.length}get capacity(){return this._capacity}set capacity(t){this._capacity=t,null!=t&&this._queue.length>t&&this._queue.splice(0,this._queue.length-t)}get front(){return this._queue[0]}get back(){return this._queue[this._queue.length-1]}[Symbol.iterator](){return this._queue[Symbol.iterator]()}constructor(t){this._capacity=t,this._queue=new Array}push(t){return null!=this._capacity&&this._queue.push(t)>this._capacity&&this.pop(),this}pop(){return this._queue.shift()}clear(){return this._queue.length=0,this}}class L extends B{get minimum(){return this._min}get maximum(){return this._max}get average(){return null==this._average&&(this._average=this.size?this._sum/this.size:0),this._average}constructor(t){super(t),this._sum=0,this._min=0,this._max=0}push(t){return t>this._max?this._max=t:t<this._min&&(this._min=t),this._average=void 0,this._sum+=t,super.push(t),this}pop(){const t=super.pop();return t===this._max?this._max=Math.max(0,...this):t===this._min&&(this._min=Math.min(0,...this)),this._average=void 0,this._sum-=t||0,t}clear(){return this._min=this._max=this._sum=0,super.clear(),this}}class R{constructor(){this.lossPercents=new L(5),this.stableBitrates=new L(15),this.stableBitrateUpdateTime=0,this.bitrateRecoveryTimeout=1e4,this.bitrateRecoveryNextTime=0}}class O extends w{constructor(t,e){super(t,e),this._vars=new R}reset(){super.reset(),this._vars=new R}_computeBitrate(t,e,s){var i;const o=this._vars,n=s&&s.stats;n&&null!=n.loss_perc&&o.lossPercents.push(n.loss_perc);const a=r.time();a>=o.stableBitrateUpdateTime&&o.lossPercents.average<.2&&(o.stableBitrateUpdateTime=a+4e3,o.stableBitrates.push(Math.min(null!==(i=null!=e?e:this.constraint)&&void 0!==i?i:0,t,this.maximum)));const c=o.stableBitrates.average,h=o.stableBitrates.minimum,u=o.stableBitrates.maximum;if(h>=.8*c&&u<=1.2*c&&this._updateVideoConstraints(c),null!=e&&null!=this.constraint&&e<this.constraint){if(this.onLog(`onVideoBitrateConstraint: ${this._formatBitrate(e-this.constraint)}`),o.bitrateConstraintTime){if(o.bitrateRecoveryTime){(a-o.bitrateRecoveryTime<o.bitrateRecoveryTimeout||2500===o.bitrateRecoveryTimeout)&&(this._increaseRecoveryTimeout(),o.bitrateRecoveryTime=void 0)}}else o.bitrateRecoveryTime||(this.onLog("VideoBitrateConstraint: First constrain! Halve bitrate!"),t=Math.round(t/2));o.bitrateConstraintTime=a}if(e&&(e<this.minimum&&(t=this.minimum),this.maximum>e&&a>=o.bitrateRecoveryNextTime)){const s=o.bitrateRecoveryNextTime&&this._bitrateRecoveryHandler(e);s?(o.bitrateRecoveryTimeout=a,o.bitrateRecoveryNextTime=0,t=s):(o.bitrateRecoveryNextTime=a+o.bitrateRecoveryTimeout,this.onLog("startVideoBitrateRecoveryTimer "+o.bitrateRecoveryTimeout))}return t}_bitrateRecoveryHandler(t){const e=this._vars,s=e.lossPercents.average;if(this.onLog("videoBitrateRecoveryHandler loss: "+s.toFixed(2)),s<.2){let s=this._increaseTargetBitrate(t);return e.bitrateConstraintTime&&s>e.stableBitrates.average&&(s=this._increaseTargetBitrate(t,1.005)),this._decreaseRecoveryTimeout(),this.onLog("videoBitrateRecoveryHandler increase bitrate to "+this._formatBitrate(s)),s}if(s<5){this._increaseRecoveryTimeout();const e=this._decreaseTargetBitrate(t);return this.onLog("videoBitrateRecoveryHandler decrease bitrate to "+this._formatBitrate(e)),e}}_increaseTargetBitrate(t,e=1.05){let s=Math.round(t*e);return s>this.maximum&&(s=this.maximum),s}_decreaseTargetBitrate(t){let e=Math.round(.99*t);return e<this.minimum&&(e=this.minimum),e}_increaseRecoveryTimeout(){this._vars.bitrateRecoveryTimeout=Math.min(6e4,2*this._vars.bitrateRecoveryTimeout)}_decreaseRecoveryTimeout(){this._vars.bitrateRecoveryTimeout=Math.max(2500,Math.round(.75*this._vars.bitrateRecoveryTimeout))}_formatBitrate(t){return(t/1e6).toFixed(3)}}class E extends e{onLog(t){}onError(t="unknown"){console.error(t)}get url(){return this._url}get reporting(){return this._reporting}constructor(t){if(super(),(t=new URL(t)).protocol.startsWith("ws"))this._ws=new s;else if(!t.protocol.startsWith("http"))throw Error("Protocol "+t.protocol+" not supported");this._url=t.toString(),this._reporting=0}report(e,s){e.onError=t=>this.onError(e.constructor.name+" error, "+t),e.onLog=t=>this.onError(e.constructor.name+", "+t);let i=e.onRelease=()=>{i&&(i=void 0,clearInterval(o),this.onLog("Stop "+e.constructor.name+" reporting"),--this._reporting>0||(this._ws&&this._ws.close(),this._fetch&&this._fetch.abort()))};const o=(s?setInterval:setTimeout)((()=>t(this,void 0,void 0,(function*(){!s&&i&&i();try{yield this._send(e)}catch(t){this.onError(e.constructor.name+" error, "+r.stringify(t))}}))),1e3*s);++this._reporting,this.onLog("Start "+e.constructor.name+" reporting every "+s+" seconds")}_send(e){return t(this,void 0,void 0,(function*(){let t,s,i;try{t=yield e.serialize()}catch(t){if(!t)return;throw t}t instanceof ArrayBuffer?(i="application/octet-stream",s=t):"string"==typeof t?(i="text/plain",s=t):(i="application/json",s=JSON.stringify(t)),this._ws?(this._ws.closed&&this._ws.open(this._url),this._ws.queueing.length=0,this._ws.send(s)):(this._fetch&&this._fetch.abort(),this._fetch=new AbortController,fetch(this._url,{method:"POST",body:s,headers:{"Content-Type":i},signal:this._fetch.signal}))}))}}class P extends e{onLog(t){}onError(t="unknown"){console.error(t)}onRelease(){}constructor(t){super(),this._streamer=t,this._lastBytesSend=0,this._lastBytesSendTime=Date.now(),t.once("stop",(()=>this.onRelease()))}serialize(){return t(this,void 0,void 0,(function*(){if(!this._streamer.running)return Promise.reject();const t={streamId:this._streamer.streamName,vbt:this._streamer.videoBitrate,vbc:this._streamer.videoBitrateConstraint},e=this._streamer.mediaReport;let s;e&&(t.server={millis:e.millis,tracks:e.tracks},e.stats&&(t.server.jitterMs=e.stats.jitter_ms,t.server.lossNum=e.stats.loss_num,t.server.lossPerc=e.stats.loss_perc,t.server.nackNum=e.stats.nack_num));try{s=yield this._streamer.connectionInfos()}catch(e){return this.onLog("Report stats without connection infos, "+r.stringify(e)),t}const i=s.candidate;if(i){if(t.sessionId=i.id,t.timestamp=i.timestamp,t.currentRoundTripTime=i.currentRoundTripTime,t.totalRoundTripTime=i.totalRoundTripTime,t.requestsReceived=i.requestsReceived,t.requestsSent=i.requestsSent,t.responsesReceived=i.responsesReceived,t.responsesSent=i.responsesSent,t.bytesSent=i.bytesSent,t.bytesReceived=i.bytesReceived,null==i.availableOutgoingBitrate){const e=t.bytesSent-this._lastBytesSend;this._lastBytesSend=t.bytesSent;const s=Date.now(),r=(s-this._lastBytesSendTime)/1e3;this._lastBytesSendTime=s,i.availableOutgoingBitrate=8*e/r}t.availableOutgoingBitrate=i.availableOutgoingBitrate}const o=s.outputs.audio;o&&(t.audio={bytesSent:o.bytesSent,packetsSent:o.packetsSent,retransmittedBytesSent:o.retransmittedBytesSent,retransmittedPacketsSent:o.retransmittedPacketsSent});const n=s.outputs.audio;return n&&(t.video={bytesSent:n.bytesSent,packetsSent:n.packetsSent,retransmittedBytesSent:n.retransmittedBytesSent,retransmittedPacketsSent:n.retransmittedPacketsSent,firCount:n.firCount,framesEncoded:n.framesEncoded,nackCount:n.nackCount,totalEncodeTime:n.totalEncodeTime,hugeFramesSent:n.hugeFramesSent,framesSent:n.framesSent,frameHeight:n.frameHeight,frameWidth:n.frameWidth}),t}))}}export{w as ABRAbstract,O as ABRGrade,C as ABRLinear,u as Connect,n as ConnectType,e as EventEmitter,f as HTTPConnector,y as MBRAbstract,b as MBRLinear,o as MType,c as Metadata,h as NetAddress,L as Numbers,k as Player,B as Queue,m as SDP,p as SIPConnector,l as StreamMetadata,x as Streamer,P as StreamerStats,E as Telemetry,r as Util,g as WSController,v as WSStreamData,s as WebSocketReliable};//# sourceMappingURL=webrtc-client.min.js.map
function t(t,e,s,i){return new(s||(s=Promise))((function(r,o){function n(t){try{c(i.next(t))}catch(t){o(t)}}function a(t){try{c(i.throw(t))}catch(t){o(t)}}function c(t){var e;t.done?r(t.value):(e=t.value,e instanceof s?e:new s((function(t){t(e)}))).then(n,a)}c((i=i.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class e{constructor(){this._events=new Map;let t=Object.getPrototypeOf(this);for(;t&&t!==Object.prototype;){for(const e of Object.getOwnPropertyNames(t))if(!(e.length<3)&&e.startsWith("on")&&t[e]instanceof Function){const s=new Set;this._events.set(e.substring(2).toLowerCase(),s);let i=t[e];Object.defineProperties(this,{[e]:{get:()=>(...t)=>{i&&i.call(this,...t);for(const e of s)e(...t)},set:t=>{i=t}}})}t=Object.getPrototypeOf(t)}}on(t,e,s){if(!e)throw Error("event to subscribe cannot be null");const i=this._event(t);i.add(e),s&&s.signal.addEventListener("abort",(()=>{i.delete(e)}))}once(t,e,s){if(!e)throw Error("event to subscribe cannot be null");const i=this._event(t);i.add((()=>{i.delete(e),e()})),s&&s.signal.addEventListener("abort",(()=>{i.delete(e)}))}off(t,e){if(!e)throw Error("event to unsubscribe cannot be null");this._event(t).delete(e)}_event(t){const e=this._events.get(t.toLowerCase());if(!e)throw Error("No event on"+t+" on class "+this.constructor.name);return e}}class s extends e{onOpen(){}onMessage(t){}onClose(t){t&&console.error(t)}get binaryType(){return"arraybuffer"}get url(){var t,e;return null!==(e=null===(t=this._ws)||void 0===t?void 0:t.url)&&void 0!==e?e:""}get extensions(){var t,e;return null!==(e=null===(t=this._ws)||void 0===t?void 0:t.extensions)&&void 0!==e?e:""}get opened(){return this._opened}get readyState(){return this._ws?this._ws.readyState:3}get closed(){return this._closed}get bufferedAmount(){var t;return this._queueingBytes+((null===(t=this._ws)||void 0===t?void 0:t.bufferedAmount)||0)}get queueing(){return this._queueing}constructor(t){super(),this._queueing=[],this._queueingBytes=0,this._opened=!1,this._closed=!0,t&&this.open(t)}open(t){this._closed=!1;const e=this._ws=new WebSocket(t);return e.binaryType=this.binaryType,e.onmessage=t=>this.onMessage(t.data),e.onclose=e=>{this._opened?1e3===e.code||1005===e.code?this.close(t.toString()+" shutdown"):this.close(t.toString()+" disconnection ("+String(e.reason||e.code)+")"):this.close(t.toString()+" connection failed ("+String(e.reason||e.code)+")")},e.onopen=t=>{this._opened=!0,this.flush(),this.onOpen()},this}send(t,e=!1){if(!this._ws)throw Error("Open socket before to send data");return e||!this._opened?(this._queueing.push(t),this._queueingBytes+="string"==typeof t?t.length:t.byteLength):this._ws.send(t),this}flush(){if(this._ws)for(const t of this._queueing)this._ws.send(t);this._queueing.length=0,this._queueingBytes=0}close(t){this._ws&&!this._closed&&(this._closed=!0,this._ws.onopen=this._ws.onclose=this._ws.onmessage=null,this._ws.close(),this._opened=!1,this._queueing.length=0,this._queueingBytes=0,this.onClose(t))}}const i=performance,r={VERSION:"1.3.0",EMPTY_FUNCTION:()=>{},time:()=>Math.floor(i.now()),timeOrigin:()=>Math.floor(i.now()+i.timeOrigin),options(t=("undefined"==typeof location?void 0:location)){if(!t)return{};try{t=new URL(t).searchParams}catch(e){"string"==typeof t&&(t.startsWith("?")&&(t=t.substring(1)),t=new URLSearchParams(t))}return r.objectFrom(t,{withType:!0,noEmptyString:!0})},objectFrom(t,e){e=Object.assign({withType:!1,noEmptyString:!1},e);const s={};if(!t)return s;for(const[i,r]of this.objectEntries(t)){if(t=r,e.withType&&null!=t&&t.substring)if(t){const e=Number(t);if(isNaN(e))switch(t.toLowerCase()){case"true":t=!0;break;case"false":t=!1;break;case"null":t=null;break;case"undefined":t=void 0}else t=e}else e.noEmptyString&&(t=!0);s[i]?(Array.isArray(s[i])||(s[i]=new Array(s[i])),s[i].push(t)):s[i]=t}return s},objectEntries:t=>t.entries?t.entries():Array.from({[Symbol.iterator]:function*(){for(const e in t)yield[e,t[e]]}}),stringify(t,e={}){if(e=Object.assign({space:" ",decimal:2,recursive:!1},e),!t)return String(t);const s=t.error||t.message;s&&(t=s);const i=Number(e.decimal)||0;if(t.toFixed)return t.toFixed(i);if(t.substring)return String(t);const o=e.space||"";let n="{"+o.replace(/[^\S\r\n]+/,""),a=!0;for(const s in t){let c=t[s];if(c){if(c.call)continue;e.recursive&&c===Object(c)&&(c=r.stringify(c,e))}a?a=!1:n+=","+o,n+=s+":"+(c&&c.toFixed?c.toFixed(i):c)}return n+(o.replace(/[^\S\r\n]+$/,"")+"}")}};var o,n;function a(t,e,s){for(let i=0;i<e.length;++i){const r=e[i];s.has(r.codec.toLowerCase())||(t.delete(r.idx),e.splice(i--,1))}}Object.freeze(r),function(t){t.AUDIO="audio",t.VIDEO="video",t.DATA="data"}(o||(o={}));class c{constructor(){this.type="",this.width=0,this.height=0,this.sources=new Map,this.tracks=new Map,this.audios=[],this.videos=[],this.datas=[]}subset(t){const e=Object.assign({},this);if(t){a(e.tracks,e.audios,t),a(e.tracks,e.videos,t);for(const[,t]of e.tracks){for(;t.up&&!e.tracks.has(t.up.idx);)t.up=t.up.up;for(;t.down&&!e.tracks.has(t.down.idx);)t.down=t.down.down}}return e}}class h{static fixProtocol(t,e){const s=e.indexOf("://");return s>=0&&(s>2&&"s"===e.charAt(s-1).toLowerCase()?(t.length<=2||!t.endsWith("s"))&&(t+="s"):t.length>2&&t.endsWith("s")&&(t=t.slice(0,-1)),e=e.substring(s+3)),t+"://"+e}get domain(){return this._domain}get port(){return this._port}toString(){return this._address}valueOf(){return this._address}constructor(t,e){this._address=t;let s=t.indexOf("/");if(s>=0&&(47===t.charCodeAt(s+1)?s>0?58===t.charCodeAt(s-1)&&(t=t.substring(s+2)):t=t.substring(2):s||(t=t.substring(1))),this._domain=t,this._port=e,s=t.lastIndexOf(":"),s>=0){const e=parseInt(t.substring(s+1));e&&e<=65535&&(this._port=e,this._domain=t.substring(0,s))}else s=t.indexOf("/"),s>=0&&(this._domain=t.substring(0,s))}}!function(t){t.WEBRTC="webrtc",t.META="meta",t.DATA="data"}(n||(n={}));const u={buildURL(t,e,s="wss"){const i=new URL(h.fixProtocol(s,e.host));if(i.pathname.length<=1)switch(t){case n.WEBRTC:i.pathname="/webrtc/"+e.streamName;break;case n.META:i.pathname="/json_"+e.streamName+".js";break;case n.DATA:i.pathname="/"+e.streamName+".json";break;default:console.warn("Unknown url type "+t)}e.accessToken&&i.searchParams.set("id",e.accessToken);for(const t in e.query)i.searchParams.set(t,e.query[t]);return i}};Object.freeze(u);const d=(t,e)=>e.maxbps-t.maxbps;class l extends e{onLog(t){}onError(t="unknown"){console.error(t)}onClose(){this.onLog("onClose")}onMetadata(t){this.onLog(r.stringify(t))}get url(){return this._ws.url}get connectParams(){return this._connectParams}get metadata(){return this._metadata}get closed(){return this._ws.closed}constructor(t){super(),this._connectParams=t,this._ws=new s(u.buildURL(n.META,t)),this._ws.onClose=t=>{this._metadata=new c,t&&this.onError(t),this.onClose()},this._ws.onMessage=t=>{try{const e=JSON.parse(t);if(e.error)throw e.error;this._metadata=new c,this._metadata.type=e.type,this._metadata.width=e.width,this._metadata.height=e.height,this._metadata.sources.clear();for(const t of e.source)this._metadata.sources.set(t.hrn,t);const s=[];this._metadata.tracks.clear();for(const[t,i]of r.objectEntries(e.meta.tracks)){switch(i.name=t,i.type=i.type.toLowerCase(),i.type){case"audio":this._metadata.audios.push(i);continue;case"video":this._metadata.videos.push(i);continue;case"meta":i.type=o.DATA,this._metadata.datas.push(i);break;default:this.onLog("Unknown track type"+i.type)}s.push(i)}this._addSortedTrack(this._metadata.audios,this._metadata.tracks),this._addSortedTrack(this._metadata.videos,this._metadata.tracks);for(const t of s)this._metadata.tracks.set(t.idx,t)}catch(t){return void this.onError(r.stringify(t))}this.onMetadata(this._metadata)}}close(t){this._ws.close(t)}_addSortedTrack(t,e){t.sort(d);for(let s=0;s<t.length;++s){const i=t[s];e.set(i.idx,i),s&&(i.up=t[s-1],t[s-1].down=i)}}}function _(t){return"send"in t}const m={fromString(t){if(Array.isArray(t))return t;const e=new Array;let s,i=e;for(let r of t.toString().split("\n")){if(r=r.trim(),!r)continue;let t=r[0];const o=r.substring(r.indexOf("=")+1).trim();switch(t.toLowerCase()){case"a":if(!o)continue;t=this.addAttribute(i,o),e===i&&"fingerprint"===t.toLowerCase()&&(s=i.fingerprint);break;case"m":e.length&&s&&!e[e.length-1].fingerprint&&(i.fingerprint=s),e.push(i={m:o});break;default:i[t]=o}}return e.length&&s&&!e[e.length-1].fingerprint&&(i.fingerprint=s),e},toString(t){if("string"==typeof t)return t;const e=[];let s="v"in t?"v="+t.v+"\n":"";"o"in t&&(s+="o="+t.o+"\n"),"s"in t&&(s+="s="+t.s+"\n");const i=t;for(const r of Object.keys(t)){if("v"===r||"o"===r||"s"===r)continue;const t=i[r];if(null==t)continue;const o=parseInt(r);if(!isNaN(o)){e[o]=t;continue}const n=Array.isArray(t)&&t.length||1;for(let e=0;e<n;++e){const i=Array.isArray(t)&&t.length?t[e]:t;r.length>1?(s+="a="+r,i&&(s+=":")):s+=r+"=",s+=i+"\n"}}for(const t of e)s+=this.toString(t);return s},addAttribute(t,e){var s;const i=m.parseAttribute(e),r=null!==(s=i.value)&&void 0!==s?s:"",o=t,n=o[i.key];return n?Array.isArray(n)?n.push(r):r!==n&&(o[i.key]=[n,r]):o[i.key]=r,i.key},removeAttribute(t,e){const s=m.parseAttribute(e),i=t;if(void 0===s.value)return delete i[e],e;const r=i[e];if(Array.isArray(s.value)){const t=r.findIndex((t=>t===s.value));t>=0&&r.splice(t,1)}else r===s.value&&delete i[e];return s.key},parseAttribute(t){const e=t.indexOf(":");return{key:(e>=0?t.substring(0,e):t).trim(),value:e>=0?t.substring(e+1).trim():void 0}}};Object.freeze(m);const p=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);class g extends e{onLog(t){}onError(t="unknown"){console.error(t)}onOpen(t){this.onLog("onOpen")}onClose(){this.onLog("onClose")}get opened(){return!(!this._peerConnection||this._peerConnection.ontrack!==r.EMPTY_FUNCTION)}get closed(){return this._closed}get stream(){return this._stream}get streamName(){return this._streamName}get codecs(){return this._codecs}constructor(t,e){super(),this._closed=!1,this._streamName=t.streamName,this._host=t.host,this._stream=e,this._connectionInfosTime=0,this._codecs=new Set}connectionInfos(e=1e3){return t(this,void 0,void 0,(function*(){if(!this._peerConnection)return Promise.reject("Not connected");if(!this._connectionInfos||r.time()-e>this._connectionInfosTime){const t=yield this._peerConnection.getStats(null);this._connectionInfos={inputs:{},outputs:{}};const e=new Map,s=new Map;for(const i of t.values())switch(i.type){case"track":e.set(i.id,i);break;case"outbound-rtp":s.set(i.trackId,i),this._connectionInfos.outputs["audio"===(i.kind||i.mediaType)?"audio":"video"]=i;break;case"inbound-rtp":s.set(i.trackId,i),this._connectionInfos.inputs["audio"===(i.kind||i.mediaType)?"audio":"video"]=i;break;case"candidate-pair":if(null!=i.selected){if(!i.selected)continue}else if(null!=i.nominated&&!i.nominated)continue;this._connectionInfos.candidate=i}for(const[t,i]of e){const e=s.get(t);e&&Object.assign(e,Object.assign(Object.assign({},i),e))}this._connectionInfosTime=r.time()}return this._connectionInfos}))}close(t){if(this._closed)return;this._closed=!0;const e=this._peerConnection;e&&(this._peerConnection=void 0,e.getReceivers().forEach((t=>t.track&&t.track.stop())),e.getSenders().forEach((t=>t.track&&t.track.stop())),e.close()),this._stream&&this._stream.getTracks().forEach((t=>t.stop())),t&&this.onError(t),this.onClose()}_open(t){if(!t){const e=new h(this._host,443).domain;t={urls:["turn:"+e+":3478?transport=tcp","turn:"+e+":3478"],username:"csc_demo",credential:"UtrAFClFFO"}}try{this._peerConnection=new RTCPeerConnection({iceServers:[t]})}catch(t){return void this.close("RTCPeerConnection failed, "+r.stringify(t))}if(this._stream)for(const t of this._stream.getTracks())this._peerConnection.addTrack(t);else this._peerConnection.ontrack=t=>{this._stream=t.streams[0],this._tryToOpen()};if(p)if(this._stream){const t=this._peerConnection.getTransceivers();for(const e of t)"audio"!==e.receiver.track.kind&&"video"!==e.receiver.track.kind||(e.direction="sendonly")}else this._peerConnection.addTransceiver("audio",{direction:"recvonly"}),this._peerConnection.addTransceiver("video",{direction:"recvonly"});let e;this._peerConnection.createOffer({offerToReceiveAudio:!this._stream,offerToReceiveVideo:!this._stream}).then((t=>{var s;if(this._peerConnection)return e=null!==(s=t.sdp)&&void 0!==s?s:"",this.onLog("Offer\r\n"+e),this._peerConnection.setLocalDescription(t)})).then((t=>{if(this._peerConnection)return e?this._sip(e):Promise.reject("invalid empty sdp offer")})).then((t=>{if(t&&this._peerConnection){this.onLog("Answer\r\n"+t);for(const e of m.fromString(t)){if(!e.rtpmap)continue;let t=e.rtpmap.indexOf(" ");if(t<0)continue;let s=e.rtpmap.substring(t+1);if(!s)return;t=s.indexOf("/"),s=t<0?s:s.substring(0,t),this._codecs.add(s.toLowerCase())}return this._peerConnection.setRemoteDescription(new RTCSessionDescription({type:"answer",sdp:t}))}})).then((()=>this._tryToOpen())).catch((t=>this.close("SIP failed, "+r.stringify(t))))}_tryToOpen(){this._stream&&this._peerConnection&&this._peerConnection.ontrack!==r.EMPTY_FUNCTION&&(this._peerConnection.ontrack=r.EMPTY_FUNCTION,this.onOpen(this._stream))}}class f extends g{onRTPProps(t){this.onLog("onRTPProps "+r.stringify(t))}onMediaReport(t){console.debug("onMediaReport "+r.stringify(t))}onVideoBitrate(t,e){this.onLog("onVideoBitrate "+r.stringify({video_bitrate:t,video_bitrate_constraint:e}))}onPlaying(t){console.debug("onPlaying "+r.stringify(t))}constructor(t,e){super(t,e),this._ws=new s(u.buildURL(n.WEBRTC,t,"wss")),this._ws.onClose=t=>this.close(t),this._ws.onOpen=()=>{this._open(t.iceServer)},this._ws.onMessage=t=>{try{this._eventHandler(JSON.parse(t))}catch(t){this.onError("Invalid signaling message, "+r.stringify(t))}}}setRTPProps(t,e){this.send("rtp_props",{nack:t,drop:e})}setVideoBitrate(t){this.send("video_bitrate",{video_bitrate:t})}setTracks(t){this.send("tracks",t)}send(t,e){try{this.onLog("Command "+t+" "+r.stringify(e)),this._ws.send(JSON.stringify(Object.assign({type:t},e)))}catch(t){this.onError(r.stringify(t))}}close(t){this._ws.close(t),this._promise&&(this._promise(Error("closing")),this._promise=void 0),super.close(t)}_sip(t){return new Promise(((e,s)=>{this._promise=t=>{t instanceof Error?s(t):e(t)},this._ws.send(JSON.stringify({type:"offer_sdp",offer_sdp:t}))}))}_eventHandler(t){var e,s;switch(t.type){case"on_answer_sdp":this._promise&&this._promise(t.answer_sdp);break;case"on_error":this.opened?this.onError(r.stringify(t)):this.close(r.stringify(t));break;case"on_video_bitrate":this.onVideoBitrate(t.video_bitrate,t.video_bitrate_constraint);break;case"on_stop":this.onLog("on_stop"),this.close();break;case"on_track_drop":{const i=null!==(e=t.mediatype)&&void 0!==e?e:"?",r=null!==(s=t.track)&&void 0!==s?s:"?";this.onError(i+" track #"+r+"dropped");break}case"on_rtp_props":this.onRTPProps(t);break;case"on_media_receive":this.onMediaReport(t);break;case"on_seek":break;case"on_time":this.onPlaying(t);break;default:this.onError("Unhandled event: "+t.type)}}}class v extends g{constructor(t,e){super(t,e),this._url=u.buildURL(n.WEBRTC,t,"https"),this._fetch=new AbortController,setTimeout((()=>{this._open(t.iceServer)}),0)}close(t){this._fetch.abort(),super.close(t)}_sip(e){return t(this,void 0,void 0,(function*(){const t=yield fetch(this._url,{method:"POST",body:e,headers:{"Content-Type":"application/sdp"},signal:this._fetch.signal});return t?t.text():Promise.reject("client rejected")}))}}class y extends e{onLog(t){}onError(t="unknown"){console.error(t)}onClose(){this.onLog("onClose")}onData(t,e,s){this.onLog(`Data received on track ${e} at ${t} : ${r.stringify(s)}`)}get url(){return this._url}get tracks(){return[...this._tracks]}set tracks(t){this._tracks=[...t],this._sendTracks()}get closed(){return!this._ws||this._ws.closed}constructor(t){super(),this._url=u.buildURL(n.DATA,t).toString(),this._tracks=Array(),this._ws=new s,this._ws.onOpen=()=>this._sendTracks(),this._ws.onClose=t=>{t&&this.onError(t),this.onClose()},this._ws.onMessage=t=>{let e;try{e=JSON.parse(t)}catch(t){return this.onError("Invalid signaling message, "+r.stringify(t))}if(e.error)return this.onError(e.error);"time"in e&&"track"in e&&"data"in e?this.onData(e.track,e.time,e.data):"on_time"!==e.type&&console.debug("Internal JSON : ",r.stringify(e))}}close(t){this._ws.close(t)}_sendTracks(){this._tracks.length?this._ws.closed?this._ws.open(this._url):this._ws.opened&&this._ws.send(JSON.stringify({type:"tracks",tracks:this._tracks.join(",")})):this.close()}}class b{onLog(t){}onError(t="unknown"){console.error(t)}get upDelay(){return this._upDelay}get learningUpStep(){return this._learningUpStep}get maximumUpDelay(){return this._maximumUpDelay}constructor(t){const e=Object.assign({learningUpStep:1400,maximumUpDelay:28e3},t);this._learningUpStep=e.learningUpStep,this._maximumUpDelay=e.maximumUpDelay,this._upDelay=0,this._testTime=0}reset(){this._upDelay=0,this._mTrack=void 0}compute(t,e,s){var i;const o=null!==(i=e.video)&&void 0!==i?i:e.audio;if(null==o)return this._mTrack=void 0,!1;const n=r.time();if(!(this._mTrack&&this._mTrack.idx===o||(this._appreciationTime=void 0,this._testTime=n,this._mTrack=t.tracks.get(o),this._mTrack)))return this.onError("Can't find track "+o+" absent from metadata"),!1;const a=o===e.video?s.video:s.audio;if(!a)return this.onError("Can't compute "+this._mTrack.type+" track "+this._mTrack.idx+" without statistics"),!1;const c=this._downBitrate(n-this._testTime,this._mTrack,a);if(c)this._appreciationTime=void 0;else{this._appreciationTime||(this._appreciationTime=n);const t=n-this._appreciationTime;if(!this._upBitrate(t,this._mTrack,a)||t<this._upDelay)return!1}let h=this.updateTrack(e.audio,t,c);if(h)e.audio=h.idx;else{if(h=this.updateTrack(e.video,t,c),!h)return!1;e.video=h.idx}return c&&(this._upDelay=Math.min(this._upDelay+this._learningUpStep,this._maximumUpDelay)),this.onLog((c?"DOWN":"UP")+" from "+this._mTrack.type+" track "+this._mTrack.idx+" ("+this._mTrack.maxbps+"bps) to "+h.type+" track "+h.idx+" ("+h.maxbps+"bps)"),!0}updateTrack(t,e,s){if(null==t)return;const i=s?"down":"up",r=e.tracks.get(t);if(r)return r[i];this.onError("Can't find track "+t+" from metadata")}}class T extends b{constructor(t){super(t),this._keyFramesDecoded=0,this._lost=0,this._nackCount=0}_downBitrate(t,e,s){const i=s.packetsLost,o=s.nackCount;if(null==i)return this.onLog("No packetsLost information in "+r.stringify(s)),!1;const n=t>0&&i>this._lost&&(!o||o>this._nackCount);return this._lost=i,this._nackCount=o||0,n}_upBitrate(t,e,s){if(e.type===o.AUDIO)return!0;if(t>1e4)return!0;const i=s.keyFramesDecoded;if(null==i)return!1;if(t){if(i>this._keyFramesDecoded){if(!this._keyFramesDecoded)return!0;this._keyFramesDecoded=0}}else this._keyFramesDecoded=i;return!1}}const k=1e3;class w extends e{onLog(t){}onError(t="unknown"){console.error(t)}onStart(t){this.onLog("onStart")}onStop(){this.onLog("onStop")}onPlaying(t){console.debug("onPlaying "+r.stringify(t))}onMetadata(t){this.onLog(r.stringify(t))}onData(t,e,s){this.onLog(`Data received on track ${e} at ${t} : ${r.stringify(s)}`)}get streamName(){return this._connector?this._connector.streamName:""}get stream(){return this._connector&&this._connector.stream}get running(){return!!this._connector}get controller(){return this._controller}get connector(){return this._connector}get metadata(){return this._metadata}get playingInfos(){return this._playingInfos}get audioTrack(){return this._audioTrack}set audioTrack(t){if(this._audioTrackFixed=null!=t,this._audioTrackFixed&&this._audioTrack!==t&&(this._audioTrack=t,this._connector)){if(!this._controller)throw Error("Cannot set audioTrack without start a controllable session");this._controller.setTracks({audio:t})}}get videoTrack(){return this._videoTrack}set videoTrack(t){if(this._videoTrackFixed=null!=t,this._videoTrackFixed&&this._videoTrack!==t&&(this._videoTrack=t,this._connector)){if(!this._controller)throw Error("Cannot set videoTrack without start a controllable session");this._controller.setTracks({video:t})}}get dataTracks(){return[...this._dataTracks]}set dataTracks(t){this._dataTracks=[...t],this._streamData&&(this._streamData.tracks=t)}constructor(t){super(),this.Connector=t,this._dataTracks=new Array}connectionInfos(){return this._connector?this._connector.connectionInfos():Promise.reject("Start player before to request connection infos")}start(e,s={}){let i,o,n;this.stop(),"connectParams"in e?(this._initStreamMetadata(Object.assign({},e.connectParams),e),e=e.connectParams):this._initStreamMetadata(Object.assign({},e),new l(e)),null!=this._audioTrack&&(e.query=Object.assign({audio:this._audioTrack.toFixed()},e.query)),null!=this._videoTrack&&(e.query=Object.assign({video:this._videoTrack.toFixed()},e.query)),this._audioTrackFixed=!1,this._videoTrackFixed=!1,this._connector=new(this.Connector||(e.host.startsWith("http")?v:f))(e),this._connector.onLog=t=>this.onLog("Signaling: "+t),this._connector.onError=t=>this.onError("Signaling: "+t),this._connector.onOpen=t=>{var e,s;this.onStart(t),(null===(e=this._streamMetadata)||void 0===e?void 0:e.metadata)&&this._streamMetadata.onMetadata(null===(s=this._streamMetadata)||void 0===s?void 0:s.metadata),o&&this._controller&&this._controller.onPlaying(o)},this._connector.onClose=()=>{null==i||i.reset(),this.stop()},this._newStreamData(Object.assign({},e)),_(this._connector)?(s&&("compute"in s?i=s:(i=new T(s),i.onLog=t=>this.onLog("MultiBitrate: "+t))),this._controller=this._connector,this._controller.onPlaying=e=>t(this,void 0,void 0,(function*(){if(o=e,this._controller&&this._controller.opened&&(this._playingInfos=o,this._updateTracks(),this.onPlaying(o),i))if(this._audioTrackFixed&&this._videoTrackFixed)i.reset();else try{const t=yield this._controller.connectionInfos(1e3);if(t===n)return;const e={audio:this._audioTrackFixed?void 0:this._audioTrack,video:this._videoTrackFixed?void 0:this._videoTrack};this._controller&&this._metadata&&i.compute(this._metadata,e,(n=t).inputs)&&(this._audioTrack=e.audio,this._videoTrack=e.video,this._controller.setTracks(e))}catch(t){this.onError("Can't compute MBR, "+r.stringify(t))}}))):s&&this.onLog("Cannot use a multiple bitrate without a controller: Connector "+this._connector.constructor.name+" doesn't implements IController")}stop(){const t=this._connector;t&&(this._connector=void 0,this._streamMetadata&&(this._streamMetadata.close(),this._streamMetadata=void 0),this._streamData&&(this._streamData.close(),this._streamData=void 0),t.close(),this._audioTrack=void 0,this._videoTrack=void 0,this._dataTracks.length=0,this._playingInfos=void 0,this._metadata=void 0,this.onStop())}_updateTracks(){if(!this._playingInfos||!this._metadata)return;const t=new Array,e=new Array;for(const s of this._playingInfos.tracks){const i=this._metadata.tracks.get(s);i&&(i.type===o.AUDIO?t.push(s):i.type===o.VIDEO&&e.push(s))}1===t.length&&(this._audioTrack=t[0]),1===e.length&&(this._videoTrack=e[0])}_initStreamMetadata(t,e){this._streamMetadata=e,e.onLog=t=>this.onLog("StreamMetadata: "+t),e.onError=t=>this.onError("StreamMetadata: "+t),e.onMetadata=t=>{this._connector&&this._connector.opened&&(this._metadata=t.subset(this._connector.codecs),this._updateTracks(),this.onMetadata(this._metadata))},e.onClose=()=>{this.onLog("StreamMetadata closed, trying to reconnect in 1000ms"),setTimeout((()=>{this._streamMetadata===e&&this._initStreamMetadata(t,new l(t))}),k)}}_newStreamData(t){const e=this._streamData=new y(t);e.onLog=t=>this.onLog("Timed Metadatas: "+t),e.onError=t=>this.onError("Timed Metadatas: "+t),e.onData=(t,e,s)=>this.onData(e,t,s),e.tracks=this._dataTracks,e.onClose=()=>{this.onLog("Timed Metadatas closed, trying to reconnect in 1000ms"),setTimeout((()=>{this._streamData===e&&this._newStreamData(t)}),k)}}}class S extends e{onLog(t){}onError(t="unknown"){console.error(t)}get startup(){return this._startup}set startup(t){this._startup=Math.max(this._minimum,Math.min(Math.round(t),this._maximum))}get minimum(){return this._minimum}set minimum(t){t=Math.round(t),(this._minimum=t)>this._maximum?this._maximum=this._startup=t:this._startup<t&&(this._startup=t)}get maximum(){return this._maximum}set maximum(t){t=Math.round(t),(this._maximum=t)<this._minimum?this._minimum=this._startup=t:this._startup>t&&(this._startup=t)}get constraint(){return this._bitrateConstraint}get value(){return this._bitrate}valueOf(){return this.value}get stream(){return this._stream}constructor(t,e){super();const s=Object.assign({startup:2e6,maximum:3e6,minimum:2e5},t);this._startup=s.startup,this._minimum=s.minimum,this._maximum=s.maximum,this._stream=e}compute(t,e,s){if(null==t)return this._bitrate=t;const i=null==this._bitrate,r=i?this.startup:Math.max(this.minimum,Math.min(this._computeBitrate(t,e,s),this.maximum));return this._bitrate=t,this._bitrateConstraint=e,i?this.onLog("Set startup bitrate to "+r):r>t?this.onLog("Increase bitrate "+t+" => "+r):r<t&&this.onLog("Decrease bitrate "+t+" => "+r),r}reset(){this._bitrate=this._bitrateConstraint=void 0}_updateVideoConstraints(t){const e=this._stream;if(!e)return;const s=e.getVideoTracks()[0];if(!s)return;const i=s.getSettings();if(!i.width||!i.height)return;const r=i.width*i.height;t>=12e5?r<645120&&this._upgradeVideoConstraint(s,2):r>645120&&r<1198080&&this._upgradeVideoConstraint(s,.5)}_upgradeVideoConstraint(t,e){const s={},i=t.getSettings().width;null!=i&&(s.width=i*e);const r=t.getSettings().height;null!=r&&(s.height=r*e),this.onLog("Resolution change "+i+"X"+r+" => "+s.width+"X"+s.height),t.applyConstraints(s)}}let C=class{constructor(){this.stableTime=0,this.stableBitrate=0,this.attempts=1,this.lastLoss=Number.POSITIVE_INFINITY}};class x extends S{constructor(t,e){super(t,e),this._vars=new C}reset(){super.reset(),this._vars=new C}_computeBitrate(t,e,s){const i=s&&s.stats,o=this._vars;if(i&&i.loss_perc)i.loss_perc>=o.lastLoss&&(o.stableTime&&++o.attempts,o.stableTime=0,t=Math.round((1-i.loss_perc/100)*t)),o.lastLoss=i.loss_perc;else{o.lastLoss=Number.POSITIVE_INFINITY;const e=r.time();e>=o.stableTime&&(o.stableTime?(this._updateVideoConstraints(t),t+=Math.ceil((this.maximum-o.stableBitrate)/o.attempts)):o.stableBitrate=t,o.stableTime=e+11)}return t}}class B extends e{onLog(t){}onError(t="unknown"){console.error(t)}onStart(t){this.onLog("onStart")}onStop(){this.onLog("onStop")}onRTPProps(t){this.onLog("onRTPProps "+r.stringify(t))}onMediaReport(t){console.debug("onMediaReport "+r.stringify(t))}onVideoBitrate(t,e){this.onLog("onVideoBitrate "+r.stringify({videoBitrate:t,videoBitrateConstraint:e}))}get streamName(){return this._connector?this._connector.streamName:""}get stream(){return this._connector&&this._connector.stream}get running(){return!!this._connector}get controller(){return this._controller}get connector(){return this._connector}get mediaReport(){return this._mediaReport}get rtpProps(){return this._rtpProps}get videoBitrate(){return this._videoBitrate}set videoBitrate(t){if(!this._controller)throw Error("Cannot set videoBitrate without start a controllable session");this._videoBitrateFixed=null!=t,this._videoBitrateFixed&&t!==this._videoBitrate&&this._controller.setVideoBitrate(t)}get videoBitrateConstraint(){return this._videoBitrateConstraint}constructor(t){super(),this.Connector=t,this._videoBitrate=0,this._videoBitrateConstraint=0}setRTPProps(t,e){if(!this._controller)throw Error("Cannot set rtpProps without start a controllable session");this._controller.setRTPProps(t,e)}connectionInfos(){return this._connector?this._connector.connectionInfos():Promise.reject("Start streamer before to request connection infos")}start(e,s,i={}){let r;this.stop(),this._videoBitrateFixed=!1,this._connector=new(this.Connector||(s.host.startsWith("http")?v:f))(s,e),this._connector.onLog=t=>this.onLog("Signaling: "+t),this._connector.onError=t=>this.onError("Signaling: "+t),this._connector.onOpen=t=>this.onStart(t),this._connector.onClose=()=>{null==r||r.reset(),this.stop()},_(this._connector)?(i&&("compute"in i?r=i:(r=new x(i),r.onLog=t=>this.onLog("AdaptiveBitrate: "+t))),this._controller=this._connector,this._controller.onOpen=t=>{this._computeVideoBitrate(r),this.onStart(t)},this._controller.onRTPProps=t=>{this._rtpProps=t,this.onRTPProps(t)},this._controller.onMediaReport=e=>t(this,void 0,void 0,(function*(){this._mediaReport=e,this._computeVideoBitrate(r),this.onMediaReport(e)})),this._controller.onVideoBitrate=(t,e)=>{this._videoBitrate=t,this._videoBitrateConstraint=e,this.onVideoBitrate(t,e)}):i&&this.onLog("Cannot use an adaptive bitrate without a controller: Connector "+this._connector.constructor.name+" doesn't implements IController")}stop(){const t=this._connector;t&&(this._connector=void 0,t.close(),this._controller=void 0,this._mediaReport=void 0,this._videoBitrate=0,this._videoBitrateConstraint=0,this._rtpProps=void 0,this.onStop())}_computeVideoBitrate(t){var e;if(!this._controller||this._videoBitrateFixed)return;const s=null!==(e=t.compute(this._videoBitrate,this.videoBitrateConstraint,this.mediaReport))&&void 0!==e?e:this._videoBitrate;s!==this._videoBitrate&&this._controller.setVideoBitrate(s)}}class L{get size(){return this._queue.length}get capacity(){return this._capacity}set capacity(t){this._capacity=t,null!=t&&this._queue.length>t&&this._queue.splice(0,this._queue.length-t)}get front(){return this._queue[0]}get back(){return this._queue[this._queue.length-1]}[Symbol.iterator](){return this._queue[Symbol.iterator]()}constructor(t){this._capacity=t,this._queue=new Array}push(t){return null!=this._capacity&&this._queue.push(t)>this._capacity&&this.pop(),this}pop(){return this._queue.shift()}clear(){return this._queue.length=0,this}}class R extends L{get minimum(){return this._min}get maximum(){return this._max}get average(){return null==this._average&&(this._average=this.size?this._sum/this.size:0),this._average}constructor(t){super(t),this._sum=0,this._min=0,this._max=0}push(t){return t>this._max?this._max=t:t<this._min&&(this._min=t),this._average=void 0,this._sum+=t,super.push(t),this}pop(){const t=super.pop();return t===this._max?this._max=Math.max(0,...this):t===this._min&&(this._min=Math.min(0,...this)),this._average=void 0,this._sum-=t||0,t}clear(){return this._min=this._max=this._sum=0,super.clear(),this}}class O{constructor(){this.lossPercents=new R(5),this.stableBitrates=new R(15),this.stableBitrateUpdateTime=0,this.bitrateRecoveryTimeout=1e4,this.bitrateRecoveryNextTime=0}}class E extends S{constructor(t,e){super(t,e),this._vars=new O}reset(){super.reset(),this._vars=new O}_computeBitrate(t,e,s){var i;const o=this._vars,n=s&&s.stats;n&&null!=n.loss_perc&&o.lossPercents.push(n.loss_perc);const a=r.time();a>=o.stableBitrateUpdateTime&&o.lossPercents.average<.2&&(o.stableBitrateUpdateTime=a+4e3,o.stableBitrates.push(Math.min(null!==(i=null!=e?e:this.constraint)&&void 0!==i?i:0,t,this.maximum)));const c=o.stableBitrates.average,h=o.stableBitrates.minimum,u=o.stableBitrates.maximum;if(h>=.8*c&&u<=1.2*c&&this._updateVideoConstraints(c),null!=e&&null!=this.constraint&&e<this.constraint){if(this.onLog(`onVideoBitrateConstraint: ${this._formatBitrate(e-this.constraint)}`),o.bitrateConstraintTime){if(o.bitrateRecoveryTime){(a-o.bitrateRecoveryTime<o.bitrateRecoveryTimeout||2500===o.bitrateRecoveryTimeout)&&(this._increaseRecoveryTimeout(),o.bitrateRecoveryTime=void 0)}}else o.bitrateRecoveryTime||(this.onLog("VideoBitrateConstraint: First constrain! Halve bitrate!"),t=Math.round(t/2));o.bitrateConstraintTime=a}if(e&&(e<this.minimum&&(t=this.minimum),this.maximum>e&&a>=o.bitrateRecoveryNextTime)){const s=o.bitrateRecoveryNextTime&&this._bitrateRecoveryHandler(e);s?(o.bitrateRecoveryTimeout=a,o.bitrateRecoveryNextTime=0,t=s):(o.bitrateRecoveryNextTime=a+o.bitrateRecoveryTimeout,this.onLog("startVideoBitrateRecoveryTimer "+o.bitrateRecoveryTimeout))}return t}_bitrateRecoveryHandler(t){const e=this._vars,s=e.lossPercents.average;if(this.onLog("videoBitrateRecoveryHandler loss: "+s.toFixed(2)),s<.2){let s=this._increaseTargetBitrate(t);return e.bitrateConstraintTime&&s>e.stableBitrates.average&&(s=this._increaseTargetBitrate(t,1.005)),this._decreaseRecoveryTimeout(),this.onLog("videoBitrateRecoveryHandler increase bitrate to "+this._formatBitrate(s)),s}if(s<5){this._increaseRecoveryTimeout();const e=this._decreaseTargetBitrate(t);return this.onLog("videoBitrateRecoveryHandler decrease bitrate to "+this._formatBitrate(e)),e}}_increaseTargetBitrate(t,e=1.05){let s=Math.round(t*e);return s>this.maximum&&(s=this.maximum),s}_decreaseTargetBitrate(t){let e=Math.round(.99*t);return e<this.minimum&&(e=this.minimum),e}_increaseRecoveryTimeout(){this._vars.bitrateRecoveryTimeout=Math.min(6e4,2*this._vars.bitrateRecoveryTimeout)}_decreaseRecoveryTimeout(){this._vars.bitrateRecoveryTimeout=Math.max(2500,Math.round(.75*this._vars.bitrateRecoveryTimeout))}_formatBitrate(t){return(t/1e6).toFixed(3)}}class P extends e{onLog(t){}onError(t="unknown"){console.error(t)}get url(){return this._url}get reporting(){return this._reporting}constructor(t){if(super(),(t=new URL(t)).protocol.startsWith("ws"))this._ws=new s;else if(!t.protocol.startsWith("http"))throw Error("Protocol "+t.protocol+" not supported");this._url=t.toString(),this._reporting=0}report(e,s){e.onError=t=>this.onError(e.constructor.name+" error, "+t),e.onLog=t=>this.onError(e.constructor.name+", "+t);let i=e.onRelease=()=>{i&&(i=void 0,clearInterval(o),this.onLog("Stop "+e.constructor.name+" reporting"),--this._reporting>0||(this._ws&&this._ws.close(),this._fetch&&this._fetch.abort()))};const o=(s?setInterval:setTimeout)((()=>t(this,void 0,void 0,(function*(){!s&&i&&i();try{yield this._send(e)}catch(t){this.onError(e.constructor.name+" error, "+r.stringify(t))}}))),1e3*s);++this._reporting,this.onLog("Start "+e.constructor.name+" reporting every "+s+" seconds")}_send(e){return t(this,void 0,void 0,(function*(){let t,s,i;try{t=yield e.serialize()}catch(t){if(!t)return;throw t}t instanceof ArrayBuffer?(i="application/octet-stream",s=t):"string"==typeof t?(i="text/plain",s=t):(i="application/json",s=JSON.stringify(t)),this._ws?(this._ws.closed&&this._ws.open(this._url),this._ws.queueing.length=0,this._ws.send(s)):(this._fetch&&this._fetch.abort(),this._fetch=new AbortController,fetch(this._url,{method:"POST",body:s,headers:{"Content-Type":i},signal:this._fetch.signal}))}))}}class M extends e{onLog(t){}onError(t="unknown"){console.error(t)}onRelease(){}constructor(t){super(),this._streamer=t,this._lastBytesSend=0,this._lastBytesSendTime=Date.now(),t.once("stop",(()=>this.onRelease()))}serialize(){return t(this,void 0,void 0,(function*(){if(!this._streamer.running)return Promise.reject();const t={streamId:this._streamer.streamName,vbt:this._streamer.videoBitrate,vbc:this._streamer.videoBitrateConstraint},e=this._streamer.mediaReport;let s;e&&(t.server={millis:e.millis,tracks:e.tracks},e.stats&&(t.server.jitterMs=e.stats.jitter_ms,t.server.lossNum=e.stats.loss_num,t.server.lossPerc=e.stats.loss_perc,t.server.nackNum=e.stats.nack_num));try{s=yield this._streamer.connectionInfos()}catch(e){return this.onLog("Report stats without connection infos, "+r.stringify(e)),t}const i=s.candidate;if(i){if(t.sessionId=i.id,t.timestamp=i.timestamp,t.currentRoundTripTime=i.currentRoundTripTime,t.totalRoundTripTime=i.totalRoundTripTime,t.requestsReceived=i.requestsReceived,t.requestsSent=i.requestsSent,t.responsesReceived=i.responsesReceived,t.responsesSent=i.responsesSent,t.bytesSent=i.bytesSent,t.bytesReceived=i.bytesReceived,null==i.availableOutgoingBitrate){const e=t.bytesSent-this._lastBytesSend;this._lastBytesSend=t.bytesSent;const s=Date.now(),r=(s-this._lastBytesSendTime)/1e3;this._lastBytesSendTime=s,i.availableOutgoingBitrate=8*e/r}t.availableOutgoingBitrate=i.availableOutgoingBitrate}const o=s.outputs.audio;o&&(t.audio={bytesSent:o.bytesSent,packetsSent:o.packetsSent,retransmittedBytesSent:o.retransmittedBytesSent,retransmittedPacketsSent:o.retransmittedPacketsSent});const n=s.outputs.audio;return n&&(t.video={bytesSent:n.bytesSent,packetsSent:n.packetsSent,retransmittedBytesSent:n.retransmittedBytesSent,retransmittedPacketsSent:n.retransmittedPacketsSent,firCount:n.firCount,framesEncoded:n.framesEncoded,nackCount:n.nackCount,totalEncodeTime:n.totalEncodeTime,hugeFramesSent:n.hugeFramesSent,framesSent:n.framesSent,frameHeight:n.frameHeight,frameWidth:n.frameWidth}),t}))}}export{S as ABRAbstract,E as ABRGrade,x as ABRLinear,u as Connect,n as ConnectType,e as EventEmitter,v as HTTPConnector,b as MBRAbstract,T as MBRLinear,o as MType,c as Metadata,h as NetAddress,R as Numbers,w as Player,L as Queue,m as SDP,g as SIPConnector,l as StreamMetadata,B as Streamer,M as StreamerStats,P as Telemetry,r as Util,f as WSController,y as WSStreamData,s as WebSocketReliable};//# sourceMappingURL=webrtc-client.min.js.map
{
"name": "@ceeblue/webrtc-client",
"version": "1.2.0",
"version": "1.3.0",
"description": "Ceeblue WebRTC Client",

@@ -5,0 +5,0 @@ "keywords": [

@@ -47,3 +47,2 @@ [Requirements](#requirements) | [Usage](#usage) | [Examples](#examples) | [Building locally](#building-locally) | [Documentation](#documentation) | [Contribution](#contribution) | [License](#license)

> ```
> - To avoid potential issues with backward compatibility or problems on iOS when using `navigator.mediaDevices.getUserMedia`, we recommend including the [WebRTC adapter](https://github.com/webrtcHacks/adapter) in the final project. This often mitigates common compatibility issues on certain older devices.

@@ -50,0 +49,0 @@ ### Publish a stream

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc