@livepeer-frameworks/player-wc 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4330,7 +4330,7 @@ const zt="important",jt=" !"+zt,qt=ve(class extends Te{constructor(e){if(super(e
4330
4330
  :host {
4331
4331
  display: none;
4332
4332
  }
4333
- `,nn=n([he("fw-context-menu")],nn),rn("fw-player",e.FwPlayer),rn("fw-player-controls",Bt),rn("fw-seek-bar",$t),rn("fw-volume-control",Ht),rn("fw-settings-menu",Gt),rn("fw-idle-screen",Vt),rn("fw-loading-spinner",Wt),rn("fw-title-overlay",Kt),rn("fw-error-overlay",Yt),rn("fw-toast",Xt),rn("fw-stats-panel",Qt),rn("fw-dev-mode-panel",Jt),rn("fw-subtitle-renderer",Zt),rn("fw-skip-indicator",en),rn("fw-speed-indicator",tn),rn("fw-context-menu",nn);class sn extends Ne{constructor(){super(...arguments),this.capability={name:"Native Player",shortname:"native",priority:1,mimes:["html5/video/mp4","html5/video/webm","html5/video/ogg","html5/audio/mp3","html5/audio/webm","html5/audio/ogg","html5/audio/wav","html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7","whep"]},this.peerConnection=null,this.sessionUrl=null,this.lastInboundStats=null,this.reconnectEnabled=!1,this.reconnectAttempts=0,this.maxReconnectAttempts=3,this.reconnectTimer=null,this.currentWhepUrl=null,this.currentHeaders=null,this.currentIceServers=null,this.container=null,this.destroyed=!1,this.liveDurationProxy=null,this.pausedAt=null,this.currentSourceUrl=null,this.currentMimeType=null,this.isMP3Source=!1,this.liveSeekEnabled=!1,this.liveSeekOffsetSec=0,this.liveSeekBaseUrl=null,this.liveSeekListeners=[],this.liveSeekTimer=null,this.pendingLiveSeekOffset=null}isMimeSupported(e){return-1!==this.capability.mimes.indexOf(e)}isBrowserSupported(e,t,n){if("whep"===e){if(!("RTCPeerConnection"in window)||!("fetch"in window))return!1;const e=De(n.meta.tracks);if(!e.compatible)return e.incompatibleCodecs.length>0&&console.debug("[WHEP] Skipping - incompatible codecs:",e.incompatibleCodecs.join(", ")),!1;const t=[];return e.details.compatibleVideoCodecs.length>0&&t.push("video"),e.details.compatibleAudioCodecs.length>0&&t.push("audio"),t.length>0&&t}if(Ie(t.url)&&("file:"!==window.location.protocol||!t.url.startsWith("http:")))return!1;const i=ke();if("html5/video/webm"===e&&i.isSafari)return!1;if("html5/application/vnd.apple.mpegurl"===e){if(document.createElement("video").canPlayType("application/vnd.apple.mpegurl")){const e=this.getAndroidVersion();return!(e&&e<7)&&["video","audio"]}return!1}const r=[],s=document.createElement("video"),a=e.replace("html5/",""),o={};for(const e of n.meta.tracks)"meta"!==e.type?(o[e.type]||(o[e.type]=[]),o[e.type].push(e)):"subtitle"===e.codec&&r.push("subtitle");for(const[e,t]of Object.entries(o)){let n=!1;for(const e of t){let t="";t=e.codecstring?e.codecstring:this.translateCodecForHtml5(e);const i=`${a};codecs="${t}"`;if("video/webm"===a){if(""!==s.canPlayType(a)){n=!0;break}}else if(""!==s.canPlayType(i)){n=!0;break}}n&&r.push(e)}return r.length>0&&r}translateCodecForHtml5(e){if(e.codecstring)return e.codecstring;const t=t=>!e.init||t>=e.init.length?"00":("0"+e.init.charCodeAt(t).toString(16)).slice(-2);switch(e.codec){case"AAC":return"mp4a.40.2";case"MP3":return"mp4a.40.34";case"AC3":return"ec-3";case"H264":return`avc1.${t(1)}${t(2)}${t(3)}`;case"HEVC":return`hev1.${t(1)}${t(6)}${t(7)}${t(8)}${t(9)}${t(10)}${t(11)}${t(12)}`;case"VP8":return"vp8";case"VP9":return"vp09.00.10.08";case"AV1":return"av01.0.04M.08";case"Opus":return"opus";default:return e.codec.toLowerCase()}}getAndroidVersion(){const e=navigator.userAgent.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);if(!e)return null;return parseInt(e[1],10)+(e[2]?parseInt(e[2],10):0)/10}async initialize(e,t,n,i){this.destroyed=!1,this.container=e,this.currentSourceUrl=t.url,this.currentMimeType=t.type,this.isMP3Source="html5/audio/mp3"===t.type,e.classList.add("fw-player-container");const r=document.createElement("video");r.classList.add("fw-player-video"),r.setAttribute("playsinline",""),r.setAttribute("crossorigin","anonymous"),n.autoplay&&(r.autoplay=!0),n.muted&&(r.muted=!0),r.controls=!0===n.controls,n.loop&&(r.loop=!0),n.poster&&(r.poster=n.poster),this.videoElement=r,e.appendChild(r),this.setupVideoEventListeners(r,n);const s="live"===i?.type;"whep"!==t.type&&s?(this.setupLiveDurationProxy(r),this.setupAutoRecovery(r),this.liveSeekEnabled=!0,this.liveSeekOffsetSec=0,this.liveSeekBaseUrl=this.stripStartUnixParam(t.url)):(this.liveSeekEnabled=!1,this.liveSeekOffsetSec=0,this.liveSeekBaseUrl=null);try{const e=t.subtitles;Array.isArray(e)&&e.forEach((e,t)=>{const n=document.createElement("track");n.kind="subtitles",n.label=e.label,n.srclang=e.lang,n.src=e.src,0===t&&(n.default=!0),r.appendChild(n)})}catch{}try{if("whep"===t.type){const e=t,n=e&&e.headers?e.headers:{},i=e&&e.iceServers?e.iceServers:[];return this.reconnectEnabled=!(!e||!e.reconnect),this.currentWhepUrl=t.url,this.currentHeaders=n,this.currentIceServers=i,await this.startWhep(r,t.url,n,i),r}return r.src=t.url,n.autoplay&&r.play().catch(e=>console.warn("HTML5 autoplay failed:",e)),r}catch(e){throw this.emit("error",e.message||String(e)),e}}setupLiveDurationProxy(e){this.liveDurationProxy=new Rt(e,{constrainSeek:!0})}setupAutoRecovery(e){e.addEventListener("pause",()=>{this.destroyed||(this.pausedAt=Date.now())}),e.addEventListener("play",()=>{if(!this.destroyed){if(this.pausedAt&&this.liveDurationProxy?.isLive()){const t=Date.now()-this.pausedAt;t>sn.PAUSE_RECOVERY_THRESHOLD&&(console.debug("[NativePlayer] Auto-recovery: reloading stream after",t,"ms pause"),e.load())}this.pausedAt=null}})}setSource(e){this.videoElement&&(this.currentSourceUrl=e,this.liveSeekEnabled&&(this.liveSeekBaseUrl=this.stripStartUnixParam(e),this.liveSeekOffsetSec=0),this.videoElement.src=e,this.videoElement.load())}seek(e){if(this.isMP3Source)console.warn("[NativePlayer] Seek not supported for MP3 files");else{if(this.liveSeekEnabled&&this.liveDurationProxy?.isLive()){let t=e-this.getDuration();return t>0&&(t=0),void this.scheduleLiveSeekOffset(t,!1)}this.liveDurationProxy?.isLive()?this.liveDurationProxy.seek(e):this.videoElement&&(this.videoElement.currentTime=e)}}getDuration(){if(this.liveSeekEnabled&&this.liveDurationProxy?.isLive()){const e=this.liveDurationProxy.getDuration(),t=this.pendingLiveSeekOffset??this.liveSeekOffsetSec;return Math.max(0,e-t)}return this.liveDurationProxy?this.liveDurationProxy.getDuration():this.videoElement?.duration??0}getCurrentTime(){if(this.liveSeekEnabled&&this.liveDurationProxy?.isLive()&&this.videoElement){const e=this.pendingLiveSeekOffset??this.liveSeekOffsetSec;return Math.max(0,this.videoElement.currentTime-e)}return this.videoElement?.currentTime??0}getSeekableRange(){if(!this.liveSeekEnabled||!this.liveDurationProxy?.isLive()||!this.videoElement)return null;const e=this.videoElement.buffered;if(!e||0===e.length)return null;const t=this.pendingLiveSeekOffset??this.liveSeekOffsetSec,n=e.start(0)-t,i=e.end(e.length-1)-t;return Number.isFinite(n)&&Number.isFinite(i)?{start:Math.max(0,n),end:Math.max(0,i)}:null}getBufferedRanges(){const e=this.videoElement;if(!e)return null;const t=e.buffered;if(!this.liveSeekEnabled||!this.liveDurationProxy?.isLive())return t;if(!t||0===t.length)return t;const n=this.pendingLiveSeekOffset??this.liveSeekOffsetSec,i=[];for(let e=0;e<t.length;e++){const r=t.start(e)-n,s=t.end(e)-n;Number.isFinite(r)&&Number.isFinite(s)&&i.push([Math.max(0,r),Math.max(0,s)])}return this.createTimeRanges(i)}isLive(){return this.liveDurationProxy?.isLive()??!1}getLiveLatency(){return this.liveDurationProxy?.getLatency()??0}jumpToLive(){this.liveSeekEnabled&&this.liveDurationProxy?.isLive()?this.scheduleLiveSeekOffset(0,!0):this.liveDurationProxy?.jumpToLive()}async destroy(){if(this.destroyed=!0,this.liveDurationProxy&&(this.liveDurationProxy.destroy(),this.liveDurationProxy=null),this.reconnectTimer){try{clearTimeout(this.reconnectTimer)}catch{}this.reconnectTimer=null}if(this.sessionUrl){const e=this.sessionUrl;this.sessionUrl=null,fetch(e,{method:"DELETE"}).catch(()=>{})}if(this.peerConnection){try{this.peerConnection.close()}catch{}this.peerConnection=null}if(this.videoElement){try{this.videoElement.srcObject=null}catch{}if(this.videoElement.pause(),this.videoElement.removeAttribute("src"),this.container)try{this.container.removeChild(this.videoElement)}catch{}}this.videoElement=null,this.container=null,this.pausedAt=null,this.currentSourceUrl=null,this.currentMimeType=null,this.liveSeekEnabled=!1,this.liveSeekOffsetSec=0,this.liveSeekBaseUrl=null,this.liveSeekListeners.forEach(e=>e()),this.liveSeekListeners=[],this.liveSeekTimer&&(clearTimeout(this.liveSeekTimer),this.liveSeekTimer=null),this.pendingLiveSeekOffset=null,this.listeners.clear()}stripStartUnixParam(e){const t=Dt(e);return delete t.startunix,xt(Lt(e),t)}buildLiveSeekUrl(e){const t=this.liveSeekBaseUrl||this.currentSourceUrl||"";if(!t)return"";if(!e||e>=0)return this.stripStartUnixParam(t);const n=Dt(t);return n.startunix=String(e),xt(Lt(t),n)}applyLiveSeekOffset(e){if(!this.videoElement)return;const t=Math.min(0,e);if(Math.abs(t-this.liveSeekOffsetSec)<.05)return;this.liveSeekOffsetSec=t;const n=this.buildLiveSeekUrl(t);if(!n)return;const i=!this.videoElement.paused;this.currentSourceUrl=n,this.videoElement.src=n,this.videoElement.load(),i&&this.videoElement.play().catch(()=>{})}createTimeRanges(e){return{length:e.length,start(t){if(t<0||t>=e.length)throw new DOMException("Index out of bounds");return e[t][0]},end(t){if(t<0||t>=e.length)throw new DOMException("Index out of bounds");return e[t][1]}}}scheduleLiveSeekOffset(e,t){const n=Math.min(0,e);if(t)return this.liveSeekTimer&&(clearTimeout(this.liveSeekTimer),this.liveSeekTimer=null),this.pendingLiveSeekOffset=null,void this.applyLiveSeekOffset(n);this.pendingLiveSeekOffset=n,this.liveSeekTimer&&clearTimeout(this.liveSeekTimer),this.liveSeekTimer=setTimeout(()=>{if(this.liveSeekTimer=null,null!==this.pendingLiveSeekOffset){const e=this.pendingLiveSeekOffset;this.pendingLiveSeekOffset=null,this.applyLiveSeekOffset(e)}},sn.LIVE_SEEK_DEBOUNCE_MS)}async getStats(){if(this.peerConnection)try{const e=await this.peerConnection.getStats(),t=Date.now(),n={type:"webrtc",timestamp:t};return e.forEach(e=>{if("inbound-rtp"===e.type){const i=e.packetsReceived>0?e.packetsLost/(e.packetsReceived+e.packetsLost)*100:0;let r=0;if(this.lastInboundStats&&this.lastInboundStats[e.kind]){const n=this.lastInboundStats[e.kind],i=(t-(this.lastInboundStats.timestamp||0))/1e3;if(i>0){const t=e.bytesReceived-(n.bytesReceived||0);r=Math.round(8*t/i)}}if("video"===e.kind){const t=e.framesDecoded>0?e.framesDropped/(e.framesDecoded+e.framesDropped)*100:0;n.video={bytesReceived:e.bytesReceived||0,packetsReceived:e.packetsReceived||0,packetsLost:e.packetsLost||0,packetLossRate:i,jitter:1e3*(e.jitter||0),framesDecoded:e.framesDecoded||0,framesDropped:e.framesDropped||0,frameDropRate:t,frameWidth:e.frameWidth||0,frameHeight:e.frameHeight||0,framesPerSecond:e.framesPerSecond||0,bitrate:r,jitterBufferDelay:e.jitterBufferDelay&&e.jitterBufferEmittedCount?e.jitterBufferDelay/e.jitterBufferEmittedCount*1e3:0}}"audio"===e.kind&&(n.audio={bytesReceived:e.bytesReceived||0,packetsReceived:e.packetsReceived||0,packetsLost:e.packetsLost||0,packetLossRate:i,jitter:1e3*(e.jitter||0),bitrate:r})}"candidate-pair"===e.type&&e.nominated&&(n.network={rtt:e.currentRoundTripTime?1e3*e.currentRoundTripTime:0,availableOutgoingBitrate:e.availableOutgoingBitrate||0,availableIncomingBitrate:e.availableIncomingBitrate||0,bytesSent:e.bytesSent||0,bytesReceived:e.bytesReceived||0})}),this.lastInboundStats={video:n.video?{bytesReceived:n.video.bytesReceived}:void 0,audio:n.audio?{bytesReceived:n.audio.bytesReceived}:void 0,timestamp:t},n}catch{return}}async getLatency(){const e=await this.getStats();if(e)return{estimatedMs:e.video?.jitterBufferDelay||0,jitterBufferMs:e.video?.jitterBufferDelay||0,rttMs:e.network?.rtt||0}}async startWhep(e,t,n,i){if(this.sessionUrl){try{fetch(this.sessionUrl,{method:"DELETE"}).catch(()=>{})}catch{}this.sessionUrl=null}const r=new RTCPeerConnection({iceServers:i});this.peerConnection=r,r.ontrack=t=>{this.destroyed||e&&t.streams[0]&&(e.srcObject=t.streams[0])},r.oniceconnectionstatechange=()=>{if(this.destroyed)return;const t=r.iceConnectionState;if(("failed"===t||"disconnected"===t)&&(this.emit("error","WHEP connection failed"),this.reconnectEnabled&&this.reconnectAttempts<this.maxReconnectAttempts&&this.currentWhepUrl)){const t=Math.min(5e3,500*Math.pow(2,this.reconnectAttempts));this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{this.destroyed||this.startWhep(e,this.currentWhepUrl,this.currentHeaders||{},this.currentIceServers||[])},t)}"connected"===t&&(this.reconnectAttempts=0)},r.addTransceiver("video",{direction:"recvonly"}),r.addTransceiver("audio",{direction:"recvonly"});const s=await r.createOffer();await r.setLocalDescription(s);const a={"Content-Type":"application/sdp"};for(const e in n)a[e]=n[e];const o=await fetch(t,{method:"POST",headers:a,body:s.sdp||""});if(!o.ok)throw new Error(`WHEP request failed: ${o.status}`);const l=await o.text();await r.setRemoteDescription(new RTCSessionDescription({type:"answer",sdp:l}));const u=o.headers.get("Location");if(u)try{this.sessionUrl=new URL(u,t).href}catch{this.sessionUrl=u}else this.sessionUrl=null}}sn.PAUSE_RECOVERY_THRESHOLD=5e3,sn.LIVE_SEEK_DEBOUNCE_MS=300;var an=Object.freeze({__proto__:null,DirectPlaybackPlayerImpl:sn,NativePlayerImpl:sn});function on(e){if(e.byteLength<12)throw new Error(`Invalid chunk: expected at least 12 bytes, got ${e.byteLength}`);const t=new DataView(e,0,12),n=t.getUint8(0),i=function(e){switch(e){case 1:return"key";case 2:return"init";default:return"delta"}}(t.getUint8(1)),r=t.getBigUint64(2,!1);return{trackIndex:n,type:i,timestamp:Number(r),offset:t.getInt16(10,!1),data:new Uint8Array(e.slice(12))}}function ln(e){return 1e3*(e.timestamp+e.offset)}function un(e){return"init"===e.type}const dn={debug:!1,maxReconnectAttempts:5,reconnectDelayMs:1e3,maxReconnectDelayMs:3e4,connectionTimeoutMs:5e3};class cn{constructor(){this.delays=[],this.pending=new Map,this.maxSamples=3}startTiming(e){this.pending.set(e,performance.now())}completeTiming(e){const t=this.pending.get(e);if(void 0===t)return null;this.pending.delete(e);const n=performance.now()-t;return this.delays.push(n),this.delays.length>this.maxSamples&&this.delays.shift(),n}getAverageDelay(){return 0===this.delays.length?0:this.delays.reduce((e,t)=>e+t,0)/this.delays.length}clear(){this.pending.clear(),this.delays=[]}}class hn{constructor(e,t={}){this.ws=null,this.state="disconnected",this.reconnectAttempts=0,this.reconnectTimer=null,this.connectionTimer=null,this.listeners=new Map,this.serverDelay=new cn,this.intentionalClose=!1,this.lastDeltaLogTime={},this.deltaLogInterval=5e3,this.url=e,this.options={...dn,...t}}connect(){return new Promise((e,t)=>{if(this.ws&&"connected"===this.state)e();else{this.intentionalClose=!1,this.setState("connecting");try{this.ws=new WebSocket(this.url),this.ws.binaryType="arraybuffer",this.connectionTimer=setTimeout(()=>{"connecting"===this.state&&(this.log("Connection timeout"),this.ws?.close(),t(new Error("Connection timeout")))},this.options.connectionTimeoutMs),this.ws.onopen=()=>{this.clearConnectionTimer(),this.setState("connected"),this.reconnectAttempts=0,this.log("Connected"),e()},this.ws.onclose=e=>{this.clearConnectionTimer(),this.log(`Disconnected: ${e.code} ${e.reason}`),!this.intentionalClose&&this.shouldReconnect()?this.scheduleReconnect():this.setState("disconnected")},this.ws.onerror=e=>{this.log("WebSocket error"),this.emit("error",new Error("WebSocket error"))},this.ws.onmessage=e=>{this.handleMessage(e)}}catch(e){this.setState("error"),t(e)}}})}disconnect(){if(this.intentionalClose=!0,this.clearReconnectTimer(),this.clearConnectionTimer(),this.ws){try{this.send({type:"hold"})}catch{}this.ws.close(),this.ws=null}this.serverDelay.clear(),this.setState("disconnected")}send(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)return this.log(`Cannot send ${e.type}: not connected`),!1;["seek","set_speed","request_codec_data"].includes(e.type)&&this.serverDelay.startTiming(e.type);const t=JSON.stringify(e);return this.log(`Sending: ${t}`),this.ws.send(t),!0}play(){return this.send({type:"play"})}hold(){return this.send({type:"hold"})}seek(e,t){const n={type:"seek",seek_time:Math.round(e)};return void 0!==t&&(n.ff_add=Math.round(t)),this.send(n)}setSpeed(e){return this.send({type:"set_speed",play_rate:e})}requestCodecData(e){return e&&e.length>0?this.send({type:"request_codec_data",supported_combinations:e}):this.send({type:"request_codec_data"})}fastForward(e){return this.send({type:"fast_forward",ff_add:Math.round(e)})}getState(){return this.state}getServerDelay(){return this.serverDelay.getAverageDelay()}isConnected(){return"connected"===this.state&&this.ws?.readyState===WebSocket.OPEN}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){const n=this.listeners.get(e);if(n)for(const i of n)try{i(t)}catch(t){console.error(`Error in ${e} listener:`,t)}}handleMessage(e){e.data instanceof ArrayBuffer?this.handleBinaryMessage(e.data):"string"==typeof e.data&&this.handleControlMessage(e.data)}handleBinaryMessage(e){try{const t=on(e);if(this.options.debug)if("delta"!==t.type)this.log(function(e){const t=((e.timestamp+e.offset)/1e3).toFixed(3);return`[Track ${e.trackIndex}] ${e.type.toUpperCase()} @ ${t}s (${e.data.byteLength} bytes)`}(t));else{const e=performance.now();e-(this.lastDeltaLogTime[t.trackIndex]||0)>this.deltaLogInterval&&(this.lastDeltaLogTime[t.trackIndex]=e)}this.emit("chunk",t)}catch(e){this.log(`Failed to parse binary chunk: ${e}`)}}handleControlMessage(e){try{const t=JSON.parse(e),n="data"in t?t.data:t,i={type:t.type,...n};switch(this.log(`Received: ${i.type}`),"codec_data"===i.type?this.serverDelay.completeTiming("request_codec_data"):"on_time"===i.type&&(this.serverDelay.completeTiming("seek"),this.serverDelay.completeTiming("set_speed")),i.type){case"codec_data":this.emit("codecdata",i);break;case"info":this.log(`Info message tracks: ${JSON.stringify(Object.keys(i.meta?.tracks??{}))}`),this.emit("info",i);break;case"on_time":i.tracks?.length&&this.log(`on_time tracks: ${JSON.stringify(i.tracks)}`),this.emit("ontime",i);break;case"tracks":this.emit("tracks",i.tracks);break;case"on_stop":this.emit("stop",void 0);break;case"error":this.emit("error",new Error(i.message));break;case"pause":case"set_speed":break;default:this.log(`Unknown message type: ${i.type}`)}}catch(e){this.log(`Failed to parse control message: ${e}`)}}setState(e){this.state!==e&&(this.state=e,this.emit("statechange",e))}shouldReconnect(){return!this.intentionalClose&&(0===this.options.maxReconnectAttempts||this.reconnectAttempts<this.options.maxReconnectAttempts)}scheduleReconnect(){this.setState("reconnecting"),this.reconnectAttempts++;const e=this.options.reconnectDelayMs,t=this.options.maxReconnectDelayMs,n=Math.min(e*Math.pow(2,this.reconnectAttempts-1),t),i=.2*n*Math.random();this.log(`Reconnecting in ${Math.round(n+i)}ms (attempt ${this.reconnectAttempts})`),this.reconnectTimer=setTimeout(()=>{this.connect().catch(e=>{this.log(`Reconnect failed: ${e.message}`),this.shouldReconnect()?this.scheduleReconnect():(this.setState("error"),this.emit("error",new Error("Max reconnection attempts exceeded")))})},n+i)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}clearConnectionTimer(){this.connectionTimer&&(clearTimeout(this.connectionTimer),this.connectionTimer=null)}log(e){this.options.debug&&console.log(`[WebCodecsWS] ${e}`)}}class fn{constructor(e={}){this.chunks=[],this.speed=1,this.lastPeakTime=0,this.currentPeak=0,this.peaks=[],this.maxJitter=e.initialJitter??120,this.chunkWindowSize=e.chunkWindowSize??8,this.peakWindowSize=e.peakWindowSize??8}addChunk(e,t=performance.now()){this.chunks.push({receiveTime:t,mediaTime:e}),this.chunks.length>this.chunkWindowSize&&this.chunks.shift();const n=this.calculateJitter();n>this.currentPeak&&(this.currentPeak=n);const i=performance.now();i>this.lastPeakTime+1e3&&(this.recordPeak(),this.lastPeakTime=i)}calculateJitter(){if(this.chunks.length<=1)return 0;if(0===this.speed||!isFinite(this.speed))return 0;const e=this.chunks[0],t=this.chunks[this.chunks.length-1],n=t.receiveTime-e.receiveTime,i=(t.mediaTime-e.mediaTime)/this.speed-n;return Math.max(0,i)}recordPeak(){if(this.peaks.push(this.currentPeak),this.peaks.length>this.peakWindowSize&&this.peaks.shift(),this.currentPeak=0,this.peaks.length>0){const e=Math.max(...this.peaks),t=this.peaks.reduce((e,t)=>e+t,0)/this.peaks.length;let n=(t+2*e)/3+1;this.maxJitter>n+500&&(n=this.maxJitter-500),this.maxJitter=(this.maxJitter+n)/2}}get(){return this.maxJitter}getState(){return{current:this.calculateJitter(),peak:this.currentPeak,weighted:this.maxJitter}}setSpeed(e){const t="auto"===e?1:e;t!==this.speed&&(this.speed=t,this.reset())}reset(){this.chunks=[],this.currentPeak=0}fullReset(){this.reset(),this.peaks=[],this.maxJitter=120,this.lastPeakTime=0}}class pn{constructor(e={}){this.trackers=new Map,this.globalSpeed=1,this.options=e}addChunk(e,t,n){let i=this.trackers.get(e);i||(i=new fn(this.options),i.setSpeed(this.globalSpeed),this.trackers.set(e,i)),i.addChunk(t,n)}getMax(){let e=0;for(const t of this.trackers.values())e=Math.max(e,t.get());return e}getForTrack(e){return this.trackers.get(e)?.get()??120}setSpeed(e){this.globalSpeed="auto"===e?1:e;for(const t of this.trackers.values())t.setSpeed(e)}reset(){for(const e of this.trackers.values())e.reset()}removeTrack(e){this.trackers.delete(e)}clear(){this.trackers.clear()}}const gn={"ultra-low":{name:"Ultra Low Latency",keepAway:50,jitterMultiplier:1,speedUpThreshold:1.5,speedDownThreshold:.5,maxSpeedUp:1.08,minSpeedDown:.95,audioBufferMs:100,optimizeForLatency:!0},low:{name:"Low Latency",keepAway:100,jitterMultiplier:1.2,speedUpThreshold:2,speedDownThreshold:.6,maxSpeedUp:1.05,minSpeedDown:.98,audioBufferMs:150,optimizeForLatency:!0},balanced:{name:"Balanced",keepAway:200,jitterMultiplier:1.5,speedUpThreshold:2.5,speedDownThreshold:.5,maxSpeedUp:1.03,minSpeedDown:.97,audioBufferMs:200,optimizeForLatency:!1},quality:{name:"Quality Priority",keepAway:500,jitterMultiplier:2,speedUpThreshold:3,speedDownThreshold:.4,maxSpeedUp:1.02,minSpeedDown:.98,audioBufferMs:300,optimizeForLatency:!1}};function mn(e){return e&&e in gn?gn[e]:gn.low}function yn(e,t){const n="string"==typeof e?mn(e):e;return t?{...n,...t,name:t.name??`${n.name} (Custom)`}:n}let bn=class{constructor(e={}){this.listeners=new Map,this.mainSpeed=1,this.tweakSpeed=1,this.lastBufferCheck=0,this.bufferCheckInterval=100,this.serverDelays=[],this.maxServerDelaysSamples=3,this.lastLiveCatchup=0,this.liveCatchupCooldown=2e3,this.liveCatchupThresholdMs=5e3,this.liveCatchupRequestMs=5e3,this.serverTime=0,this.localTimeAtServerUpdate=0,this.seekState={active:!1,id:0,targetTime:0,startedAt:0},this.isLive=!0,this.profile=e.profile??mn("low"),this.isLive=e.isLive??!0,this.onSpeedChange=e.onSpeedChange,this.onFastForwardRequest=e.onFastForwardRequest,this.jitterTracker=new pn({initialJitter:120})}setProfile(e){this.profile=e}setLive(e){this.isLive=e}recordChunkArrival(e,t){this.jitterTracker.addChunk(e,t)}updateServerTime(e){this.serverTime=e,this.localTimeAtServerUpdate=performance.now()}recordServerDelay(e){this.serverDelays.push(e),this.serverDelays.length>this.maxServerDelaysSamples&&this.serverDelays.shift()}getServerDelay(){return 0===this.serverDelays.length?0:this.serverDelays.reduce((e,t)=>e+t,0)/this.serverDelays.length}getEstimatedServerTime(){const e=(performance.now()-this.localTimeAtServerUpdate)/1e3;return this.serverTime+e*this.getCombinedSpeed()}getDesiredBuffer(){const e="undefined"!=typeof navigator&&/Chrome/.test(navigator.userAgent)&&!/Edge|Edg/.test(navigator.userAgent)?1e3:100,t=this.getServerDelay(),n=this.jitterTracker.getMax()*this.profile.jitterMultiplier,i=Math.max(e+t,2*t)+n;return this.isLive?i:i+2e3}evaluateBuffer(e){const t=performance.now();if(t-this.lastBufferCheck<this.bufferCheckInterval)return this.getState(e);this.lastBufferCheck=t;const n=this.getDesiredBuffer(),i=e/n,r=this.jitterTracker.getMax();return this.isLive&&e<this.liveCatchupThresholdMs&&e>Math.max(1.1*r,r+250)&&e-n<1e3&&t-this.lastLiveCatchup>this.liveCatchupCooldown&&(this.lastLiveCatchup=t,this.requestFastForward(this.liveCatchupRequestMs),this.emit("livecatchup",{fastForwardMs:this.liveCatchupRequestMs})),i>this.profile.speedUpThreshold&&this.isLive?this.setTweakSpeed(this.profile.maxSpeedUp,"catchup"):i<this.profile.speedDownThreshold?(this.setTweakSpeed(this.profile.minSpeedDown,"slowdown"),i<.3&&this.isLive&&(this.requestFastForward(n-e),this.emit("underrun",void 0)),this.emit("bufferlow",{current:e,desired:n})):1!==this.tweakSpeed&&this.setTweakSpeed(1,"normal"),this.getState(e)}getState(e){const t=e??0,n=this.getDesiredBuffer();return{buffer:{current:t,desired:n,ratio:n>0?t/n:1},jitter:this.jitterTracker.getMax()>0?{current:0,peak:0,weighted:this.jitterTracker.getMax()}:{current:0,peak:0,weighted:0},playbackSpeed:this.getCombinedSpeed(),serverTime:this.serverTime,serverDelay:this.getServerDelay(),avOffset:0}}getCombinedSpeed(){return this.mainSpeed*this.tweakSpeed}setMainSpeed(e){this.mainSpeed=e,this.jitterTracker.setSpeed(e),this.notifySpeedChange()}setTweakSpeed(e,t){this.tweakSpeed!==e&&(this.tweakSpeed=e,this.notifySpeedChange(),this.emit("speedchange",{speed:this.getCombinedSpeed(),reason:t}))}notifySpeedChange(){this.onSpeedChange?.(this.mainSpeed,this.tweakSpeed)}requestFastForward(e){this.onFastForwardRequest?.(Math.max(0,e))}startSeek(e){return this.seekState.id++,this.seekState={active:!0,id:this.seekState.id,targetTime:e,startedAt:performance.now()},this.jitterTracker.reset(),this.emit("seekstart",{seekId:this.seekState.id,time:e}),this.seekState.id}isSeekActive(e){return this.seekState.active&&this.seekState.id===e}completeSeek(e){this.seekState.id===e&&(this.seekState.active=!1,this.emit("seekcomplete",{seekId:e}))}cancelSeek(){this.seekState.active&&(this.seekState.active=!1)}isSeeking(){return this.seekState.active}addTrack(e,t){}removeTrack(e){this.jitterTracker.removeTrack(e)}reset(){this.mainSpeed=1,this.tweakSpeed=1,this.serverDelays=[],this.serverTime=0,this.localTimeAtServerUpdate=0,this.lastLiveCatchup=0,this.jitterTracker.reset(),this.seekState={active:!1,id:0,targetTime:0,startedAt:0}}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){const n=this.listeners.get(e);if(n)for(const i of n)try{i(t)}catch(t){console.error(`Error in ${e} listener:`,t)}}};function vn(){return void 0!==globalThis.MediaStreamTrackGenerator}class Tn{constructor(){this.closed=!1,this.canvas=document.createElement("canvas"),this.canvas.width=1920,this.canvas.height=1080;const e=this.canvas.getContext("2d",{desynchronized:!0});if(!e)throw new Error("Failed to create canvas 2D context");this.ctx=e;const t=this.canvas.captureStream().getVideoTracks();if(0===t.length)throw new Error("Failed to capture stream from canvas");this.track=t[0],this._writable=new WritableStream({write:e=>{this.closed||(this.canvas.width===e.displayWidth&&this.canvas.height===e.displayHeight||(this.canvas.width=e.displayWidth,this.canvas.height=e.displayHeight),this.ctx.drawImage(e,0,0,this.canvas.width,this.canvas.height)),e.close()},close:()=>{this.close()},abort:()=>{this.close()}})}get writable(){return this._writable}getTrack(){return this.track}close(){this.closed||(this.closed=!0,this.track.stop())}}class En{constructor(){this.workletNode=null,this.closed=!1,this.initialized=!1,this.sampleBuffer=[],this.maxBufferChunks=20,this.audioContext=new AudioContext({latencyHint:"interactive"}),this.destination=this.audioContext.createMediaStreamDestination();const e=this.destination.stream.getAudioTracks();if(0===e.length)throw new Error("Failed to create audio destination");this.track=e[0],this.initPromise=this.initializeWorklet(),this._writable=new WritableStream({write:e=>{if(this.closed)return void e.close();const t=this.audioDataToSamples(e);e.close(),this.sampleBuffer.push(t),this.sampleBuffer.length>this.maxBufferChunks&&this.sampleBuffer.shift(),this.feedSamples()},close:()=>{this.close()},abort:()=>{this.close()}})}async initializeWorklet(){const e=new Blob(["\n class SyncedAudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.ringBuffer = [];\n this.maxBufferSize = 10;\n\n this.port.onmessage = (e) => {\n if (e.data.type === 'samples') {\n // Add samples to ring buffer\n this.ringBuffer.push(e.data.samples);\n if (this.ringBuffer.length > this.maxBufferSize) {\n this.ringBuffer.shift(); // Drop oldest\n }\n }\n };\n }\n\n process(inputs, outputs, parameters) {\n const output = outputs[0];\n if (!output || output.length === 0) return true;\n\n const channel = output[0];\n\n if (this.ringBuffer.length > 0) {\n const samples = this.ringBuffer.shift();\n const len = Math.min(samples.length, channel.length);\n for (let i = 0; i < len; i++) {\n channel[i] = samples[i];\n }\n // Fill remainder with last sample (smooth transition)\n for (let i = len; i < channel.length; i++) {\n channel[i] = samples[len - 1] || 0;\n }\n } else {\n // No samples - output silence\n channel.fill(0);\n }\n\n return true;\n }\n }\n\n registerProcessor('synced-audio-processor', SyncedAudioProcessor);\n "],{type:"application/javascript"}),t=URL.createObjectURL(e);try{await this.audioContext.audioWorklet.addModule(t),this.workletNode=new AudioWorkletNode(this.audioContext,"synced-audio-processor"),this.workletNode.connect(this.destination),this.initialized=!0}finally{URL.revokeObjectURL(t)}}audioDataToSamples(e){const t=e.numberOfChannels,n=e.numberOfFrames,i=new Float32Array(n*t);if(e.copyTo(i,{planeIndex:0}),1===t)return i;const r=new Float32Array(n);for(let e=0;e<n;e++){let n=0;for(let r=0;r<t;r++)n+=i[e*t+r];r[e]=n/t}return r}feedSamples(){if(!this.initialized||!this.workletNode||0===this.sampleBuffer.length)return;const e=this.sampleBuffer.shift();e&&this.workletNode.port.postMessage({type:"samples",samples:e},{transfer:[e.buffer]})}get writable(){return this._writable}getTrack(){return this.track}async waitForInit(){await this.initPromise}close(){this.closed||(this.closed=!0,this.track.stop(),this.workletNode?.disconnect(),this.audioContext.close(),this.sampleBuffer=[])}}function _n(e){const t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return t}function Sn(e){return{length:e.length,start(t){if(t<0||t>=e.length)throw new DOMException("Index out of bounds");return e[t][0]},end(t){if(t<0||t>=e.length)throw new DOMException("Index out of bounds");return e[t][1]}}}class wn extends Ne{constructor(){super(...arguments),this.capability={name:"WebCodecs Player",shortname:"webcodecs",priority:0,mimes:["ws/video/raw","wss/video/raw","ws/video/h264","wss/video/h264"]},this.wsController=null,this.syncController=null,this.worker=null,this.mediaStream=null,this.container=null,this.pipelines=new Map,this.tracks=[],this.tracksByIndex=new Map,this.queuedInitData=new Map,this.queuedChunks=new Map,this.isDestroyed=!1,this.debugging=!1,this.verboseDebugging=!1,this.streamType="live",this.payloadFormat="avcc",this.workerUidCounter=0,this.workerListeners=new Map,this._duration=1/0,this._currentTime=0,this._bufferMs=0,this._avDrift=0,this._frameCallbackId=null,this._statsInterval=null,this._framesDropped=0,this._framesDecoded=0,this._bytesReceived=0,this._messagesReceived=0,this._isPaused=!0,this._suppressPlayPauseSync=!1,this._pendingStepPause=!1,this._stepPauseTimeout=null}static getCodecCacheKey(e){const t=e.codecstring??e.codec?.toLowerCase()??"",n=e.init??"";return`${t}|${n.length>0?`${n.length}_${n.charCodeAt(0)}_${n.charCodeAt(n.length-1)}`:""}`}static async isTrackSupported(e){const t=wn.getCodecCacheKey(e);if(wn.codecCache.has(t)){return{supported:wn.codecCache.get(t),config:{codec:e.codecstring??e.codec}}}const n={codec:e.codecstring??(e.codec??"").toLowerCase()};let i;e.init&&""!==e.init&&(n.description=_n(e.init));try{switch(e.type){case"video":if("JPEG"===e.codec)if("ImageDecoder"in window){i={supported:await window.ImageDecoder.isTypeSupported("image/jpeg"),config:{codec:"image/jpeg"}}}else i={supported:!1,config:{codec:"image/jpeg"}};else{const e=await VideoDecoder.isConfigSupported(n);i={supported:!0===e.supported,config:e.config}}break;case"audio":{n.numberOfChannels=e.channels??2,n.sampleRate=e.rate??48e3;const t=await AudioDecoder.isConfigSupported(n);i={supported:!0===t.supported,config:t.config};break}default:i={supported:!1,config:n}}}catch(t){console.warn(`[WebCodecs] isConfigSupported failed for ${e.codec}:`,t),i={supported:!1,config:n}}return wn.codecCache.set(t,i.supported),i}static async validateTracks(e){const t=new Set,n=e.filter(e=>"video"===e.type||"audio"===e.type).map(async e=>{const n=await wn.isTrackSupported(e);return n.supported&&t.add(e.type),{track:e,supported:n.supported}}),i=await Promise.all(n);for(const{track:e,supported:t}of i)console.debug(`[WebCodecs] Track ${e.idx} (${e.type} ${e.codec}): ${t?"supported":"UNSUPPORTED"}`);return Array.from(t)}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(!("WebSocket"in window))return!1;if(!("Worker"in window))return!1;if(!("VideoDecoder"in window)||!("AudioDecoder"in window))return!1;const i=new URL(t.url.replace(/^ws/,"http"),location.href);if("https:"===location.protocol&&"http:"===i.protocol)return!1;const r={};for(const e of n.meta.tracks)if("video"===e.type||"audio"===e.type){const t=wn.getCodecCacheKey(e);wn.codecCache.has(t)?wn.codecCache.get(t)&&(r[e.type]=!0):r[e.type]=!0}else"meta"===e.type&&"subtitle"===e.codec&&(r.subtitle=!0);return e.includes("video/h264")&&delete r.audio,0!==Object.keys(r).length&&Object.keys(r)}async initialize(e,t,n,i){if(this.tracksByIndex.clear(),this.pipelines.clear(),this.tracks=[],this.queuedInitData.clear(),this.queuedChunks.clear(),this.isDestroyed=!1,this._duration=1/0,this._currentTime=0,this._bufferMs=0,this._avDrift=0,this._framesDropped=0,this._framesDecoded=0,this._bytesReceived=0,this._messagesReceived=0,this.payloadFormat=t.type?.includes("h264")?"annexb":"avcc","annexb"===this.payloadFormat&&this.log("Using Annex B payload format (ws/video/h264)"),this.container=e,e.classList.add("fw-player-container"),i?.meta?.tracks){this.log(`Pre-populating ${i.meta.tracks.length} tracks from streamInfo`);for(const e of i.meta.tracks)if(void 0!==e.idx){const t={idx:e.idx,type:e.type,codec:e.codec,codecstring:e.codecstring,init:e.init,width:e.width,height:e.height,fpks:e.fpks,channels:e.channels,rate:e.rate,size:e.size};this.tracksByIndex.set(e.idx,t),this.log(`Pre-registered track ${e.idx}: ${e.type} ${e.codec}`)}}const r=n;this.debugging=r.debug??r.devMode??!1,this.verboseDebugging=r.verboseDebug??!1,this.streamType="live"===t.type?"live":"vod";const s=yn(r.latencyProfile??function(e,t=!1){return e?t?"low":"balanced":"quality"}("live"===this.streamType),r.customLatencyProfile);this.log(`Initializing WebCodecs player with ${s.name} profile`);const a=document.createElement("video");a.classList.add("fw-player-video"),a.setAttribute("playsinline",""),a.setAttribute("crossorigin","anonymous"),n.autoplay&&(a.autoplay=!0),n.muted&&(a.muted=!0),a.controls=!0===n.controls,n.loop&&"live"!==this.streamType&&(a.loop=!0),n.poster&&(a.poster=n.poster),this.videoElement=a,e.appendChild(a),this._onVideoPlay=()=>{this._suppressPlayPauseSync||(this._isPaused=!1,this.sendToWorker({type:"frametiming",action:"setPaused",paused:!1,uid:this.workerUidCounter++}).catch(()=>{}))},this._onVideoPause=()=>{this._suppressPlayPauseSync||(this._isPaused=!0,this.sendToWorker({type:"frametiming",action:"setPaused",paused:!0,uid:this.workerUidCounter++}).catch(()=>{}))},a.addEventListener("play",this._onVideoPlay),a.addEventListener("pause",this._onVideoPause),this.mediaStream=new MediaStream,a.srcObject=this.mediaStream,await this.initializeWorker(),this.syncController=new bn({profile:s,isLive:"live"===this.streamType,onSpeedChange:(e,t)=>{this.sendToWorker({type:"frametiming",action:"setSpeed",speed:e,tweak:t,uid:this.workerUidCounter++}),this.videoElement&&(this.videoElement.playbackRate=e*t)},onFastForwardRequest:e=>{this.wsController?.fastForward(e)}}),this.wsController=new hn(t.url,{debug:this.debugging}),this.setupWebSocketHandlers();const o=new Set,l=new Set;if(i?.meta?.tracks){this.log("Validating track codecs with isConfigSupported()...");for(const e of i.meta.tracks)if("video"===e.type||"audio"===e.type){const t={idx:e.idx??0,type:e.type,codec:e.codec,codecstring:e.codecstring,init:e.init,width:e.width,height:e.height,channels:e.channels,rate:e.rate};(await wn.isTrackSupported(t)).supported?("audio"===e.type?o.add(e.codec):l.add(e.codec),this.log(`Track ${e.idx} (${e.type} ${e.codec}): SUPPORTED`)):this.log(`Track ${e.idx} (${e.type} ${e.codec}): NOT SUPPORTED`,"warn")}}0===o.size&&0===l.size&&(this.log("No validated codecs, using default codec list"),["AAC","MP3","opus","FLAC","AC3"].forEach(e=>o.add(e)),["H264","HEVC","VP8","VP9","AV1","JPEG"].forEach(e=>l.add(e)));const u=[[Array.from(o),Array.from(l)]];this.log(`Requesting codecs: audio=[${u[0][0].join(", ")}], video=[${u[0][1].join(", ")}]`);try{await this.wsController.connect(),this.wsController.requestCodecData(u)}catch(e){throw this.log(`Failed to connect: ${e}`,"error"),this.emit("error",e instanceof Error?e:new Error(String(e))),e}for(const[e,t]of this.tracksByIndex)"video"!==t.type&&"audio"!==t.type||(this.log(`Creating pipeline proactively for track ${e} (${t.type} ${t.codec})`),await this.createPipeline(t));return this.setupVideoEventListeners(a,n),this.setupFrameCallback(),this.isDestroyed=!1,a}async destroy(){if(!this.isDestroyed){this.isDestroyed=!0,this.log("Destroying WebCodecs player"),this.cancelFrameCallback(),this._statsInterval&&(clearInterval(this._statsInterval),this._statsInterval=null),this.wsController?.disconnect(),this.wsController=null;for(const e of this.pipelines.values())await this.closePipeline(e.idx,!1);if(this.pipelines.clear(),this.worker?.terminate(),this.worker=null,this.workerListeners.clear(),this.mediaStream){for(const e of this.mediaStream.getTracks())e.stop(),this.mediaStream.removeTrack(e);this.mediaStream=null}this.videoElement&&(this._onVideoPlay&&(this.videoElement.removeEventListener("play",this._onVideoPlay),this._onVideoPlay=void 0),this._onVideoPause&&(this.videoElement.removeEventListener("pause",this._onVideoPause),this._onVideoPause=void 0),this._stepPauseTimeout&&(clearTimeout(this._stepPauseTimeout),this._stepPauseTimeout=null),this._pendingStepPause=!1,this.videoElement.srcObject=null,this.videoElement.remove(),this.videoElement=null),this.syncController=null}}tryLoadWorker(e){return new Promise((t,n)=>{let i;try{i=new Worker(e,{type:"module"})}catch(e){return void n(e)}const r=()=>{clearTimeout(o),i.removeEventListener("error",s),i.removeEventListener("message",a)},s=e=>{r(),i.terminate(),n(new Error(e.message||"Worker failed to load"))},a=()=>{r(),t(i)},o=setTimeout(()=>{r(),t(i)},500);i.addEventListener("error",s),i.addEventListener("message",a)})}async initializeWorker(){const e=["/workers/decoder.worker.js"];try{e.push(new URL("../workers/decoder.worker.js",t&&"SCRIPT"===t.tagName.toUpperCase()&&t.src||new URL("fw-player.iife.js",document.baseURI).href).href)}catch{}let n=null;for(const t of e)try{this.log(`Trying worker path: ${t}`),this.worker=await this.tryLoadWorker(t),this.log(`Worker loaded from: ${t}`);break}catch(e){n=e instanceof Error?e:new Error(String(e)),this.log(`Worker path failed: ${t} - ${n.message}`,"warn")}if(!this.worker)throw new Error(`Failed to initialize WebCodecs worker. Last error: ${n?.message??"unknown"}`);this.worker.onmessage=e=>{this.handleWorkerMessage(e.data)},this.worker.onerror=e=>{this.log(`Worker error: ${e?.message??"unknown error"}`,"error"),this.emit("error",new Error(`Worker error: ${e?.message??"unknown"}`))},this.sendToWorker({type:"debugging",value:this.verboseDebugging?"verbose":this.debugging,uid:this.workerUidCounter++})}sendToWorker(e,t){return new Promise((n,i)=>{if(this.isDestroyed)return void i(new Error("Player destroyed"));if(!this.worker)return void i(new Error("Worker not initialized"));const r=e.uid;this.workerListeners.set(r,e=>{this.workerListeners.delete(r),"ack"===e.type&&"error"===e.status?i(new Error(e.error)):n(e)}),t?this.worker.postMessage(e,t):this.worker.postMessage(e)})}handleWorkerMessage(e){switch(void 0!==e.uid&&this.workerListeners.has(e.uid)&&this.workerListeners.get(e.uid)(e),e.type){case"addtrack":{const t=this.pipelines.get(e.idx);t&&this.mediaStream&&(e.track?this.mediaStream.addTrack(e.track):t.generator&&this.mediaStream.addTrack(t.generator.getTrack()));break}case"removetrack":{const t=this.pipelines.get(e.idx);if(t?.generator&&this.mediaStream){const e=t.generator.getTrack();this.mediaStream.removeTrack(e)}break}case"setplaybackrate":this.videoElement&&(this.videoElement.playbackRate=e.speed);break;case"sendevent":"timeupdate"===e.kind?(this._pendingStepPause&&this.finishStepPause(),"number"==typeof e.time&&Number.isFinite(e.time)?(this._currentTime=e.time,this.emit("timeupdate",this._currentTime)):this.videoElement&&this.emit("timeupdate",this.videoElement.currentTime)):"error"===e.kind&&this.emit("error",new Error(e.message??"Unknown error"));break;case"writeframe":{const t=this.pipelines.get(e.idx);if(t?.safariAudioWriter){const n=e.frame,i=e.uid;t.safariAudioWriter.write(n).then(()=>{this.worker?.postMessage({type:"writeframe",idx:e.idx,uid:i,status:"ok"})}).catch(t=>{this.worker?.postMessage({type:"writeframe",idx:e.idx,uid:i,status:"error",error:t.message})})}else this.worker?.postMessage({type:"writeframe",idx:e.idx,uid:e.uid,status:"error",error:"Pipeline not active or no audio writer"});break}case"log":if(this.debugging){const t=e.level??"info";("error"===t?console.error:"warn"===t?console.warn:console.log)(`[WebCodecs Worker] ${e.msg}`)}break;case"stats":break;case"closed":this.pipelines.delete(e.idx)}}setupWebSocketHandlers(){this.wsController&&(this.wsController.on("codecdata",e=>this.handleCodecData(e)),this.wsController.on("info",e=>this.handleInfo(e)),this.wsController.on("ontime",e=>this.handleOnTime(e)),this.wsController.on("tracks",e=>this.handleTracksChange(e)),this.wsController.on("chunk",e=>this.handleChunk(e)),this.wsController.on("stop",()=>this.handleStop()),this.wsController.on("error",e=>this.handleError(e)),this.wsController.on("statechange",e=>{this.log(`Connection state: ${e}`),"error"===e&&this.emit("error",new Error("WebSocket connection failed"))}))}async handleCodecData(e){const t=e.codecs??[],n=e.tracks??[];if(this.log(`Received codec data: codecs=[${t.join(", ")||"none"}], tracks=[${n.join(", ")||"none"}]`),0===t.length||0===n.length)return this.log("No playable codecs/tracks selected by server","warn"),void this.wsController?.play();for(let e=0;e<n.length;e++){const i=n[e],r=t[e];if(r){const e=this.tracksByIndex.get(i);e?e.codec=r:this.tracksByIndex.set(i,{idx:i,type:r.match(/^(H264|HEVC|VP[89]|AV1|JPEG)/i)?"video":r.match(/^(AAC|MP3|opus|FLAC|AC3|pcm)/i)?"audio":"meta",codec:r}),this.log(`Track ${i}: codec=${r}`)}}for(const e of n){const t=this.tracksByIndex.get(e);!t||"video"!==t.type&&"audio"!==t.type||await this.createPipeline(t)}this.wsController?.play()}async handleInfo(e){if(this.log("Received stream info"),e.meta?.tracks){const t=e.meta.tracks;this.log(`Info contains ${Object.keys(t).length} tracks`);for(const[e,n]of Object.entries(t))if(void 0!==n.idx&&(this.tracksByIndex.set(n.idx,n),this.log(`Registered track ${n.idx}: ${n.type} ${n.codec}`),this.queuedInitData.has(n.idx)&&("video"===n.type||"audio"===n.type))){this.log(`Processing queued INIT data for track ${n.idx}`),await this.createPipeline(n);const e=this.queuedInitData.get(n.idx);this.configurePipeline(n.idx,e),this.queuedInitData.delete(n.idx)}this.tracks=Object.values(t)}}handleOnTime(e){this.syncController?.updateServerTime(e.current),null===this._frameCallbackId&&(this._currentTime=e.current);const t=this.wsController?.getServerDelay()??0;t>0&&this.syncController?.recordServerDelay(t),void 0!==e.total&&isFinite(e.total)&&e.total>0&&(this._duration=e.total);const n=this.syncController?.getState();if(n&&(this._bufferMs=n.buffer.current),e.tracks&&e.tracks.length>0)for(const t of e.tracks)if(!this.pipelines.has(t)){const e=this.tracksByIndex.get(t);!e||"video"!==e.type&&"audio"!==e.type||(this.log(`Creating pipeline from on_time for track ${e.idx} (${e.type} ${e.codec})`),this.createPipeline(e).then(()=>{const t=this.queuedInitData.get(e.idx);t&&(this.configurePipeline(e.idx,t),this.queuedInitData.delete(e.idx))}))}}async handleTracksChange(e){this.log(`Tracks changed: ${e.map(e=>`${e.idx}:${e.type}`).join(", ")}`);const t=new Set(e.map(e=>e.idx)),n=new Set(this.pipelines.keys());for(const e of n)t.has(e)||await this.closePipeline(e,!0);for(const t of e)this.tracksByIndex.set(t.idx,t),"video"!==t.type&&"audio"!==t.type||this.pipelines.has(t.idx)||await this.createPipeline(t);this.tracks=e}handleChunk(e){if(this.isDestroyed)return;const t=this.pipelines.get(e.trackIndex);if(!t){const t=this.tracksByIndex.get(e.trackIndex);return t?void("video"!==t.type&&"audio"!==t.type||(this.log(`Creating pipeline for discovered track ${t.idx} (${t.type} ${t.codec})`),this.createPipeline(t).then(()=>{if(this.isDestroyed)return;const n=this.queuedInitData.get(t.idx);n&&(this.configurePipeline(t.idx,n),this.queuedInitData.delete(t.idx)),this.handleChunk(e)}))):un(e)?(this.log(`Received INIT for unknown track ${e.trackIndex}, queuing for later`),void this.queuedInitData.set(e.trackIndex,e.data)):void this.log(`Received chunk for unknown track ${e.trackIndex} without track info`,"warn")}if(un(e))this.configurePipeline(t.idx,e.data);else{if(!t.configured){if("audio"===t.track.type||"key"===e.type){this.log(`Received ${e.type.toUpperCase()} frame for unconfigured ${t.track.type} track ${e.trackIndex}, configuring`),this.queuedChunks.has(e.trackIndex)||this.queuedChunks.set(e.trackIndex,[]),this.queuedChunks.get(e.trackIndex).unshift(e);const n=t.track.init?_n(t.track.init):new Uint8Array(0);return void this.configurePipeline(e.trackIndex,n).catch(t=>{this.log(`Failed to configure track ${e.trackIndex}: ${t}`,"error")})}return this.queuedChunks.has(e.trackIndex)||this.queuedChunks.set(e.trackIndex,[]),this.queuedChunks.get(e.trackIndex).push(e),void(this.verboseDebugging&&this.log(`Queued chunk for track ${e.trackIndex} (waiting for decoder config)`))}this.syncController?.recordChunkArrival(e.trackIndex,e.timestamp),this.sendChunkToWorker(e)}}sendChunkToWorker(e){const t={type:"receive",idx:e.trackIndex,chunk:{type:"key"===e.type?"key":"delta",timestamp:ln(e),data:e.data},uid:this.workerUidCounter++};this.worker?.postMessage(t,[e.data.buffer])}handleStop(){this.log("Stream stopped"),this.emit("ended",void 0)}handleError(e){this.log(`WebSocket error: ${e.message}`,"error"),this.emit("error",e)}async createPipeline(e){if(this.pipelines.has(e.idx))return;this.log(`Creating pipeline for track ${e.idx} (${e.type} ${e.codec})`);const t={idx:e.idx,track:e,generator:null,configured:!1};if(this.pipelines.set(e.idx,t),this.syncController?.addTrack(e.idx,e),await this.sendToWorker({type:"create",idx:e.idx,track:e,opts:{optimizeForLatency:"live"===this.streamType,payloadFormat:this.payloadFormat},uid:this.workerUidCounter++}),vn()){const n=new MediaStreamTrackGenerator({kind:e.type});t.generator={writable:n.writable,getTrack:()=>n,close:()=>n.stop?.()},await this.sendToWorker({type:"setwritable",idx:e.idx,writable:n.writable,uid:this.workerUidCounter++},[n.writable])}else if(function(){if("undefined"==typeof navigator)return!1;const e=navigator.userAgent;return/^((?!chrome|android).)*safari/i.test(e)}()){if(this.log(`Safari detected - using worker-based track generator for ${e.type}`),"audio"===e.type&&"undefined"!=typeof MediaStreamTrackGenerator){const e=new MediaStreamTrackGenerator({kind:"audio"});t.safariAudioGenerator=e,t.safariAudioWriter=e.writable.getWriter(),this.mediaStream&&this.mediaStream.addTrack(e)}await this.sendToWorker({type:"creategenerator",idx:e.idx,uid:this.workerUidCounter++})}else t.generator=function(e){if(vn()){const t=new(0,globalThis.MediaStreamTrackGenerator)({kind:e});return{writable:t.writable,getTrack:()=>t,close:()=>t.stop?.()}}if("video"===e){const e=new Tn;return{writable:e.writable,getTrack:()=>e.getTrack(),close:()=>e.close()}}{const e=new En;return{writable:e.writable,getTrack:()=>e.getTrack(),close:()=>e.close(),waitForInit:()=>e.waitForInit()}}}(e.type),t.generator.waitForInit&&await t.generator.waitForInit(),this.log("Using MediaStreamTrackGenerator polyfill - main thread decode"),this.mediaStream&&t.generator&&this.mediaStream.addTrack(t.generator.getTrack());e.init&&""!==e.init?this.log(`Track ${e.idx} (${e.codec}) has init data (${e.init.length} bytes), waiting for first frame`):(this.log(`Track ${e.idx} (${e.codec}) doesn't need init data, configuring immediately`),await this.configurePipeline(e.idx,new Uint8Array(0)))}async configurePipeline(e,t){const n=this.pipelines.get(e);if(!n||n.configured)return;this.log(`Configuring decoder for track ${e}`);const i=new Uint8Array(t);await this.sendToWorker({type:"configure",idx:e,header:i,uid:this.workerUidCounter++}),n.configured=!0;const r=this.queuedChunks.get(e);if(r&&r.length>0){this.log(`Flushing ${r.length} queued chunks for track ${e}`);let t=0;for(let e=0;e<r.length;e++)if("key"===r[e].type){t=e;break}t>0&&this.log(`Skipping ${t} delta frames, starting from keyframe`);for(let e=t;e<r.length;e++)this.sendChunkToWorker(r[e]);this.queuedChunks.delete(e)}}async closePipeline(e,t){const n=this.pipelines.get(e);n&&(this.log(`Closing pipeline ${e}`),await this.sendToWorker({type:"close",idx:e,waitEmpty:t,uid:this.workerUidCounter++}),n.generator?.close(),this.syncController?.removeTrack(e),this.pipelines.delete(e))}async play(){this._isPaused=!1,this.wsController?.play(),this.sendToWorker({type:"frametiming",action:"setPaused",paused:!1,uid:this.workerUidCounter++}),await(this.videoElement?.play())}pause(){this._isPaused=!0,this.wsController?.hold(),this.sendToWorker({type:"frametiming",action:"setPaused",paused:!0,uid:this.workerUidCounter++}),this.videoElement?.pause()}finishStepPause(){if(!this.videoElement)return this._pendingStepPause=!1,this._suppressPlayPauseSync=!1,void(this._stepPauseTimeout&&(clearTimeout(this._stepPauseTimeout),this._stepPauseTimeout=null));this._stepPauseTimeout&&(clearTimeout(this._stepPauseTimeout),this._stepPauseTimeout=null),this._pendingStepPause=!1,this._suppressPlayPauseSync=!1;try{this.videoElement.pause()}catch{}}frameStep(e,t){if(this._isPaused&&this.videoElement){if(this.log(`Frame step requested dir=${e} paused=${this._isPaused} videoPaused=${this.videoElement.paused}`),this.sendToWorker({type:"frametiming",action:"setPaused",paused:!0,uid:this.workerUidCounter++}).catch(()=>{}),this.videoElement.paused){const e=this.videoElement;this._suppressPlayPauseSync=!0,this._pendingStepPause=!0;try{const t=e.play();t&&"function"==typeof t.catch&&t.catch(()=>{})}catch{}"requestVideoFrameCallback"in e&&e.requestVideoFrameCallback(()=>this.finishStepPause()),this._stepPauseTimeout=setTimeout(()=>this.finishStepPause(),200)}this.sendToWorker({type:"framestep",direction:e,uid:this.workerUidCounter++})}}seek(e){if(!this.wsController||!this.syncController)return;const t=1e3*e,n=this.syncController.startSeek(t);this._currentTime=e,this.emit("timeupdate",this._currentTime),this.sendToWorker({type:"seek",seekTime:t,uid:this.workerUidCounter++});const i=this.syncController.getDesiredBuffer();this.wsController.seek(t,i),setTimeout(()=>{this.syncController?.isSeekActive(n)&&(this.syncController.completeSeek(n),this.sendToWorker({type:"frametiming",action:"reset",uid:this.workerUidCounter++}))},100)}setPlaybackRate(e){this.syncController?.setMainSpeed(e)}isPaused(){return this._isPaused}isLive(){return"live"===this.streamType}jumpToLive(){if("live"===this.streamType&&this.wsController){const e=this.syncController?.getDesiredBuffer()??2e3;this.wsController.send({type:"fast_forward",ff_add:5e3});const t=this.syncController?.getEstimatedServerTime()??0;t>0&&this.wsController.seek(1e3*t,e),this.log("Jump to live: requested fresh data from server")}}canSeek(){return null!==this.wsController&&!this.isDestroyed}get duration(){return this._duration}getDuration(){return this._duration}get currentTime(){return this._currentTime}getCurrentTime(){return this._currentTime}get buffered(){if(this._bufferMs<=0)return Sn([]);const e=this._currentTime;return Sn([[e,e+this._bufferMs/1e3]])}async getStats(){const e=this.syncController?.getState();return{latency:{buffer:e?.buffer.current??0,target:e?.buffer.desired??0,jitter:e?.jitter.weighted??0},sync:{avDrift:this._avDrift,playbackSpeed:e?.playbackSpeed??1},decoder:{videoQueueSize:0,audioQueueSize:0,framesDropped:this._framesDropped,framesDecoded:this._framesDecoded},network:{bytesReceived:this._bytesReceived,messagesReceived:this._messagesReceived}}}setupFrameCallback(){if(this.videoElement)if("requestVideoFrameCallback"in HTMLVideoElement.prototype){const e=(t,n)=>{!this.isDestroyed&&this.videoElement&&(this.onVideoFrame(n),this._frameCallbackId=this.videoElement.requestVideoFrameCallback(e))};this._frameCallbackId=this.videoElement.requestVideoFrameCallback(e),this.log("requestVideoFrameCallback enabled for accurate frame timing")}else this.log("requestVideoFrameCallback not available, using fallback timing")}onVideoFrame(e){this._currentTime=e.mediaTime;const t=this.syncController?.getState();t&&(this._bufferMs=t.buffer.current),this.emit("timeupdate",this._currentTime),this._framesDecoded=e.presentedFrames}cancelFrameCallback(){null!==this._frameCallbackId&&this.videoElement&&("cancelVideoFrameCallback"in HTMLVideoElement.prototype&&this.videoElement.cancelVideoFrameCallback(this._frameCallbackId),this._frameCallbackId=null)}log(e,t="info"){(this.debugging||"info"!==t)&&console[t](`[WebCodecs] ${e}`)}}wn.codecCache=new Map;var kn=Object.freeze({__proto__:null,JitterTracker:fn,LATENCY_PROFILES:gn,MultiTrackJitterTracker:pn,SyncController:bn,WebCodecsPlayerImpl:wn,WebSocketController:hn,getLatencyProfile:mn,mergeLatencyProfile:yn,parseRawChunk:on});var In=Object.freeze({__proto__:null,MistWebRTCPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"MistServer WebRTC",shortname:"mist-webrtc",priority:2,mimes:["webrtc","mist/webrtc"]},this.signaling=null,this.peerConnection=null,this.dataChannel=null,this.container=null,this.destroyed=!1,this.seekOffset=0,this.durationMs=0,this.isLiveStream=!0,this.playRate="auto",this.bufferWindow=0,this.currentTracks=[],this.currentSource=null,this.currentOptions=null,this.lastInboundStats=null}async checkH264Available(e=5){for(let t=0;t<e;t++){try{const e=RTCRtpReceiver.getCapabilities?.("video");if(e?.codecs.some(e=>"video/H264"===e.mimeType))return!0}catch{}t<e-1&&await new Promise(e=>setTimeout(e,100))}return console.warn("[MistWebRTC] H264 not available after retries"),!1}async loadBrowserEqualizer(e){if(!window.WebRTCBrowserEqualizerLoaded)return new Promise(t=>{const n=document.createElement("script");n.src=`${e}/webrtc.js`,n.onload=()=>{console.debug("[MistWebRTC] Browser equalizer loaded"),t()},n.onerror=()=>{console.warn("[MistWebRTC] Failed to load browser equalizer"),t()},document.head.appendChild(n)})}arraysEqual(e,t){if(e.length!==t.length)return!1;const n=[...e].sort(),i=[...t].sort();return n.every((e,t)=>e===i[t])}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(!("RTCPeerConnection"in window)||!("WebSocket"in window))return!1;const i=De(n.meta.tracks);if(!i.compatible)return console.debug("[MistWebRTC] Skipping - incompatible codecs:",i.incompatibleCodecs.join(", ")),!1;const r=[];return i.details.compatibleVideoCodecs.length>0&&r.push("video"),i.details.compatibleAudioCodecs.length>0&&r.push("audio"),r.length>0&&r}async initialize(e,t,n){this.destroyed=!1,this.container=e,this.currentSource=t,this.currentOptions=n,e.classList.add("fw-player-container");try{const e=new URL(t.url,window.location.href),n=`${e.protocol}//${e.host}`;await this.loadBrowserEqualizer(n)}catch{}await this.checkH264Available();const i=document.createElement("video");i.classList.add("fw-player-video"),i.setAttribute("playsinline",""),i.setAttribute("crossorigin","anonymous"),n.autoplay&&(i.autoplay=!0),n.muted&&(i.muted=!0),i.controls=!0===n.controls,n.loop&&(i.loop=!0),n.poster&&(i.poster=n.poster),this.videoElement=i,e.appendChild(i),this.setupVideoEventListeners(i,n);try{return await this.setupWebRTC(i,t,n),i}catch(e){throw this.emit("error",e.message||String(e)),e}}async destroy(){if(this.destroyed=!0,this.signaling){try{this.signaling.stop(),this.signaling.close()}catch{}this.signaling=null}if(this.dataChannel){try{this.dataChannel.close()}catch{}this.dataChannel=null}if(this.peerConnection){try{this.peerConnection.close()}catch{}this.peerConnection=null}if(this.videoElement){try{this.videoElement.srcObject=null}catch{}if(this.videoElement.pause(),this.container)try{this.container.removeChild(this.videoElement)}catch{}}this.videoElement=null,this.container=null,this.listeners.clear()}seek(e){this.signaling?.isConnected&&this.videoElement&&(this.videoElement.pause(),this.seekOffset=e-this.videoElement.currentTime,this.signaling.seek(e).catch(e=>{console.warn("[MistWebRTC] Seek failed:",e)}))}setPlaybackRate(e){this.signaling?.setSpeed(e),this.playRate=e}jumpToLive(){this.signaling?.isConnected&&this.videoElement&&(this.videoElement.pause(),this.seekOffset=0,this.signaling.seek("live").catch(e=>{console.warn("[MistWebRTC] Jump to live failed:",e)}))}isLive(){return this.isLiveStream}getDuration(){return this.durationMs>0?this.durationMs/1e3:super.getDuration()}getCurrentTime(){const e=this.videoElement;return e?this.seekOffset+e.currentTime:0}getQualities(){return[{id:"auto",label:"Auto",isAuto:!0,active:"auto"===this.playRate}]}selectQuality(e){this.signaling?.isConnected&&("auto"===e?this.signaling.setSpeed("auto"):this.signaling.setTracks({video:e}))}selectTextTrack(e){this.signaling?.isConnected&&(null===e?this.signaling.setTracks({video:"none"}):this.signaling.setTracks({video:e}))}async getStats(){if(this.peerConnection)try{const e=await this.peerConnection.getStats(),t=Date.now(),n={type:"webrtc",timestamp:t};return e.forEach(e=>{if("inbound-rtp"===e.type){const i=e.packetsReceived>0?e.packetsLost/(e.packetsReceived+e.packetsLost)*100:0;let r=0;if(this.lastInboundStats&&this.lastInboundStats[e.kind]){const n=this.lastInboundStats[e.kind],i=(t-this.lastInboundStats.timestamp)/1e3;if(i>0&&n){const t=e.bytesReceived-n.bytesReceived;r=Math.round(8*t/i)}}if("video"===e.kind){const t=e.framesDecoded>0?e.framesDropped/(e.framesDecoded+e.framesDropped)*100:0;n.video={bytesReceived:e.bytesReceived||0,packetsReceived:e.packetsReceived||0,packetsLost:e.packetsLost||0,packetLossRate:i,jitter:1e3*(e.jitter||0),framesDecoded:e.framesDecoded||0,framesDropped:e.framesDropped||0,frameDropRate:t,frameWidth:e.frameWidth||0,frameHeight:e.frameHeight||0,framesPerSecond:e.framesPerSecond||0,bitrate:r,jitterBufferDelay:e.jitterBufferDelay&&e.jitterBufferEmittedCount?e.jitterBufferDelay/e.jitterBufferEmittedCount*1e3:0}}"audio"===e.kind&&(n.audio={bytesReceived:e.bytesReceived||0,packetsReceived:e.packetsReceived||0,packetsLost:e.packetsLost||0,packetLossRate:i,jitter:1e3*(e.jitter||0),bitrate:r})}"candidate-pair"===e.type&&e.nominated&&(n.network={rtt:e.currentRoundTripTime?1e3*e.currentRoundTripTime:0,availableOutgoingBitrate:e.availableOutgoingBitrate||0,availableIncomingBitrate:e.availableIncomingBitrate||0,bytesSent:e.bytesSent||0,bytesReceived:e.bytesReceived||0})}),this.lastInboundStats={video:n.video?{bytesReceived:n.video.bytesReceived}:void 0,audio:n.audio?{bytesReceived:n.audio.bytesReceived}:void 0,timestamp:t},n}catch{return}}async getLatency(){const e=await this.getStats();if(e)return{estimatedMs:e.video?.jitterBufferDelay||0,jitterBufferMs:e.video?.jitterBufferDelay||0,rttMs:e.network?.rtt||0}}getBufferWindow(){return this.bufferWindow}setQualityForSize(e){this.signaling?.isConnected&&this.signaling.setTracks({video:`~${e.width}x${e.height}`})}getMetaDataChannel(){return this.dataChannel}setupVideoEventListeners(e,t){if(super.setupVideoEventListeners(e,t),!t.autoplay){const t=()=>{e.pause(),this.signaling?.pause(),e.removeEventListener("play",t)};e.addEventListener("play",t)}e.addEventListener("ended",async()=>{if(e.loop&&!this.isLiveStream&&this.currentSource&&this.currentOptions){console.debug("[MistWebRTC] VoD ended with loop enabled, reconnecting...");try{if(this.signaling){try{this.signaling.stop(),this.signaling.close()}catch{}this.signaling=null}if(this.dataChannel){try{this.dataChannel.close()}catch{}this.dataChannel=null}if(this.peerConnection){try{this.peerConnection.close()}catch{}this.peerConnection=null}await this.setupWebRTC(e,this.currentSource,this.currentOptions)}catch(e){console.error("[MistWebRTC] Failed to reconnect for loop:",e),this.emit("error","Failed to reconnect for loop")}}})}async setupWebRTC(e,t,n){const i=t,r=i?.iceServers||[];this.signaling=new Ct({url:t.url,timeout:5e3,onLog:e=>console.debug(`[MistWebRTC] ${e}`)});const s=new RTCPeerConnection({iceServers:r});this.peerConnection=s,this.dataChannel=s.createDataChannel("*",{protocol:"JSON"}),this.dataChannel.onmessage=e=>{this.destroyed||console.debug("[MistWebRTC] DataChannel message:",e.data)},s.ontrack=t=>{this.destroyed||e&&t.streams[0]&&(e.srcObject=t.streams[0])},s.onconnectionstatechange=()=>{if(this.destroyed)return;const e=s.connectionState;console.debug(`[MistWebRTC] Connection state: ${e}`),"failed"===e&&this.emit("error","WebRTC connection failed (firewall?)")},s.oniceconnectionstatechange=()=>{if(this.destroyed)return;const e=s.iceConnectionState;console.debug(`[MistWebRTC] ICE state: ${e}`),"failed"===e&&this.emit("error","ICE connection failed")},this.setupSignalingHandlers(s,e),this.signaling.connect(),await new Promise((e,t)=>{const n=setTimeout(()=>{t(new Error("Signaling connection timeout"))},1e4);this.signaling.once("connected",()=>{clearTimeout(n),e()}),this.signaling.once("error",({message:e})=>{clearTimeout(n),t(new Error(e))})}),await this.createAndSendOffer(s),await new Promise((e,t)=>{const n=setTimeout(()=>{t(new Error("SDP answer timeout"))},1e4);this.signaling.once("answer_sdp",async({result:i,answer_sdp:r})=>{if(clearTimeout(n),i)try{await s.setRemoteDescription({type:"answer",sdp:r}),e()}catch(e){t(e)}else t(new Error("Failed to get SDP answer"))})})}setupSignalingHandlers(e,t){this.signaling&&(this.signaling.on("connected",()=>{this.destroyed||t.dispatchEvent(new Event("webrtc_connected"))}),this.signaling.on("time_update",e=>{this.destroyed||this.handleTimeUpdate(e,t)}),this.signaling.on("seeked",({live_point:e})=>{this.destroyed||(t.dispatchEvent(new CustomEvent("seeked",{detail:{seekOffset:this.seekOffset}})),e&&this.signaling&&this.signaling.setSpeed("auto"),t.play().catch(()=>{}))}),this.signaling.on("speed_changed",({play_rate_curr:e})=>{this.destroyed||(this.playRate=e,t.dispatchEvent(new CustomEvent("ratechange",{detail:{play_rate_curr:e}})))}),this.signaling.on("stopped",()=>{this.destroyed||(this.isLiveStream=!1,t.pause(),this.emit("ended",void 0))}),this.signaling.on("error",({message:e})=>{this.destroyed||this.emit("error",e)}),this.signaling.on("disconnected",()=>{this.destroyed||(t.dispatchEvent(new Event("webrtc_disconnected")),t.pause())}))}handleTimeUpdate(e,t){this.seekOffset=e.current/1e3-t.currentTime;const n=0===e.end?1/0:e.end;if(this.durationMs=n,this.isLiveStream=!isFinite(n)||0===n,this.bufferWindow=e.end-e.begin,e.tracks&&!this.arraysEqual(e.tracks,this.currentTracks)){for(const n of e.tracks)this.currentTracks.includes(n)||t.dispatchEvent(new CustomEvent("playerUpdate_trackChanged",{detail:{trackId:n}}));this.currentTracks=[...e.tracks]}!e.paused&&t.paused&&t.play().catch(()=>{})}async createAndSendOffer(e){if(!this.signaling)return;e.addTransceiver("video",{direction:"recvonly"}),e.addTransceiver("audio",{direction:"recvonly"});const t=await e.createOffer({offerToReceiveAudio:!0,offerToReceiveVideo:!0});await e.setLocalDescription(t),t.sdp&&this.signaling.sendOfferSDP(t.sdp)}}});var An=Object.freeze({__proto__:null,VideoJsPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"Video.js Player",shortname:"videojs",priority:2,mimes:["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"]},this.videojsPlayer=null,this.container=null,this.destroyed=!1,this.timeCorrection=0,this.proxyElement=null,this.currentStreamInfo=null,this.liveDurationProxy=null}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){try{const e=new URL(t.url).protocol;if("undefined"!=typeof location&&location.protocol!==e)return console.debug("[VideoJS] HTTP/HTTPS mismatch - skipping"),!1}catch{}const i=[],r={};for(const e of n.meta.tracks)"meta"!==e.type?(r[e.type]||(r[e.type]=[]),r[e.type].push(e)):"subtitle"===e.codec&&i.push("subtitle");const s=["OPUS","Opus","opus","VORBIS","Vorbis","FLAC"],a=document.createElement("video");for(const[e,t]of Object.entries(r)){let n=!1;for(const i of t){if("audio"===e&&s.includes(i.codec)){console.debug(`[VideoJS] Codec incompatible with HLS: ${i.codec}`);continue}let t=i.codec;if(i.init){const e=e=>!i.init||e>=i.init.length?"00":("0"+i.init.charCodeAt(e).toString(16)).slice(-2);switch(i.codec){case"H264":t=`avc1.${e(1)}${e(2)}${e(3)}`;break;case"AAC":t="mp4a.40.2";break;case"MP3":t="mp4a.40.34";break;case"HEVC":t="hev1.1.6.L93.B0"}}const r="audio"===e?`audio/mp4;codecs="${t}"`:`video/mp4;codecs="${t}"`;if(""!==a.canPlayType(r)){n=!0;break}console.debug(`[VideoJS] Codec not supported: ${r}`)}n&&i.push(e)}return 0===Object.keys(r).length?["video","audio"]:i.length>0&&i}async initialize(e,t,n,i){this.destroyed=!1,this.container=e,this.currentStreamInfo=i||null,e.classList.add("fw-player-container");const r=document.createElement("video");r.classList.add("fw-player-video"),r.setAttribute("playsinline",""),r.setAttribute("crossorigin","anonymous"),r.className="video-js vjs-default-skin fw-player-video",n.autoplay&&(r.autoplay=!0),n.muted&&(r.muted=!0),r.controls=!0===n.controls,n.loop&&(r.loop=!0),n.poster&&(r.poster=n.poster),this.videoElement=r,e.appendChild(r),this.setupVideoEventListeners(r,n);try{const e=await Promise.resolve().then(function(){return ng}),i=e.default||e,s=!0===n.controls,a=navigator.userAgent.match(/android\s([\d.]*)/i),o=a?parseFloat(a[1]):null,l={autoplay:n.autoplay,controls:s,muted:n.muted,sources:[{src:t.url,type:this.getVideoJsType(t.type)}],loadingSpinner:s,bigPlayButton:s,textTrackDisplay:s,errorDisplay:s,controlBar:s,liveTracker:s,html5:{vhs:{enableLowInitialPlaylist:!0,bandwidth:5e6,useBandwidthFromLocalStorage:!0,handlePartialData:!0,liveRangeSafeTimeDelta:.3,...n.vhsConfig},...o&&o<7?{hls:{overrideNative:!0}}:{}},nativeAudioTracks:!(o&&o<7)&&void 0,nativeVideoTracks:!(o&&o<7)&&void 0};if(console.debug("[VideoJS] Creating player with options:",l),this.videojsPlayer=i(r,l),console.debug("[VideoJS] Player created"),!s){const e=this.videojsPlayer.el();e&&e.classList.add("vjs-fw-custom-controls")}return this.videojsPlayer.on("error",()=>{if(this.destroyed)return;const e=this.videojsPlayer?.error(),t=e?.message||"";if(t.includes("NS_ERROR_DOM_MEDIA_OVERFLOW_ERR"))return console.warn("[VideoJS] Firefox segment error, requesting reload"),void this.emit("reloadrequested",{reason:"NS_ERROR_DOM_MEDIA_OVERFLOW_ERR"});this.emit("error",t||"VideoJS playback error")}),this.videojsPlayer.ready(()=>{if(this.destroyed)return;const e=this.videojsPlayer.tech?.({IWillNotUseThisInPlugins:!0});console.debug("[VideoJS] ready - tech:",e?.name||"unknown","videoWidth:",r.videoWidth,"videoHeight:",r.videoHeight,"readyState:",r.readyState,"networkState:",r.networkState),this.currentStreamInfo&&(this.proxyElement=this.createTimeCorrectedProxy(r,this.currentStreamInfo));const t=this.videojsPlayer.duration();isFinite(t)||this.liveDurationProxy||(this.liveDurationProxy=new Rt(r,{constrainSeek:!0,liveOffset:0}),console.debug("[VideoJS] LiveDurationProxy initialized for live stream")),n.autoplay&&(r.muted||(r.muted=!0),this.videojsPlayer.play().catch(e=>{console.warn("VideoJS autoplay failed:",e)}))}),this.videojsPlayer.on("loadedmetadata",()=>{console.debug("[VideoJS] loadedmetadata - duration:",this.videojsPlayer.duration(),"videoWidth:",r.videoWidth,"videoHeight:",r.videoHeight)}),this.videojsPlayer.on("loadeddata",()=>{const e=this.videojsPlayer.tech?.({IWillNotUseThisInPlugins:!0}),t=e?.vhs||e?.hls;t&&console.debug("[VideoJS] VHS state -","bandwidth:",t.bandwidth,"seekable:",t.seekable?.()?.length>0?`${t.seekable().start(0)}-${t.seekable().end(0)}`:"none","buffered:",r.buffered.length>0?`${r.buffered.end(0)}s`:"none")}),this.videojsPlayer.on("canplay",()=>{console.debug("[VideoJS] canplay")}),this.videojsPlayer.on("playing",()=>{console.debug("[VideoJS] playing - currentTime:",this.videojsPlayer.currentTime())}),this.videojsPlayer.on("waiting",()=>{console.debug("[VideoJS] waiting/buffering")}),this.videojsPlayer.on("stalled",()=>{console.debug("[VideoJS] stalled")}),r.addEventListener("loadeddata",()=>{console.debug("[VideoJS] video loadeddata - readyState:",r.readyState,"videoWidth:",r.videoWidth,"videoHeight:",r.videoHeight)}),this.videojsPlayer.on("progress",()=>{if(!this.destroyed)try{const e=this.videojsPlayer.seekable();if(e&&e.length>0){const t=e.start(0),n=e.end(e.length-1),i=1e3*(n-t);this.emit("seekablechange",{start:t+this.timeCorrection,end:n+this.timeCorrection,bufferWindow:i})}}catch{}}),this.proxyElement||r}catch(e){throw this.emit("error",e.message||String(e)),e}}createTimeCorrectedProxy(e,t){let n=1/0;for(const e of t.meta.tracks)void 0!==e.firstms&&e.firstms<n&&(n=e.firstms);if(this.timeCorrection=n!==1/0?n/1e3:0,0===this.timeCorrection||"undefined"==typeof Proxy)return e;console.debug(`[VideoJS] Applying timestamp correction: ${this.timeCorrection}s (firstms=${n})`);const i=this.timeCorrection,r=this.videojsPlayer;return new Proxy(e,{get:(e,t)=>{if("currentTime"===t){const t=r?r.currentTime():e.currentTime;return isNaN(t)?0:t+i}if("duration"===t){const t=e.duration;return isNaN(t)?0:t+i}if("buffered"===t){const t=e.buffered;return{length:t.length,start:e=>t.start(e)+i,end:e=>t.end(e)+i}}const n=e[t];return"function"==typeof n?n.bind(e):n},set:(e,t,n)=>{if("currentTime"===t){const t=n-i;return r?r.currentTime(t):e.currentTime=t,!0}return e[t]=n,!0}})}getVideoJsType(e){return e?e.includes("mpegurl")?"application/x-mpegURL":e.includes("dash")?"application/dash+xml":e.includes("mp4")?"video/mp4":e.includes("webm")?"video/webm":e.replace("html5/",""):"application/x-mpegURL"}setPlaybackRate(e){super.setPlaybackRate(e);try{this.videojsPlayer&&this.videojsPlayer.playbackRate(e)}catch{}}getCurrentTime(){const e=this.proxyElement||this.videoElement;return e?.currentTime??0}seek(e){const t=e-this.timeCorrection;this.videojsPlayer?this.videojsPlayer.currentTime(t):this.videoElement&&(this.videoElement.currentTime=t)}async getStats(){const e=this.videoElement;if(!e)return;let t=0;if(e.buffered.length>0)for(let n=0;n<e.buffered.length;n++)if(e.buffered.start(n)<=e.currentTime&&e.buffered.end(n)>e.currentTime){t=e.buffered.end(n)-e.currentTime;break}return{type:"videojs",buffered:t,currentTime:e.currentTime,duration:e.duration,readyState:e.readyState,networkState:e.networkState,playbackRate:e.playbackRate}}isLiveStream(){if(this.liveDurationProxy)return this.liveDurationProxy.isLive();const e=this.videoElement;return!!e&&!isFinite(e.duration)}getDuration(){return this.liveDurationProxy?this.liveDurationProxy.getDuration():this.videoElement?.duration??0}jumpToLive(){const e=this.videoElement;if(e){if(this.videojsPlayer&&this.videojsPlayer.liveTracker){const e=this.videojsPlayer.liveTracker;if(e.isLive&&e.isLive()){const t=e.liveCurrentTime?.();if("number"==typeof t&&t>0)return console.debug("[VideoJS] jumpToLive using liveTracker:",t),void this.videojsPlayer.currentTime(t)}}if(this.liveDurationProxy&&this.liveDurationProxy.isLive())return console.debug("[VideoJS] jumpToLive using LiveDurationProxy"),void this.liveDurationProxy.jumpToLive();if(this.videojsPlayer)try{const e=this.videojsPlayer.seekable();if(e&&e.length>0){const t=e.end(e.length-1);if(isFinite(t)&&t>0)return console.debug("[VideoJS] jumpToLive using seekable.end:",t),void this.videojsPlayer.currentTime(t)}}catch{}if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);isFinite(t)&&t>0&&(console.debug("[VideoJS] jumpToLive using video.seekable.end:",t),e.currentTime=t)}}}getSeekableRange(){const e=this.videoElement;if(!e?.seekable||0===e.seekable.length)return null;let t=e.seekable.start(0),n=e.seekable.end(e.seekable.length-1);if(this.videojsPlayer?.liveTracker){const e=this.videojsPlayer.liveTracker,i=e.seekableEnd?.(),r=e.seekableStart?.();"number"==typeof r&&Number.isFinite(r)&&(t=r),"number"==typeof i&&Number.isFinite(i)&&i>0&&(n=Math.min(n,i))}return!Number.isFinite(t)||!Number.isFinite(n)||n<=t?null:{start:t,end:n}}getLiveLatency(){const e=this.videoElement;if(!e)return 0;if(this.videojsPlayer&&this.videojsPlayer.liveTracker){const t=this.videojsPlayer.liveTracker;if(t.isLive?.()&&"function"==typeof t.seekableEnd){const n=t.seekableEnd();if("number"==typeof n&&isFinite(n))return Math.max(0,1e3*(n-e.currentTime))}}return this.liveDurationProxy?1e3*this.liveDurationProxy.getLatency():0}async destroy(){if(this.destroyed=!0,this.liveDurationProxy&&(this.liveDurationProxy.destroy(),this.liveDurationProxy=null),this.videojsPlayer){try{this.videojsPlayer.dispose()}catch(e){console.warn("Error disposing VideoJS:",e)}this.videojsPlayer=null}if(this.videoElement&&this.container)try{this.container.removeChild(this.videoElement)}catch{}this.videoElement=null,this.container=null,this.proxyElement=null,this.currentStreamInfo=null,this.timeCorrection=0,this.listeners.clear()}}});var Cn=Object.freeze({__proto__:null,HlsJsPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"HLS.js Player",shortname:"hlsjs",priority:3,mimes:["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"]},this.hls=null,this.container=null,this.failureCount=0,this.destroyed=!1,this.liveDurationProxy=null}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(Ie(t.url))return!1;const i=ke();if(i.isAndroid&&i.isMobile)return!1;if(!i.supportsMediaSource){return!!document.createElement("video").canPlayType("application/vnd.apple.mpegurl")&&["video","audio"]}const r=[],s={};if(!n.meta.tracks||0===n.meta.tracks.length)return["video","audio"];for(const e of n.meta.tracks)if("meta"!==e.type)s[e.type]||(s[e.type]=[]),s[e.type].push(e);else if("subtitle"===e.codec)for(const e of n.source)if("html5/text/vtt"===e.type){r.push("subtitle");break}const a=["OPUS","Opus","opus","VORBIS","Vorbis","FLAC"];for(const[e,t]of Object.entries(s)){let n=!1;for(const i of t){if("audio"===e&&a.includes(i.codec)){console.debug(`[HLS.js] Codec incompatible with HLS: ${i.codec}`);continue}const t=`${"audio"===e?"audio/mp4":"video/mp4"};codecs="${_e(i)}"`;if(MediaSource.isTypeSupported&&MediaSource.isTypeSupported(t)){n=!0;break}console.debug(`[HLS.js] Codec not supported: ${t}`)}n&&r.push(e)}return r.length>0&&r}async initialize(e,t,n){console.log("[HLS.js] initialize() starting for",t.url.slice(0,60)+"..."),this.destroyed=!1,this.container=e,e.classList.add("fw-player-container");const i=document.createElement("video");i.classList.add("fw-player-video"),i.setAttribute("playsinline",""),i.setAttribute("crossorigin","anonymous"),n.autoplay&&(i.autoplay=!0),n.muted&&(i.muted=!0),i.controls=!0===n.controls,n.loop&&(i.loop=!0),n.poster&&(i.poster=n.poster),this.videoElement=i,e.appendChild(i),this.setupVideoEventListeners(i,n);try{console.log("[HLS.js] Dynamically importing hls.js module...");const e=await Promise.resolve().then(function(){return pw}),r=e.default||e;if(console.log("[HLS.js] hls.js module imported, Hls.isSupported():",r.isSupported?.()),r.isSupported()){const e={enableWorker:!1,lowLatencyMode:!0,abrEwmaDefaultEstimate:5e6,maxBufferLength:6,maxMaxBufferLength:15,backBufferLength:1/0,liveSyncDuration:4,liveMaxLatencyDuration:8,abrEwmaFastLive:2,abrEwmaSlowLive:6,...n.hlsConfig};this.hls=new r(e),this.hls.attachMedia(i),this.hls.on(r.Events.MEDIA_ATTACHED,()=>{this.hls.loadSource(t.url)}),this.hls.on(r.Events.ERROR,(e,t)=>{if(!this.destroyed&&t?.fatal)if(this.failureCount<3){this.failureCount++;try{this.hls.recoverMediaError()}catch{}}else{const e=`HLS fatal error: ${t?.type||"unknown"}`;this.emit("error",e)}}),this.hls.on(r.Events.MANIFEST_PARSED,()=>{if(this.destroyed)return;(!isFinite(i.duration)||this.hls.levels?.[0]?.details?.live)&&!this.liveDurationProxy&&(this.liveDurationProxy=new Rt(i,{constrainSeek:!0,liveOffset:0}),console.debug("[HLS.js] LiveDurationProxy initialized for live stream")),n.autoplay&&i.play().catch(e=>console.warn("HLS autoplay failed:",e))})}else{if(!i.canPlayType("application/vnd.apple.mpegurl"))throw new Error("HLS not supported in this browser");i.src=t.url,n.autoplay&&i.play().catch(e=>console.warn("Native HLS autoplay failed:",e))}try{const e=t.subtitles;Array.isArray(e)&&e.forEach((e,t)=>{const n=document.createElement("track");n.kind="subtitles",n.label=e.label,n.srclang=e.lang,n.src=e.src,0===t&&(n.default=!0),i.appendChild(n)})}catch{}return console.log("[HLS.js] initialize() complete, returning video element"),i}catch(e){throw this.emit("error",e.message||String(e)),e}}async destroy(){if(console.debug("[HLS.js] destroy() called"),this.destroyed=!0,this.liveDurationProxy&&(this.liveDurationProxy.destroy(),this.liveDurationProxy=null),this.hls){try{this.hls.destroy(),console.debug("[HLS.js] hls.destroy() completed")}catch(e){console.warn("[HLS.js] Error destroying:",e)}this.hls=null}if(this.videoElement&&this.container)try{this.container.removeChild(this.videoElement)}catch{}this.videoElement=null,this.container=null,this.listeners.clear()}getDuration(){return this.liveDurationProxy?this.liveDurationProxy.getDuration():this.videoElement?.duration??0}isLiveStream(){if(this.liveDurationProxy)return this.liveDurationProxy.isLive();const e=this.videoElement;return!!e&&!isFinite(e.duration)}seek(e){const t=this.videoElement;t&&(this.liveDurationProxy&&this.liveDurationProxy.isLive()?this.liveDurationProxy.seek(e):t.currentTime=e)}jumpToLive(){const e=this.videoElement;if(e){if(this.hls&&"number"==typeof this.hls.liveSyncPosition&&this.hls.liveSyncPosition>0)return console.debug("[HLS.js] jumpToLive using liveSyncPosition:",this.hls.liveSyncPosition),void(e.currentTime=this.hls.liveSyncPosition);if(this.liveDurationProxy&&this.liveDurationProxy.isLive())return console.debug("[HLS.js] jumpToLive using LiveDurationProxy"),void this.liveDurationProxy.jumpToLive();if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);isFinite(t)&&t>0&&(console.debug("[HLS.js] jumpToLive using seekable.end:",t),e.currentTime=t)}}}getSeekableRange(){const e=this.videoElement;if(!e?.seekable||0===e.seekable.length)return null;const t=e.seekable.start(0);let n=e.seekable.end(e.seekable.length-1);if(this.liveDurationProxy?.isLive()&&this.hls&&"number"==typeof this.hls.liveSyncPosition){const e=this.hls.liveSyncPosition;Number.isFinite(e)&&e>0&&(n=Math.min(n,e))}return!Number.isFinite(t)||!Number.isFinite(n)||n<=t?null:{start:t,end:n}}getLiveLatency(){const e=this.videoElement;return e?this.hls&&"number"==typeof this.hls.liveSyncPosition?Math.max(0,1e3*(this.hls.liveSyncPosition-e.currentTime)):this.liveDurationProxy?1e3*this.liveDurationProxy.getLatency():0:0}getQualities(){const e=[],t=this.videoElement;if(!this.hls||!t)return e;const n=this.hls.levels||[],i={id:"auto",label:"Auto",isAuto:!0,active:this.hls.autoLevelEnabled};return e.push(i),n.forEach((t,n)=>{e.push({id:String(n),label:t.height?`${t.height}p`:`${Math.round((t.bitrate||0)/1e3)}kbps`,bitrate:t.bitrate,width:t.width,height:t.height,active:this.hls.currentLevel===n})}),e}selectQuality(e){if(!this.hls)return;if("auto"===e)return this.hls.currentLevel=-1,void(this.hls.autoLevelEnabled=!0);const t=parseInt(e,10);isNaN(t)||(this.hls.autoLevelEnabled=!1,this.hls.currentLevel=t)}getTextTracks(){const e=this.videoElement;if(!e)return[];const t=e.textTracks,n=[];for(let e=0;e<t.length;e++){const i=t[e];n.push({id:String(e),label:i.label||`CC ${e+1}`,lang:i.language,active:"showing"===i.mode})}return n}selectTextTrack(e){const t=this.videoElement;if(!t)return;const n=t.textTracks;for(let t=0;t<n.length;t++){const i=n[t];null!==e&&String(t)===e?i.mode="showing":i.mode="disabled"}}async getStats(){if(!this.hls)return;const e=(this.hls.levels||[]).map(e=>({bitrate:e.bitrate||0,width:e.width||0,height:e.height||0})),t=this.hls.currentLevel,n=e[t];let i=0;const r=this.videoElement;if(r&&r.buffered.length>0)for(let e=0;e<r.buffered.length;e++)if(r.buffered.start(e)<=r.currentTime&&r.buffered.end(e)>r.currentTime){i=r.buffered.end(e)-r.currentTime;break}let s;return r&&void 0!==this.hls.liveSyncPosition&&!isFinite(r.duration)&&(s=1e3*(this.hls.liveSyncPosition-r.currentTime)),{type:"hls",bandwidthEstimate:this.hls.bandwidthEstimate||0,currentLevel:t,currentBitrate:n?.bitrate||0,loadLevel:this.hls.loadLevel||0,levels:e,buffered:i,latency:s}}}});var Rn=Object.freeze({__proto__:null,DashJsPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"Dash.js Player",shortname:"dashjs",priority:100,mimes:["dash/video/mp4"]},this.dashPlayer=null,this.container=null,this.destroyed=!1,this.debugging=!1,this.lastProgress=Date.now(),this.videoProxy=null,this.streamType="unknown",this.subsLoaded=!1,this.pendingSubtitleId=null}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(Ie(t.url))return!1;if(Ae())return!1;if(!ke().supportsMediaSource)return!1;const i=[],r={};for(const e of n.meta.tracks)if("meta"!==e.type)r[e.type]||(r[e.type]=[]),r[e.type].push(e);else if("subtitle"===e.codec)for(const e of n.source)if("html5/text/vtt"===e.type){i.push("subtitle");break}const s=["OPUS","Opus","opus","VORBIS","Vorbis"];for(const[e,t]of Object.entries(r)){let n=!1;for(const i of t){if("audio"===e&&s.includes(i.codec)){console.debug(`[DashJS] Codec incompatible with DASH fMP4: ${i.codec}`);continue}const t=`${"audio"===e?"audio/mp4":"video/mp4"};codecs="${_e(i)}"`;if(MediaSource.isTypeSupported&&MediaSource.isTypeSupported(t)){n=!0;break}console.debug(`[DashJS] Codec not supported: ${t}`)}n&&i.push(e)}return i.length>0&&i}isLiveStream(){if("live"===this.streamType)return!0;if("vod"===this.streamType)return!1;const e=this.videoElement;return!(!e||e.duration!==1/0&&isFinite(e.duration))}createVideoProxy(e){if(!("Proxy"in window))return e;e.addEventListener("progress",()=>{this.lastProgress=Date.now()});const t=this;return new Proxy(e,{get(e,n,i){if("duration"===n&&t.isLiveStream()){const n=e.buffered;if(n.length>0){return n.end(n.length-1)+(Date.now()-t.lastProgress)/1e3}}const r=Reflect.get(e,n,i);return"function"==typeof r?r.bind(e):r},set:(e,t,n)=>Reflect.set(e,t,n)})}setupEventLogging(e){const t=["METRIC_ADDED","METRIC_UPDATED","METRIC_CHANGED","METRICS_CHANGED","FRAGMENT_LOADING_STARTED","FRAGMENT_LOADING_COMPLETED","LOG","PLAYBACK_TIME_UPDATED","PLAYBACK_PROGRESS"],n=e.MediaPlayer?.events||{};for(const e of Object.keys(n))t.includes(e)||this.dashPlayer.on(n[e],e=>{this.destroyed||this.debugging&&console.log("DASH event:",e.type)})}setupSubtitleHandling(){this.dashPlayer.on("allTextTracksAdded",()=>{this.destroyed||(this.subsLoaded=!0,null!==this.pendingSubtitleId&&(this.selectTextTrack(this.pendingSubtitleId),this.pendingSubtitleId=null))})}setupStalledHandling(){this.videoElement?.addEventListener("progress",()=>{})}async initialize(e,t,n){this.destroyed=!1,this.container=e,this.subsLoaded=!1,this.pendingSubtitleId=null,e.classList.add("fw-player-container");const i=t.type;this.streamType="live"===i?"live":"vod"===i?"vod":"unknown";const r=document.createElement("video");r.classList.add("fw-player-video"),r.setAttribute("playsinline",""),r.setAttribute("crossorigin","anonymous"),n.autoplay&&(r.autoplay=!0),n.muted&&(r.muted=!0),r.controls=!0===n.controls,n.loop&&"live"!==this.streamType&&(r.loop=!0),n.poster&&(r.poster=n.poster),this.videoProxy=this.createVideoProxy(r),this.videoElement=r,e.appendChild(r),this.setupVideoEventListeners(r,n),this.setupStalledHandling();try{console.debug("[DashJS] Importing dashjs module...");const e=await Promise.resolve().then(function(){return zw}),i=e.default||e;console.debug("[DashJS] Module imported:",i),this.dashPlayer=i.MediaPlayer().create(),console.debug("[DashJS] MediaPlayer created"),this.setupEventLogging(i),this.setupSubtitleHandling(),this.dashPlayer.on("error",e=>{if(this.destroyed)return;const t=`DASH error: ${e?.event?.message||e?.message||"unknown"}`;console.error("[DashJS] Error event:",e),this.emit("error",t)}),this.dashPlayer.on("manifestLoaded",e=>{console.debug("[DashJS] manifestLoaded:",e)}),this.dashPlayer.on("canPlay",()=>{console.debug("[DashJS] canPlay event")}),this.dashPlayer.on("streamInitialized",()=>{if(this.destroyed)return;const e=this.dashPlayer.isDynamic?.()??!1;console.debug("[DashJS v5] streamInitialized - isDynamic:",e)}),this.dashPlayer.updateSettings({streaming:{buffer:{fastSwitchEnabled:!0,stableBufferTime:4,bufferTimeAtTopQuality:8,bufferTimeAtTopQualityLongForm:15,bufferToKeep:10,bufferPruningInterval:10},gaps:{jumpGaps:!0,jumpLargeGaps:!0,smallGapLimit:1.5,threshold:.3},abr:{autoSwitchBitrate:{video:!0,audio:!0},limitBitrateByPortal:!1,useDefaultABRRules:!0,initialBitrate:{video:5e6,audio:128e3}},liveCatchup:{enabled:!0,maxDrift:1.5,playbackRate:{max:.15,min:-.15},playbackBufferMin:.3,mode:"liveCatchupModeDefault"},retryAttempts:{MPD:5,MediaSegment:5,InitializationSegment:5,BitstreamSwitchingSegment:5,IndexSegment:5,XLinkExpansion:3,other:3},retryIntervals:{MPD:1e3,MediaSegment:1e3,InitializationSegment:1e3,BitstreamSwitchingSegment:1e3,IndexSegment:1e3,XLinkExpansion:1e3,other:1e3},timeoutAttempts:{MPD:2,MediaSegment:2,InitializationSegment:2,BitstreamSwitchingSegment:2,IndexSegment:2,XLinkExpansion:1,other:1},abandonLoadTimeout:5e3,xhrWithCredentials:!1,text:{defaultEnabled:!1},delay:{liveDelay:2,liveDelayFragmentCount:null,useSuggestedPresentationDelay:!1}},debug:{logLevel:4}}),this.dashPlayer.on("fragmentLoadingStarted",e=>{console.debug("[DashJS] Fragment loading started:",e.request?.url?.split("/").pop())}),this.dashPlayer.on("fragmentLoadingCompleted",e=>{console.debug("[DashJS] Fragment loading completed:",e.request?.url?.split("/").pop())}),this.dashPlayer.on("fragmentLoadingAbandoned",e=>{console.warn("[DashJS] Fragment loading ABANDONED:",e.request?.url?.split("/").pop(),e)}),this.dashPlayer.on("fragmentLoadingFailed",e=>{console.error("[DashJS] Fragment loading FAILED:",e.request?.url?.split("/").pop(),e)}),console.debug("[DashJS v5] Initializing with URL:",t.url),this.dashPlayer.initialize(r,t.url,n.autoplay??!1),console.debug("[DashJS v5] Initialize called");try{const e=t.subtitles;Array.isArray(e)&&e.forEach((e,t)=>{const n=document.createElement("track");n.kind="subtitles",n.label=e.label,n.srclang=e.lang,n.src=e.src,0===t&&(n.default=!0),r.appendChild(n)})}catch{}return r}catch(e){throw this.emit("error",e.message||String(e)),e}}async getStats(){if(this.dashPlayer&&this.videoElement)try{const e=this.dashPlayer.getCurrentRepresentationForType?.("video"),t=this.dashPlayer.getRepresentationsByType?.("video")||[],n=this.dashPlayer.getBufferLength("video")||0,i=e?t.findIndex(t=>t.id===e.id):0;return{type:"dash",currentQuality:i>=0?i:0,bufferLevel:n,bitrateInfoList:t.map(e=>({bitrate:e.bandwidth||0,width:e.width||0,height:e.height||0})),currentBitrate:e?.bandwidth||0,playbackRate:this.videoElement.playbackRate}}catch{return}}setPlaybackRate(e){this.videoElement&&(this.videoElement.playbackRate=e)}setSource(e){this.dashPlayer&&this.dashPlayer.attachSource(e)}getDuration(){return this.videoProxy&&this.isLiveStream()?this.videoProxy.duration??0:this.videoElement?.duration??0}jumpToLive(){const e=this.videoElement;if(e&&this.isLiveStream()){if(this.dashPlayer&&"function"==typeof this.dashPlayer.seekToLive)return console.debug("[DashJS] jumpToLive using seekToLive()"),void this.dashPlayer.seekToLive();if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);isFinite(t)&&t>0&&(console.debug("[DashJS] jumpToLive using seekable.end:",t),e.currentTime=t)}}}getLiveLatency(){const e=this.videoElement;if(!e||!this.isLiveStream())return 0;if(this.dashPlayer&&"function"==typeof this.dashPlayer.getCurrentLiveLatency)return 1e3*this.dashPlayer.getCurrentLiveLatency();if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);if(isFinite(t))return Math.max(0,1e3*(t-e.currentTime))}return 0}async destroy(){if(this.destroyed=!0,this.subsLoaded=!1,this.pendingSubtitleId=null,this.videoProxy=null,this.dashPlayer){try{this.dashPlayer.reset()}catch(e){console.warn("Error destroying DASH.js:",e)}this.dashPlayer=null}if(this.videoElement&&this.container)try{this.container.removeChild(this.videoElement)}catch{}this.videoElement=null,this.container=null,this.listeners.clear()}getQualities(){const e=[],t=this.videoElement;if(!this.dashPlayer||!t)return e;try{const t=this.dashPlayer.getRepresentationsByType?.("video")||[],n=this.dashPlayer.getSettings?.(),i=!1!==n?.streaming?.abr?.autoSwitchBitrate?.video;e.push({id:"auto",label:"Auto",isAuto:!0,active:i}),t.forEach((t,n)=>{e.push({id:String(n),label:t.height?`${t.height}p`:`${Math.round((t.bandwidth||0)/1e3)}kbps`,bitrate:t.bandwidth,width:t.width,height:t.height})})}catch{}return e}selectQuality(e){if(!this.dashPlayer)return;if("auto"===e)return void this.dashPlayer.updateSettings({streaming:{abr:{autoSwitchBitrate:{video:!0}}}});const t=parseInt(e,10);if(!isNaN(t)){this.dashPlayer.updateSettings({streaming:{abr:{autoSwitchBitrate:{video:!1}}}});try{this.dashPlayer.setRepresentationForTypeByIndex?.("video",t)}catch{}}}getTextTracks(){const e=this.videoElement;if(!this.dashPlayer||!e)return[];const t=[];try{const n=e.textTracks||[];for(let e=0;e<n.length;e++){const i=n[e];t.push({id:String(e),label:i.label||`CC ${e+1}`,lang:i.language,active:"showing"===i.mode})}}catch{}return t}selectTextTrack(e){const t=this.videoElement;if(!this.dashPlayer||!t)return;if(!this.subsLoaded)return void(this.pendingSubtitleId=e);try{const t=this.dashPlayer.getTracksFor("text");if(t&&t.length>0){const n=null===e?-1:parseInt(e,10);if(n>=0&&n<t.length)return void this.dashPlayer.setTextTrack(n);if(null===e||n<0)return void this.dashPlayer.setTextTrack(-1)}}catch{}const n=t.textTracks;for(let t=0;t<n.length;t++){const i=n[t];null!==e&&String(t)===e?i.mode="showing":i.mode="disabled"}}}});var xn=Object.freeze({__proto__:null,MistPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"Legacy",shortname:"mist-legacy",priority:99,mimes:["mist/legacy"]},this.container=null,this.mistDiv=null,this.proxyVideo=null,this.previousContainerOverflow=null,this.destroyed=!1}isMimeSupported(e){return"mist/legacy"===e}isBrowserSupported(e,t,n){return"mist/legacy"===e&&["video","audio"]}async initialize(e,t,n){this.destroyed=!1,this.container=e,e.classList.add("fw-player-container");const i=t.streamName||"stream",r=`${i.replace(/[^a-zA-Z0-9]/g,"_")}_${Math.random().toString(36).slice(2,10)}`;this.mistDiv=document.createElement("div"),this.mistDiv.className="mistvideo fw-player-container",this.mistDiv.id=r,this.mistDiv.style.width="100%",this.mistDiv.style.height="100%",this.mistDiv.style.overflow="hidden",this.previousContainerOverflow=e.style.overflow??"",e.style.overflow="hidden",e.appendChild(this.mistDiv);const s=this.getPlayerJsUrl(t);await this.loadAndPlay(i,r,s,n);const a=this.findVideoElement()||this.createProxyVideo(e);return this.videoElement=a,this.setupVideoEventListeners(a,n),a}getPlayerJsUrl(e){if(e.mistPlayerUrl)return e.mistPlayerUrl;try{const t=new URL(e.url);return`${t.protocol}//${t.host}/player.js`}catch{return"/player.js"}}async loadAndPlay(e,t,n,i){const r=()=>{if(!this.destroyed&&window.mistPlay){const n={target:document.getElementById(t),fillSpace:!0,controls:!0,skin:i.devMode?"dev":"default",...void 0!==i.autoplay&&{autoplay:i.autoplay},...void 0!==i.muted&&{muted:i.muted},...i.poster&&{poster:i.poster}};console.debug("[Legacy] mistPlay options:",n),window.mistPlay(e,n)}};window.mistplayers?r():await new Promise((e,t)=>{const i=document.createElement("script");i.src=n,i.onload=()=>{r(),e()},i.onerror=()=>t(new Error(`Failed to load MistServer player from ${n}`)),document.head.appendChild(i)})}findVideoElement(){return this.mistDiv?this.mistDiv.querySelector("video"):null}createProxyVideo(e){const t=document.createElement("video");return t.style.display="none",e.appendChild(t),this.proxyVideo=t,t}async destroy(){if(this.destroyed=!0,this.mistDiv){try{const e=this.mistDiv.MistVideoObject?.reference;e&&"function"==typeof e.unload&&e.unload()}catch{}try{this.mistDiv.remove()}catch{try{this.mistDiv.parentNode?.removeChild(this.mistDiv)}catch{}}this.mistDiv=null}if(this.proxyVideo){try{this.proxyVideo.remove()}catch{try{this.proxyVideo.parentNode?.removeChild(this.proxyVideo)}catch{}}this.proxyVideo=null}if(this.container)try{null!==this.previousContainerOverflow&&(this.container.style.overflow=this.previousContainerOverflow)}catch{}this.videoElement=null,this.container=null,this.previousContainerOverflow=null,this.listeners.clear()}}});class Dn{constructor(e){this.ws=null,this.reconnectAttempts=0,this.reconnectTimer=null,this.wasConnected=!1,this.isDestroyed=!1,this.pendingRetryTimers=new Set,this.listeners={},this.url=e.url,this.maxReconnectAttempts=e.maxReconnectAttempts??5,this.onMessage=e.onMessage,this.onOpen=e.onOpen,this.onClose=e.onClose,this.onError=e.onError}connect(){if(this.isDestroyed)return;try{const e=window.location.protocol.replace(/^http/,"ws"),t=new URL(this.url,window.location.href).protocol;e!==t&&this.onError(`Protocol mismatch ${e} vs ${t}`)}catch{}const e=new WebSocket(this.url);e.binaryType="arraybuffer",this.ws=e,e.onopen=()=>{this.wasConnected=!0,this.reconnectAttempts=0,this.clearReconnectTimer(),this.onOpen()},e.onmessage=e=>{this.onMessage(e.data)},e.onerror=()=>{this.onError("WebSocket error")},e.onclose=()=>{if(!this.isDestroyed)if(this.wasConnected&&this.reconnectAttempts<this.maxReconnectAttempts){const e=Math.min(5e3,500*Math.pow(2,this.reconnectAttempts));this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{this.isDestroyed||this.connect()},e)}else this.onClose(),this.onError("WebSocket closed")}}send(e,t=0){if(this.isDestroyed)return!1;if(t>5)return this.onError("Too many send retries"),!1;const n=n=>{const i=setTimeout(()=>{this.pendingRetryTimers.delete(i),this.isDestroyed||this.send(e,t+1)},n);this.pendingRetryTimers.add(i)};if(!this.ws)return!this.isDestroyed&&t<5&&n(500),!1;if(this.ws.readyState<WebSocket.OPEN)return!this.isDestroyed&&t<5&&n(500),!1;if(this.ws.readyState>=WebSocket.CLOSING)return!this.isDestroyed&&t<5&&(this.connect(),n(1e3)),!1;try{return this.ws.send(JSON.stringify(e)),!0}catch{return!1}}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}destroy(){console.debug("[WebSocketManager] destroy() called"),this.isDestroyed=!0,this.clearReconnectTimer();for(const e of this.pendingRetryTimers)clearTimeout(e);if(this.pendingRetryTimers.clear(),this.listeners={},this.ws){try{this.ws.close()}catch{}this.ws=null}console.debug("[WebSocketManager] destroy() completed")}isConnected(){return this.ws?.readyState===WebSocket.OPEN}addListener(e,t){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push(t)}removeListener(e,t){if(!(e in this.listeners))return!1;const n=this.listeners[e].indexOf(t);return!(n<0)&&(this.listeners[e].splice(n,1),!0)}notifyListeners(e){if(e.type in this.listeners){const t=this.listeners[e.type];for(let n=t.length-1;n>=0;n--)try{t[n](e)}catch(e){console.error("MEWS listener error:",e)}}}}class Ln{constructor(e){this.sourceBuffer=null,this.queue=[],this._busy=!1,this.do_on_updateend=[],this.msgqueue=!1,this._codecs=[],this.fragmentCount=0,this.paused=!1,this.debugging=!1,this.mediaSource=e.mediaSource,this.videoElement=e.videoElement,this.onError=e.onError}initWithCodecs(e){if(this.sourceBuffer)return!0;if(!e||!e.length)return this.onError("No codecs provided"),!1;const t=`video/mp4;codecs="${e.join(",")}"`;if(!MediaSource.isTypeSupported(t))return this.onError(`Unsupported MSE codec: ${t}`),!1;try{return this.sourceBuffer=this.mediaSource.addSourceBuffer(t),this.sourceBuffer.mode="segments",this._codecs=e.slice(),this.installEventHandlers(),this.drainMessageQueue(),this.flushQueue(),!0}catch(e){return this.onError(e?.message||"Failed to create SourceBuffer"),!1}}getCodecs(){return this._codecs}append(e){e&&e.byteLength&&(this.msgqueue?this.msgqueue[this.msgqueue.length-1].push(e):this.sourceBuffer?this.sourceBuffer.updating||this.queue.length||this._busy?this.queue.push(e):this._append(e):this.queue.push(e))}_append(e){if(e&&e.buffer&&this.sourceBuffer){if(this._busy)return this.debugging&&console.warn("MEWS: wanted to append but busy, requeuing"),void this.queue.unshift(e);this._busy=!0;try{if(e.buffer instanceof SharedArrayBuffer){const t=new ArrayBuffer(e.byteLength);new Uint8Array(t).set(e),this.sourceBuffer.appendBuffer(t)}else this.sourceBuffer.appendBuffer(e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength))}catch(t){switch(t?.name){case"QuotaExceededError":{const t=this.videoElement.buffered;if(t.length&&this.videoElement.currentTime-t.start(0)>1)return this.debugging&&console.log("MEWS: QuotaExceededError, cleaning buffer"),this._clean(1),this._busy=!1,void this._append(e);if(t.length){const n=t.end(t.length-1);return this.debugging&&console.log("MEWS: QuotaExceededError, skipping ahead"),this.videoElement.currentTime=n,this._busy=!1,void this._append(e)}break}case"InvalidStateError":if(this.videoElement.error)return void(this._busy=!1)}this.onError(t?.message||"Append buffer failed"),this._busy=!1}}}_doNext(e){this.do_on_updateend.push(e)}_do(e){this.sourceBuffer?this.sourceBuffer.updating||this._busy?this._doNext(e):e():this._doNext(e)}scheduleAfterUpdate(e){this._doNext(e)}changeCodecs(e,t){if(this.codecsEqual(this._codecs,e))return void(this.debugging&&console.log("MEWS: keeping source buffer, codecs same"));const n=`video/mp4;codecs="${e.join(",")}"`;if(!MediaSource.isTypeSupported(n))return void this.onError(`Unsupported codec for switch: ${n}`);this.msgqueue?this.msgqueue.push([]):this.msgqueue=[[]];const i=e.slice();"number"==typeof t&&t>0?this.awaitSwitchingPoint(n,t,i):this.clearAndReinit(n,i)}codecsEqual(e,t){if(e.length!==t.length)return!1;for(const n of e)if(!t.includes(n))return!1;return!0}findBufferIndex(e){const t=this.videoElement.buffered;for(let n=0;n<t.length;n++)if(t.start(n)<=e&&t.end(n)>=e)return n;return!1}_clean(e=180){if(!this.sourceBuffer)return;const t=this.videoElement.currentTime;t<=e||this._do(()=>{if(this.sourceBuffer)try{this.sourceBuffer.remove(0,Math.max(.1,t-e))}catch{}})}clearAndReinit(e,t){this._do(n=>{if(this.sourceBuffer)if(this.sourceBuffer.updating)this._doNext(()=>this.clearAndReinit(e,t));else{try{isNaN(this.mediaSource.duration)||this.sourceBuffer.remove(0,1/0)}catch{}this._doNext(()=>{this.reinitBuffer(e,t,n)})}else this.reinitBuffer(e,t,n)})}reinitBuffer(e,t,n){const i=this.queue.slice();if(this.queue=[],this.sourceBuffer&&"open"===this.mediaSource.readyState)try{this.mediaSource.removeSourceBuffer(this.sourceBuffer)}catch{}this.sourceBuffer=null,this._busy=!1;try{this.sourceBuffer=this.mediaSource.addSourceBuffer(e),this.sourceBuffer.mode="segments",this._codecs=t,this.installEventHandlers(),n?.length&&(this.do_on_updateend=n),this.drainMessageQueue();for(const e of i)this.append(e)}catch(e){this.onError(e?.message||"Failed to reinit SourceBuffer")}}awaitSwitchingPoint(e,t,n){const i=t/1e3,r=()=>{this.clearAndReinit(e,n)},s=()=>{this.videoElement.currentTime>=i&&(this.videoElement.removeEventListener("timeupdate",s),this.videoElement.removeEventListener("waiting",a),r())},a=()=>{this.videoElement.removeEventListener("timeupdate",s),this.videoElement.removeEventListener("waiting",a),r()};this.videoElement.addEventListener("timeupdate",s),this.videoElement.addEventListener("waiting",a)}drainMessageQueue(){if(!this.msgqueue||0===this.msgqueue.length)return;const e=this.msgqueue[0];let t=!1;if(e.length)for(const t of e)this.sourceBuffer&&(this.sourceBuffer.updating||this.queue.length||this._busy)?this.queue.push(t):this._append(t);else t=!0;this.msgqueue.shift(),0===this.msgqueue.length&&(this.msgqueue=!1),this.debugging&&console.log("MEWS: drained msgqueue",this.msgqueue?`${this.msgqueue.length} more queue(s) remain`:""),t&&this.sourceBuffer&&this.sourceBuffer.dispatchEvent(new Event("updateend"))}installEventHandlers(){this.sourceBuffer&&(this.sourceBuffer.addEventListener("updateend",()=>{if(!this.sourceBuffer)return void(this.debugging&&console.log("MEWS: updateend but sourceBuffer is null"));this.fragmentCount>=500?(this.fragmentCount=0,this._clean(10)):this.fragmentCount++;const e=this.do_on_updateend.slice();this.do_on_updateend=[];for(let t=0;t<e.length;t++){if(!this.sourceBuffer){this.debugging&&console.warn("MEWS: doing updateend but sb was reset");break}if(this.sourceBuffer.updating){this.do_on_updateend=this.do_on_updateend.concat(e.slice(t)),this.debugging&&console.warn("MEWS: doing updateend but was interrupted");break}try{e[t](t<e.length-1?e.slice(t+1):[])}catch(e){console.error("MEWS: error in do_on_updateend:",e)}}this._busy=!1,this.sourceBuffer&&this.queue.length>0&&!this.sourceBuffer.updating&&!this.videoElement.error&&this._append(this.queue.shift())}),this.sourceBuffer.addEventListener("error",()=>{this.onError("SourceBuffer error")}))}flushQueue(){if(!this.sourceBuffer)return;const e=this.queue.slice();this.queue=[];for(const t of e)this.append(t)}hasActiveMessageQueue(){return!1!==this.msgqueue}destroy(){if(this.sourceBuffer)try{this.sourceBuffer.abort()}catch{}this.sourceBuffer=null,this.queue=[],this._busy=!1,this.do_on_updateend=[],this.msgqueue=!1,this.paused=!1}}var Pn,Nn,Mn=Object.freeze({__proto__:null,MewsWsPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"MEWS WebSocket Player",shortname:"mews",priority:2,mimes:["ws/video/mp4","wss/video/mp4","ws/video/webm","wss/video/webm"]},this.wsManager=null,this.sbManager=null,this.mediaSource=null,this.objectUrl=null,this.container=null,this.isDestroyed=!1,this.debugging=!1,this.serverDelays=[],this.pendingDelayTypes={},this.supportedCodecs=[],this.isReady=!1,this.readyResolvers=[],this.lastDuration=1/0,this.streamType="unknown",this.currentTracks=[],this.lastCodecs=null,this.requestedRate=1,this.bitCounter=[],this.bitsSince=[],this.currentBps=null,this.nWaiting=0,this.nWaitingThreshold=3,this.seeking=!1,this.analyticsConfig={enabled:!1,endpoint:null},this.analyticsTimer=null}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(!("WebSocket"in window)||!("MediaSource"in window)||!("Promise"in window))return!1;if(/Mac OS X/.test(navigator.userAgent))return!1;const i=e.split("/")[2]||"mp4",r={};let s=!1;this.supportedCodecs=[];for(const e of n.meta.tracks){if("meta"===e.type){"subtitle"===e.codec&&(s=!0);continue}const t=`video/${i};codecs="${_e(e)}"`;MediaSource.isTypeSupported(t)&&(this.supportedCodecs.push(e.codec),r[e.type]=1)}if(s){const e=n.source?.some(e=>"html5/text/vtt"===e.type);e&&(r.subtitle=1)}return 0!==Object.keys(r).length&&Object.keys(r)}async initialize(e,t,n,i){this.container=e,e.classList.add("fw-player-container");const r=document.createElement("video");r.classList.add("fw-player-video"),r.setAttribute("playsinline",""),r.setAttribute("crossorigin","anonymous"),n.autoplay&&(r.autoplay=!0),n.muted&&(r.muted=!0),r.controls=!0===n.controls,n.loop&&(r.loop=!0),n.poster&&(r.poster=n.poster),"live"===this.streamType&&(r.loop=!1),this.videoElement=r,e.appendChild(r),this.setupVideoEventListeners(r,n);const s=n;this.analyticsConfig={enabled:!!s.analytics?.enabled,endpoint:s.analytics?.endpoint||null},"live"===i?.type?this.streamType="live":"vod"===i?.type&&(this.streamType="vod");try{return this.mediaSource=new MediaSource,this.mediaSource.addEventListener("sourceopen",()=>this.handleSourceOpen(t)),this.mediaSource.addEventListener("sourceclose",()=>this.handleSourceClose()),this.mediaSource.addEventListener("sourceended",()=>this.handleSourceEnded()),this.objectUrl=URL.createObjectURL(this.mediaSource),r.src=this.objectUrl,this.isDestroyed=!1,this.startTelemetry(),r}catch(e){throw this.emit("error",e.message||String(e)),e}}handleSourceOpen(e){this.mediaSource&&this.videoElement&&(this.sbManager=new Ln({mediaSource:this.mediaSource,videoElement:this.videoElement,onError:e=>this.emit("error",e)}),this.installWaitingHandler(),this.installSeekingHandler(),this.installPauseHandler(),this.installLoopHandler(),this.wsManager=new Dn({url:e.url,maxReconnectAttempts:5,onMessage:e=>this.handleMessage(e),onOpen:()=>this.handleWsOpen(),onClose:()=>this.handleWsClose(),onError:e=>this.emit("error",e)}),this.wsManager.connect())}handleSourceClose(){this.debugging&&console.log("MEWS: MediaSource closed"),this.send({type:"stop"})}handleSourceEnded(){this.debugging&&console.log("MEWS: MediaSource ended"),this.send({type:"stop"})}handleWsOpen(){const e=t=>{if("open"===this.mediaSource?.readyState){const e=t.data?.codecs||[],n=this.sbManager?.initWithCodecs(e);if(n&&!this.isReady){this.isReady=!0;for(const e of this.readyResolvers)e();this.readyResolvers=[]}}this.wsManager?.removeListener("codec_data",e)};this.wsManager?.addListener("codec_data",e),this.logDelay("codec_data"),this.send({type:"request_codec_data",supported_codecs:this.supportedCodecs})}handleWsClose(){this.debugging&&console.log("MEWS: WebSocket closed")}handleMessage(e){if("string"==typeof e){try{const t=JSON.parse(e);this.handleControlMessage(t),this.wsManager?.notifyListeners(t)}catch(e){this.debugging&&console.error("MEWS: Failed to parse message",e)}return}const t=new Uint8Array(e);this.sbManager?.append(t),this.trackBits(e)}handleControlMessage(e){switch(this.debugging&&"on_time"!==e.type&&console.log("MEWS: message",e),e.type){case"on_stop":this.handleOnStop();break;case"on_time":this.handleOnTime(e);break;case"tracks":this.handleTracks(e);break;case"pause":this.handlePause();break;case"codec_data":this.resolveDelay("codec_data");break;case"seek":this.resolveDelay("seek");break;case"set_speed":this.resolveDelay("set_speed")}}handleOnStop(){this.streamType="vod";const e=()=>{this.sbManager&&(this.sbManager.paused=!0),this.emit("ended",void 0),this.videoElement?.removeEventListener("waiting",e)};this.videoElement?.addEventListener("waiting",e)}handleOnTime(e){const t=e.data;if(!t||!this.videoElement)return;const n=t.current,i=t.end,r=t.jitter||0,s=n-1e3*this.videoElement.currentTime,a=this.getServerDelay(),o=/Chrome/.test(navigator.userAgent)&&!/Edge|Edg/.test(navigator.userAgent)?1e3:100,l=Math.max(o+a,2*a),u=l+r,d="live"!==this.streamType?l+2e3:l;if(this.debugging&&console.log("MEWS: on_time","current:",n/1e3,"video:",this.videoElement.currentTime,"rate:",this.requestedRate+"x","buffer:",Math.round(s),"/",Math.round(l),"live"===this.streamType?"latency:"+Math.round((i||0)-1e3*this.videoElement.currentTime)+"ms":""),this.sbManager){if(void 0!==i&&this.lastDuration!==i/1e3&&(this.lastDuration=i/1e3),this.sbManager.paused=!1,"live"===this.streamType?this.tuneLivePlaybackRate(s,u,t.play_rate_curr):this.tuneVodDeliverySpeed(s,d,t.play_rate_curr),t.tracks&&this.currentTracks.join(",")!==t.tracks.join(",")){if(this.debugging)for(const e of t.tracks)this.currentTracks.includes(e)||console.log("MEWS: track changed",e);this.currentTracks=t.tracks}}else this.debugging&&console.log("MEWS: on_time but no sourceBuffer")}tuneLivePlaybackRate(e,t,n){this.videoElement&&(1===this.requestedRate?"auto"===n&&this.videoElement.currentTime>0&&(e>2*t?(this.requestedRate=1+.08*Math.min(1,(e-t)/t),this.videoElement.playbackRate=this.requestedRate,this.debugging&&console.log("MEWS: speeding up to",this.requestedRate)):e<0?(this.requestedRate=.8,this.videoElement.playbackRate=this.requestedRate,this.debugging&&console.log("MEWS: slowing down to",this.requestedRate)):e<t/2&&(this.requestedRate=1+.08*Math.min(1,(e-t)/t),this.videoElement.playbackRate=this.requestedRate,this.debugging&&console.log("MEWS: adjusting to",this.requestedRate))):this.requestedRate>1?e<t&&(this.videoElement.playbackRate=1,this.requestedRate=1,this.debugging&&console.log("MEWS: returning to normal rate")):e>t&&(this.videoElement.playbackRate=1,this.requestedRate=1,this.debugging&&console.log("MEWS: returning to normal rate")))}tuneVodDeliverySpeed(e,t,n){1===this.requestedRate?"auto"===n&&(e<t/2?e<-1e4?this.send({type:"seek",seek_time:Math.round(1e3*(this.videoElement?.currentTime||0))}):(this.requestedRate=2,this.send({type:"set_speed",play_rate:this.requestedRate}),this.debugging&&console.log("MEWS: requesting faster delivery")):e-t>t&&(this.requestedRate=.5,this.send({type:"set_speed",play_rate:this.requestedRate}),this.debugging&&console.log("MEWS: requesting slower delivery"))):this.requestedRate>1?e>t&&(this.send({type:"set_speed",play_rate:"auto"}),this.requestedRate=1,this.debugging&&console.log("MEWS: returning to realtime delivery")):e<t&&(this.send({type:"set_speed",play_rate:"auto"}),this.requestedRate=1,this.debugging&&console.log("MEWS: returning to realtime delivery"))}handleTracks(e){const t=e.data?.codecs||[],n=e.data?.current;if(!t.length)return void this.emit("error","Track switch contains no codecs");const i=this.lastCodecs||this.sbManager?.getCodecs()||[];if(this.codecsEqual(i,t))return this.debugging&&console.log("MEWS: keeping buffer, codecs same"),void(0===this.videoElement?.currentTime&&n&&0!==n&&this.setSeekingPosition(n/1e3));this.lastCodecs=t,this.sbManager?.changeCodecs(t,n)}handlePause(){this.sbManager&&(this.sbManager.paused=!0)}setSeekingPosition(e){if(!this.videoElement||!this.sbManager)return;const t=this.videoElement.currentTime;t>e&&(e=t);const n=this.videoElement.buffered;!n.length||n.end(n.length-1)<e?this.sbManager.scheduleAfterUpdate(()=>this.setSeekingPosition(e)):(this.videoElement.currentTime=e,this.videoElement.currentTime<e-.001&&this.sbManager.scheduleAfterUpdate(()=>this.setSeekingPosition(e)))}codecsEqual(e,t){if(e.length!==t.length)return!1;for(const n of e)if(!t.includes(n))return!1;return!0}async play(){const e=this.videoElement;if(e&&e.paused)return this.isReady||await new Promise((e,t)=>{const n=setTimeout(()=>{t(new Error("MEWS: Timeout waiting for codec data"))},5e3);this.readyResolvers.push(()=>{clearTimeout(n),e()})}),new Promise((t,n)=>{let i=!1;const r=s=>{if(i)return;if(i=!0,this.wsManager?.removeListener("on_time",r),!this.sbManager)return this.debugging&&console.log("MEWS: play waiting for sourceBuffer"),i=!1,void this.wsManager?.addListener("on_time",r);const a=s.data;if("live"===this.streamType){const i=()=>{if(!e.buffered.length)return;const i=this.sbManager?.findBufferIndex(a.current/1e3);"number"==typeof i&&((e.buffered.start(i)>e.currentTime||e.buffered.end(i)<e.currentTime)&&(e.currentTime=a.current/1e3,this.debugging&&console.log("MEWS: seeking to live position",e.currentTime)),e.play().then(t).catch(e=>{this.pause(),n(e)}),this.sbManager.paused=!1)};this.sbManager?.scheduleAfterUpdate(i)}else this.sbManager.paused=!1,e.buffered.length&&e.buffered.start(0)>e.currentTime&&(e.currentTime=e.buffered.start(0)),e.play().then(t).catch(n)};this.wsManager?.addListener("on_time",r);"live"===this.streamType&&0===e.currentTime?this.send({type:"play",seek_time:"live"}):this.send({type:"play"})})}pause(){this.videoElement?.pause(),this.send({type:"hold"}),this.sbManager&&(this.sbManager.paused=!0)}seek(e){if(!this.videoElement||isNaN(e)||e<0)return;const t=Math.round(Math.max(0,1e3*e-(250+this.getServerDelay())));this.logDelay("seek"),this.send({type:"seek",seek_time:t});const n=()=>{this.wsManager?.removeListener("seek",n);const e=t=>{this.wsManager?.removeListener("on_time",e);const n=t.data.current/1e3;this.trySetCurrentTime(n)};this.wsManager?.addListener("on_time",e)};this.wsManager?.addListener("seek",n),this.videoElement.currentTime=e,this.debugging&&console.log("MEWS: seeking to",e)}trySetCurrentTime(e,t=10){const n=this.videoElement;n&&(n.currentTime=e,n.currentTime<e-.001&&t>0&&this.sbManager?.scheduleAfterUpdate(()=>this.trySetCurrentTime(e,t-1)))}getCurrentTime(){return this.videoElement?.currentTime??0}getDuration(){return isFinite(this.lastDuration)?this.lastDuration:super.getDuration()}setPlaybackRate(e){super.setPlaybackRate(e);const t=1===e?"auto":e;this.logDelay("set_speed"),this.send({type:"set_speed",play_rate:t})}getQualities(){return[{id:"auto",label:"Auto",isAuto:!0,active:!0}]}selectQuality(e){"auto"===e&&this.send({type:"set_speed",play_rate:"auto"})}setTracks(e){Object.keys(e).length&&this.send({type:"tracks",...e})}selectTextTrack(e){null===e?this.send({type:"tracks",subtitle:"none"}):this.send({type:"tracks",subtitle:e})}isLive(){return"live"===this.streamType}jumpToLive(){"live"===this.streamType&&this.wsManager&&(this.send({type:"play",seek_time:"live"}),this.videoElement?.play().catch(()=>{}))}async getStats(){return{currentBps:this.currentBps,waitingEvents:this.nWaiting,isLive:"live"===this.streamType,serverDelay:this.getServerDelay()}}installWaitingHandler(){this.videoElement&&this.videoElement.addEventListener("waiting",()=>{if(this.seeking)return;const e=this.videoElement;if(!e.buffered||!e.buffered.length)return;const t=this.sbManager?.findBufferIndex(e.currentTime);if(!1!==t&&"number"==typeof t&&t+1<e.buffered.length){const n=e.buffered.start(t+1);n-e.currentTime<10&&(this.debugging&&console.log("MEWS: skipping buffer gap to",n),e.currentTime=n)}this.nWaiting++,this.nWaiting>=this.nWaitingThreshold&&this.currentBps&&(this.nWaiting=0,this.debugging&&console.log("MEWS: ABR triggered, requesting lower bitrate"),this.setTracks({video:`<${Math.round(this.currentBps)}bps,minbps`}))})}installSeekingHandler(){this.videoElement&&(this.videoElement.addEventListener("seeking",()=>{this.seeking=!0}),this.videoElement.addEventListener("seeked",()=>{this.seeking=!1}))}installPauseHandler(){this.videoElement&&this.videoElement.addEventListener("pause",()=>{if(this.sbManager&&!this.sbManager.paused){this.debugging&&console.log("MEWS: browser paused, pausing download"),this.send({type:"hold"}),this.sbManager.paused=!0;const e=()=>{this.sbManager?.paused&&this.send({type:"play"}),this.videoElement?.removeEventListener("play",e)};this.videoElement?.addEventListener("play",e)}})}installLoopHandler(){this.videoElement&&this.videoElement.addEventListener("ended",()=>{const e=this.videoElement;e&&e.loop&&"live"!==this.streamType&&(this.seek(0),this.sbManager?._do(()=>{}))})}send(e){this.wsManager&&this.wsManager.send(e)}logDelay(e){this.pendingDelayTypes[e]=Date.now()}resolveDelay(e){const t=this.pendingDelayTypes[e];if(t){const n=Date.now()-t;this.serverDelays.unshift(n),this.serverDelays.length>5&&this.serverDelays.pop(),delete this.pendingDelayTypes[e]}}getServerDelay(){if(!this.serverDelays.length)return 500;const e=Math.min(3,this.serverDelays.length);let t=0;for(let n=0;n<e;n++)t+=this.serverDelays[n];return t/e}trackBits(e){if(this.bitCounter.push(8*e.byteLength),this.bitsSince.push(Date.now()),this.bitCounter.length>5&&(this.bitCounter.shift(),this.bitsSince.shift()),this.bitCounter.length>=2){const e=this.bitCounter[this.bitCounter.length-1],t=(this.bitsSince[this.bitsSince.length-1]-this.bitsSince[0])/1e3;t>0&&(this.currentBps=Math.round(e/t))}}startTelemetry(){if(!this.analyticsConfig.enabled||!this.analyticsConfig.endpoint)return;const e=this.analyticsConfig.endpoint;this.analyticsTimer=setInterval(async()=>{if(!this.videoElement)return;const t=await this.getStats(),n={t:Date.now(),bps:t.currentBps||0,waiting:t.waitingEvents||0};try{await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})}catch{}},5e3)}async destroy(){if(console.debug("[MEWS] destroy() called"),this.isDestroyed=!0,this.isReady=!1,this.readyResolvers=[],this.analyticsTimer&&(clearInterval(this.analyticsTimer),this.analyticsTimer=null),this.wsManager?.destroy(),this.wsManager=null,this.sbManager?.destroy(),this.sbManager=null,"open"===this.mediaSource?.readyState)try{this.mediaSource.endOfStream()}catch{}if(this.objectUrl&&(URL.revokeObjectURL(this.objectUrl),this.objectUrl=null),this.videoElement&&this.container)try{this.container.removeChild(this.videoElement)}catch{}this.videoElement=null,this.container=null,this.mediaSource=null,this.listeners.clear(),console.debug("[MEWS] destroy() completed")}}}),On="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function Fn(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function Un(e){return e&&Object.prototype.hasOwnProperty.call(e,"default")&&1===Object.keys(e).length?e.default:e}function Bn(){return Nn?Pn:(Nn=1,e="undefined"!=typeof window?window:void 0!==On?On:"undefined"!=typeof self?self:{},Pn=e);var e}var zn,jn,qn=Fn(Bn()),$n=Un(Object.freeze({__proto__:null,default:{}}));function Hn(){if(jn)return zn;jn=1;var e,t=void 0!==On?On:"undefined"!=typeof window?window:{},n=$n;return"undefined"!=typeof document?e=document:(e=t["__GLOBAL_DOCUMENT_CACHE@4"])||(e=t["__GLOBAL_DOCUMENT_CACHE@4"]=n),zn=e}var Gn,Vn,Wn,Kn,Yn,Xn,Qn,Jn,Zn,ei,ti=Fn(Hn()),ni={exports:{}},ii={exports:{}};function ri(){if(Wn)return Vn;Wn=1,Vn=function(t){if(!t)return!1;var n=e.call(t);return"[object Function]"===n||"function"==typeof t&&"[object RegExp]"!==n||"undefined"!=typeof window&&(t===window.setTimeout||t===window.alert||t===window.confirm||t===window.prompt)};var e=Object.prototype.toString;return Vn}function si(){if(Yn)return Kn;function e(e,n){var i="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(i)return(i=i.call(e)).next.bind(i);if(Array.isArray(e)||(i=function(e,n){if(!e)return;if("string"==typeof e)return t(e,n);var i=Object.prototype.toString.call(e).slice(8,-1);"Object"===i&&e.constructor&&(i=e.constructor.name);if("Map"===i||"Set"===i)return Array.from(e);if("Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i))return t(e,n)}(e))||n){i&&(e=i);var r=0;return function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function t(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n<t;n++)i[n]=e[n];return i}return Yn=1,Kn=function(){function t(){this.typeToInterceptorsMap_=new Map,this.enabled_=!1}var n=t.prototype;return n.getIsEnabled=function(){return this.enabled_},n.enable=function(){this.enabled_=!0},n.disable=function(){this.enabled_=!1},n.reset=function(){this.typeToInterceptorsMap_=new Map,this.enabled_=!1},n.addInterceptor=function(e,t){this.typeToInterceptorsMap_.has(e)||this.typeToInterceptorsMap_.set(e,new Set);var n=this.typeToInterceptorsMap_.get(e);return!n.has(t)&&(n.add(t),!0)},n.removeInterceptor=function(e,t){var n=this.typeToInterceptorsMap_.get(e);return!(!n||!n.has(t))&&(n.delete(t),!0)},n.clearInterceptorsByType=function(e){return!!this.typeToInterceptorsMap_.get(e)&&(this.typeToInterceptorsMap_.delete(e),this.typeToInterceptorsMap_.set(e,new Set),!0)},n.clear=function(){return!!this.typeToInterceptorsMap_.size&&(this.typeToInterceptorsMap_=new Map,!0)},n.getForType=function(e){return this.typeToInterceptorsMap_.get(e)||new Set},n.execute=function(t,n){for(var i,r=e(this.getForType(t));!(i=r()).done;){var s=i.value;try{n=s(n)}catch(e){}}return n},t}()}var ai,oi,li,ui,di,ci,hi,fi=function(){if(ei)return ni.exports;ei=1;var e=Bn(),t=(Gn||(Gn=1,function(e){function t(){return e.exports=t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var i in n)({}).hasOwnProperty.call(n,i)&&(e[i]=n[i])}return e},e.exports.__esModule=!0,e.exports.default=e.exports,t.apply(null,arguments)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports}(ii)),ii.exports),n=ri(),i=si(),r=function(){if(Qn)return Xn;Qn=1;var e=function(){function e(){this.maxAttempts_=1,this.delayFactor_=.1,this.fuzzFactor_=.1,this.initialDelay_=1e3,this.enabled_=!1}var n=e.prototype;return n.getIsEnabled=function(){return this.enabled_},n.enable=function(){this.enabled_=!0},n.disable=function(){this.enabled_=!1},n.reset=function(){this.maxAttempts_=1,this.delayFactor_=.1,this.fuzzFactor_=.1,this.initialDelay_=1e3,this.enabled_=!1},n.getMaxAttempts=function(){return this.maxAttempts_},n.setMaxAttempts=function(e){this.maxAttempts_=e},n.getDelayFactor=function(){return this.delayFactor_},n.setDelayFactor=function(e){this.delayFactor_=e},n.getFuzzFactor=function(){return this.fuzzFactor_},n.setFuzzFactor=function(e){this.fuzzFactor_=e},n.getInitialDelay=function(){return this.initialDelay_},n.setInitialDelay=function(e){this.initialDelay_=e},n.createRetry=function(e){var n=void 0===e?{}:e,i=n.maxAttempts,r=n.delayFactor,s=n.fuzzFactor,a=n.initialDelay;return new t({maxAttempts:i||this.maxAttempts_,delayFactor:r||this.delayFactor_,fuzzFactor:s||this.fuzzFactor_,initialDelay:a||this.initialDelay_})},e}(),t=function(){function e(e){this.maxAttempts_=e.maxAttempts,this.delayFactor_=e.delayFactor,this.fuzzFactor_=e.fuzzFactor,this.currentDelay_=e.initialDelay,this.currentAttempt_=1}var t=e.prototype;return t.moveToNextAttempt=function(){this.currentAttempt_++;var e=this.currentDelay_*this.delayFactor_;this.currentDelay_=this.currentDelay_+e},t.shouldRetry=function(){return this.currentAttempt_<this.maxAttempts_},t.getCurrentDelay=function(){return this.currentDelay_},t.getCurrentMinPossibleDelay=function(){return(1-this.fuzzFactor_)*this.currentDelay_},t.getCurrentMaxPossibleDelay=function(){return(1+this.fuzzFactor_)*this.currentDelay_},t.getCurrentFuzzedDelay=function(){var e=this.getCurrentMinPossibleDelay(),t=this.getCurrentMaxPossibleDelay();return e+Math.random()*(t-e)},e}();return Xn=e}();o.httpHandler=function(){if(Zn)return Jn;Zn=1;var e=Bn();return Jn=function(t,n){return void 0===n&&(n=!1),function(i,r,s){if(i)t(i);else if(r.statusCode>=400&&r.statusCode<=599){var a=s;if(n)if(e.TextDecoder){var o=(void 0===(l=r.headers&&r.headers["content-type"])&&(l=""),l.toLowerCase().split(";").reduce(function(e,t){var n=t.split("="),i=n[0],r=n[1];return"charset"===i.trim()?r.trim():e},"utf-8"));try{a=new TextDecoder(o).decode(s)}catch(e){}}else a=String.fromCharCode.apply(null,new Uint8Array(s));t({cause:a})}else t(null,s);var l}}}(),o.requestInterceptorsStorage=new i,o.responseInterceptorsStorage=new i,o.retryManager=new r;
4333
+ `,nn=n([he("fw-context-menu")],nn),rn("fw-player",e.FwPlayer),rn("fw-player-controls",Bt),rn("fw-seek-bar",$t),rn("fw-volume-control",Ht),rn("fw-settings-menu",Gt),rn("fw-idle-screen",Vt),rn("fw-loading-spinner",Wt),rn("fw-title-overlay",Kt),rn("fw-error-overlay",Yt),rn("fw-toast",Xt),rn("fw-stats-panel",Qt),rn("fw-dev-mode-panel",Jt),rn("fw-subtitle-renderer",Zt),rn("fw-skip-indicator",en),rn("fw-speed-indicator",tn),rn("fw-context-menu",nn);class sn extends Ne{constructor(){super(...arguments),this.capability={name:"Native Player",shortname:"native",priority:1,mimes:["html5/video/mp4","html5/video/webm","html5/video/ogg","html5/audio/mp3","html5/audio/webm","html5/audio/ogg","html5/audio/wav","html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7","whep"]},this.peerConnection=null,this.sessionUrl=null,this.lastInboundStats=null,this.reconnectEnabled=!1,this.reconnectAttempts=0,this.maxReconnectAttempts=3,this.reconnectTimer=null,this.currentWhepUrl=null,this.currentHeaders=null,this.currentIceServers=null,this.container=null,this.destroyed=!1,this.liveDurationProxy=null,this.pausedAt=null,this.currentSourceUrl=null,this.currentMimeType=null,this.isMP3Source=!1,this.liveSeekEnabled=!1,this.liveSeekOffsetSec=0,this.liveSeekBaseUrl=null,this.liveSeekListeners=[],this.liveSeekTimer=null,this.pendingLiveSeekOffset=null}isMimeSupported(e){return-1!==this.capability.mimes.indexOf(e)}isBrowserSupported(e,t,n){if("whep"===e){if(!("RTCPeerConnection"in window)||!("fetch"in window))return!1;const e=De(n.meta.tracks);if(!e.compatible)return e.incompatibleCodecs.length>0&&console.debug("[WHEP] Skipping - incompatible codecs:",e.incompatibleCodecs.join(", ")),!1;const t=[];return e.details.compatibleVideoCodecs.length>0&&t.push("video"),e.details.compatibleAudioCodecs.length>0&&t.push("audio"),t.length>0&&t}if(Ie(t.url)&&("file:"!==window.location.protocol||!t.url.startsWith("http:")))return!1;const i=ke();if("html5/video/webm"===e&&i.isSafari)return!1;if("html5/application/vnd.apple.mpegurl"===e){if(document.createElement("video").canPlayType("application/vnd.apple.mpegurl")){const e=this.getAndroidVersion();return!(e&&e<7)&&["video","audio"]}return!1}const r=[],s=document.createElement("video"),a=e.replace("html5/",""),o={};for(const e of n.meta.tracks)"meta"!==e.type?(o[e.type]||(o[e.type]=[]),o[e.type].push(e)):"subtitle"===e.codec&&r.push("subtitle");for(const[e,t]of Object.entries(o)){let n=!1;for(const e of t){let t="";t=e.codecstring?e.codecstring:this.translateCodecForHtml5(e);const i=`${a};codecs="${t}"`;if("video/webm"===a){if(""!==s.canPlayType(a)){n=!0;break}}else if(""!==s.canPlayType(i)){n=!0;break}}n&&r.push(e)}return r.length>0&&r}translateCodecForHtml5(e){if(e.codecstring)return e.codecstring;const t=t=>!e.init||t>=e.init.length?"00":("0"+e.init.charCodeAt(t).toString(16)).slice(-2);switch(e.codec){case"AAC":return"mp4a.40.2";case"MP3":return"mp4a.40.34";case"AC3":return"ec-3";case"H264":return`avc1.${t(1)}${t(2)}${t(3)}`;case"HEVC":return`hev1.${t(1)}${t(6)}${t(7)}${t(8)}${t(9)}${t(10)}${t(11)}${t(12)}`;case"VP8":return"vp8";case"VP9":return"vp09.00.10.08";case"AV1":return"av01.0.04M.08";case"Opus":return"opus";default:return e.codec.toLowerCase()}}getAndroidVersion(){const e=navigator.userAgent.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);if(!e)return null;return parseInt(e[1],10)+(e[2]?parseInt(e[2],10):0)/10}async initialize(e,t,n,i){this.destroyed=!1,this.container=e,this.currentSourceUrl=t.url,this.currentMimeType=t.type,this.isMP3Source="html5/audio/mp3"===t.type,e.classList.add("fw-player-container");const r=document.createElement("video");r.classList.add("fw-player-video"),r.setAttribute("playsinline",""),r.setAttribute("crossorigin","anonymous"),n.autoplay&&(r.autoplay=!0),n.muted&&(r.muted=!0),r.controls=!0===n.controls,n.loop&&(r.loop=!0),n.poster&&(r.poster=n.poster),this.videoElement=r,e.appendChild(r),this.setupVideoEventListeners(r,n);const s="live"===i?.type;"whep"!==t.type&&s?(this.setupLiveDurationProxy(r),this.setupAutoRecovery(r),this.liveSeekEnabled=!0,this.liveSeekOffsetSec=0,this.liveSeekBaseUrl=this.stripStartUnixParam(t.url)):(this.liveSeekEnabled=!1,this.liveSeekOffsetSec=0,this.liveSeekBaseUrl=null);try{const e=t.subtitles;Array.isArray(e)&&e.forEach((e,t)=>{const n=document.createElement("track");n.kind="subtitles",n.label=e.label,n.srclang=e.lang,n.src=e.src,0===t&&(n.default=!0),r.appendChild(n)})}catch{}try{if("whep"===t.type){const e=t,n=e&&e.headers?e.headers:{},i=e&&e.iceServers?e.iceServers:[];return this.reconnectEnabled=!(!e||!e.reconnect),this.currentWhepUrl=t.url,this.currentHeaders=n,this.currentIceServers=i,await this.startWhep(r,t.url,n,i),r}return r.src=t.url,n.autoplay&&r.play().catch(e=>console.warn("HTML5 autoplay failed:",e)),r}catch(e){throw this.emit("error",e.message||String(e)),e}}setupLiveDurationProxy(e){this.liveDurationProxy=new Rt(e,{constrainSeek:!0})}setupAutoRecovery(e){e.addEventListener("pause",()=>{this.destroyed||(this.pausedAt=Date.now())}),e.addEventListener("play",()=>{if(!this.destroyed){if(this.pausedAt&&this.liveDurationProxy?.isLive()){const t=Date.now()-this.pausedAt;t>sn.PAUSE_RECOVERY_THRESHOLD&&(console.debug("[NativePlayer] Auto-recovery: reloading stream after",t,"ms pause"),e.load())}this.pausedAt=null}})}setSource(e){this.videoElement&&(this.currentSourceUrl=e,this.liveSeekEnabled&&(this.liveSeekBaseUrl=this.stripStartUnixParam(e),this.liveSeekOffsetSec=0),this.videoElement.src=e,this.videoElement.load())}seek(e){if(this.isMP3Source)console.warn("[NativePlayer] Seek not supported for MP3 files");else{if(this.liveSeekEnabled&&this.liveDurationProxy?.isLive()){let t=e-this.getDuration();return t>0&&(t=0),void this.scheduleLiveSeekOffset(t,!1)}this.liveDurationProxy?.isLive()?this.liveDurationProxy.seek(e):this.videoElement&&(this.videoElement.currentTime=e)}}getDuration(){if(this.liveSeekEnabled&&this.liveDurationProxy?.isLive()){const e=this.liveDurationProxy.getDuration(),t=this.pendingLiveSeekOffset??this.liveSeekOffsetSec;return Math.max(0,e-t)}return this.liveDurationProxy?this.liveDurationProxy.getDuration():this.videoElement?.duration??0}getCurrentTime(){if(this.liveSeekEnabled&&this.liveDurationProxy?.isLive()&&this.videoElement){const e=this.pendingLiveSeekOffset??this.liveSeekOffsetSec;return Math.max(0,this.videoElement.currentTime-e)}return this.videoElement?.currentTime??0}getSeekableRange(){if(!this.liveSeekEnabled||!this.liveDurationProxy?.isLive()||!this.videoElement)return null;const e=this.videoElement.buffered;if(!e||0===e.length)return null;const t=this.pendingLiveSeekOffset??this.liveSeekOffsetSec,n=e.start(0)-t,i=e.end(e.length-1)-t;return Number.isFinite(n)&&Number.isFinite(i)?{start:Math.max(0,n),end:Math.max(0,i)}:null}getBufferedRanges(){const e=this.videoElement;if(!e)return null;const t=e.buffered;if(!this.liveSeekEnabled||!this.liveDurationProxy?.isLive())return t;if(!t||0===t.length)return t;const n=this.pendingLiveSeekOffset??this.liveSeekOffsetSec,i=[];for(let e=0;e<t.length;e++){const r=t.start(e)-n,s=t.end(e)-n;Number.isFinite(r)&&Number.isFinite(s)&&i.push([Math.max(0,r),Math.max(0,s)])}return this.createTimeRanges(i)}isLive(){return this.liveDurationProxy?.isLive()??!1}getLiveLatency(){return this.liveDurationProxy?.getLatency()??0}jumpToLive(){this.liveSeekEnabled&&this.liveDurationProxy?.isLive()?this.scheduleLiveSeekOffset(0,!0):this.liveDurationProxy?.jumpToLive()}async destroy(){if(this.destroyed=!0,this.liveDurationProxy&&(this.liveDurationProxy.destroy(),this.liveDurationProxy=null),this.reconnectTimer){try{clearTimeout(this.reconnectTimer)}catch{}this.reconnectTimer=null}if(this.sessionUrl){const e=this.sessionUrl;this.sessionUrl=null,fetch(e,{method:"DELETE"}).catch(()=>{})}if(this.peerConnection){try{this.peerConnection.close()}catch{}this.peerConnection=null}if(this.videoElement){try{this.videoElement.srcObject=null}catch{}if(this.videoElement.pause(),this.videoElement.removeAttribute("src"),this.container)try{this.container.removeChild(this.videoElement)}catch{}}this.videoElement=null,this.container=null,this.pausedAt=null,this.currentSourceUrl=null,this.currentMimeType=null,this.liveSeekEnabled=!1,this.liveSeekOffsetSec=0,this.liveSeekBaseUrl=null,this.liveSeekListeners.forEach(e=>e()),this.liveSeekListeners=[],this.liveSeekTimer&&(clearTimeout(this.liveSeekTimer),this.liveSeekTimer=null),this.pendingLiveSeekOffset=null,this.listeners.clear()}stripStartUnixParam(e){const t=Dt(e);return delete t.startunix,xt(Lt(e),t)}buildLiveSeekUrl(e){const t=this.liveSeekBaseUrl||this.currentSourceUrl||"";if(!t)return"";if(!e||e>=0)return this.stripStartUnixParam(t);const n=Dt(t);return n.startunix=String(e),xt(Lt(t),n)}applyLiveSeekOffset(e){if(!this.videoElement)return;const t=Math.min(0,e);if(Math.abs(t-this.liveSeekOffsetSec)<.05)return;this.liveSeekOffsetSec=t;const n=this.buildLiveSeekUrl(t);if(!n)return;const i=!this.videoElement.paused;this.currentSourceUrl=n,this.videoElement.src=n,this.videoElement.load(),i&&this.videoElement.play().catch(()=>{})}createTimeRanges(e){return{length:e.length,start(t){if(t<0||t>=e.length)throw new DOMException("Index out of bounds");return e[t][0]},end(t){if(t<0||t>=e.length)throw new DOMException("Index out of bounds");return e[t][1]}}}scheduleLiveSeekOffset(e,t){const n=Math.min(0,e);if(t)return this.liveSeekTimer&&(clearTimeout(this.liveSeekTimer),this.liveSeekTimer=null),this.pendingLiveSeekOffset=null,void this.applyLiveSeekOffset(n);this.pendingLiveSeekOffset=n,this.liveSeekTimer&&clearTimeout(this.liveSeekTimer),this.liveSeekTimer=setTimeout(()=>{if(this.liveSeekTimer=null,null!==this.pendingLiveSeekOffset){const e=this.pendingLiveSeekOffset;this.pendingLiveSeekOffset=null,this.applyLiveSeekOffset(e)}},sn.LIVE_SEEK_DEBOUNCE_MS)}async getStats(){if(this.peerConnection)try{const e=await this.peerConnection.getStats(),t=Date.now(),n={type:"webrtc",timestamp:t};return e.forEach(e=>{if("inbound-rtp"===e.type){const i=e.packetsReceived>0?e.packetsLost/(e.packetsReceived+e.packetsLost)*100:0;let r=0;if(this.lastInboundStats&&this.lastInboundStats[e.kind]){const n=this.lastInboundStats[e.kind],i=(t-(this.lastInboundStats.timestamp||0))/1e3;if(i>0){const t=e.bytesReceived-(n.bytesReceived||0);r=Math.round(8*t/i)}}if("video"===e.kind){const t=e.framesDecoded>0?e.framesDropped/(e.framesDecoded+e.framesDropped)*100:0;n.video={bytesReceived:e.bytesReceived||0,packetsReceived:e.packetsReceived||0,packetsLost:e.packetsLost||0,packetLossRate:i,jitter:1e3*(e.jitter||0),framesDecoded:e.framesDecoded||0,framesDropped:e.framesDropped||0,frameDropRate:t,frameWidth:e.frameWidth||0,frameHeight:e.frameHeight||0,framesPerSecond:e.framesPerSecond||0,bitrate:r,jitterBufferDelay:e.jitterBufferDelay&&e.jitterBufferEmittedCount?e.jitterBufferDelay/e.jitterBufferEmittedCount*1e3:0}}"audio"===e.kind&&(n.audio={bytesReceived:e.bytesReceived||0,packetsReceived:e.packetsReceived||0,packetsLost:e.packetsLost||0,packetLossRate:i,jitter:1e3*(e.jitter||0),bitrate:r})}"candidate-pair"===e.type&&e.nominated&&(n.network={rtt:e.currentRoundTripTime?1e3*e.currentRoundTripTime:0,availableOutgoingBitrate:e.availableOutgoingBitrate||0,availableIncomingBitrate:e.availableIncomingBitrate||0,bytesSent:e.bytesSent||0,bytesReceived:e.bytesReceived||0})}),this.lastInboundStats={video:n.video?{bytesReceived:n.video.bytesReceived}:void 0,audio:n.audio?{bytesReceived:n.audio.bytesReceived}:void 0,timestamp:t},n}catch{return}}async getLatency(){const e=await this.getStats();if(e)return{estimatedMs:e.video?.jitterBufferDelay||0,jitterBufferMs:e.video?.jitterBufferDelay||0,rttMs:e.network?.rtt||0}}async startWhep(e,t,n,i){if(this.sessionUrl){try{fetch(this.sessionUrl,{method:"DELETE"}).catch(()=>{})}catch{}this.sessionUrl=null}const r=new RTCPeerConnection({iceServers:i});this.peerConnection=r,r.ontrack=t=>{this.destroyed||e&&t.streams[0]&&(e.srcObject=t.streams[0])},r.oniceconnectionstatechange=()=>{if(this.destroyed)return;const t=r.iceConnectionState;if(("failed"===t||"disconnected"===t)&&(this.emit("error","WHEP connection failed"),this.reconnectEnabled&&this.reconnectAttempts<this.maxReconnectAttempts&&this.currentWhepUrl)){const t=Math.min(5e3,500*Math.pow(2,this.reconnectAttempts));this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{this.destroyed||this.startWhep(e,this.currentWhepUrl,this.currentHeaders||{},this.currentIceServers||[])},t)}"connected"===t&&(this.reconnectAttempts=0)},r.addTransceiver("video",{direction:"recvonly"}),r.addTransceiver("audio",{direction:"recvonly"});const s=await r.createOffer();await r.setLocalDescription(s);const a={"Content-Type":"application/sdp"};for(const e in n)a[e]=n[e];const o=await fetch(t,{method:"POST",headers:a,body:s.sdp||""});if(!o.ok)throw new Error(`WHEP request failed: ${o.status}`);const l=await o.text();await r.setRemoteDescription(new RTCSessionDescription({type:"answer",sdp:l}));const u=o.headers.get("Location");if(u)try{this.sessionUrl=new URL(u,t).href}catch{this.sessionUrl=u}else this.sessionUrl=null}}sn.PAUSE_RECOVERY_THRESHOLD=5e3,sn.LIVE_SEEK_DEBOUNCE_MS=300;var an=Object.freeze({__proto__:null,DirectPlaybackPlayerImpl:sn,NativePlayerImpl:sn});function on(e){if(e.byteLength<12)throw new Error(`Invalid chunk: expected at least 12 bytes, got ${e.byteLength}`);const t=new DataView(e,0,12),n=t.getUint8(0),i=function(e){switch(e){case 1:return"key";case 2:return"init";default:return"delta"}}(t.getUint8(1)),r=t.getBigUint64(2,!1);return{trackIndex:n,type:i,timestamp:Number(r),offset:t.getInt16(10,!1),data:new Uint8Array(e.slice(12))}}function ln(e){return 1e3*(e.timestamp+e.offset)}function un(e){return"init"===e.type}const dn={debug:!1,maxReconnectAttempts:5,reconnectDelayMs:1e3,maxReconnectDelayMs:3e4,connectionTimeoutMs:5e3};class cn{constructor(){this.delays=[],this.pending=new Map,this.maxSamples=3}startTiming(e){this.pending.set(e,performance.now())}completeTiming(e){const t=this.pending.get(e);if(void 0===t)return null;this.pending.delete(e);const n=performance.now()-t;return this.delays.push(n),this.delays.length>this.maxSamples&&this.delays.shift(),n}getAverageDelay(){return 0===this.delays.length?0:this.delays.reduce((e,t)=>e+t,0)/this.delays.length}clear(){this.pending.clear(),this.delays=[]}}class hn{constructor(e,t={}){this.ws=null,this.state="disconnected",this.reconnectAttempts=0,this.reconnectTimer=null,this.connectionTimer=null,this.listeners=new Map,this.serverDelay=new cn,this.intentionalClose=!1,this.lastDeltaLogTime={},this.deltaLogInterval=5e3,this.url=e,this.options={...dn,...t}}connect(){return new Promise((e,t)=>{if(this.ws&&"connected"===this.state)e();else{this.intentionalClose=!1,this.setState("connecting");try{this.ws=new WebSocket(this.url),this.ws.binaryType="arraybuffer",this.connectionTimer=setTimeout(()=>{"connecting"===this.state&&(this.log("Connection timeout"),this.ws?.close(),t(new Error("Connection timeout")))},this.options.connectionTimeoutMs),this.ws.onopen=()=>{this.clearConnectionTimer(),this.setState("connected"),this.reconnectAttempts=0,this.log("Connected"),e()},this.ws.onclose=e=>{this.clearConnectionTimer(),this.log(`Disconnected: ${e.code} ${e.reason}`),!this.intentionalClose&&this.shouldReconnect()?this.scheduleReconnect():this.setState("disconnected")},this.ws.onerror=e=>{this.log("WebSocket error"),this.emit("error",new Error("WebSocket error"))},this.ws.onmessage=e=>{this.handleMessage(e)}}catch(e){this.setState("error"),t(e)}}})}disconnect(){if(this.intentionalClose=!0,this.clearReconnectTimer(),this.clearConnectionTimer(),this.ws){try{this.send({type:"hold"})}catch{}this.ws.close(),this.ws=null}this.serverDelay.clear(),this.setState("disconnected")}send(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)return this.log(`Cannot send ${e.type}: not connected`),!1;["seek","set_speed","request_codec_data"].includes(e.type)&&this.serverDelay.startTiming(e.type);const t=JSON.stringify(e);return this.log(`Sending: ${t}`),this.ws.send(t),!0}play(){return this.send({type:"play"})}hold(){return this.send({type:"hold"})}seek(e,t){const n={type:"seek",seek_time:Math.round(e)};return void 0!==t&&(n.ff_add=Math.round(t)),this.send(n)}setSpeed(e){return this.send({type:"set_speed",play_rate:e})}requestCodecData(e){return e&&e.length>0?this.send({type:"request_codec_data",supported_combinations:e}):this.send({type:"request_codec_data"})}fastForward(e){return this.send({type:"fast_forward",ff_add:Math.round(e)})}getState(){return this.state}getServerDelay(){return this.serverDelay.getAverageDelay()}isConnected(){return"connected"===this.state&&this.ws?.readyState===WebSocket.OPEN}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){const n=this.listeners.get(e);if(n)for(const i of n)try{i(t)}catch(t){console.error(`Error in ${e} listener:`,t)}}handleMessage(e){e.data instanceof ArrayBuffer?this.handleBinaryMessage(e.data):"string"==typeof e.data&&this.handleControlMessage(e.data)}handleBinaryMessage(e){try{const t=on(e);if(this.options.debug)if("delta"!==t.type)this.log(function(e){const t=((e.timestamp+e.offset)/1e3).toFixed(3);return`[Track ${e.trackIndex}] ${e.type.toUpperCase()} @ ${t}s (${e.data.byteLength} bytes)`}(t));else{const e=performance.now();e-(this.lastDeltaLogTime[t.trackIndex]||0)>this.deltaLogInterval&&(this.lastDeltaLogTime[t.trackIndex]=e)}this.emit("chunk",t)}catch(e){this.log(`Failed to parse binary chunk: ${e}`)}}handleControlMessage(e){try{const t=JSON.parse(e),n="data"in t?t.data:t,i={type:t.type,...n};switch(this.log(`Received: ${i.type}`),"codec_data"===i.type?this.serverDelay.completeTiming("request_codec_data"):"on_time"===i.type&&(this.serverDelay.completeTiming("seek"),this.serverDelay.completeTiming("set_speed")),i.type){case"codec_data":this.emit("codecdata",i);break;case"info":this.log(`Info message tracks: ${JSON.stringify(Object.keys(i.meta?.tracks??{}))}`),this.emit("info",i);break;case"on_time":i.tracks?.length&&this.log(`on_time tracks: ${JSON.stringify(i.tracks)}`),this.emit("ontime",i);break;case"tracks":this.emit("tracks",i.tracks);break;case"on_stop":this.emit("stop",void 0);break;case"error":this.emit("error",new Error(i.message));break;case"pause":case"set_speed":break;default:this.log(`Unknown message type: ${i.type}`)}}catch(e){this.log(`Failed to parse control message: ${e}`)}}setState(e){this.state!==e&&(this.state=e,this.emit("statechange",e))}shouldReconnect(){return!this.intentionalClose&&(0===this.options.maxReconnectAttempts||this.reconnectAttempts<this.options.maxReconnectAttempts)}scheduleReconnect(){this.setState("reconnecting"),this.reconnectAttempts++;const e=this.options.reconnectDelayMs,t=this.options.maxReconnectDelayMs,n=Math.min(e*Math.pow(2,this.reconnectAttempts-1),t),i=.2*n*Math.random();this.log(`Reconnecting in ${Math.round(n+i)}ms (attempt ${this.reconnectAttempts})`),this.reconnectTimer=setTimeout(()=>{this.connect().catch(e=>{this.log(`Reconnect failed: ${e.message}`),this.shouldReconnect()?this.scheduleReconnect():(this.setState("error"),this.emit("error",new Error("Max reconnection attempts exceeded")))})},n+i)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}clearConnectionTimer(){this.connectionTimer&&(clearTimeout(this.connectionTimer),this.connectionTimer=null)}log(e){this.options.debug&&console.log(`[WebCodecsWS] ${e}`)}}class fn{constructor(e={}){this.chunks=[],this.speed=1,this.lastPeakTime=0,this.currentPeak=0,this.peaks=[],this.maxJitter=e.initialJitter??120,this.chunkWindowSize=e.chunkWindowSize??8,this.peakWindowSize=e.peakWindowSize??8}addChunk(e,t=performance.now()){this.chunks.push({receiveTime:t,mediaTime:e}),this.chunks.length>this.chunkWindowSize&&this.chunks.shift();const n=this.calculateJitter();n>this.currentPeak&&(this.currentPeak=n);const i=performance.now();i>this.lastPeakTime+1e3&&(this.recordPeak(),this.lastPeakTime=i)}calculateJitter(){if(this.chunks.length<=1)return 0;if(0===this.speed||!isFinite(this.speed))return 0;const e=this.chunks[0],t=this.chunks[this.chunks.length-1],n=t.receiveTime-e.receiveTime,i=(t.mediaTime-e.mediaTime)/this.speed-n;return Math.max(0,i)}recordPeak(){if(this.peaks.push(this.currentPeak),this.peaks.length>this.peakWindowSize&&this.peaks.shift(),this.currentPeak=0,this.peaks.length>0){const e=Math.max(...this.peaks),t=this.peaks.reduce((e,t)=>e+t,0)/this.peaks.length;let n=(t+2*e)/3+1;this.maxJitter>n+500&&(n=this.maxJitter-500),this.maxJitter=(this.maxJitter+n)/2}}get(){return this.maxJitter}getState(){return{current:this.calculateJitter(),peak:this.currentPeak,weighted:this.maxJitter}}setSpeed(e){const t="auto"===e?1:e;t!==this.speed&&(this.speed=t,this.reset())}reset(){this.chunks=[],this.currentPeak=0}fullReset(){this.reset(),this.peaks=[],this.maxJitter=120,this.lastPeakTime=0}}class pn{constructor(e={}){this.trackers=new Map,this.globalSpeed=1,this.options=e}addChunk(e,t,n){let i=this.trackers.get(e);i||(i=new fn(this.options),i.setSpeed(this.globalSpeed),this.trackers.set(e,i)),i.addChunk(t,n)}getMax(){let e=0;for(const t of this.trackers.values())e=Math.max(e,t.get());return e}getForTrack(e){return this.trackers.get(e)?.get()??120}setSpeed(e){this.globalSpeed="auto"===e?1:e;for(const t of this.trackers.values())t.setSpeed(e)}reset(){for(const e of this.trackers.values())e.reset()}removeTrack(e){this.trackers.delete(e)}clear(){this.trackers.clear()}}const gn={"ultra-low":{name:"Ultra Low Latency",keepAway:50,jitterMultiplier:1,speedUpThreshold:1.5,speedDownThreshold:.5,maxSpeedUp:1.08,minSpeedDown:.95,audioBufferMs:100,optimizeForLatency:!0},low:{name:"Low Latency",keepAway:100,jitterMultiplier:1.2,speedUpThreshold:2,speedDownThreshold:.6,maxSpeedUp:1.05,minSpeedDown:.98,audioBufferMs:150,optimizeForLatency:!0},balanced:{name:"Balanced",keepAway:200,jitterMultiplier:1.5,speedUpThreshold:2.5,speedDownThreshold:.5,maxSpeedUp:1.03,minSpeedDown:.97,audioBufferMs:200,optimizeForLatency:!1},quality:{name:"Quality Priority",keepAway:500,jitterMultiplier:2,speedUpThreshold:3,speedDownThreshold:.4,maxSpeedUp:1.02,minSpeedDown:.98,audioBufferMs:300,optimizeForLatency:!1}};function mn(e){return e&&e in gn?gn[e]:gn.low}function yn(e,t){const n="string"==typeof e?mn(e):e;return t?{...n,...t,name:t.name??`${n.name} (Custom)`}:n}let bn=class{constructor(e={}){this.listeners=new Map,this.mainSpeed=1,this.tweakSpeed=1,this.lastBufferCheck=0,this.bufferCheckInterval=100,this.serverDelays=[],this.maxServerDelaysSamples=3,this.lastLiveCatchup=0,this.liveCatchupCooldown=2e3,this.liveCatchupThresholdMs=5e3,this.liveCatchupRequestMs=5e3,this.serverTime=0,this.localTimeAtServerUpdate=0,this.seekState={active:!1,id:0,targetTime:0,startedAt:0},this.isLive=!0,this.profile=e.profile??mn("low"),this.isLive=e.isLive??!0,this.onSpeedChange=e.onSpeedChange,this.onFastForwardRequest=e.onFastForwardRequest,this.jitterTracker=new pn({initialJitter:120})}setProfile(e){this.profile=e}setLive(e){this.isLive=e}recordChunkArrival(e,t){this.jitterTracker.addChunk(e,t)}updateServerTime(e){this.serverTime=e,this.localTimeAtServerUpdate=performance.now()}recordServerDelay(e){this.serverDelays.push(e),this.serverDelays.length>this.maxServerDelaysSamples&&this.serverDelays.shift()}getServerDelay(){return 0===this.serverDelays.length?0:this.serverDelays.reduce((e,t)=>e+t,0)/this.serverDelays.length}getEstimatedServerTime(){const e=(performance.now()-this.localTimeAtServerUpdate)/1e3;return this.serverTime+e*this.getCombinedSpeed()}getDesiredBuffer(){const e="undefined"!=typeof navigator&&/Chrome/.test(navigator.userAgent)&&!/Edge|Edg/.test(navigator.userAgent)?1e3:100,t=this.getServerDelay(),n=this.jitterTracker.getMax()*this.profile.jitterMultiplier,i=Math.max(e+t,2*t)+n;return this.isLive?i:i+2e3}evaluateBuffer(e){const t=performance.now();if(t-this.lastBufferCheck<this.bufferCheckInterval)return this.getState(e);this.lastBufferCheck=t;const n=this.getDesiredBuffer(),i=e/n,r=this.jitterTracker.getMax();return this.isLive&&e<this.liveCatchupThresholdMs&&e>Math.max(1.1*r,r+250)&&e-n<1e3&&t-this.lastLiveCatchup>this.liveCatchupCooldown&&(this.lastLiveCatchup=t,this.requestFastForward(this.liveCatchupRequestMs),this.emit("livecatchup",{fastForwardMs:this.liveCatchupRequestMs})),i>this.profile.speedUpThreshold&&this.isLive?this.setTweakSpeed(this.profile.maxSpeedUp,"catchup"):i<this.profile.speedDownThreshold?(this.setTweakSpeed(this.profile.minSpeedDown,"slowdown"),i<.3&&this.isLive&&(this.requestFastForward(n-e),this.emit("underrun",void 0)),this.emit("bufferlow",{current:e,desired:n})):1!==this.tweakSpeed&&this.setTweakSpeed(1,"normal"),this.getState(e)}getState(e){const t=e??0,n=this.getDesiredBuffer();return{buffer:{current:t,desired:n,ratio:n>0?t/n:1},jitter:this.jitterTracker.getMax()>0?{current:0,peak:0,weighted:this.jitterTracker.getMax()}:{current:0,peak:0,weighted:0},playbackSpeed:this.getCombinedSpeed(),serverTime:this.serverTime,serverDelay:this.getServerDelay(),avOffset:0}}getCombinedSpeed(){return this.mainSpeed*this.tweakSpeed}setMainSpeed(e){this.mainSpeed=e,this.jitterTracker.setSpeed(e),this.notifySpeedChange()}setTweakSpeed(e,t){this.tweakSpeed!==e&&(this.tweakSpeed=e,this.notifySpeedChange(),this.emit("speedchange",{speed:this.getCombinedSpeed(),reason:t}))}notifySpeedChange(){this.onSpeedChange?.(this.mainSpeed,this.tweakSpeed)}requestFastForward(e){this.onFastForwardRequest?.(Math.max(0,e))}startSeek(e){return this.seekState.id++,this.seekState={active:!0,id:this.seekState.id,targetTime:e,startedAt:performance.now()},this.jitterTracker.reset(),this.emit("seekstart",{seekId:this.seekState.id,time:e}),this.seekState.id}isSeekActive(e){return this.seekState.active&&this.seekState.id===e}completeSeek(e){this.seekState.id===e&&(this.seekState.active=!1,this.emit("seekcomplete",{seekId:e}))}cancelSeek(){this.seekState.active&&(this.seekState.active=!1)}isSeeking(){return this.seekState.active}addTrack(e,t){}removeTrack(e){this.jitterTracker.removeTrack(e)}reset(){this.mainSpeed=1,this.tweakSpeed=1,this.serverDelays=[],this.serverTime=0,this.localTimeAtServerUpdate=0,this.lastLiveCatchup=0,this.jitterTracker.reset(),this.seekState={active:!1,id:0,targetTime:0,startedAt:0}}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){const n=this.listeners.get(e);if(n)for(const i of n)try{i(t)}catch(t){console.error(`Error in ${e} listener:`,t)}}};function vn(){return void 0!==globalThis.MediaStreamTrackGenerator}class Tn{constructor(){this.closed=!1,this.canvas=document.createElement("canvas"),this.canvas.width=1920,this.canvas.height=1080;const e=this.canvas.getContext("2d",{desynchronized:!0});if(!e)throw new Error("Failed to create canvas 2D context");this.ctx=e;const t=this.canvas.captureStream().getVideoTracks();if(0===t.length)throw new Error("Failed to capture stream from canvas");this.track=t[0],this._writable=new WritableStream({write:e=>{this.closed||(this.canvas.width===e.displayWidth&&this.canvas.height===e.displayHeight||(this.canvas.width=e.displayWidth,this.canvas.height=e.displayHeight),this.ctx.drawImage(e,0,0,this.canvas.width,this.canvas.height)),e.close()},close:()=>{this.close()},abort:()=>{this.close()}})}get writable(){return this._writable}getTrack(){return this.track}close(){this.closed||(this.closed=!0,this.track.stop())}}class En{constructor(){this.workletNode=null,this.closed=!1,this.initialized=!1,this.sampleBuffer=[],this.maxBufferChunks=20,this.audioContext=new AudioContext({latencyHint:"interactive"}),this.destination=this.audioContext.createMediaStreamDestination();const e=this.destination.stream.getAudioTracks();if(0===e.length)throw new Error("Failed to create audio destination");this.track=e[0],this.initPromise=this.initializeWorklet(),this._writable=new WritableStream({write:e=>{if(this.closed)return void e.close();const t=this.audioDataToSamples(e);e.close(),this.sampleBuffer.push(t),this.sampleBuffer.length>this.maxBufferChunks&&this.sampleBuffer.shift(),this.feedSamples()},close:()=>{this.close()},abort:()=>{this.close()}})}async initializeWorklet(){const e=new Blob(["\n class SyncedAudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.ringBuffer = [];\n this.maxBufferSize = 10;\n\n this.port.onmessage = (e) => {\n if (e.data.type === 'samples') {\n // Add samples to ring buffer\n this.ringBuffer.push(e.data.samples);\n if (this.ringBuffer.length > this.maxBufferSize) {\n this.ringBuffer.shift(); // Drop oldest\n }\n }\n };\n }\n\n process(inputs, outputs, parameters) {\n const output = outputs[0];\n if (!output || output.length === 0) return true;\n\n const channel = output[0];\n\n if (this.ringBuffer.length > 0) {\n const samples = this.ringBuffer.shift();\n const len = Math.min(samples.length, channel.length);\n for (let i = 0; i < len; i++) {\n channel[i] = samples[i];\n }\n // Fill remainder with last sample (smooth transition)\n for (let i = len; i < channel.length; i++) {\n channel[i] = samples[len - 1] || 0;\n }\n } else {\n // No samples - output silence\n channel.fill(0);\n }\n\n return true;\n }\n }\n\n registerProcessor('synced-audio-processor', SyncedAudioProcessor);\n "],{type:"application/javascript"}),t=URL.createObjectURL(e);try{await this.audioContext.audioWorklet.addModule(t),this.workletNode=new AudioWorkletNode(this.audioContext,"synced-audio-processor"),this.workletNode.connect(this.destination),this.initialized=!0}finally{URL.revokeObjectURL(t)}}audioDataToSamples(e){const t=e.numberOfChannels,n=e.numberOfFrames,i=new Float32Array(n*t);if(e.copyTo(i,{planeIndex:0}),1===t)return i;const r=new Float32Array(n);for(let e=0;e<n;e++){let n=0;for(let r=0;r<t;r++)n+=i[e*t+r];r[e]=n/t}return r}feedSamples(){if(!this.initialized||!this.workletNode||0===this.sampleBuffer.length)return;const e=this.sampleBuffer.shift();e&&this.workletNode.port.postMessage({type:"samples",samples:e},{transfer:[e.buffer]})}get writable(){return this._writable}getTrack(){return this.track}async waitForInit(){await this.initPromise}close(){this.closed||(this.closed=!0,this.track.stop(),this.workletNode?.disconnect(),this.audioContext.close(),this.sampleBuffer=[])}}function _n(e){const t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return t}function Sn(e){return{length:e.length,start(t){if(t<0||t>=e.length)throw new DOMException("Index out of bounds");return e[t][0]},end(t){if(t<0||t>=e.length)throw new DOMException("Index out of bounds");return e[t][1]}}}class wn extends Ne{constructor(){super(...arguments),this.capability={name:"WebCodecs Player",shortname:"webcodecs",priority:0,mimes:["ws/video/raw","wss/video/raw","ws/video/h264","wss/video/h264"]},this.wsController=null,this.syncController=null,this.worker=null,this.mediaStream=null,this.container=null,this.pipelines=new Map,this.tracks=[],this.tracksByIndex=new Map,this.queuedInitData=new Map,this.queuedChunks=new Map,this.isDestroyed=!1,this.debugging=!1,this.verboseDebugging=!1,this.streamType="live",this.payloadFormat="avcc",this.workerUidCounter=0,this.workerListeners=new Map,this._duration=1/0,this._currentTime=0,this._bufferMs=0,this._avDrift=0,this._frameCallbackId=null,this._statsInterval=null,this._framesDropped=0,this._framesDecoded=0,this._bytesReceived=0,this._messagesReceived=0,this._isPaused=!0,this._suppressPlayPauseSync=!1,this._pendingStepPause=!1,this._stepPauseTimeout=null}static getCodecCacheKey(e){const t=e.codecstring??e.codec?.toLowerCase()??"",n=e.init??"";return`${t}|${n.length>0?`${n.length}_${n.charCodeAt(0)}_${n.charCodeAt(n.length-1)}`:""}`}static async isTrackSupported(e){const t=wn.getCodecCacheKey(e);if(wn.codecCache.has(t)){return{supported:wn.codecCache.get(t),config:{codec:e.codecstring??e.codec}}}const n={codec:e.codecstring??(e.codec??"").toLowerCase()};let i;e.init&&""!==e.init&&(n.description=_n(e.init));try{switch(e.type){case"video":if("JPEG"===e.codec)if("ImageDecoder"in window){i={supported:await window.ImageDecoder.isTypeSupported("image/jpeg"),config:{codec:"image/jpeg"}}}else i={supported:!1,config:{codec:"image/jpeg"}};else{const e=await VideoDecoder.isConfigSupported(n);i={supported:!0===e.supported,config:e.config}}break;case"audio":{n.numberOfChannels=e.channels??2,n.sampleRate=e.rate??48e3;const t=await AudioDecoder.isConfigSupported(n);i={supported:!0===t.supported,config:t.config};break}default:i={supported:!1,config:n}}}catch(t){console.warn(`[WebCodecs] isConfigSupported failed for ${e.codec}:`,t),i={supported:!1,config:n}}return wn.codecCache.set(t,i.supported),i}static async validateTracks(e){const t=new Set,n=e.filter(e=>"video"===e.type||"audio"===e.type).map(async e=>{const n=await wn.isTrackSupported(e);return n.supported&&t.add(e.type),{track:e,supported:n.supported}}),i=await Promise.all(n);for(const{track:e,supported:t}of i)console.debug(`[WebCodecs] Track ${e.idx} (${e.type} ${e.codec}): ${t?"supported":"UNSUPPORTED"}`);return Array.from(t)}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(!("WebSocket"in window))return!1;if(!("Worker"in window))return!1;if(!("VideoDecoder"in window)||!("AudioDecoder"in window))return!1;const i=new URL(t.url.replace(/^ws/,"http"),location.href);if("https:"===location.protocol&&"http:"===i.protocol)return!1;const r={};for(const e of n.meta.tracks)if("video"===e.type||"audio"===e.type){const t=wn.getCodecCacheKey(e);wn.codecCache.has(t)?wn.codecCache.get(t)&&(r[e.type]=!0):r[e.type]=!0}else"meta"===e.type&&"subtitle"===e.codec&&(r.subtitle=!0);return e.includes("video/h264")&&delete r.audio,0!==Object.keys(r).length&&Object.keys(r)}async initialize(e,t,n,i){if(this.tracksByIndex.clear(),this.pipelines.clear(),this.tracks=[],this.queuedInitData.clear(),this.queuedChunks.clear(),this.isDestroyed=!1,this._duration=1/0,this._currentTime=0,this._bufferMs=0,this._avDrift=0,this._framesDropped=0,this._framesDecoded=0,this._bytesReceived=0,this._messagesReceived=0,this.payloadFormat=t.type?.includes("h264")?"annexb":"avcc","annexb"===this.payloadFormat&&this.log("Using Annex B payload format (ws/video/h264)"),this.container=e,e.classList.add("fw-player-container"),i?.meta?.tracks){this.log(`Pre-populating ${i.meta.tracks.length} tracks from streamInfo`);for(const e of i.meta.tracks)if(void 0!==e.idx){const t={idx:e.idx,type:e.type,codec:e.codec,codecstring:e.codecstring,init:e.init,width:e.width,height:e.height,fpks:e.fpks,channels:e.channels,rate:e.rate,size:e.size};this.tracksByIndex.set(e.idx,t),this.log(`Pre-registered track ${e.idx}: ${e.type} ${e.codec}`)}}const r=n;this.debugging=r.debug??r.devMode??!1,this.verboseDebugging=r.verboseDebug??!1,this.streamType="live"===t.type?"live":"vod";const s=yn(r.latencyProfile??function(e,t=!1){return e?t?"low":"balanced":"quality"}("live"===this.streamType),r.customLatencyProfile);this.log(`Initializing WebCodecs player with ${s.name} profile`);const a=document.createElement("video");a.classList.add("fw-player-video"),a.setAttribute("playsinline",""),a.setAttribute("crossorigin","anonymous"),n.autoplay&&(a.autoplay=!0),n.muted&&(a.muted=!0),a.controls=!0===n.controls,n.loop&&"live"!==this.streamType&&(a.loop=!0),n.poster&&(a.poster=n.poster),this.videoElement=a,e.appendChild(a),this._onVideoPlay=()=>{this._suppressPlayPauseSync||(this._isPaused=!1,this.sendToWorker({type:"frametiming",action:"setPaused",paused:!1,uid:this.workerUidCounter++}).catch(()=>{}))},this._onVideoPause=()=>{this._suppressPlayPauseSync||(this._isPaused=!0,this.sendToWorker({type:"frametiming",action:"setPaused",paused:!0,uid:this.workerUidCounter++}).catch(()=>{}))},a.addEventListener("play",this._onVideoPlay),a.addEventListener("pause",this._onVideoPause),this.mediaStream=new MediaStream,a.srcObject=this.mediaStream,await this.initializeWorker(),this.syncController=new bn({profile:s,isLive:"live"===this.streamType,onSpeedChange:(e,t)=>{this.sendToWorker({type:"frametiming",action:"setSpeed",speed:e,tweak:t,uid:this.workerUidCounter++}),this.videoElement&&(this.videoElement.playbackRate=e*t)},onFastForwardRequest:e=>{this.wsController?.fastForward(e)}}),this.wsController=new hn(t.url,{debug:this.debugging}),this.setupWebSocketHandlers();const o=new Set,l=new Set;if(i?.meta?.tracks){this.log("Validating track codecs with isConfigSupported()...");for(const e of i.meta.tracks)if("video"===e.type||"audio"===e.type){const t={idx:e.idx??0,type:e.type,codec:e.codec,codecstring:e.codecstring,init:e.init,width:e.width,height:e.height,channels:e.channels,rate:e.rate};(await wn.isTrackSupported(t)).supported?("audio"===e.type?o.add(e.codec):l.add(e.codec),this.log(`Track ${e.idx} (${e.type} ${e.codec}): SUPPORTED`)):this.log(`Track ${e.idx} (${e.type} ${e.codec}): NOT SUPPORTED`,"warn")}}0===o.size&&0===l.size&&(this.log("No validated codecs, using default codec list"),["AAC","MP3","opus","FLAC","AC3"].forEach(e=>o.add(e)),["H264","HEVC","VP8","VP9","AV1","JPEG"].forEach(e=>l.add(e)));const u=[[Array.from(o),Array.from(l)]];this.log(`Requesting codecs: audio=[${u[0][0].join(", ")}], video=[${u[0][1].join(", ")}]`);try{await this.wsController.connect(),this.wsController.requestCodecData(u)}catch(e){throw this.log(`Failed to connect: ${e}`,"error"),this.emit("error",e instanceof Error?e:new Error(String(e))),e}for(const[e,t]of this.tracksByIndex)"video"!==t.type&&"audio"!==t.type||(this.log(`Creating pipeline proactively for track ${e} (${t.type} ${t.codec})`),await this.createPipeline(t));return this.setupVideoEventListeners(a,n),this.setupFrameCallback(),this.isDestroyed=!1,a}async destroy(){if(!this.isDestroyed){this.isDestroyed=!0,this.log("Destroying WebCodecs player"),this.cancelFrameCallback(),this._statsInterval&&(clearInterval(this._statsInterval),this._statsInterval=null),this.wsController?.disconnect(),this.wsController=null;for(const e of this.pipelines.values())await this.closePipeline(e.idx,!1);if(this.pipelines.clear(),this.worker?.terminate(),this.worker=null,this.workerListeners.clear(),this.mediaStream){for(const e of this.mediaStream.getTracks())e.stop(),this.mediaStream.removeTrack(e);this.mediaStream=null}this.videoElement&&(this._onVideoPlay&&(this.videoElement.removeEventListener("play",this._onVideoPlay),this._onVideoPlay=void 0),this._onVideoPause&&(this.videoElement.removeEventListener("pause",this._onVideoPause),this._onVideoPause=void 0),this._stepPauseTimeout&&(clearTimeout(this._stepPauseTimeout),this._stepPauseTimeout=null),this._pendingStepPause=!1,this.videoElement.srcObject=null,this.videoElement.remove(),this.videoElement=null),this.syncController=null}}tryLoadWorker(e){return new Promise((t,n)=>{let i;try{i=new Worker(e,{type:"module"})}catch(e){return void n(e)}const r=()=>{clearTimeout(o),i.removeEventListener("error",s),i.removeEventListener("message",a)},s=e=>{r(),i.terminate(),n(new Error(e.message||"Worker failed to load"))},a=()=>{r(),t(i)},o=setTimeout(()=>{r(),t(i)},500);i.addEventListener("error",s),i.addEventListener("message",a)})}async initializeWorker(){const e=["/workers/decoder.worker.js"];try{e.push(new URL("../workers/decoder.worker.js",t&&"SCRIPT"===t.tagName.toUpperCase()&&t.src||new URL("fw-player.iife.js",document.baseURI).href).href)}catch{}let n=null;for(const t of e)try{this.log(`Trying worker path: ${t}`),this.worker=await this.tryLoadWorker(t),this.log(`Worker loaded from: ${t}`);break}catch(e){n=e instanceof Error?e:new Error(String(e)),this.log(`Worker path failed: ${t} - ${n.message}`,"warn")}if(!this.worker)throw new Error(`Failed to initialize WebCodecs worker. Last error: ${n?.message??"unknown"}`);this.worker.onmessage=e=>{this.handleWorkerMessage(e.data)},this.worker.onerror=e=>{this.log(`Worker error: ${e?.message??"unknown error"}`,"error"),this.emit("error",new Error(`Worker error: ${e?.message??"unknown"}`))},this.sendToWorker({type:"debugging",value:this.verboseDebugging?"verbose":this.debugging,uid:this.workerUidCounter++})}sendToWorker(e,t){return new Promise((n,i)=>{if(this.isDestroyed)return void i(new Error("Player destroyed"));if(!this.worker)return void i(new Error("Worker not initialized"));const r=e.uid;this.workerListeners.set(r,e=>{this.workerListeners.delete(r),"ack"===e.type&&"error"===e.status?i(new Error(e.error)):n(e)}),t?this.worker.postMessage(e,t):this.worker.postMessage(e)})}handleWorkerMessage(e){switch(void 0!==e.uid&&this.workerListeners.has(e.uid)&&this.workerListeners.get(e.uid)(e),e.type){case"addtrack":{const t=this.pipelines.get(e.idx);t&&this.mediaStream&&(e.track?this.mediaStream.addTrack(e.track):t.generator&&this.mediaStream.addTrack(t.generator.getTrack()));break}case"removetrack":{const t=this.pipelines.get(e.idx);if(t?.generator&&this.mediaStream){const e=t.generator.getTrack();this.mediaStream.removeTrack(e)}break}case"setplaybackrate":this.videoElement&&(this.videoElement.playbackRate=e.speed);break;case"sendevent":"timeupdate"===e.kind?(this._pendingStepPause&&this.finishStepPause(),"number"==typeof e.time&&Number.isFinite(e.time)?(this._currentTime=e.time,this.emit("timeupdate",this._currentTime)):this.videoElement&&this.emit("timeupdate",this.videoElement.currentTime)):"error"===e.kind&&this.emit("error",new Error(e.message??"Unknown error"));break;case"writeframe":{const t=this.pipelines.get(e.idx);if(t?.safariAudioWriter){const n=e.frame,i=e.uid;t.safariAudioWriter.write(n).then(()=>{this.worker?.postMessage({type:"writeframe",idx:e.idx,uid:i,status:"ok"})}).catch(t=>{this.worker?.postMessage({type:"writeframe",idx:e.idx,uid:i,status:"error",error:t.message})})}else this.worker?.postMessage({type:"writeframe",idx:e.idx,uid:e.uid,status:"error",error:"Pipeline not active or no audio writer"});break}case"log":if(this.debugging){const t=e.level??"info";("error"===t?console.error:"warn"===t?console.warn:console.log)(`[WebCodecs Worker] ${e.msg}`)}break;case"stats":break;case"closed":this.pipelines.delete(e.idx)}}setupWebSocketHandlers(){this.wsController&&(this.wsController.on("codecdata",e=>this.handleCodecData(e)),this.wsController.on("info",e=>this.handleInfo(e)),this.wsController.on("ontime",e=>this.handleOnTime(e)),this.wsController.on("tracks",e=>this.handleTracksChange(e)),this.wsController.on("chunk",e=>this.handleChunk(e)),this.wsController.on("stop",()=>this.handleStop()),this.wsController.on("error",e=>this.handleError(e)),this.wsController.on("statechange",e=>{this.log(`Connection state: ${e}`),"error"===e&&this.emit("error",new Error("WebSocket connection failed"))}))}async handleCodecData(e){const t=e.codecs??[],n=e.tracks??[];if(this.log(`Received codec data: codecs=[${t.join(", ")||"none"}], tracks=[${n.join(", ")||"none"}]`),0===t.length||0===n.length)return this.log("No playable codecs/tracks selected by server","warn"),void this.wsController?.play();for(let e=0;e<n.length;e++){const i=n[e],r=t[e];if(r){const e=this.tracksByIndex.get(i);e?e.codec=r:this.tracksByIndex.set(i,{idx:i,type:r.match(/^(H264|HEVC|VP[89]|AV1|JPEG)/i)?"video":r.match(/^(AAC|MP3|opus|FLAC|AC3|pcm)/i)?"audio":"meta",codec:r}),this.log(`Track ${i}: codec=${r}`)}}for(const e of n){const t=this.tracksByIndex.get(e);!t||"video"!==t.type&&"audio"!==t.type||await this.createPipeline(t)}this.wsController?.play()}async handleInfo(e){if(this.log("Received stream info"),e.meta?.tracks){const t=e.meta.tracks;this.log(`Info contains ${Object.keys(t).length} tracks`);for(const[e,n]of Object.entries(t))if(void 0!==n.idx&&(this.tracksByIndex.set(n.idx,n),this.log(`Registered track ${n.idx}: ${n.type} ${n.codec}`),this.queuedInitData.has(n.idx)&&("video"===n.type||"audio"===n.type))){this.log(`Processing queued INIT data for track ${n.idx}`),await this.createPipeline(n);const e=this.queuedInitData.get(n.idx);this.configurePipeline(n.idx,e),this.queuedInitData.delete(n.idx)}this.tracks=Object.values(t)}}handleOnTime(e){this.syncController?.updateServerTime(e.current),null===this._frameCallbackId&&(this._currentTime=e.current);const t=this.wsController?.getServerDelay()??0;t>0&&this.syncController?.recordServerDelay(t),void 0!==e.total&&isFinite(e.total)&&e.total>0&&(this._duration=e.total);const n=this.syncController?.getState();if(n&&(this._bufferMs=n.buffer.current),e.tracks&&e.tracks.length>0)for(const t of e.tracks)if(!this.pipelines.has(t)){const e=this.tracksByIndex.get(t);!e||"video"!==e.type&&"audio"!==e.type||(this.log(`Creating pipeline from on_time for track ${e.idx} (${e.type} ${e.codec})`),this.createPipeline(e).then(()=>{const t=this.queuedInitData.get(e.idx);t&&(this.configurePipeline(e.idx,t),this.queuedInitData.delete(e.idx))}))}}async handleTracksChange(e){this.log(`Tracks changed: ${e.map(e=>`${e.idx}:${e.type}`).join(", ")}`);const t=new Set(e.map(e=>e.idx)),n=new Set(this.pipelines.keys());for(const e of n)t.has(e)||await this.closePipeline(e,!0);for(const t of e)this.tracksByIndex.set(t.idx,t),"video"!==t.type&&"audio"!==t.type||this.pipelines.has(t.idx)||await this.createPipeline(t);this.tracks=e}handleChunk(e){if(this.isDestroyed)return;const t=this.pipelines.get(e.trackIndex);if(!t){const t=this.tracksByIndex.get(e.trackIndex);return t?void("video"!==t.type&&"audio"!==t.type||(this.log(`Creating pipeline for discovered track ${t.idx} (${t.type} ${t.codec})`),this.createPipeline(t).then(()=>{if(this.isDestroyed)return;const n=this.queuedInitData.get(t.idx);n&&(this.configurePipeline(t.idx,n),this.queuedInitData.delete(t.idx)),this.handleChunk(e)}))):un(e)?(this.log(`Received INIT for unknown track ${e.trackIndex}, queuing for later`),void this.queuedInitData.set(e.trackIndex,e.data)):void this.log(`Received chunk for unknown track ${e.trackIndex} without track info`,"warn")}if(un(e))this.configurePipeline(t.idx,e.data);else{if(!t.configured){if("audio"===t.track.type||"key"===e.type){this.log(`Received ${e.type.toUpperCase()} frame for unconfigured ${t.track.type} track ${e.trackIndex}, configuring`),this.queuedChunks.has(e.trackIndex)||this.queuedChunks.set(e.trackIndex,[]),this.queuedChunks.get(e.trackIndex).unshift(e);const n=t.track.init?_n(t.track.init):new Uint8Array(0);return void this.configurePipeline(e.trackIndex,n).catch(t=>{this.log(`Failed to configure track ${e.trackIndex}: ${t}`,"error")})}return this.queuedChunks.has(e.trackIndex)||this.queuedChunks.set(e.trackIndex,[]),this.queuedChunks.get(e.trackIndex).push(e),void(this.verboseDebugging&&this.log(`Queued chunk for track ${e.trackIndex} (waiting for decoder config)`))}this.syncController?.recordChunkArrival(e.trackIndex,e.timestamp),this.sendChunkToWorker(e)}}sendChunkToWorker(e){const t={type:"receive",idx:e.trackIndex,chunk:{type:"key"===e.type?"key":"delta",timestamp:ln(e),data:e.data},uid:this.workerUidCounter++};this.worker?.postMessage(t,[e.data.buffer])}handleStop(){this.log("Stream stopped"),this.emit("ended",void 0)}handleError(e){this.log(`WebSocket error: ${e.message}`,"error"),this.emit("error",e)}async createPipeline(e){if(this.pipelines.has(e.idx))return;this.log(`Creating pipeline for track ${e.idx} (${e.type} ${e.codec})`);const t={idx:e.idx,track:e,generator:null,configured:!1};if(this.pipelines.set(e.idx,t),this.syncController?.addTrack(e.idx,e),await this.sendToWorker({type:"create",idx:e.idx,track:e,opts:{optimizeForLatency:"live"===this.streamType,payloadFormat:this.payloadFormat},uid:this.workerUidCounter++}),vn()){const n=new MediaStreamTrackGenerator({kind:e.type});t.generator={writable:n.writable,getTrack:()=>n,close:()=>n.stop?.()},await this.sendToWorker({type:"setwritable",idx:e.idx,writable:n.writable,uid:this.workerUidCounter++},[n.writable])}else if(function(){if("undefined"==typeof navigator)return!1;const e=navigator.userAgent;return/^((?!chrome|android).)*safari/i.test(e)}()){if(this.log(`Safari detected - using worker-based track generator for ${e.type}`),"audio"===e.type&&"undefined"!=typeof MediaStreamTrackGenerator){const e=new MediaStreamTrackGenerator({kind:"audio"});t.safariAudioGenerator=e,t.safariAudioWriter=e.writable.getWriter(),this.mediaStream&&this.mediaStream.addTrack(e)}await this.sendToWorker({type:"creategenerator",idx:e.idx,uid:this.workerUidCounter++})}else t.generator=function(e){if(vn()){const t=new(0,globalThis.MediaStreamTrackGenerator)({kind:e});return{writable:t.writable,getTrack:()=>t,close:()=>t.stop?.()}}if("video"===e){const e=new Tn;return{writable:e.writable,getTrack:()=>e.getTrack(),close:()=>e.close()}}{const e=new En;return{writable:e.writable,getTrack:()=>e.getTrack(),close:()=>e.close(),waitForInit:()=>e.waitForInit()}}}(e.type),t.generator.waitForInit&&await t.generator.waitForInit(),this.log("Using MediaStreamTrackGenerator polyfill - main thread decode"),this.mediaStream&&t.generator&&this.mediaStream.addTrack(t.generator.getTrack());e.init&&""!==e.init?this.log(`Track ${e.idx} (${e.codec}) has init data (${e.init.length} bytes), waiting for first frame`):(this.log(`Track ${e.idx} (${e.codec}) doesn't need init data, configuring immediately`),await this.configurePipeline(e.idx,new Uint8Array(0)))}async configurePipeline(e,t){const n=this.pipelines.get(e);if(!n||n.configured)return;this.log(`Configuring decoder for track ${e}`);const i=new Uint8Array(t);await this.sendToWorker({type:"configure",idx:e,header:i,uid:this.workerUidCounter++}),n.configured=!0;const r=this.queuedChunks.get(e);if(r&&r.length>0){this.log(`Flushing ${r.length} queued chunks for track ${e}`);let t=0;for(let e=0;e<r.length;e++)if("key"===r[e].type){t=e;break}t>0&&this.log(`Skipping ${t} delta frames, starting from keyframe`);for(let e=t;e<r.length;e++)this.sendChunkToWorker(r[e]);this.queuedChunks.delete(e)}}async closePipeline(e,t){const n=this.pipelines.get(e);n&&(this.log(`Closing pipeline ${e}`),await this.sendToWorker({type:"close",idx:e,waitEmpty:t,uid:this.workerUidCounter++}),n.generator?.close(),this.syncController?.removeTrack(e),this.pipelines.delete(e))}async play(){this._isPaused=!1,this.wsController?.play(),this.sendToWorker({type:"frametiming",action:"setPaused",paused:!1,uid:this.workerUidCounter++}),await(this.videoElement?.play())}pause(){this._isPaused=!0,this.wsController?.hold(),this.sendToWorker({type:"frametiming",action:"setPaused",paused:!0,uid:this.workerUidCounter++}),this.videoElement?.pause()}finishStepPause(){if(!this.videoElement)return this._pendingStepPause=!1,this._suppressPlayPauseSync=!1,void(this._stepPauseTimeout&&(clearTimeout(this._stepPauseTimeout),this._stepPauseTimeout=null));this._stepPauseTimeout&&(clearTimeout(this._stepPauseTimeout),this._stepPauseTimeout=null),this._pendingStepPause=!1,this._suppressPlayPauseSync=!1;try{this.videoElement.pause()}catch{}}frameStep(e,t){if(this._isPaused&&this.videoElement){if(this.log(`Frame step requested dir=${e} paused=${this._isPaused} videoPaused=${this.videoElement.paused}`),this.sendToWorker({type:"frametiming",action:"setPaused",paused:!0,uid:this.workerUidCounter++}).catch(()=>{}),this.videoElement.paused){const e=this.videoElement;this._suppressPlayPauseSync=!0,this._pendingStepPause=!0;try{const t=e.play();t&&"function"==typeof t.catch&&t.catch(()=>{})}catch{}"requestVideoFrameCallback"in e&&e.requestVideoFrameCallback(()=>this.finishStepPause()),this._stepPauseTimeout=setTimeout(()=>this.finishStepPause(),200)}this.sendToWorker({type:"framestep",direction:e,uid:this.workerUidCounter++})}}seek(e){if(!this.wsController||!this.syncController)return;const t=1e3*e,n=this.syncController.startSeek(t);this._currentTime=e,this.emit("timeupdate",this._currentTime),this.sendToWorker({type:"seek",seekTime:t,uid:this.workerUidCounter++});const i=this.syncController.getDesiredBuffer();this.wsController.seek(t,i),setTimeout(()=>{this.syncController?.isSeekActive(n)&&(this.syncController.completeSeek(n),this.sendToWorker({type:"frametiming",action:"reset",uid:this.workerUidCounter++}))},100)}setPlaybackRate(e){this.syncController?.setMainSpeed(e)}isPaused(){return this._isPaused}isLive(){return"live"===this.streamType}jumpToLive(){if("live"===this.streamType&&this.wsController){const e=this.syncController?.getDesiredBuffer()??2e3;this.wsController.send({type:"fast_forward",ff_add:5e3});const t=this.syncController?.getEstimatedServerTime()??0;t>0&&this.wsController.seek(1e3*t,e),this.log("Jump to live: requested fresh data from server")}}canSeek(){return null!==this.wsController&&!this.isDestroyed}get duration(){return this._duration}getDuration(){return this._duration}get currentTime(){return this._currentTime}getCurrentTime(){return this._currentTime}get buffered(){if(this._bufferMs<=0)return Sn([]);const e=this._currentTime;return Sn([[e,e+this._bufferMs/1e3]])}async getStats(){const e=this.syncController?.getState();return{latency:{buffer:e?.buffer.current??0,target:e?.buffer.desired??0,jitter:e?.jitter.weighted??0},sync:{avDrift:this._avDrift,playbackSpeed:e?.playbackSpeed??1},decoder:{videoQueueSize:0,audioQueueSize:0,framesDropped:this._framesDropped,framesDecoded:this._framesDecoded},network:{bytesReceived:this._bytesReceived,messagesReceived:this._messagesReceived}}}setupFrameCallback(){if(this.videoElement)if("requestVideoFrameCallback"in HTMLVideoElement.prototype){const e=(t,n)=>{!this.isDestroyed&&this.videoElement&&(this.onVideoFrame(n),this._frameCallbackId=this.videoElement.requestVideoFrameCallback(e))};this._frameCallbackId=this.videoElement.requestVideoFrameCallback(e),this.log("requestVideoFrameCallback enabled for accurate frame timing")}else this.log("requestVideoFrameCallback not available, using fallback timing")}onVideoFrame(e){this._currentTime=e.mediaTime;const t=this.syncController?.getState();t&&(this._bufferMs=t.buffer.current),this.emit("timeupdate",this._currentTime),this._framesDecoded=e.presentedFrames}cancelFrameCallback(){null!==this._frameCallbackId&&this.videoElement&&("cancelVideoFrameCallback"in HTMLVideoElement.prototype&&this.videoElement.cancelVideoFrameCallback(this._frameCallbackId),this._frameCallbackId=null)}log(e,t="info"){(this.debugging||"info"!==t)&&console[t](`[WebCodecs] ${e}`)}}wn.codecCache=new Map;var kn=Object.freeze({__proto__:null,JitterTracker:fn,LATENCY_PROFILES:gn,MultiTrackJitterTracker:pn,SyncController:bn,WebCodecsPlayerImpl:wn,WebSocketController:hn,getLatencyProfile:mn,mergeLatencyProfile:yn,parseRawChunk:on});var In=Object.freeze({__proto__:null,MistWebRTCPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"MistServer WebRTC",shortname:"mist-webrtc",priority:2,mimes:["webrtc","mist/webrtc"]},this.signaling=null,this.peerConnection=null,this.dataChannel=null,this.container=null,this.destroyed=!1,this.seekOffset=0,this.durationMs=0,this.isLiveStream=!0,this.playRate="auto",this.bufferWindow=0,this.currentTracks=[],this.currentSource=null,this.currentOptions=null,this.lastInboundStats=null}async checkH264Available(e=5){for(let t=0;t<e;t++){try{const e=RTCRtpReceiver.getCapabilities?.("video");if(e?.codecs.some(e=>"video/H264"===e.mimeType))return!0}catch{}t<e-1&&await new Promise(e=>setTimeout(e,100))}return console.warn("[MistWebRTC] H264 not available after retries"),!1}async loadBrowserEqualizer(e){if(!window.WebRTCBrowserEqualizerLoaded)return new Promise(t=>{const n=document.createElement("script");n.src=`${e}/webrtc.js`,n.onload=()=>{console.debug("[MistWebRTC] Browser equalizer loaded"),t()},n.onerror=()=>{console.warn("[MistWebRTC] Failed to load browser equalizer"),t()},document.head.appendChild(n)})}arraysEqual(e,t){if(e.length!==t.length)return!1;const n=[...e].sort(),i=[...t].sort();return n.every((e,t)=>e===i[t])}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(!("RTCPeerConnection"in window)||!("WebSocket"in window))return!1;const i=De(n.meta.tracks);if(!i.compatible)return console.debug("[MistWebRTC] Skipping - incompatible codecs:",i.incompatibleCodecs.join(", ")),!1;const r=[];return i.details.compatibleVideoCodecs.length>0&&r.push("video"),i.details.compatibleAudioCodecs.length>0&&r.push("audio"),r.length>0&&r}async initialize(e,t,n){this.destroyed=!1,this.container=e,this.currentSource=t,this.currentOptions=n,e.classList.add("fw-player-container");try{const e=new URL(t.url,window.location.href),n=`${e.protocol}//${e.host}`;await this.loadBrowserEqualizer(n)}catch{}await this.checkH264Available();const i=document.createElement("video");i.classList.add("fw-player-video"),i.setAttribute("playsinline",""),i.setAttribute("crossorigin","anonymous"),n.autoplay&&(i.autoplay=!0),n.muted&&(i.muted=!0),i.controls=!0===n.controls,n.loop&&(i.loop=!0),n.poster&&(i.poster=n.poster),this.videoElement=i,e.appendChild(i),this.setupVideoEventListeners(i,n);try{return await this.setupWebRTC(i,t,n),i}catch(e){throw this.emit("error",e.message||String(e)),e}}async destroy(){if(this.destroyed=!0,this.signaling){try{this.signaling.stop(),this.signaling.close()}catch{}this.signaling=null}if(this.dataChannel){try{this.dataChannel.close()}catch{}this.dataChannel=null}if(this.peerConnection){try{this.peerConnection.close()}catch{}this.peerConnection=null}if(this.videoElement){try{this.videoElement.srcObject=null}catch{}if(this.videoElement.pause(),this.container)try{this.container.removeChild(this.videoElement)}catch{}}this.videoElement=null,this.container=null,this.listeners.clear()}seek(e){this.signaling?.isConnected&&this.videoElement&&(this.videoElement.pause(),this.seekOffset=e-this.videoElement.currentTime,this.signaling.seek(e).catch(e=>{console.warn("[MistWebRTC] Seek failed:",e)}))}setPlaybackRate(e){this.signaling?.setSpeed(e),this.playRate=e}jumpToLive(){this.signaling?.isConnected&&this.videoElement&&(this.videoElement.pause(),this.seekOffset=0,this.signaling.seek("live").catch(e=>{console.warn("[MistWebRTC] Jump to live failed:",e)}))}isLive(){return this.isLiveStream}getDuration(){return this.durationMs>0?this.durationMs/1e3:super.getDuration()}getCurrentTime(){const e=this.videoElement;return e?this.seekOffset+e.currentTime:0}getQualities(){return[{id:"auto",label:"Auto",isAuto:!0,active:"auto"===this.playRate}]}selectQuality(e){this.signaling?.isConnected&&("auto"===e?this.signaling.setSpeed("auto"):this.signaling.setTracks({video:e}))}selectTextTrack(e){this.signaling?.isConnected&&(null===e?this.signaling.setTracks({video:"none"}):this.signaling.setTracks({video:e}))}async getStats(){if(this.peerConnection)try{const e=await this.peerConnection.getStats(),t=Date.now(),n={type:"webrtc",timestamp:t};return e.forEach(e=>{if("inbound-rtp"===e.type){const i=e.packetsReceived>0?e.packetsLost/(e.packetsReceived+e.packetsLost)*100:0;let r=0;if(this.lastInboundStats&&this.lastInboundStats[e.kind]){const n=this.lastInboundStats[e.kind],i=(t-this.lastInboundStats.timestamp)/1e3;if(i>0&&n){const t=e.bytesReceived-n.bytesReceived;r=Math.round(8*t/i)}}if("video"===e.kind){const t=e.framesDecoded>0?e.framesDropped/(e.framesDecoded+e.framesDropped)*100:0;n.video={bytesReceived:e.bytesReceived||0,packetsReceived:e.packetsReceived||0,packetsLost:e.packetsLost||0,packetLossRate:i,jitter:1e3*(e.jitter||0),framesDecoded:e.framesDecoded||0,framesDropped:e.framesDropped||0,frameDropRate:t,frameWidth:e.frameWidth||0,frameHeight:e.frameHeight||0,framesPerSecond:e.framesPerSecond||0,bitrate:r,jitterBufferDelay:e.jitterBufferDelay&&e.jitterBufferEmittedCount?e.jitterBufferDelay/e.jitterBufferEmittedCount*1e3:0}}"audio"===e.kind&&(n.audio={bytesReceived:e.bytesReceived||0,packetsReceived:e.packetsReceived||0,packetsLost:e.packetsLost||0,packetLossRate:i,jitter:1e3*(e.jitter||0),bitrate:r})}"candidate-pair"===e.type&&e.nominated&&(n.network={rtt:e.currentRoundTripTime?1e3*e.currentRoundTripTime:0,availableOutgoingBitrate:e.availableOutgoingBitrate||0,availableIncomingBitrate:e.availableIncomingBitrate||0,bytesSent:e.bytesSent||0,bytesReceived:e.bytesReceived||0})}),this.lastInboundStats={video:n.video?{bytesReceived:n.video.bytesReceived}:void 0,audio:n.audio?{bytesReceived:n.audio.bytesReceived}:void 0,timestamp:t},n}catch{return}}async getLatency(){const e=await this.getStats();if(e)return{estimatedMs:e.video?.jitterBufferDelay||0,jitterBufferMs:e.video?.jitterBufferDelay||0,rttMs:e.network?.rtt||0}}getBufferWindow(){return this.bufferWindow}setQualityForSize(e){this.signaling?.isConnected&&this.signaling.setTracks({video:`~${e.width}x${e.height}`})}getMetaDataChannel(){return this.dataChannel}setupVideoEventListeners(e,t){if(super.setupVideoEventListeners(e,t),!t.autoplay){const t=()=>{e.pause(),this.signaling?.pause(),e.removeEventListener("play",t)};e.addEventListener("play",t)}e.addEventListener("ended",async()=>{if(e.loop&&!this.isLiveStream&&this.currentSource&&this.currentOptions){console.debug("[MistWebRTC] VoD ended with loop enabled, reconnecting...");try{if(this.signaling){try{this.signaling.stop(),this.signaling.close()}catch{}this.signaling=null}if(this.dataChannel){try{this.dataChannel.close()}catch{}this.dataChannel=null}if(this.peerConnection){try{this.peerConnection.close()}catch{}this.peerConnection=null}await this.setupWebRTC(e,this.currentSource,this.currentOptions)}catch(e){console.error("[MistWebRTC] Failed to reconnect for loop:",e),this.emit("error","Failed to reconnect for loop")}}})}async setupWebRTC(e,t,n){const i=t,r=i?.iceServers||[];this.signaling=new Ct({url:t.url,timeout:5e3,onLog:e=>console.debug(`[MistWebRTC] ${e}`)});const s=new RTCPeerConnection({iceServers:r});this.peerConnection=s,this.dataChannel=s.createDataChannel("*",{protocol:"JSON"}),this.dataChannel.onmessage=e=>{this.destroyed||console.debug("[MistWebRTC] DataChannel message:",e.data)},s.ontrack=t=>{this.destroyed||e&&t.streams[0]&&(e.srcObject=t.streams[0])},s.onconnectionstatechange=()=>{if(this.destroyed)return;const e=s.connectionState;console.debug(`[MistWebRTC] Connection state: ${e}`),"failed"===e&&this.emit("error","WebRTC connection failed (firewall?)")},s.oniceconnectionstatechange=()=>{if(this.destroyed)return;const e=s.iceConnectionState;console.debug(`[MistWebRTC] ICE state: ${e}`),"failed"===e&&this.emit("error","ICE connection failed")},this.setupSignalingHandlers(s,e),this.signaling.connect(),await new Promise((e,t)=>{const n=setTimeout(()=>{t(new Error("Signaling connection timeout"))},1e4);this.signaling.once("connected",()=>{clearTimeout(n),e()}),this.signaling.once("error",({message:e})=>{clearTimeout(n),t(new Error(e))})}),await this.createAndSendOffer(s),await new Promise((e,t)=>{const n=setTimeout(()=>{t(new Error("SDP answer timeout"))},1e4);this.signaling.once("answer_sdp",async({result:i,answer_sdp:r})=>{if(clearTimeout(n),i)try{await s.setRemoteDescription({type:"answer",sdp:r}),e()}catch(e){t(e)}else t(new Error("Failed to get SDP answer"))})})}setupSignalingHandlers(e,t){this.signaling&&(this.signaling.on("connected",()=>{this.destroyed||t.dispatchEvent(new Event("webrtc_connected"))}),this.signaling.on("time_update",e=>{this.destroyed||this.handleTimeUpdate(e,t)}),this.signaling.on("seeked",({live_point:e})=>{this.destroyed||(t.dispatchEvent(new CustomEvent("seeked",{detail:{seekOffset:this.seekOffset}})),e&&this.signaling&&this.signaling.setSpeed("auto"),t.play().catch(()=>{}))}),this.signaling.on("speed_changed",({play_rate_curr:e})=>{this.destroyed||(this.playRate=e,t.dispatchEvent(new CustomEvent("ratechange",{detail:{play_rate_curr:e}})))}),this.signaling.on("stopped",()=>{this.destroyed||(this.isLiveStream=!1,t.pause(),this.emit("ended",void 0))}),this.signaling.on("error",({message:e})=>{this.destroyed||this.emit("error",e)}),this.signaling.on("disconnected",()=>{this.destroyed||(t.dispatchEvent(new Event("webrtc_disconnected")),t.pause())}))}handleTimeUpdate(e,t){this.seekOffset=e.current/1e3-t.currentTime;const n=0===e.end?1/0:e.end;if(this.durationMs=n,this.isLiveStream=!isFinite(n)||0===n,this.bufferWindow=e.end-e.begin,e.tracks&&!this.arraysEqual(e.tracks,this.currentTracks)){for(const n of e.tracks)this.currentTracks.includes(n)||t.dispatchEvent(new CustomEvent("playerUpdate_trackChanged",{detail:{trackId:n}}));this.currentTracks=[...e.tracks]}!e.paused&&t.paused&&t.play().catch(()=>{})}async createAndSendOffer(e){if(!this.signaling)return;e.addTransceiver("video",{direction:"recvonly"}),e.addTransceiver("audio",{direction:"recvonly"});const t=await e.createOffer({offerToReceiveAudio:!0,offerToReceiveVideo:!0});await e.setLocalDescription(t),t.sdp&&this.signaling.sendOfferSDP(t.sdp)}}});var An=Object.freeze({__proto__:null,VideoJsPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"Video.js Player",shortname:"videojs",priority:2,mimes:["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"]},this.videojsPlayer=null,this.container=null,this.destroyed=!1,this.timeCorrection=0,this.proxyElement=null,this.currentStreamInfo=null,this.liveDurationProxy=null}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){try{const e=new URL(t.url).protocol;if("undefined"!=typeof location&&location.protocol!==e)return console.debug("[VideoJS] HTTP/HTTPS mismatch - skipping"),!1}catch{}const i=[],r={};for(const e of n.meta.tracks)"meta"!==e.type?(r[e.type]||(r[e.type]=[]),r[e.type].push(e)):"subtitle"===e.codec&&i.push("subtitle");const s=["OPUS","Opus","opus","VORBIS","Vorbis","FLAC"],a=document.createElement("video");for(const[e,t]of Object.entries(r)){let n=!1;for(const i of t){if("audio"===e&&s.includes(i.codec)){console.debug(`[VideoJS] Codec incompatible with HLS: ${i.codec}`);continue}let t=i.codec;if(i.init){const e=e=>!i.init||e>=i.init.length?"00":("0"+i.init.charCodeAt(e).toString(16)).slice(-2);switch(i.codec){case"H264":t=`avc1.${e(1)}${e(2)}${e(3)}`;break;case"AAC":t="mp4a.40.2";break;case"MP3":t="mp4a.40.34";break;case"HEVC":t="hev1.1.6.L93.B0"}}const r="audio"===e?`audio/mp4;codecs="${t}"`:`video/mp4;codecs="${t}"`;if(""!==a.canPlayType(r)){n=!0;break}console.debug(`[VideoJS] Codec not supported: ${r}`)}n&&i.push(e)}return 0===Object.keys(r).length?["video","audio"]:i.length>0&&i}async initialize(e,t,n,i){this.destroyed=!1,this.container=e,this.currentStreamInfo=i||null,e.classList.add("fw-player-container");const r=document.createElement("video");r.classList.add("fw-player-video"),r.setAttribute("playsinline",""),r.setAttribute("crossorigin","anonymous"),r.className="video-js vjs-default-skin fw-player-video",n.autoplay&&(r.autoplay=!0),n.muted&&(r.muted=!0),r.controls=!0===n.controls,n.loop&&(r.loop=!0),n.poster&&(r.poster=n.poster),this.videoElement=r,e.appendChild(r),this.setupVideoEventListeners(r,n);try{const e=await Promise.resolve().then(function(){return ng}),i=e.default||e,s=!0===n.controls,a=navigator.userAgent.match(/android\s([\d.]*)/i),o=a?parseFloat(a[1]):null,l={autoplay:n.autoplay,controls:s,muted:n.muted,sources:[{src:t.url,type:this.getVideoJsType(t.type)}],loadingSpinner:s,bigPlayButton:s,textTrackDisplay:s,errorDisplay:s,controlBar:s,liveTracker:s,html5:{vhs:{enableLowInitialPlaylist:!0,bandwidth:5e6,useBandwidthFromLocalStorage:!0,handlePartialData:!0,liveRangeSafeTimeDelta:.3,...n.vhsConfig},...o&&o<7?{hls:{overrideNative:!0}}:{}},nativeAudioTracks:!(o&&o<7)&&void 0,nativeVideoTracks:!(o&&o<7)&&void 0};if(console.debug("[VideoJS] Creating player with options:",l),this.videojsPlayer=i(r,l),console.debug("[VideoJS] Player created"),!s){const e=this.videojsPlayer.el();e&&e.classList.add("vjs-fw-custom-controls")}return this.videojsPlayer.on("error",()=>{if(this.destroyed)return;const e=this.videojsPlayer?.error(),t=e?.message||"";if(t.includes("NS_ERROR_DOM_MEDIA_OVERFLOW_ERR"))return console.warn("[VideoJS] Firefox segment error, requesting reload"),void this.emit("reloadrequested",{reason:"NS_ERROR_DOM_MEDIA_OVERFLOW_ERR"});this.emit("error",t||"VideoJS playback error")}),this.videojsPlayer.ready(()=>{if(this.destroyed)return;const e=this.videojsPlayer.tech?.({IWillNotUseThisInPlugins:!0});console.debug("[VideoJS] ready - tech:",e?.name||"unknown","videoWidth:",r.videoWidth,"videoHeight:",r.videoHeight,"readyState:",r.readyState,"networkState:",r.networkState),this.currentStreamInfo&&(this.proxyElement=this.createTimeCorrectedProxy(r,this.currentStreamInfo));const t=this.videojsPlayer.duration();isFinite(t)||this.liveDurationProxy||(this.liveDurationProxy=new Rt(r,{constrainSeek:!0,liveOffset:0}),console.debug("[VideoJS] LiveDurationProxy initialized for live stream")),n.autoplay&&(r.muted||(r.muted=!0),this.videojsPlayer.play().catch(e=>{console.warn("VideoJS autoplay failed:",e)}))}),this.videojsPlayer.on("loadedmetadata",()=>{console.debug("[VideoJS] loadedmetadata - duration:",this.videojsPlayer.duration(),"videoWidth:",r.videoWidth,"videoHeight:",r.videoHeight)}),this.videojsPlayer.on("loadeddata",()=>{const e=this.videojsPlayer.tech?.({IWillNotUseThisInPlugins:!0}),t=e?.vhs||e?.hls;t&&console.debug("[VideoJS] VHS state -","bandwidth:",t.bandwidth,"seekable:",t.seekable?.()?.length>0?`${t.seekable().start(0)}-${t.seekable().end(0)}`:"none","buffered:",r.buffered.length>0?`${r.buffered.end(0)}s`:"none")}),this.videojsPlayer.on("canplay",()=>{console.debug("[VideoJS] canplay")}),this.videojsPlayer.on("playing",()=>{console.debug("[VideoJS] playing - currentTime:",this.videojsPlayer.currentTime())}),this.videojsPlayer.on("waiting",()=>{console.debug("[VideoJS] waiting/buffering")}),this.videojsPlayer.on("stalled",()=>{console.debug("[VideoJS] stalled")}),r.addEventListener("loadeddata",()=>{console.debug("[VideoJS] video loadeddata - readyState:",r.readyState,"videoWidth:",r.videoWidth,"videoHeight:",r.videoHeight)}),this.videojsPlayer.on("progress",()=>{if(!this.destroyed)try{const e=this.videojsPlayer.seekable();if(e&&e.length>0){const t=e.start(0),n=e.end(e.length-1),i=1e3*(n-t);this.emit("seekablechange",{start:t+this.timeCorrection,end:n+this.timeCorrection,bufferWindow:i})}}catch{}}),this.proxyElement||r}catch(e){throw this.emit("error",e.message||String(e)),e}}createTimeCorrectedProxy(e,t){let n=1/0;for(const e of t.meta.tracks)void 0!==e.firstms&&e.firstms<n&&(n=e.firstms);if(this.timeCorrection=n!==1/0?n/1e3:0,0===this.timeCorrection||"undefined"==typeof Proxy)return e;console.debug(`[VideoJS] Applying timestamp correction: ${this.timeCorrection}s (firstms=${n})`);const i=this.timeCorrection,r=this.videojsPlayer;return new Proxy(e,{get:(e,t)=>{if("currentTime"===t){const t=r?r.currentTime():e.currentTime;return isNaN(t)?0:t+i}if("duration"===t){const t=e.duration;return isNaN(t)?0:t+i}if("buffered"===t){const t=e.buffered;return{length:t.length,start:e=>t.start(e)+i,end:e=>t.end(e)+i}}const n=e[t];return"function"==typeof n?n.bind(e):n},set:(e,t,n)=>{if("currentTime"===t){const t=n-i;return r?r.currentTime(t):e.currentTime=t,!0}return e[t]=n,!0}})}getVideoJsType(e){return e?e.includes("mpegurl")?"application/x-mpegURL":e.includes("dash")?"application/dash+xml":e.includes("mp4")?"video/mp4":e.includes("webm")?"video/webm":e.replace("html5/",""):"application/x-mpegURL"}setPlaybackRate(e){super.setPlaybackRate(e);try{this.videojsPlayer&&this.videojsPlayer.playbackRate(e)}catch{}}getCurrentTime(){const e=this.proxyElement||this.videoElement;return e?.currentTime??0}seek(e){const t=e-this.timeCorrection;this.videojsPlayer?this.videojsPlayer.currentTime(t):this.videoElement&&(this.videoElement.currentTime=t)}async getStats(){const e=this.videoElement;if(!e)return;let t=0;if(e.buffered.length>0)for(let n=0;n<e.buffered.length;n++)if(e.buffered.start(n)<=e.currentTime&&e.buffered.end(n)>e.currentTime){t=e.buffered.end(n)-e.currentTime;break}return{type:"videojs",buffered:t,currentTime:e.currentTime,duration:e.duration,readyState:e.readyState,networkState:e.networkState,playbackRate:e.playbackRate}}isLiveStream(){if(this.liveDurationProxy)return this.liveDurationProxy.isLive();const e=this.videoElement;return!!e&&!isFinite(e.duration)}getDuration(){return this.liveDurationProxy?this.liveDurationProxy.getDuration():this.videoElement?.duration??0}jumpToLive(){const e=this.videoElement;if(e){if(this.videojsPlayer&&this.videojsPlayer.liveTracker){const e=this.videojsPlayer.liveTracker;if(e.isLive&&e.isLive()){const t=e.liveCurrentTime?.();if("number"==typeof t&&t>0)return console.debug("[VideoJS] jumpToLive using liveTracker:",t),void this.videojsPlayer.currentTime(t)}}if(this.liveDurationProxy&&this.liveDurationProxy.isLive())return console.debug("[VideoJS] jumpToLive using LiveDurationProxy"),void this.liveDurationProxy.jumpToLive();if(this.videojsPlayer)try{const e=this.videojsPlayer.seekable();if(e&&e.length>0){const t=e.end(e.length-1);if(isFinite(t)&&t>0)return console.debug("[VideoJS] jumpToLive using seekable.end:",t),void this.videojsPlayer.currentTime(t)}}catch{}if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);isFinite(t)&&t>0&&(console.debug("[VideoJS] jumpToLive using video.seekable.end:",t),e.currentTime=t)}}}getSeekableRange(){const e=this.videoElement;if(!e?.seekable||0===e.seekable.length)return null;let t=e.seekable.start(0),n=e.seekable.end(e.seekable.length-1);if(this.videojsPlayer?.liveTracker){const e=this.videojsPlayer.liveTracker,i=e.seekableEnd?.(),r=e.seekableStart?.();"number"==typeof r&&Number.isFinite(r)&&(t=r),"number"==typeof i&&Number.isFinite(i)&&i>0&&(n=Math.min(n,i))}return!Number.isFinite(t)||!Number.isFinite(n)||n<=t?null:{start:t,end:n}}getLiveLatency(){const e=this.videoElement;if(!e)return 0;if(this.videojsPlayer&&this.videojsPlayer.liveTracker){const t=this.videojsPlayer.liveTracker;if(t.isLive?.()&&"function"==typeof t.seekableEnd){const n=t.seekableEnd();if("number"==typeof n&&isFinite(n))return Math.max(0,1e3*(n-e.currentTime))}}return this.liveDurationProxy?1e3*this.liveDurationProxy.getLatency():0}async destroy(){if(this.destroyed=!0,this.liveDurationProxy&&(this.liveDurationProxy.destroy(),this.liveDurationProxy=null),this.videojsPlayer){try{this.videojsPlayer.dispose()}catch(e){console.warn("Error disposing VideoJS:",e)}this.videojsPlayer=null}if(this.videoElement&&this.container)try{this.container.removeChild(this.videoElement)}catch{}this.videoElement=null,this.container=null,this.proxyElement=null,this.currentStreamInfo=null,this.timeCorrection=0,this.listeners.clear()}}});var Cn=Object.freeze({__proto__:null,HlsJsPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"HLS.js Player",shortname:"hlsjs",priority:3,mimes:["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"]},this.hls=null,this.container=null,this.failureCount=0,this.destroyed=!1,this.liveDurationProxy=null}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(Ie(t.url))return!1;const i=ke();if(i.isAndroid&&i.isMobile)return!1;if(!i.supportsMediaSource){return!!document.createElement("video").canPlayType("application/vnd.apple.mpegurl")&&["video","audio"]}const r=[],s={};if(!n.meta.tracks||0===n.meta.tracks.length)return["video","audio"];for(const e of n.meta.tracks)if("meta"!==e.type)s[e.type]||(s[e.type]=[]),s[e.type].push(e);else if("subtitle"===e.codec)for(const e of n.source)if("html5/text/vtt"===e.type){r.push("subtitle");break}const a=["OPUS","Opus","opus","VORBIS","Vorbis","FLAC"];for(const[e,t]of Object.entries(s)){let n=!1;for(const i of t){if("audio"===e&&a.includes(i.codec)){console.debug(`[HLS.js] Codec incompatible with HLS: ${i.codec}`);continue}const t=`${"audio"===e?"audio/mp4":"video/mp4"};codecs="${_e(i)}"`;if(MediaSource.isTypeSupported&&MediaSource.isTypeSupported(t)){n=!0;break}console.debug(`[HLS.js] Codec not supported: ${t}`)}n&&r.push(e)}return r.length>0&&r}async initialize(e,t,n){console.log("[HLS.js] initialize() starting for",t.url.slice(0,60)+"..."),this.destroyed=!1,this.container=e,e.classList.add("fw-player-container");const i=document.createElement("video");i.classList.add("fw-player-video"),i.setAttribute("playsinline",""),i.setAttribute("crossorigin","anonymous"),n.autoplay&&(i.autoplay=!0),n.muted&&(i.muted=!0),i.controls=!0===n.controls,n.loop&&(i.loop=!0),n.poster&&(i.poster=n.poster),this.videoElement=i,e.appendChild(i),this.setupVideoEventListeners(i,n);try{console.log("[HLS.js] Dynamically importing hls.js module...");const e=await Promise.resolve().then(function(){return pw}),r=e.default||e;if(console.log("[HLS.js] hls.js module imported, Hls.isSupported():",r.isSupported?.()),r.isSupported()){const e={enableWorker:!1,lowLatencyMode:!0,abrEwmaDefaultEstimate:5e6,maxBufferLength:6,maxMaxBufferLength:15,backBufferLength:1/0,liveSyncDuration:4,liveMaxLatencyDuration:8,abrEwmaFastLive:2,abrEwmaSlowLive:6,...n.hlsConfig};this.hls=new r(e),this.hls.attachMedia(i),this.hls.on(r.Events.MEDIA_ATTACHED,()=>{this.hls.loadSource(t.url)}),this.hls.on(r.Events.ERROR,(e,t)=>{if(!this.destroyed&&t?.fatal)if(this.failureCount<3){this.failureCount++;try{this.hls.recoverMediaError()}catch{}}else{const e=`HLS fatal error: ${t?.type||"unknown"}`;this.emit("error",e)}}),this.hls.on(r.Events.MANIFEST_PARSED,()=>{if(this.destroyed)return;(!isFinite(i.duration)||this.hls.levels?.[0]?.details?.live)&&!this.liveDurationProxy&&(this.liveDurationProxy=new Rt(i,{constrainSeek:!0,liveOffset:0}),console.debug("[HLS.js] LiveDurationProxy initialized for live stream")),n.autoplay&&i.play().catch(e=>console.warn("HLS autoplay failed:",e))})}else{if(!i.canPlayType("application/vnd.apple.mpegurl"))throw new Error("HLS not supported in this browser");i.src=t.url,n.autoplay&&i.play().catch(e=>console.warn("Native HLS autoplay failed:",e))}try{const e=t.subtitles;Array.isArray(e)&&e.forEach((e,t)=>{const n=document.createElement("track");n.kind="subtitles",n.label=e.label,n.srclang=e.lang,n.src=e.src,0===t&&(n.default=!0),i.appendChild(n)})}catch{}return console.log("[HLS.js] initialize() complete, returning video element"),i}catch(e){throw this.emit("error",e.message||String(e)),e}}async destroy(){if(console.debug("[HLS.js] destroy() called"),this.destroyed=!0,this.liveDurationProxy&&(this.liveDurationProxy.destroy(),this.liveDurationProxy=null),this.hls){try{this.hls.destroy(),console.debug("[HLS.js] hls.destroy() completed")}catch(e){console.warn("[HLS.js] Error destroying:",e)}this.hls=null}if(this.videoElement&&this.container)try{this.container.removeChild(this.videoElement)}catch{}this.videoElement=null,this.container=null,this.listeners.clear()}getDuration(){return this.liveDurationProxy?this.liveDurationProxy.getDuration():this.videoElement?.duration??0}isLiveStream(){if(this.liveDurationProxy)return this.liveDurationProxy.isLive();const e=this.videoElement;return!!e&&!isFinite(e.duration)}seek(e){const t=this.videoElement;t&&(this.liveDurationProxy&&this.liveDurationProxy.isLive()?this.liveDurationProxy.seek(e):t.currentTime=e)}jumpToLive(){const e=this.videoElement;if(e){if(this.hls&&"number"==typeof this.hls.liveSyncPosition&&this.hls.liveSyncPosition>0)return console.debug("[HLS.js] jumpToLive using liveSyncPosition:",this.hls.liveSyncPosition),void(e.currentTime=this.hls.liveSyncPosition);if(this.liveDurationProxy&&this.liveDurationProxy.isLive())return console.debug("[HLS.js] jumpToLive using LiveDurationProxy"),void this.liveDurationProxy.jumpToLive();if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);isFinite(t)&&t>0&&(console.debug("[HLS.js] jumpToLive using seekable.end:",t),e.currentTime=t)}}}getSeekableRange(){const e=this.videoElement;if(!e?.seekable||0===e.seekable.length)return null;const t=e.seekable.start(0);let n=e.seekable.end(e.seekable.length-1);if(this.liveDurationProxy?.isLive()&&this.hls&&"number"==typeof this.hls.liveSyncPosition){const e=this.hls.liveSyncPosition;Number.isFinite(e)&&e>0&&(n=Math.min(n,e))}return!Number.isFinite(t)||!Number.isFinite(n)||n<=t?null:{start:t,end:n}}getLiveLatency(){const e=this.videoElement;return e?this.hls&&"number"==typeof this.hls.liveSyncPosition?Math.max(0,1e3*(this.hls.liveSyncPosition-e.currentTime)):this.liveDurationProxy?1e3*this.liveDurationProxy.getLatency():0:0}getQualities(){const e=[],t=this.videoElement;if(!this.hls||!t)return e;const n=this.hls.levels||[],i={id:"auto",label:"Auto",isAuto:!0,active:this.hls.autoLevelEnabled};return e.push(i),n.forEach((t,n)=>{e.push({id:String(n),label:t.height?`${t.height}p`:`${Math.round((t.bitrate||0)/1e3)}kbps`,bitrate:t.bitrate,width:t.width,height:t.height,active:this.hls.currentLevel===n})}),e}selectQuality(e){if(!this.hls)return;if("auto"===e)return this.hls.currentLevel=-1,void(this.hls.autoLevelEnabled=!0);const t=parseInt(e,10);isNaN(t)||(this.hls.autoLevelEnabled=!1,this.hls.currentLevel=t)}getTextTracks(){const e=this.videoElement;if(!e)return[];const t=e.textTracks,n=[];for(let e=0;e<t.length;e++){const i=t[e];n.push({id:String(e),label:i.label||`CC ${e+1}`,lang:i.language,active:"showing"===i.mode})}return n}selectTextTrack(e){const t=this.videoElement;if(!t)return;const n=t.textTracks;for(let t=0;t<n.length;t++){const i=n[t];null!==e&&String(t)===e?i.mode="showing":i.mode="disabled"}}async getStats(){if(!this.hls)return;const e=(this.hls.levels||[]).map(e=>({bitrate:e.bitrate||0,width:e.width||0,height:e.height||0})),t=this.hls.currentLevel,n=e[t];let i=0;const r=this.videoElement;if(r&&r.buffered.length>0)for(let e=0;e<r.buffered.length;e++)if(r.buffered.start(e)<=r.currentTime&&r.buffered.end(e)>r.currentTime){i=r.buffered.end(e)-r.currentTime;break}let s;return r&&void 0!==this.hls.liveSyncPosition&&!isFinite(r.duration)&&(s=1e3*(this.hls.liveSyncPosition-r.currentTime)),{type:"hls",bandwidthEstimate:this.hls.bandwidthEstimate||0,currentLevel:t,currentBitrate:n?.bitrate||0,loadLevel:this.hls.loadLevel||0,levels:e,buffered:i,latency:s}}}});var Rn=Object.freeze({__proto__:null,DashJsPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"Dash.js Player",shortname:"dashjs",priority:100,mimes:["dash/video/mp4"]},this.dashPlayer=null,this.container=null,this.destroyed=!1,this.debugging=!1,this.lastProgress=Date.now(),this.videoProxy=null,this.streamType="unknown",this.subsLoaded=!1,this.pendingSubtitleId=null}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(Ie(t.url))return!1;if(Ae())return!1;if(!ke().supportsMediaSource)return!1;const i=[],r={};for(const e of n.meta.tracks)if("meta"!==e.type)r[e.type]||(r[e.type]=[]),r[e.type].push(e);else if("subtitle"===e.codec)for(const e of n.source)if("html5/text/vtt"===e.type){i.push("subtitle");break}const s=["OPUS","Opus","opus","VORBIS","Vorbis"];for(const[e,t]of Object.entries(r)){let n=!1;for(const i of t){if("audio"===e&&s.includes(i.codec)){console.debug(`[DashJS] Codec incompatible with DASH fMP4: ${i.codec}`);continue}const t=`${"audio"===e?"audio/mp4":"video/mp4"};codecs="${_e(i)}"`;if(MediaSource.isTypeSupported&&MediaSource.isTypeSupported(t)){n=!0;break}console.debug(`[DashJS] Codec not supported: ${t}`)}n&&i.push(e)}return i.length>0&&i}isLiveStream(){if("live"===this.streamType)return!0;if("vod"===this.streamType)return!1;const e=this.videoElement;return!(!e||e.duration!==1/0&&isFinite(e.duration))}createVideoProxy(e){if(!("Proxy"in window))return e;e.addEventListener("progress",()=>{this.lastProgress=Date.now()});const t=this;return new Proxy(e,{get(e,n,i){if("duration"===n&&t.isLiveStream()){const n=e.buffered;if(n.length>0){return n.end(n.length-1)+(Date.now()-t.lastProgress)/1e3}}const r=Reflect.get(e,n,i);return"function"==typeof r?r.bind(e):r},set:(e,t,n)=>Reflect.set(e,t,n)})}setupEventLogging(e){const t=["METRIC_ADDED","METRIC_UPDATED","METRIC_CHANGED","METRICS_CHANGED","FRAGMENT_LOADING_STARTED","FRAGMENT_LOADING_COMPLETED","LOG","PLAYBACK_TIME_UPDATED","PLAYBACK_PROGRESS"],n=e.MediaPlayer?.events||{};for(const e of Object.keys(n))t.includes(e)||this.dashPlayer.on(n[e],e=>{this.destroyed||this.debugging&&console.log("DASH event:",e.type)})}setupSubtitleHandling(){this.dashPlayer.on("allTextTracksAdded",()=>{this.destroyed||(this.subsLoaded=!0,null!==this.pendingSubtitleId&&(this.selectTextTrack(this.pendingSubtitleId),this.pendingSubtitleId=null))})}setupStalledHandling(){this.videoElement?.addEventListener("progress",()=>{})}async initialize(e,t,n){this.destroyed=!1,this.container=e,this.subsLoaded=!1,this.pendingSubtitleId=null,e.classList.add("fw-player-container");const i=t.type;this.streamType="live"===i?"live":"vod"===i?"vod":"unknown";const r=document.createElement("video");r.classList.add("fw-player-video"),r.setAttribute("playsinline",""),r.setAttribute("crossorigin","anonymous"),n.autoplay&&(r.autoplay=!0),n.muted&&(r.muted=!0),r.controls=!0===n.controls,n.loop&&"live"!==this.streamType&&(r.loop=!0),n.poster&&(r.poster=n.poster),this.videoProxy=this.createVideoProxy(r),this.videoElement=r,e.appendChild(r),this.setupVideoEventListeners(r,n),this.setupStalledHandling();try{console.debug("[DashJS] Importing dashjs module...");const e=await Promise.resolve().then(function(){return zw}),i=e.default||e;console.debug("[DashJS] Module imported:",i),this.dashPlayer=i.MediaPlayer().create(),console.debug("[DashJS] MediaPlayer created"),this.setupEventLogging(i),this.setupSubtitleHandling(),this.dashPlayer.on("error",e=>{if(this.destroyed)return;const t=`DASH error: ${e?.event?.message||e?.message||"unknown"}`;console.error("[DashJS] Error event:",e),this.emit("error",t)}),this.dashPlayer.on("manifestLoaded",e=>{console.debug("[DashJS] manifestLoaded:",e)}),this.dashPlayer.on("canPlay",()=>{console.debug("[DashJS] canPlay event")}),this.dashPlayer.on("streamInitialized",()=>{if(this.destroyed)return;const e=this.dashPlayer.isDynamic?.()??!1;console.debug("[DashJS v5] streamInitialized - isDynamic:",e)}),this.dashPlayer.updateSettings({streaming:{buffer:{fastSwitchEnabled:!0,stableBufferTime:4,bufferTimeAtTopQuality:8,bufferTimeAtTopQualityLongForm:15,bufferToKeep:10,bufferPruningInterval:10},gaps:{jumpGaps:!0,jumpLargeGaps:!0,smallGapLimit:1.5,threshold:.3},abr:{autoSwitchBitrate:{video:!0,audio:!0},limitBitrateByPortal:!1,useDefaultABRRules:!0,initialBitrate:{video:5e6,audio:128e3}},liveCatchup:{enabled:!0,maxDrift:1.5,playbackRate:{max:.15,min:-.15},playbackBufferMin:.3,mode:"liveCatchupModeDefault"},retryAttempts:{MPD:5,MediaSegment:5,InitializationSegment:5,BitstreamSwitchingSegment:5,IndexSegment:5,XLinkExpansion:3,other:3},retryIntervals:{MPD:1e3,MediaSegment:1e3,InitializationSegment:1e3,BitstreamSwitchingSegment:1e3,IndexSegment:1e3,XLinkExpansion:1e3,other:1e3},timeoutAttempts:{MPD:2,MediaSegment:2,InitializationSegment:2,BitstreamSwitchingSegment:2,IndexSegment:2,XLinkExpansion:1,other:1},abandonLoadTimeout:5e3,xhrWithCredentials:!1,text:{defaultEnabled:!1},delay:{liveDelay:2,liveDelayFragmentCount:null,useSuggestedPresentationDelay:!1}},debug:{logLevel:4}}),this.dashPlayer.on("fragmentLoadingStarted",e=>{console.debug("[DashJS] Fragment loading started:",e.request?.url?.split("/").pop())}),this.dashPlayer.on("fragmentLoadingCompleted",e=>{console.debug("[DashJS] Fragment loading completed:",e.request?.url?.split("/").pop())}),this.dashPlayer.on("fragmentLoadingAbandoned",e=>{console.warn("[DashJS] Fragment loading ABANDONED:",e.request?.url?.split("/").pop(),e)}),this.dashPlayer.on("fragmentLoadingFailed",e=>{console.error("[DashJS] Fragment loading FAILED:",e.request?.url?.split("/").pop(),e)}),console.debug("[DashJS v5] Initializing with URL:",t.url),this.dashPlayer.initialize(r,t.url,n.autoplay??!1),console.debug("[DashJS v5] Initialize called");try{const e=t.subtitles;Array.isArray(e)&&e.forEach((e,t)=>{const n=document.createElement("track");n.kind="subtitles",n.label=e.label,n.srclang=e.lang,n.src=e.src,0===t&&(n.default=!0),r.appendChild(n)})}catch{}return r}catch(e){throw this.emit("error",e.message||String(e)),e}}async getStats(){if(this.dashPlayer&&this.videoElement)try{const e=this.dashPlayer.getCurrentRepresentationForType?.("video"),t=this.dashPlayer.getRepresentationsByType?.("video")||[],n=this.dashPlayer.getBufferLength("video")||0,i=e?t.findIndex(t=>t.id===e.id):0;return{type:"dash",currentQuality:i>=0?i:0,bufferLevel:n,bitrateInfoList:t.map(e=>({bitrate:e.bandwidth||0,width:e.width||0,height:e.height||0})),currentBitrate:e?.bandwidth||0,playbackRate:this.videoElement.playbackRate}}catch{return}}setPlaybackRate(e){this.videoElement&&(this.videoElement.playbackRate=e)}setSource(e){this.dashPlayer&&this.dashPlayer.attachSource(e)}getDuration(){return this.videoProxy&&this.isLiveStream()?this.videoProxy.duration??0:this.videoElement?.duration??0}jumpToLive(){const e=this.videoElement;if(e&&this.isLiveStream()){if(this.dashPlayer&&"function"==typeof this.dashPlayer.seekToLive)return console.debug("[DashJS] jumpToLive using seekToLive()"),void this.dashPlayer.seekToLive();if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);isFinite(t)&&t>0&&(console.debug("[DashJS] jumpToLive using seekable.end:",t),e.currentTime=t)}}}getLiveLatency(){const e=this.videoElement;if(!e||!this.isLiveStream())return 0;if(this.dashPlayer&&"function"==typeof this.dashPlayer.getCurrentLiveLatency)return 1e3*this.dashPlayer.getCurrentLiveLatency();if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);if(isFinite(t))return Math.max(0,1e3*(t-e.currentTime))}return 0}async destroy(){if(this.destroyed=!0,this.subsLoaded=!1,this.pendingSubtitleId=null,this.videoProxy=null,this.dashPlayer){try{this.dashPlayer.reset()}catch(e){console.warn("Error destroying DASH.js:",e)}this.dashPlayer=null}if(this.videoElement&&this.container)try{this.container.removeChild(this.videoElement)}catch{}this.videoElement=null,this.container=null,this.listeners.clear()}getQualities(){const e=[],t=this.videoElement;if(!this.dashPlayer||!t)return e;try{const t=this.dashPlayer.getRepresentationsByType?.("video")||[],n=this.dashPlayer.getSettings?.(),i=!1!==n?.streaming?.abr?.autoSwitchBitrate?.video;e.push({id:"auto",label:"Auto",isAuto:!0,active:i}),t.forEach((t,n)=>{e.push({id:String(n),label:t.height?`${t.height}p`:`${Math.round((t.bandwidth||0)/1e3)}kbps`,bitrate:t.bandwidth,width:t.width,height:t.height})})}catch{}return e}selectQuality(e){if(!this.dashPlayer)return;if("auto"===e)return void this.dashPlayer.updateSettings({streaming:{abr:{autoSwitchBitrate:{video:!0}}}});const t=parseInt(e,10);if(!isNaN(t)){this.dashPlayer.updateSettings({streaming:{abr:{autoSwitchBitrate:{video:!1}}}});try{this.dashPlayer.setRepresentationForTypeByIndex?.("video",t)}catch{}}}getTextTracks(){const e=this.videoElement;if(!this.dashPlayer||!e)return[];const t=[];try{const n=e.textTracks||[];for(let e=0;e<n.length;e++){const i=n[e];t.push({id:String(e),label:i.label||`CC ${e+1}`,lang:i.language,active:"showing"===i.mode})}}catch{}return t}selectTextTrack(e){const t=this.videoElement;if(!this.dashPlayer||!t)return;if(!this.subsLoaded)return void(this.pendingSubtitleId=e);try{const t=this.dashPlayer.getTracksFor("text");if(t&&t.length>0){const n=null===e?-1:parseInt(e,10);if(n>=0&&n<t.length)return void this.dashPlayer.setTextTrack(n);if(null===e||n<0)return void this.dashPlayer.setTextTrack(-1)}}catch{}const n=t.textTracks;for(let t=0;t<n.length;t++){const i=n[t];null!==e&&String(t)===e?i.mode="showing":i.mode="disabled"}}}});var xn=Object.freeze({__proto__:null,MistPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"Legacy",shortname:"mist-legacy",priority:99,mimes:["mist/legacy"]},this.container=null,this.mistDiv=null,this.proxyVideo=null,this.previousContainerOverflow=null,this.destroyed=!1}isMimeSupported(e){return"mist/legacy"===e}isBrowserSupported(e,t,n){return"mist/legacy"===e&&["video","audio"]}async initialize(e,t,n){this.destroyed=!1,this.container=e,e.classList.add("fw-player-container");const i=t.streamName||"stream",r=`${i.replace(/[^a-zA-Z0-9]/g,"_")}_${Math.random().toString(36).slice(2,10)}`;this.mistDiv=document.createElement("div"),this.mistDiv.className="mistvideo fw-player-container",this.mistDiv.id=r,this.mistDiv.style.width="100%",this.mistDiv.style.height="100%",this.mistDiv.style.overflow="hidden",this.previousContainerOverflow=e.style.overflow??"",e.style.overflow="hidden",e.appendChild(this.mistDiv);const s=this.getPlayerJsUrl(t);await this.loadAndPlay(i,this.mistDiv,s,n);const a=this.findVideoElement()||this.createProxyVideo(e);return this.videoElement=a,this.setupVideoEventListeners(a,n),a}getPlayerJsUrl(e){if(e.mistPlayerUrl)return e.mistPlayerUrl;try{const t=new URL(e.url);return`${t.protocol}//${t.host}/player.js`}catch{return"/player.js"}}async loadAndPlay(e,t,n,i){const r=()=>{if(!this.destroyed&&window.mistPlay){const n={target:t,fillSpace:!0,controls:!0,skin:i.devMode?"dev":"default",...void 0!==i.autoplay&&{autoplay:i.autoplay},...void 0!==i.muted&&{muted:i.muted},...i.poster&&{poster:i.poster}};console.debug("[Legacy] mistPlay options:",n),window.mistPlay(e,n)}};window.mistplayers?r():await new Promise((e,t)=>{const i=document.createElement("script");i.src=n,i.onload=()=>{r(),e()},i.onerror=()=>t(new Error(`Failed to load MistServer player from ${n}`)),document.head.appendChild(i)})}findVideoElement(){return this.mistDiv?this.mistDiv.querySelector("video"):null}createProxyVideo(e){const t=document.createElement("video");return t.style.display="none",e.appendChild(t),this.proxyVideo=t,t}async destroy(){if(this.destroyed=!0,this.mistDiv){try{const e=this.mistDiv.MistVideoObject?.reference;e&&"function"==typeof e.unload&&e.unload()}catch{}try{this.mistDiv.remove()}catch{try{this.mistDiv.parentNode?.removeChild(this.mistDiv)}catch{}}this.mistDiv=null}if(this.proxyVideo){try{this.proxyVideo.remove()}catch{try{this.proxyVideo.parentNode?.removeChild(this.proxyVideo)}catch{}}this.proxyVideo=null}if(this.container)try{null!==this.previousContainerOverflow&&(this.container.style.overflow=this.previousContainerOverflow)}catch{}this.videoElement=null,this.container=null,this.previousContainerOverflow=null,this.listeners.clear()}}});class Dn{constructor(e){this.ws=null,this.reconnectAttempts=0,this.reconnectTimer=null,this.wasConnected=!1,this.isDestroyed=!1,this.pendingRetryTimers=new Set,this.listeners={},this.url=e.url,this.maxReconnectAttempts=e.maxReconnectAttempts??5,this.onMessage=e.onMessage,this.onOpen=e.onOpen,this.onClose=e.onClose,this.onError=e.onError}connect(){if(this.isDestroyed)return;try{const e=window.location.protocol.replace(/^http/,"ws"),t=new URL(this.url,window.location.href).protocol;e!==t&&this.onError(`Protocol mismatch ${e} vs ${t}`)}catch{}const e=new WebSocket(this.url);e.binaryType="arraybuffer",this.ws=e,e.onopen=()=>{this.wasConnected=!0,this.reconnectAttempts=0,this.clearReconnectTimer(),this.onOpen()},e.onmessage=e=>{this.onMessage(e.data)},e.onerror=()=>{this.onError("WebSocket error")},e.onclose=()=>{if(!this.isDestroyed)if(this.wasConnected&&this.reconnectAttempts<this.maxReconnectAttempts){const e=Math.min(5e3,500*Math.pow(2,this.reconnectAttempts));this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{this.isDestroyed||this.connect()},e)}else this.onClose(),this.onError("WebSocket closed")}}send(e,t=0){if(this.isDestroyed)return!1;if(t>5)return this.onError("Too many send retries"),!1;const n=n=>{const i=setTimeout(()=>{this.pendingRetryTimers.delete(i),this.isDestroyed||this.send(e,t+1)},n);this.pendingRetryTimers.add(i)};if(!this.ws)return!this.isDestroyed&&t<5&&n(500),!1;if(this.ws.readyState<WebSocket.OPEN)return!this.isDestroyed&&t<5&&n(500),!1;if(this.ws.readyState>=WebSocket.CLOSING)return!this.isDestroyed&&t<5&&(this.connect(),n(1e3)),!1;try{return this.ws.send(JSON.stringify(e)),!0}catch{return!1}}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}destroy(){console.debug("[WebSocketManager] destroy() called"),this.isDestroyed=!0,this.clearReconnectTimer();for(const e of this.pendingRetryTimers)clearTimeout(e);if(this.pendingRetryTimers.clear(),this.listeners={},this.ws){try{this.ws.close()}catch{}this.ws=null}console.debug("[WebSocketManager] destroy() completed")}isConnected(){return this.ws?.readyState===WebSocket.OPEN}addListener(e,t){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push(t)}removeListener(e,t){if(!(e in this.listeners))return!1;const n=this.listeners[e].indexOf(t);return!(n<0)&&(this.listeners[e].splice(n,1),!0)}notifyListeners(e){if(e.type in this.listeners){const t=this.listeners[e.type];for(let n=t.length-1;n>=0;n--)try{t[n](e)}catch(e){console.error("MEWS listener error:",e)}}}}class Ln{constructor(e){this.sourceBuffer=null,this.queue=[],this._busy=!1,this.do_on_updateend=[],this.msgqueue=!1,this._codecs=[],this.fragmentCount=0,this.paused=!1,this.debugging=!1,this.mediaSource=e.mediaSource,this.videoElement=e.videoElement,this.onError=e.onError}initWithCodecs(e){if(this.sourceBuffer)return!0;if(!e||!e.length)return this.onError("No codecs provided"),!1;const t=`video/mp4;codecs="${e.join(",")}"`;if(!MediaSource.isTypeSupported(t))return this.onError(`Unsupported MSE codec: ${t}`),!1;try{return this.sourceBuffer=this.mediaSource.addSourceBuffer(t),this.sourceBuffer.mode="segments",this._codecs=e.slice(),this.installEventHandlers(),this.drainMessageQueue(),this.flushQueue(),!0}catch(e){return this.onError(e?.message||"Failed to create SourceBuffer"),!1}}getCodecs(){return this._codecs}append(e){e&&e.byteLength&&(this.msgqueue?this.msgqueue[this.msgqueue.length-1].push(e):this.sourceBuffer?this.sourceBuffer.updating||this.queue.length||this._busy?this.queue.push(e):this._append(e):this.queue.push(e))}_append(e){if(e&&e.buffer&&this.sourceBuffer){if(this._busy)return this.debugging&&console.warn("MEWS: wanted to append but busy, requeuing"),void this.queue.unshift(e);this._busy=!0;try{if(e.buffer instanceof SharedArrayBuffer){const t=new ArrayBuffer(e.byteLength);new Uint8Array(t).set(e),this.sourceBuffer.appendBuffer(t)}else this.sourceBuffer.appendBuffer(e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength))}catch(t){switch(t?.name){case"QuotaExceededError":{const t=this.videoElement.buffered;if(t.length&&this.videoElement.currentTime-t.start(0)>1)return this.debugging&&console.log("MEWS: QuotaExceededError, cleaning buffer"),this._clean(1),this._busy=!1,void this._append(e);if(t.length){const n=t.end(t.length-1);return this.debugging&&console.log("MEWS: QuotaExceededError, skipping ahead"),this.videoElement.currentTime=n,this._busy=!1,void this._append(e)}break}case"InvalidStateError":if(this.videoElement.error)return void(this._busy=!1)}this.onError(t?.message||"Append buffer failed"),this._busy=!1}}}_doNext(e){this.do_on_updateend.push(e)}_do(e){this.sourceBuffer?this.sourceBuffer.updating||this._busy?this._doNext(e):e():this._doNext(e)}scheduleAfterUpdate(e){this._doNext(e)}changeCodecs(e,t){if(this.codecsEqual(this._codecs,e))return void(this.debugging&&console.log("MEWS: keeping source buffer, codecs same"));const n=`video/mp4;codecs="${e.join(",")}"`;if(!MediaSource.isTypeSupported(n))return void this.onError(`Unsupported codec for switch: ${n}`);this.msgqueue?this.msgqueue.push([]):this.msgqueue=[[]];const i=e.slice();"number"==typeof t&&t>0?this.awaitSwitchingPoint(n,t,i):this.clearAndReinit(n,i)}codecsEqual(e,t){if(e.length!==t.length)return!1;for(const n of e)if(!t.includes(n))return!1;return!0}findBufferIndex(e){const t=this.videoElement.buffered;for(let n=0;n<t.length;n++)if(t.start(n)<=e&&t.end(n)>=e)return n;return!1}_clean(e=180){if(!this.sourceBuffer)return;const t=this.videoElement.currentTime;t<=e||this._do(()=>{if(this.sourceBuffer)try{this.sourceBuffer.remove(0,Math.max(.1,t-e))}catch{}})}clearAndReinit(e,t){this._do(n=>{if(this.sourceBuffer)if(this.sourceBuffer.updating)this._doNext(()=>this.clearAndReinit(e,t));else{try{isNaN(this.mediaSource.duration)||this.sourceBuffer.remove(0,1/0)}catch{}this._doNext(()=>{this.reinitBuffer(e,t,n)})}else this.reinitBuffer(e,t,n)})}reinitBuffer(e,t,n){const i=this.queue.slice();if(this.queue=[],this.sourceBuffer&&"open"===this.mediaSource.readyState)try{this.mediaSource.removeSourceBuffer(this.sourceBuffer)}catch{}this.sourceBuffer=null,this._busy=!1;try{this.sourceBuffer=this.mediaSource.addSourceBuffer(e),this.sourceBuffer.mode="segments",this._codecs=t,this.installEventHandlers(),n?.length&&(this.do_on_updateend=n),this.drainMessageQueue();for(const e of i)this.append(e)}catch(e){this.onError(e?.message||"Failed to reinit SourceBuffer")}}awaitSwitchingPoint(e,t,n){const i=t/1e3,r=()=>{this.clearAndReinit(e,n)},s=()=>{this.videoElement.currentTime>=i&&(this.videoElement.removeEventListener("timeupdate",s),this.videoElement.removeEventListener("waiting",a),r())},a=()=>{this.videoElement.removeEventListener("timeupdate",s),this.videoElement.removeEventListener("waiting",a),r()};this.videoElement.addEventListener("timeupdate",s),this.videoElement.addEventListener("waiting",a)}drainMessageQueue(){if(!this.msgqueue||0===this.msgqueue.length)return;const e=this.msgqueue[0];let t=!1;if(e.length)for(const t of e)this.sourceBuffer&&(this.sourceBuffer.updating||this.queue.length||this._busy)?this.queue.push(t):this._append(t);else t=!0;this.msgqueue.shift(),0===this.msgqueue.length&&(this.msgqueue=!1),this.debugging&&console.log("MEWS: drained msgqueue",this.msgqueue?`${this.msgqueue.length} more queue(s) remain`:""),t&&this.sourceBuffer&&this.sourceBuffer.dispatchEvent(new Event("updateend"))}installEventHandlers(){this.sourceBuffer&&(this.sourceBuffer.addEventListener("updateend",()=>{if(!this.sourceBuffer)return void(this.debugging&&console.log("MEWS: updateend but sourceBuffer is null"));this.fragmentCount>=500?(this.fragmentCount=0,this._clean(10)):this.fragmentCount++;const e=this.do_on_updateend.slice();this.do_on_updateend=[];for(let t=0;t<e.length;t++){if(!this.sourceBuffer){this.debugging&&console.warn("MEWS: doing updateend but sb was reset");break}if(this.sourceBuffer.updating){this.do_on_updateend=this.do_on_updateend.concat(e.slice(t)),this.debugging&&console.warn("MEWS: doing updateend but was interrupted");break}try{e[t](t<e.length-1?e.slice(t+1):[])}catch(e){console.error("MEWS: error in do_on_updateend:",e)}}this._busy=!1,this.sourceBuffer&&this.queue.length>0&&!this.sourceBuffer.updating&&!this.videoElement.error&&this._append(this.queue.shift())}),this.sourceBuffer.addEventListener("error",()=>{this.onError("SourceBuffer error")}))}flushQueue(){if(!this.sourceBuffer)return;const e=this.queue.slice();this.queue=[];for(const t of e)this.append(t)}hasActiveMessageQueue(){return!1!==this.msgqueue}destroy(){if(this.sourceBuffer)try{this.sourceBuffer.abort()}catch{}this.sourceBuffer=null,this.queue=[],this._busy=!1,this.do_on_updateend=[],this.msgqueue=!1,this.paused=!1}}var Pn,Nn,Mn=Object.freeze({__proto__:null,MewsWsPlayerImpl:class extends Ne{constructor(){super(...arguments),this.capability={name:"MEWS WebSocket Player",shortname:"mews",priority:2,mimes:["ws/video/mp4","wss/video/mp4","ws/video/webm","wss/video/webm"]},this.wsManager=null,this.sbManager=null,this.mediaSource=null,this.objectUrl=null,this.container=null,this.isDestroyed=!1,this.debugging=!1,this.serverDelays=[],this.pendingDelayTypes={},this.supportedCodecs=[],this.isReady=!1,this.readyResolvers=[],this.lastDuration=1/0,this.streamType="unknown",this.currentTracks=[],this.lastCodecs=null,this.requestedRate=1,this.bitCounter=[],this.bitsSince=[],this.currentBps=null,this.nWaiting=0,this.nWaitingThreshold=3,this.seeking=!1,this.analyticsConfig={enabled:!1,endpoint:null},this.analyticsTimer=null}isMimeSupported(e){return this.capability.mimes.includes(e)}isBrowserSupported(e,t,n){if(!("WebSocket"in window)||!("MediaSource"in window)||!("Promise"in window))return!1;if(/Mac OS X/.test(navigator.userAgent))return!1;const i=e.split("/")[2]||"mp4",r={};let s=!1;this.supportedCodecs=[];for(const e of n.meta.tracks){if("meta"===e.type){"subtitle"===e.codec&&(s=!0);continue}const t=`video/${i};codecs="${_e(e)}"`;MediaSource.isTypeSupported(t)&&(this.supportedCodecs.push(e.codec),r[e.type]=1)}if(s){const e=n.source?.some(e=>"html5/text/vtt"===e.type);e&&(r.subtitle=1)}return 0!==Object.keys(r).length&&Object.keys(r)}async initialize(e,t,n,i){this.container=e,e.classList.add("fw-player-container");const r=document.createElement("video");r.classList.add("fw-player-video"),r.setAttribute("playsinline",""),r.setAttribute("crossorigin","anonymous"),n.autoplay&&(r.autoplay=!0),n.muted&&(r.muted=!0),r.controls=!0===n.controls,n.loop&&(r.loop=!0),n.poster&&(r.poster=n.poster),"live"===this.streamType&&(r.loop=!1),this.videoElement=r,e.appendChild(r),this.setupVideoEventListeners(r,n);const s=n;this.analyticsConfig={enabled:!!s.analytics?.enabled,endpoint:s.analytics?.endpoint||null},"live"===i?.type?this.streamType="live":"vod"===i?.type&&(this.streamType="vod");try{return this.mediaSource=new MediaSource,this.mediaSource.addEventListener("sourceopen",()=>this.handleSourceOpen(t)),this.mediaSource.addEventListener("sourceclose",()=>this.handleSourceClose()),this.mediaSource.addEventListener("sourceended",()=>this.handleSourceEnded()),this.objectUrl=URL.createObjectURL(this.mediaSource),r.src=this.objectUrl,this.isDestroyed=!1,this.startTelemetry(),r}catch(e){throw this.emit("error",e.message||String(e)),e}}handleSourceOpen(e){this.mediaSource&&this.videoElement&&(this.sbManager=new Ln({mediaSource:this.mediaSource,videoElement:this.videoElement,onError:e=>this.emit("error",e)}),this.installWaitingHandler(),this.installSeekingHandler(),this.installPauseHandler(),this.installLoopHandler(),this.wsManager=new Dn({url:e.url,maxReconnectAttempts:5,onMessage:e=>this.handleMessage(e),onOpen:()=>this.handleWsOpen(),onClose:()=>this.handleWsClose(),onError:e=>this.emit("error",e)}),this.wsManager.connect())}handleSourceClose(){this.debugging&&console.log("MEWS: MediaSource closed"),this.send({type:"stop"})}handleSourceEnded(){this.debugging&&console.log("MEWS: MediaSource ended"),this.send({type:"stop"})}handleWsOpen(){const e=t=>{if("open"===this.mediaSource?.readyState){const e=t.data?.codecs||[],n=this.sbManager?.initWithCodecs(e);if(n&&!this.isReady){this.isReady=!0;for(const e of this.readyResolvers)e();this.readyResolvers=[]}}this.wsManager?.removeListener("codec_data",e)};this.wsManager?.addListener("codec_data",e),this.logDelay("codec_data"),this.send({type:"request_codec_data",supported_codecs:this.supportedCodecs})}handleWsClose(){this.debugging&&console.log("MEWS: WebSocket closed")}handleMessage(e){if("string"==typeof e){try{const t=JSON.parse(e);this.handleControlMessage(t),this.wsManager?.notifyListeners(t)}catch(e){this.debugging&&console.error("MEWS: Failed to parse message",e)}return}const t=new Uint8Array(e);this.sbManager?.append(t),this.trackBits(e)}handleControlMessage(e){switch(this.debugging&&"on_time"!==e.type&&console.log("MEWS: message",e),e.type){case"on_stop":this.handleOnStop();break;case"on_time":this.handleOnTime(e);break;case"tracks":this.handleTracks(e);break;case"pause":this.handlePause();break;case"codec_data":this.resolveDelay("codec_data");break;case"seek":this.resolveDelay("seek");break;case"set_speed":this.resolveDelay("set_speed")}}handleOnStop(){this.streamType="vod";const e=()=>{this.sbManager&&(this.sbManager.paused=!0),this.emit("ended",void 0),this.videoElement?.removeEventListener("waiting",e)};this.videoElement?.addEventListener("waiting",e)}handleOnTime(e){const t=e.data;if(!t||!this.videoElement)return;const n=t.current,i=t.end,r=t.jitter||0,s=n-1e3*this.videoElement.currentTime,a=this.getServerDelay(),o=/Chrome/.test(navigator.userAgent)&&!/Edge|Edg/.test(navigator.userAgent)?1e3:100,l=Math.max(o+a,2*a),u=l+r,d="live"!==this.streamType?l+2e3:l;if(this.debugging&&console.log("MEWS: on_time","current:",n/1e3,"video:",this.videoElement.currentTime,"rate:",this.requestedRate+"x","buffer:",Math.round(s),"/",Math.round(l),"live"===this.streamType?"latency:"+Math.round((i||0)-1e3*this.videoElement.currentTime)+"ms":""),this.sbManager){if(void 0!==i&&this.lastDuration!==i/1e3&&(this.lastDuration=i/1e3),this.sbManager.paused=!1,"live"===this.streamType?this.tuneLivePlaybackRate(s,u,t.play_rate_curr):this.tuneVodDeliverySpeed(s,d,t.play_rate_curr),t.tracks&&this.currentTracks.join(",")!==t.tracks.join(",")){if(this.debugging)for(const e of t.tracks)this.currentTracks.includes(e)||console.log("MEWS: track changed",e);this.currentTracks=t.tracks}}else this.debugging&&console.log("MEWS: on_time but no sourceBuffer")}tuneLivePlaybackRate(e,t,n){this.videoElement&&(1===this.requestedRate?"auto"===n&&this.videoElement.currentTime>0&&(e>2*t?(this.requestedRate=1+.08*Math.min(1,(e-t)/t),this.videoElement.playbackRate=this.requestedRate,this.debugging&&console.log("MEWS: speeding up to",this.requestedRate)):e<0?(this.requestedRate=.8,this.videoElement.playbackRate=this.requestedRate,this.debugging&&console.log("MEWS: slowing down to",this.requestedRate)):e<t/2&&(this.requestedRate=1+.08*Math.min(1,(e-t)/t),this.videoElement.playbackRate=this.requestedRate,this.debugging&&console.log("MEWS: adjusting to",this.requestedRate))):this.requestedRate>1?e<t&&(this.videoElement.playbackRate=1,this.requestedRate=1,this.debugging&&console.log("MEWS: returning to normal rate")):e>t&&(this.videoElement.playbackRate=1,this.requestedRate=1,this.debugging&&console.log("MEWS: returning to normal rate")))}tuneVodDeliverySpeed(e,t,n){1===this.requestedRate?"auto"===n&&(e<t/2?e<-1e4?this.send({type:"seek",seek_time:Math.round(1e3*(this.videoElement?.currentTime||0))}):(this.requestedRate=2,this.send({type:"set_speed",play_rate:this.requestedRate}),this.debugging&&console.log("MEWS: requesting faster delivery")):e-t>t&&(this.requestedRate=.5,this.send({type:"set_speed",play_rate:this.requestedRate}),this.debugging&&console.log("MEWS: requesting slower delivery"))):this.requestedRate>1?e>t&&(this.send({type:"set_speed",play_rate:"auto"}),this.requestedRate=1,this.debugging&&console.log("MEWS: returning to realtime delivery")):e<t&&(this.send({type:"set_speed",play_rate:"auto"}),this.requestedRate=1,this.debugging&&console.log("MEWS: returning to realtime delivery"))}handleTracks(e){const t=e.data?.codecs||[],n=e.data?.current;if(!t.length)return void this.emit("error","Track switch contains no codecs");const i=this.lastCodecs||this.sbManager?.getCodecs()||[];if(this.codecsEqual(i,t))return this.debugging&&console.log("MEWS: keeping buffer, codecs same"),void(0===this.videoElement?.currentTime&&n&&0!==n&&this.setSeekingPosition(n/1e3));this.lastCodecs=t,this.sbManager?.changeCodecs(t,n)}handlePause(){this.sbManager&&(this.sbManager.paused=!0)}setSeekingPosition(e){if(!this.videoElement||!this.sbManager)return;const t=this.videoElement.currentTime;t>e&&(e=t);const n=this.videoElement.buffered;!n.length||n.end(n.length-1)<e?this.sbManager.scheduleAfterUpdate(()=>this.setSeekingPosition(e)):(this.videoElement.currentTime=e,this.videoElement.currentTime<e-.001&&this.sbManager.scheduleAfterUpdate(()=>this.setSeekingPosition(e)))}codecsEqual(e,t){if(e.length!==t.length)return!1;for(const n of e)if(!t.includes(n))return!1;return!0}async play(){const e=this.videoElement;if(e&&e.paused)return this.isReady||await new Promise((e,t)=>{const n=setTimeout(()=>{t(new Error("MEWS: Timeout waiting for codec data"))},5e3);this.readyResolvers.push(()=>{clearTimeout(n),e()})}),new Promise((t,n)=>{let i=!1;const r=s=>{if(i)return;if(i=!0,this.wsManager?.removeListener("on_time",r),!this.sbManager)return this.debugging&&console.log("MEWS: play waiting for sourceBuffer"),i=!1,void this.wsManager?.addListener("on_time",r);const a=s.data;if("live"===this.streamType){const i=()=>{if(!e.buffered.length)return;const i=this.sbManager?.findBufferIndex(a.current/1e3);"number"==typeof i&&((e.buffered.start(i)>e.currentTime||e.buffered.end(i)<e.currentTime)&&(e.currentTime=a.current/1e3,this.debugging&&console.log("MEWS: seeking to live position",e.currentTime)),e.play().then(t).catch(e=>{this.pause(),n(e)}),this.sbManager.paused=!1)};this.sbManager?.scheduleAfterUpdate(i)}else this.sbManager.paused=!1,e.buffered.length&&e.buffered.start(0)>e.currentTime&&(e.currentTime=e.buffered.start(0)),e.play().then(t).catch(n)};this.wsManager?.addListener("on_time",r);"live"===this.streamType&&0===e.currentTime?this.send({type:"play",seek_time:"live"}):this.send({type:"play"})})}pause(){this.videoElement?.pause(),this.send({type:"hold"}),this.sbManager&&(this.sbManager.paused=!0)}seek(e){if(!this.videoElement||isNaN(e)||e<0)return;const t=Math.round(Math.max(0,1e3*e-(250+this.getServerDelay())));this.logDelay("seek"),this.send({type:"seek",seek_time:t});const n=()=>{this.wsManager?.removeListener("seek",n);const e=t=>{this.wsManager?.removeListener("on_time",e);const n=t.data.current/1e3;this.trySetCurrentTime(n)};this.wsManager?.addListener("on_time",e)};this.wsManager?.addListener("seek",n),this.videoElement.currentTime=e,this.debugging&&console.log("MEWS: seeking to",e)}trySetCurrentTime(e,t=10){const n=this.videoElement;n&&(n.currentTime=e,n.currentTime<e-.001&&t>0&&this.sbManager?.scheduleAfterUpdate(()=>this.trySetCurrentTime(e,t-1)))}getCurrentTime(){return this.videoElement?.currentTime??0}getDuration(){return isFinite(this.lastDuration)?this.lastDuration:super.getDuration()}setPlaybackRate(e){super.setPlaybackRate(e);const t=1===e?"auto":e;this.logDelay("set_speed"),this.send({type:"set_speed",play_rate:t})}getQualities(){return[{id:"auto",label:"Auto",isAuto:!0,active:!0}]}selectQuality(e){"auto"===e&&this.send({type:"set_speed",play_rate:"auto"})}setTracks(e){Object.keys(e).length&&this.send({type:"tracks",...e})}selectTextTrack(e){null===e?this.send({type:"tracks",subtitle:"none"}):this.send({type:"tracks",subtitle:e})}isLive(){return"live"===this.streamType}jumpToLive(){"live"===this.streamType&&this.wsManager&&(this.send({type:"play",seek_time:"live"}),this.videoElement?.play().catch(()=>{}))}async getStats(){return{currentBps:this.currentBps,waitingEvents:this.nWaiting,isLive:"live"===this.streamType,serverDelay:this.getServerDelay()}}installWaitingHandler(){this.videoElement&&this.videoElement.addEventListener("waiting",()=>{if(this.seeking)return;const e=this.videoElement;if(!e.buffered||!e.buffered.length)return;const t=this.sbManager?.findBufferIndex(e.currentTime);if(!1!==t&&"number"==typeof t&&t+1<e.buffered.length){const n=e.buffered.start(t+1);n-e.currentTime<10&&(this.debugging&&console.log("MEWS: skipping buffer gap to",n),e.currentTime=n)}this.nWaiting++,this.nWaiting>=this.nWaitingThreshold&&this.currentBps&&(this.nWaiting=0,this.debugging&&console.log("MEWS: ABR triggered, requesting lower bitrate"),this.setTracks({video:`<${Math.round(this.currentBps)}bps,minbps`}))})}installSeekingHandler(){this.videoElement&&(this.videoElement.addEventListener("seeking",()=>{this.seeking=!0}),this.videoElement.addEventListener("seeked",()=>{this.seeking=!1}))}installPauseHandler(){this.videoElement&&this.videoElement.addEventListener("pause",()=>{if(this.sbManager&&!this.sbManager.paused){this.debugging&&console.log("MEWS: browser paused, pausing download"),this.send({type:"hold"}),this.sbManager.paused=!0;const e=()=>{this.sbManager?.paused&&this.send({type:"play"}),this.videoElement?.removeEventListener("play",e)};this.videoElement?.addEventListener("play",e)}})}installLoopHandler(){this.videoElement&&this.videoElement.addEventListener("ended",()=>{const e=this.videoElement;e&&e.loop&&"live"!==this.streamType&&(this.seek(0),this.sbManager?._do(()=>{}))})}send(e){this.wsManager&&this.wsManager.send(e)}logDelay(e){this.pendingDelayTypes[e]=Date.now()}resolveDelay(e){const t=this.pendingDelayTypes[e];if(t){const n=Date.now()-t;this.serverDelays.unshift(n),this.serverDelays.length>5&&this.serverDelays.pop(),delete this.pendingDelayTypes[e]}}getServerDelay(){if(!this.serverDelays.length)return 500;const e=Math.min(3,this.serverDelays.length);let t=0;for(let n=0;n<e;n++)t+=this.serverDelays[n];return t/e}trackBits(e){if(this.bitCounter.push(8*e.byteLength),this.bitsSince.push(Date.now()),this.bitCounter.length>5&&(this.bitCounter.shift(),this.bitsSince.shift()),this.bitCounter.length>=2){const e=this.bitCounter[this.bitCounter.length-1],t=(this.bitsSince[this.bitsSince.length-1]-this.bitsSince[0])/1e3;t>0&&(this.currentBps=Math.round(e/t))}}startTelemetry(){if(!this.analyticsConfig.enabled||!this.analyticsConfig.endpoint)return;const e=this.analyticsConfig.endpoint;this.analyticsTimer=setInterval(async()=>{if(!this.videoElement)return;const t=await this.getStats(),n={t:Date.now(),bps:t.currentBps||0,waiting:t.waitingEvents||0};try{await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})}catch{}},5e3)}async destroy(){if(console.debug("[MEWS] destroy() called"),this.isDestroyed=!0,this.isReady=!1,this.readyResolvers=[],this.analyticsTimer&&(clearInterval(this.analyticsTimer),this.analyticsTimer=null),this.wsManager?.destroy(),this.wsManager=null,this.sbManager?.destroy(),this.sbManager=null,"open"===this.mediaSource?.readyState)try{this.mediaSource.endOfStream()}catch{}if(this.objectUrl&&(URL.revokeObjectURL(this.objectUrl),this.objectUrl=null),this.videoElement&&this.container)try{this.container.removeChild(this.videoElement)}catch{}this.videoElement=null,this.container=null,this.mediaSource=null,this.listeners.clear(),console.debug("[MEWS] destroy() completed")}}}),On="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function Fn(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function Un(e){return e&&Object.prototype.hasOwnProperty.call(e,"default")&&1===Object.keys(e).length?e.default:e}function Bn(){return Nn?Pn:(Nn=1,e="undefined"!=typeof window?window:void 0!==On?On:"undefined"!=typeof self?self:{},Pn=e);var e}var zn,jn,qn=Fn(Bn()),$n=Un(Object.freeze({__proto__:null,default:{}}));function Hn(){if(jn)return zn;jn=1;var e,t=void 0!==On?On:"undefined"!=typeof window?window:{},n=$n;return"undefined"!=typeof document?e=document:(e=t["__GLOBAL_DOCUMENT_CACHE@4"])||(e=t["__GLOBAL_DOCUMENT_CACHE@4"]=n),zn=e}var Gn,Vn,Wn,Kn,Yn,Xn,Qn,Jn,Zn,ei,ti=Fn(Hn()),ni={exports:{}},ii={exports:{}};function ri(){if(Wn)return Vn;Wn=1,Vn=function(t){if(!t)return!1;var n=e.call(t);return"[object Function]"===n||"function"==typeof t&&"[object RegExp]"!==n||"undefined"!=typeof window&&(t===window.setTimeout||t===window.alert||t===window.confirm||t===window.prompt)};var e=Object.prototype.toString;return Vn}function si(){if(Yn)return Kn;function e(e,n){var i="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(i)return(i=i.call(e)).next.bind(i);if(Array.isArray(e)||(i=function(e,n){if(!e)return;if("string"==typeof e)return t(e,n);var i=Object.prototype.toString.call(e).slice(8,-1);"Object"===i&&e.constructor&&(i=e.constructor.name);if("Map"===i||"Set"===i)return Array.from(e);if("Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i))return t(e,n)}(e))||n){i&&(e=i);var r=0;return function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function t(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n<t;n++)i[n]=e[n];return i}return Yn=1,Kn=function(){function t(){this.typeToInterceptorsMap_=new Map,this.enabled_=!1}var n=t.prototype;return n.getIsEnabled=function(){return this.enabled_},n.enable=function(){this.enabled_=!0},n.disable=function(){this.enabled_=!1},n.reset=function(){this.typeToInterceptorsMap_=new Map,this.enabled_=!1},n.addInterceptor=function(e,t){this.typeToInterceptorsMap_.has(e)||this.typeToInterceptorsMap_.set(e,new Set);var n=this.typeToInterceptorsMap_.get(e);return!n.has(t)&&(n.add(t),!0)},n.removeInterceptor=function(e,t){var n=this.typeToInterceptorsMap_.get(e);return!(!n||!n.has(t))&&(n.delete(t),!0)},n.clearInterceptorsByType=function(e){return!!this.typeToInterceptorsMap_.get(e)&&(this.typeToInterceptorsMap_.delete(e),this.typeToInterceptorsMap_.set(e,new Set),!0)},n.clear=function(){return!!this.typeToInterceptorsMap_.size&&(this.typeToInterceptorsMap_=new Map,!0)},n.getForType=function(e){return this.typeToInterceptorsMap_.get(e)||new Set},n.execute=function(t,n){for(var i,r=e(this.getForType(t));!(i=r()).done;){var s=i.value;try{n=s(n)}catch(e){}}return n},t}()}var ai,oi,li,ui,di,ci,hi,fi=function(){if(ei)return ni.exports;ei=1;var e=Bn(),t=(Gn||(Gn=1,function(e){function t(){return e.exports=t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var i in n)({}).hasOwnProperty.call(n,i)&&(e[i]=n[i])}return e},e.exports.__esModule=!0,e.exports.default=e.exports,t.apply(null,arguments)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports}(ii)),ii.exports),n=ri(),i=si(),r=function(){if(Qn)return Xn;Qn=1;var e=function(){function e(){this.maxAttempts_=1,this.delayFactor_=.1,this.fuzzFactor_=.1,this.initialDelay_=1e3,this.enabled_=!1}var n=e.prototype;return n.getIsEnabled=function(){return this.enabled_},n.enable=function(){this.enabled_=!0},n.disable=function(){this.enabled_=!1},n.reset=function(){this.maxAttempts_=1,this.delayFactor_=.1,this.fuzzFactor_=.1,this.initialDelay_=1e3,this.enabled_=!1},n.getMaxAttempts=function(){return this.maxAttempts_},n.setMaxAttempts=function(e){this.maxAttempts_=e},n.getDelayFactor=function(){return this.delayFactor_},n.setDelayFactor=function(e){this.delayFactor_=e},n.getFuzzFactor=function(){return this.fuzzFactor_},n.setFuzzFactor=function(e){this.fuzzFactor_=e},n.getInitialDelay=function(){return this.initialDelay_},n.setInitialDelay=function(e){this.initialDelay_=e},n.createRetry=function(e){var n=void 0===e?{}:e,i=n.maxAttempts,r=n.delayFactor,s=n.fuzzFactor,a=n.initialDelay;return new t({maxAttempts:i||this.maxAttempts_,delayFactor:r||this.delayFactor_,fuzzFactor:s||this.fuzzFactor_,initialDelay:a||this.initialDelay_})},e}(),t=function(){function e(e){this.maxAttempts_=e.maxAttempts,this.delayFactor_=e.delayFactor,this.fuzzFactor_=e.fuzzFactor,this.currentDelay_=e.initialDelay,this.currentAttempt_=1}var t=e.prototype;return t.moveToNextAttempt=function(){this.currentAttempt_++;var e=this.currentDelay_*this.delayFactor_;this.currentDelay_=this.currentDelay_+e},t.shouldRetry=function(){return this.currentAttempt_<this.maxAttempts_},t.getCurrentDelay=function(){return this.currentDelay_},t.getCurrentMinPossibleDelay=function(){return(1-this.fuzzFactor_)*this.currentDelay_},t.getCurrentMaxPossibleDelay=function(){return(1+this.fuzzFactor_)*this.currentDelay_},t.getCurrentFuzzedDelay=function(){var e=this.getCurrentMinPossibleDelay(),t=this.getCurrentMaxPossibleDelay();return e+Math.random()*(t-e)},e}();return Xn=e}();o.httpHandler=function(){if(Zn)return Jn;Zn=1;var e=Bn();return Jn=function(t,n){return void 0===n&&(n=!1),function(i,r,s){if(i)t(i);else if(r.statusCode>=400&&r.statusCode<=599){var a=s;if(n)if(e.TextDecoder){var o=(void 0===(l=r.headers&&r.headers["content-type"])&&(l=""),l.toLowerCase().split(";").reduce(function(e,t){var n=t.split("="),i=n[0],r=n[1];return"charset"===i.trim()?r.trim():e},"utf-8"));try{a=new TextDecoder(o).decode(s)}catch(e){}}else a=String.fromCharCode.apply(null,new Uint8Array(s));t({cause:a})}else t(null,s);var l}}}(),o.requestInterceptorsStorage=new i,o.responseInterceptorsStorage=new i,o.retryManager=new r;
4334
4334
  /**
4335
4335
  * @license
4336
4336
  * slighly modified parse-headers 2.0.2 <https://github.com/kesla/parse-headers/>