@livepeer-frameworks/player-wc 0.1.3 → 0.1.5
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.
- package/dist/cjs/components/fw-dev-mode-panel.js +1 -0
- package/dist/cjs/components/fw-dev-mode-panel.js.map +1 -1
- package/dist/cjs/components/fw-player-controls.js +12 -3
- package/dist/cjs/components/fw-player-controls.js.map +1 -1
- package/dist/cjs/components/fw-player.js +50 -10
- package/dist/cjs/components/fw-player.js.map +1 -1
- package/dist/cjs/components/fw-settings-menu.js +18 -1
- package/dist/cjs/components/fw-settings-menu.js.map +1 -1
- package/dist/cjs/controllers/player-controller-host.js +23 -1
- package/dist/cjs/controllers/player-controller-host.js.map +1 -1
- package/dist/cjs/styles/shared-styles.js +18 -0
- package/dist/cjs/styles/shared-styles.js.map +1 -1
- package/dist/esm/components/fw-dev-mode-panel.js +1 -0
- package/dist/esm/components/fw-dev-mode-panel.js.map +1 -1
- package/dist/esm/components/fw-player-controls.js +12 -3
- package/dist/esm/components/fw-player-controls.js.map +1 -1
- package/dist/esm/components/fw-player.js +50 -10
- package/dist/esm/components/fw-player.js.map +1 -1
- package/dist/esm/components/fw-settings-menu.js +18 -1
- package/dist/esm/components/fw-settings-menu.js.map +1 -1
- package/dist/esm/controllers/player-controller-host.js +23 -1
- package/dist/esm/controllers/player-controller-host.js.map +1 -1
- package/dist/esm/styles/shared-styles.js +18 -0
- package/dist/esm/styles/shared-styles.js.map +1 -1
- package/dist/fw-player.iife.js +40 -20
- package/dist/types/components/fw-player-controls.d.ts +1 -0
- package/dist/types/components/fw-player.d.ts +4 -0
- package/dist/types/components/fw-settings-menu.d.ts +1 -0
- package/package.json +2 -2
- package/src/components/fw-dev-mode-panel.ts +1 -0
- package/src/components/fw-player-controls.ts +10 -3
- package/src/components/fw-player.ts +50 -10
- package/src/components/fw-settings-menu.ts +41 -1
- package/src/controllers/player-controller-host.ts +23 -1
- package/src/styles/shared-styles.ts +18 -0
package/dist/fw-player.iife.js
CHANGED
|
@@ -57,7 +57,7 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
57
57
|
* @license
|
|
58
58
|
* Copyright 2018 Google LLC
|
|
59
59
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
60
|
-
*/const Se=_e(class extends Ee{constructor(e){if(super(e),e.type!==Te||"class"!==e.name||e.strings?.length>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(e){return" "+Object.keys(e).filter(t=>e[t]).join(" ")+" "}update(e,[t]){if(void 0===this.st){this.st=new Set,void 0!==e.strings&&(this.nt=new Set(e.strings.join(" ").split(/\s/).filter(e=>""!==e)));for(const e in t)t[e]&&!this.nt?.has(e)&&this.st.add(e);return this.render(t)}const n=e.element.classList;for(const e of this.st)e in t||(n.remove(e),this.st.delete(e));for(const e in t){const i=!!t[e];i===this.st.has(e)||this.nt?.has(e)||(i?(n.add(e),this.st.add(e)):(n.remove(e),this.st.delete(e)))}return Q}});function we(e){const t=e.codec.toUpperCase();if(e.codecstring)return e.codecstring;if("audio"===e.type)switch(t){case"AAC":case"MP4A":return"mp4a.40.2";case"MP3":return"mp4a.40.34";case"AC3":case"AC-3":return"ac-3";case"EAC3":case"EC3":case"E-AC3":case"EC-3":return"ec-3";case"OPUS":return"opus";case"VORBIS":return"vorbis";case"FLAC":return"flac";case"PCM":case"PCMS16LE":return"pcm";default:return t.toLowerCase()}if("video"===e.type)switch(t){case"H264":case"AVC":case"AVC1":{const t=function(e){if(!e)return null;try{const t=Ie(e);for(let e=0;e<t.length-4;e++)if(0===t[e]&&0===t[e+1]){let n=e+2;0===t[n]&&n++,1===t[n]&&n++;if(7===(31&t[n])&&n+3<t.length){const e=t[n+1],i=t[n+2],r=t[n+3];return`avc1.${ke(e)}${ke(i)}${ke(r)}`}}if(t.length>=4){const e=t[0],n=t[1],i=t[2];if(e>0&&e<255&&i>0&&i<100)return`avc1.${ke(e)}${ke(n)}${ke(i)}`}}catch{}return null}(e.init);return t||"avc1.42E01E"}case"H265":case"HEVC":case"HEV1":case"HVC1":{const t=function(e){if(!e)return null;try{const t=Ie(e);if(t.length>0)for(let e=0;e<t.length-3;e++){const n=t[e];if(n>=1&&n<=5){return`hev1.${n}.6.L${t[e+1]||93}.B0`}}}catch{}return null}(e.init);return t||"hev1.1.6.L93.B0"}case"VP8":return"vp8";case"VP9":return"vp09.00.10.08";case"AV1":return"av01.0.01M.08";case"THEORA":return"theora";default:return t.toLowerCase()}return t.toLowerCase()}function ke(e){return e.toString(16).padStart(2,"0").toUpperCase()}function Ie(e){const t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}function Ae(){const e=navigator.userAgent.toLowerCase();return{isChrome:/chrome|crios/.test(e)&&!/edge|edg/.test(e),isFirefox:/firefox/.test(e),isSafari:/safari/.test(e)&&!/chrome|crios/.test(e),isEdge:/edge|edg/.test(e),isAndroid:/android/.test(e),isIOS:/iphone|ipad|ipod/.test(e),isMobile:/mobile|android|iphone|ipad|ipod/.test(e),supportsMediaSource:"MediaSource"in window,supportsWebRTC:"RTCPeerConnection"in window,supportsWebSocket:"WebSocket"in window}}function Ce(e){const t=window.location.protocol,n=new URL(e).protocol;return("file:"!==t||"http:"!==n)&&t!==n}function De(){return"file:"===window.location.protocol}function Re(){const e=Ae(),t=function(){const e=navigator.userAgent.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);return e?parseInt(e[1],10)+(e[2]?parseInt(e[2],10):0)/10:null}();return{supportsNativeHLS:e.isSafari||e.isIOS||t&&t>=7,supportsMSE:e.supportsMediaSource,supportsWebSocket:e.supportsWebSocket,supportsWebRTC:e.supportsWebRTC&&"RTCRtpReceiver"in window,preferVideoJs:t&&t<7,avoidMEWSOnMac:e.isSafari,fileProtocolLimitations:De()}}const xe={video:["H264","VP8","VP9","AV1"],audio:["OPUS","PCMU","PCMA","G711","G722"]};function Le(e,t){if("undefined"!=typeof RTCRtpReceiver&&RTCRtpReceiver.getCapabilities)try{const n=RTCRtpReceiver.getCapabilities(e);if(n?.codecs){const i=`${e}/${t}`.toLowerCase();return n.codecs.some(e=>e.mimeType.toLowerCase()===i)}}catch{}return xe[e].includes(t.toUpperCase())}function Me(e){const t=e.filter(e=>"video"===e.type),n=e.filter(e=>"audio"===e.type),i=[],r=[],s=[];for(const e of t)Le("video",e.codec)?i.push(e.codec):s.push(`video:${e.codec}`);for(const e of n)Le("audio",e.codec)?r.push(e.codec):s.push(`audio:${e.codec}`);const a=0===t.length||i.length>0,o=0===n.length||r.length>0;return{videoCompatible:a,audioCompatible:o,compatible:a&&o,incompatibleCodecs:s,details:{videoTracks:t.length,audioTracks:n.length,compatibleVideoCodecs:i,compatibleAudioCodecs:r}}}var Ne,Pe;!function(e){e[e.TRANSIENT=1]="TRANSIENT",e[e.RECOVERABLE=2]="RECOVERABLE",e[e.DEGRADED=3]="DEGRADED",e[e.FATAL=4]="FATAL"}(Ne||(Ne={})),function(e){e.NETWORK_TIMEOUT="NETWORK_TIMEOUT",e.WEBSOCKET_DISCONNECT="WEBSOCKET_DISCONNECT",e.SEGMENT_LOAD_ERROR="SEGMENT_LOAD_ERROR",e.ICE_DISCONNECTED="ICE_DISCONNECTED",e.BUFFER_UNDERRUN="BUFFER_UNDERRUN",e.CODEC_DECODE_ERROR="CODEC_DECODE_ERROR",e.PROTOCOL_UNSUPPORTED="PROTOCOL_UNSUPPORTED",e.CODEC_INCOMPATIBLE="CODEC_INCOMPATIBLE",e.ICE_FAILED="ICE_FAILED",e.MANIFEST_STALE="MANIFEST_STALE",e.PLAYER_INIT_FAILED="PLAYER_INIT_FAILED",e.QUALITY_DROPPED="QUALITY_DROPPED",e.BANDWIDTH_LIMITED="BANDWIDTH_LIMITED",e.ALL_PROTOCOLS_EXHAUSTED="ALL_PROTOCOLS_EXHAUSTED",e.ALL_PROTOCOLS_BLACKLISTED="ALL_PROTOCOLS_BLACKLISTED",e.STREAM_OFFLINE="STREAM_OFFLINE",e.AUTH_REQUIRED="AUTH_REQUIRED",e.GEO_BLOCKED="GEO_BLOCKED",e.DRM_ERROR="DRM_ERROR",e.CONTENT_UNAVAILABLE="CONTENT_UNAVAILABLE",e.UNKNOWN="UNKNOWN"}(Pe||(Pe={}));class Oe{constructor(){this.listeners=new Map,this.videoElement=null}getVideoElement(){return this.videoElement}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){const n=this.listeners.get(e);n&&n.delete(t)}emit(e,t){const n=this.listeners.get(e);n&&n.forEach(n=>{try{n(t)}catch(t){console.error(`Error in ${e} listener:`,t)}})}setupVideoEventListeners(e,t){const n=(t,n)=>{e.addEventListener(t,()=>{n(),this.emit(t,void 0)})};n("play",()=>t.onPlay?.()),n("pause",()=>t.onPause?.()),n("ended",()=>t.onEnded?.()),e.addEventListener("waiting",()=>t.onWaiting?.()),e.addEventListener("playing",()=>t.onPlaying?.()),e.addEventListener("canplay",()=>t.onCanPlay?.()),e.addEventListener("durationchange",()=>{t.onDurationChange?.(e.duration)}),e.addEventListener("timeupdate",()=>{const n=e.currentTime;t.onTimeUpdate?.(n),this.emit("timeupdate",n)}),e.addEventListener("error",()=>{const n=e.error?`Video error: ${e.error.message}`:"Unknown video error";t.onError?.(n),this.emit("error",n)}),this.emit("ready",e),t.onReady&&t.onReady(e)}getCurrentTime(){return this.videoElement?.currentTime||0}getDuration(){return this.videoElement?.duration||0}getSeekableRange(){return null}getBufferedRanges(){return this.videoElement?.buffered??null}isPaused(){return this.videoElement?.paused??!0}isMuted(){return this.videoElement?.muted??!1}async play(){if(this.videoElement)return this.videoElement.play()}pause(){this.videoElement?.pause()}seek(e){this.videoElement&&(this.videoElement.currentTime=e)}setVolume(e){this.videoElement&&(this.videoElement.volume=Math.max(0,Math.min(1,e)))}setMuted(e){this.videoElement&&(this.videoElement.muted=e)}setPlaybackRate(e){this.videoElement&&(this.videoElement.playbackRate=e)}getTextTracks(){const e=this.videoElement;if(!e||!e.textTracks)return[];const t=[],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})}return t}selectTextTrack(e){const t=this.videoElement;if(!t||!t.textTracks)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"}}isLive(){const e=this.videoElement;return!!e&&(!isFinite(e.duration)||e.duration===1/0)}jumpToLive(){const e=this.videoElement;if(!e)return;const t=e.seekable;if(t&&t.length>0)try{e.currentTime=t.end(t.length-1)}catch{}}async requestPiP(){const e=this.videoElement;if(e)if(document.pictureInPictureElement!==e)try{e.requestPictureInPicture?await e.requestPictureInPicture():e.webkitSetPresentationMode&&e.webkitSetPresentationMode("picture-in-picture")}catch{}else try{await(document.exitPictureInPicture?.())}catch{}}setSize(e,t){this.videoElement&&(this.videoElement.style.width=`${e}px`,this.videoElement.style.height=`${t}px`)}async getStats(){}async getLatency(){}}const Fe={[Pe.NETWORK_TIMEOUT]:{maxAttempts:3,baseDelayMs:500,maxDelayMs:4e3,jitterPercent:20},[Pe.WEBSOCKET_DISCONNECT]:{maxAttempts:5,baseDelayMs:500,maxDelayMs:5e3,jitterPercent:20},[Pe.SEGMENT_LOAD_ERROR]:{maxAttempts:3,baseDelayMs:200,maxDelayMs:2e3,jitterPercent:10},[Pe.ICE_DISCONNECTED]:{maxAttempts:3,baseDelayMs:500,maxDelayMs:3e3,jitterPercent:20},[Pe.BUFFER_UNDERRUN]:{maxAttempts:1,baseDelayMs:5e3,maxDelayMs:5e3,jitterPercent:0},[Pe.CODEC_DECODE_ERROR]:{maxAttempts:3,baseDelayMs:100,maxDelayMs:1e3,jitterPercent:10},[Pe.PROTOCOL_UNSUPPORTED]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.CODEC_INCOMPATIBLE]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.ICE_FAILED]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.MANIFEST_STALE]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.PLAYER_INIT_FAILED]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.QUALITY_DROPPED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.BANDWIDTH_LIMITED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.ALL_PROTOCOLS_EXHAUSTED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.ALL_PROTOCOLS_BLACKLISTED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.STREAM_OFFLINE]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.AUTH_REQUIRED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.GEO_BLOCKED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.DRM_ERROR]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.CONTENT_UNAVAILABLE]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.UNKNOWN]:{maxAttempts:1,baseDelayMs:1e3,maxDelayMs:1e3,jitterPercent:0}},Ue={[Pe.NETWORK_TIMEOUT]:Ne.TRANSIENT,[Pe.WEBSOCKET_DISCONNECT]:Ne.TRANSIENT,[Pe.SEGMENT_LOAD_ERROR]:Ne.TRANSIENT,[Pe.ICE_DISCONNECTED]:Ne.TRANSIENT,[Pe.BUFFER_UNDERRUN]:Ne.TRANSIENT,[Pe.CODEC_DECODE_ERROR]:Ne.TRANSIENT,[Pe.PROTOCOL_UNSUPPORTED]:Ne.RECOVERABLE,[Pe.CODEC_INCOMPATIBLE]:Ne.RECOVERABLE,[Pe.ICE_FAILED]:Ne.RECOVERABLE,[Pe.MANIFEST_STALE]:Ne.RECOVERABLE,[Pe.PLAYER_INIT_FAILED]:Ne.RECOVERABLE,[Pe.QUALITY_DROPPED]:Ne.DEGRADED,[Pe.BANDWIDTH_LIMITED]:Ne.DEGRADED,[Pe.ALL_PROTOCOLS_EXHAUSTED]:Ne.FATAL,[Pe.ALL_PROTOCOLS_BLACKLISTED]:Ne.FATAL,[Pe.STREAM_OFFLINE]:Ne.FATAL,[Pe.AUTH_REQUIRED]:Ne.FATAL,[Pe.GEO_BLOCKED]:Ne.FATAL,[Pe.DRM_ERROR]:Ne.FATAL,[Pe.CONTENT_UNAVAILABLE]:Ne.FATAL,[Pe.UNKNOWN]:Ne.FATAL},ze={[Pe.NETWORK_TIMEOUT]:"Network timeout",[Pe.WEBSOCKET_DISCONNECT]:"Connection lost",[Pe.SEGMENT_LOAD_ERROR]:"Failed to load video segment",[Pe.ICE_DISCONNECTED]:"Connection interrupted",[Pe.BUFFER_UNDERRUN]:"Buffering",[Pe.CODEC_DECODE_ERROR]:"Decode error",[Pe.PROTOCOL_UNSUPPORTED]:"Protocol not supported",[Pe.CODEC_INCOMPATIBLE]:"Codec not supported",[Pe.ICE_FAILED]:"Connection failed",[Pe.MANIFEST_STALE]:"Stream manifest outdated",[Pe.PLAYER_INIT_FAILED]:"Player initialization failed",[Pe.QUALITY_DROPPED]:"Quality reduced",[Pe.BANDWIDTH_LIMITED]:"Bandwidth limited",[Pe.ALL_PROTOCOLS_EXHAUSTED]:"Unable to play video",[Pe.ALL_PROTOCOLS_BLACKLISTED]:"No compatible playback protocols available",[Pe.STREAM_OFFLINE]:"Stream is offline",[Pe.AUTH_REQUIRED]:"Sign in to watch",[Pe.GEO_BLOCKED]:"Not available in your region",[Pe.DRM_ERROR]:"Playback not supported",[Pe.CONTENT_UNAVAILABLE]:"Content unavailable",[Pe.UNKNOWN]:"Playback error"};class Be{constructor(e={}){this.retryCounts=new Map,this.lastErrorTime=new Map,this.listeners=new Map,this.lastQualityToastTime=0,this.alternativesRemaining=e.alternativesCount??0,this.debug=e.debug??!1}setAlternativesRemaining(e){this.alternativesRemaining=e}reset(){this.retryCounts.clear(),this.lastErrorTime.clear(),this.lastQualityToastTime=0,this.log("Error state reset")}classify(e,t){const n=Fe[e],i=(this.retryCounts.get(e)??0)+1,r=Math.max(0,n.maxAttempts-i);this.retryCounts.set(e,i),this.lastErrorTime.set(e,Date.now());const s={severity:Ue[e],code:e,message:ze[e],retriesRemaining:r,alternativesRemaining:this.alternativesRemaining,originalError:t,timestamp:Date.now()};if(this.log(`Classified error: ${e}, attempt ${i}/${n.maxAttempts}, severity ${s.severity}`),s.severity===Ne.TRANSIENT&&r>0){const t=this.calculateBackoff(e,i);return this.emit("recoveryAttempted",{code:e,attempt:i,maxAttempts:n.maxAttempts}),{type:"retry",delayMs:t}}if(s.severity===Ne.TRANSIENT&&0===r||s.severity===Ne.RECOVERABLE){if(this.alternativesRemaining>0)return{type:"swap",reason:s.message};const e=s.code,t=s.message;s.severity=Ne.FATAL,s.code=Pe.ALL_PROTOCOLS_EXHAUSTED,s.message=`${t} (no alternatives remaining)`,s.details={...s.details,originalCode:e,originalMessage:t}}if(s.severity===Ne.DEGRADED){const e=Date.now();return e-this.lastQualityToastTime>=Be.QUALITY_TOAST_DEBOUNCE_MS?(this.lastQualityToastTime=e,this.emit("qualityChanged",{direction:"down",reason:s.message}),{type:"toast",message:s.message}):{type:"toast",message:""}}return this.emit("playbackFailed",s),{type:"fatal",error:s}}classifyWithDetails(e,t,n,i){if(Ue[e]===Ne.FATAL){const r={severity:Ne.FATAL,code:e,message:t,retriesRemaining:0,alternativesRemaining:this.alternativesRemaining,originalError:i,timestamp:Date.now(),details:n};return this.emit("playbackFailed",r),{type:"fatal",error:r}}const r=this.classify(e,i);return"fatal"===r.type&&(r.error.message=t,r.error.details=n),r}notifyProtocolSwap(e,t,n,i,r){this.emit("protocolSwapped",{fromPlayer:e,toPlayer:t,fromProtocol:n,toProtocol:i,reason:r})}calculateBackoff(e,t){const n=Fe[e],i=n.baseDelayMs*Math.pow(2,t-1),r=Math.min(i,n.maxDelayMs),s=r*(n.jitterPercent/100),a=(2*Math.random()-1)*s;return Math.round(r+a)}static mapErrorToCode(e){const t=("string"==typeof e?e:e.message).toLowerCase();return t.includes("timeout")||t.includes("timed out")?Pe.NETWORK_TIMEOUT:t.includes("websocket")||t.includes("socket")?Pe.WEBSOCKET_DISCONNECT:t.includes("fetch")||t.includes("network")?Pe.NETWORK_TIMEOUT:t.includes("offline")||t.includes("not found")||t.includes("stream not found")?Pe.STREAM_OFFLINE:t.includes("segment")?Pe.SEGMENT_LOAD_ERROR:t.includes("manifest")||t.includes("playlist")?t.includes("404")?Pe.STREAM_OFFLINE:Pe.MANIFEST_STALE:t.includes("ice")&&t.includes("disconnect")?Pe.ICE_DISCONNECTED:t.includes("ice")&&t.includes("fail")?Pe.ICE_FAILED:t.includes("codec")||t.includes("decode")?Pe.CODEC_DECODE_ERROR:t.includes("not supported")||t.includes("unsupported")?Pe.PROTOCOL_UNSUPPORTED:t.includes("buffer")||t.includes("underrun")?Pe.BUFFER_UNDERRUN:t.includes("401")||t.includes("auth")||t.includes("unauthorized")?Pe.AUTH_REQUIRED:t.includes("403")||t.includes("forbidden")||t.includes("geo")?Pe.GEO_BLOCKED:t.includes("drm")||t.includes("eme")||t.includes("key")?Pe.DRM_ERROR:Pe.UNKNOWN}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){const n=this.listeners.get(e);n&&n.delete(t)}emit(e,t){const n=this.listeners.get(e);n&&n.forEach(n=>{try{n(t)}catch(t){console.error(`Error in ${e} listener:`,t)}})}log(e){this.debug&&console.log(`[ErrorClassifier] ${e}`)}}Be.QUALITY_TOAST_DEBOUNCE_MS=1e4;const je={video:2,audio:1,subtitle:.5};const $e=new Set(["flash/7","flash/10","flash/11","silverlight","html5/application/sdp","sdp","html5/video/mpeg","html5/application/vnd.ms-sstr+xml","srt","rtsp","rtmp","dtsc","html5/image/jpeg","html5/text/javascript","html5/text/vtt","html5/text/plain"]);function qe(e){return $e.has(e)}const He={"html5/video/webm":.8,"html5/audio/webm":.6,"ws/video/webm":.8,"wss/video/webm":.8,"ws/video/mp4":.5,"wss/video/mp4":.5,webrtc:.5,"mist/webrtc":.5,"dash/video/mp4":.9,"dash/video/webm":.95,"html5/application/vnd.apple.mpegurl;version=7":.2,"ll-hls":.2,cmaf:.2};const Ge={webcodecs:.95,videojs:.95,hlsjs:.9,native:.85,"mist-webrtc":.85,mews:.75,"mist-legacy":.7,dashjs:.5};const Ve={"low-latency":{"ws/video/raw":.55,"wss/video/raw":.55,"ws/video/h264":.52,"wss/video/h264":.52,whep:.5,webrtc:.25,"mist/webrtc":.25,"ws/video/mp4":.3,"wss/video/mp4":.3,"html5/video/mp4":.15,"html5/application/vnd.apple.mpegurl":.05},quality:{"ws/video/mp4":.45,"wss/video/mp4":.45,"ws/video/raw":.4,"wss/video/raw":.4,"ws/video/h264":.38,"wss/video/h264":.38,"html5/application/vnd.apple.mpegurl":.3,"html5/video/mp4":.2,whep:.05,webrtc:.05,"mist/webrtc":.05},vod:{"html5/video/mp4":.5,"html5/application/vnd.apple.mpegurl":.45,"dash/video/mp4":.4,"ws/video/mp4":.35,"wss/video/mp4":.35,whep:-1,webrtc:-1,"mist/webrtc":-1},auto:{"ws/video/raw":.5,"wss/video/raw":.5,"ws/video/h264":.48,"wss/video/h264":.48,"html5/video/mp4":.42,whep:.38,webrtc:.2,"mist/webrtc":.2,"ws/video/mp4":.3,"wss/video/mp4":.3,"html5/application/vnd.apple.mpegurl":.2}};const Ye={whep:{prefer:["native"]},webrtc:{prefer:["mist-webrtc","native"]},"mist/webrtc":{prefer:["mist-webrtc"]},"ws/video/raw":{prefer:["webcodecs"]},"wss/video/raw":{prefer:["webcodecs"]},"ws/video/h264":{prefer:["webcodecs"]},"wss/video/h264":{prefer:["webcodecs"]},"ws/video/mp4":{prefer:["mews"]},"wss/video/mp4":{prefer:["mews"]},"ws/video/webm":{prefer:["mews"]},"wss/video/webm":{prefer:["mews"]},"html5/application/vnd.apple.mpegurl":{prefer:["videojs","hlsjs"],avoid:["native"]},"html5/application/vnd.apple.mpegurl;version=7":{prefer:["videojs","hlsjs"],avoid:["native"]},"dash/video/mp4":{prefer:["dashjs","videojs"]},"html5/video/mp4":{prefer:["native"]},"html5/video/webm":{prefer:["native"]},"html5/audio/aac":{prefer:["native"]},"html5/audio/mp3":{prefer:["native"]},"html5/audio/flac":{prefer:["native"]},"html5/audio/wav":{prefer:["native"]}};function We(e,t,n,i={}){const{maxPriority:r=10,totalSources:s=1,trackScores:a={},bandwidth:o,targetBandwidth:l,playerShortname:u,mimeType:d,playbackMode:c="auto",weights:h={tracks:.5,priority:.1,source:.05,quality:.05,reliability:.1,mode:.1,routing:.08,protocolPenalty:1}}=i,f=function(e,t=je){if(!0===e)return 1.9;if(!1===e||0===e.length)return 0;let n=0;for(const i of e){const e=t[i];void 0!==e&&(n+=e)}return n}(e,{...je,...a}),p=function(e,t){return 1-e/Math.max(t,1)}(t,r),g=function(e,t){return 1-e/Math.max(t-1,1)}(n,s),m=function(e,t){return e&&t?Math.min(e,t)/Math.max(e,t):1}(o,l),y=u?function(e){return Ge[e]??.5}(u):.5,b=d?function(e,t){return t?Ve[t]?.[e]??0:0}(d,c):0,v=d&&u?function(e,t){const n=Ye[e];if(!n)return 0;if(n.avoid?.includes(t))return-.1;if(n.prefer?.includes(t))return.15-.05*n.prefer.indexOf(t);return 0}(d,u):0,T=d?function(e){if(He[e])return He[e];const t=e.toLowerCase();return t.includes("webm")?.5:t.startsWith("dash/")?.4:t.includes("cmaf")||t.includes("ll-hls")?.2:0}(d):0,_=f*h.tracks+p*h.priority+g*h.source+m*h.quality+y*(h.reliability??0)+b*(h.mode??0)+v*(h.routing??0)-T*(h.protocolPenalty??1);return{base:f,trackTypes:Array.isArray(e)?e:[],total:_,breakdown:{trackScore:f,priorityScore:p,sourceScore:g,reliabilityScore:y,modeBonus:b,routingBonus:v,protocolPenalty:T}}}class Ke{constructor(e={}){this.players=new Map,this.currentPlayer=null,this.listeners=new Map,this.fallbackAttempts=0,this.cachedCombinations=null,this.cachedSelection=null,this.cacheKey=null,this.lastLoggedWinner=null,this.lastContainer=null,this.lastStreamInfo=null,this.lastPlayerOptions={},this.lastManagerOptions={},this.excludedCombos=new Set,this.opQueue=Promise.resolve(),this.options={debug:!1,autoFallback:!0,maxFallbackAttempts:3,...e},this.errorClassifier=new Be({alternativesCount:0,debug:this.options.debug}),this.errorClassifier.on("recoveryAttempted",e=>this.emit("recoveryAttempted",e)),this.errorClassifier.on("protocolSwapped",e=>this.emit("protocolSwapped",e)),this.errorClassifier.on("qualityChanged",e=>this.emit("qualityChanged",e)),this.errorClassifier.on("playbackFailed",e=>this.emit("playbackFailed",e))}registerPlayer(e){this.players.set(e.capability.shortname,e),this.invalidateCache(),this.log(`Registered player: ${e.capability.name}`)}unregisterPlayer(e){const t=this.players.get(e);t&&(t.destroy(),this.players.delete(e),this.invalidateCache(),this.log(`Unregistered player: ${e}`))}getRegisteredPlayers(){return Array.from(this.players.values())}computeCacheKey(e,t){return JSON.stringify({sources:e.source.map(e=>`${e.type}:${e.url??""}`).sort(),tracks:e.meta?.tracks?.map(e=>e.codec).sort()??[],mode:t,forcePlayer:this.options.forcePlayer,forceSource:this.options.forceSource,forceType:this.options.forceType})}getComboKey(e,t){return`${e}:${t.type}:${t.url??""}`}invalidateCache(){this.cachedCombinations=null,this.cachedSelection=null,this.cacheKey=null}getCurrentSelection(){return this.cachedSelection}getCachedCombinations(){return this.cachedCombinations}getAllCombinations(e,t){const n=t||this.options.playbackMode,i=n&&"auto"!==n?n:"vod"===e.type?"vod":"auto",r=this.computeCacheKey(e,i);if(r===this.cacheKey&&this.cachedCombinations)return this.cachedCombinations;const s=this.computeAllCombinations(e,i);this.cachedCombinations=s,this.cacheKey=r;const a=this.pickBestFromCombinations(s);if(this.hasSelectionChanged(a)){if(this.cachedSelection=a,this.options.debug&&a){const e=`${a.player}:${a.source?.type}`;e!==this.lastLoggedWinner&&(console.log(`[PlayerManager] Selection: ${a.player} + ${a.source?.type} (score: ${a.score.toFixed(3)})`),this.lastLoggedWinner=e)}this.emit("selection-changed",a)}return this.emit("combinations-updated",s),s}selectBestPlayer(e,t){const n={...this.options,...t};if("mist-legacy"===n.forcePlayer||"mist/legacy"===n.forceType){if(this.players.get("mist-legacy")&&e.source.length>0){const t=e.source[0],n={score:.1,player:"mist-legacy",source:{url:t.url,type:"mist/legacy",streamName:t.streamName,mistPlayerUrl:t.mistPlayerUrl},source_index:0};return this.emit("playerSelected",{player:n.player,source:n.source,score:n.score}),n}}let i=this.getAllCombinations(e,n.playbackMode).filter(e=>e.compatible);if(n.forcePlayer&&(i=i.filter(e=>e.player===n.forcePlayer)),n.forceType&&(i=i.filter(e=>e.sourceType===n.forceType)),void 0!==n.forceSource&&(i=i.filter(e=>e.sourceIndex===n.forceSource)),0===i.length)return this.log("No suitable player found"),!1;const r=i[0],s={score:r.score,player:r.player,source:r.source,source_index:r.sourceIndex};return this.emit("playerSelected",{player:s.player,source:s.source,score:s.score}),s}computeAllCombinations(e,t){const n=[],i=Array.from(this.players.values()),r=Math.max(...i.map(e=>e.capability.priority),1),s=e.source.filter(e=>!qe(e.type)),a=new Map;s.forEach((e,t)=>a.set(e,t));const o=s.length,l=[];e.meta.tracks.some(e=>"video"===e.type)&&l.push("video"),e.meta.tracks.some(e=>"audio"===e.type)&&l.push("audio");const u=new Set;for(const s of i)for(let i=0;i<e.source.length;i++){const d=e.source[i],c=this.getComboKey(s.capability.shortname,d);if(u.has(c))continue;u.add(c);const h=a.get(d);if(void 0===h){n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:0,compatible:!1,incompatibleReason:`Protocol "${d.type}" is blacklisted`});continue}if(!s.isMimeSupported(d.type)){n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:0,compatible:!1,incompatibleReason:`MIME type "${d.type}" not supported`});continue}const f=s.isBrowserSupported(d.type,d,e);if(!f){const e=1-s.capability.priority/Math.max(r,1),a=1-h/Math.max(o-1,1),l=We(["video","audio"],s.capability.priority,h,{maxPriority:r,totalSources:o,playerShortname:s.capability.shortname,mimeType:d.type,playbackMode:t});n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:l.total,compatible:!1,codecIncompatible:!0,incompatibleReason:"Codec not supported by browser",scoreBreakdown:{trackScore:0,trackTypes:[],priorityScore:e,sourceScore:a,weights:{tracks:.5,priority:.1,source:.05}}});continue}if(Array.isArray(f)&&l.length>0){const e=l.filter(e=>!f.includes(e));if(e.length>0){const a=1-s.capability.priority/Math.max(r,1),l=1-h/Math.max(o-1,1),u=We(f,s.capability.priority,h,{maxPriority:r,totalSources:o,playerShortname:s.capability.shortname,mimeType:d.type,playbackMode:t});n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:u.total,compatible:!1,incompatibleReason:`Missing required tracks: ${e.join(", ")}`,scoreBreakdown:{trackScore:0,trackTypes:f,priorityScore:a,sourceScore:l,weights:{tracks:.5,priority:.1,source:.05}}});continue}}const p=Array.isArray(f)?f.reduce((e,t)=>e+({video:2,audio:1,subtitle:.5}[t]||0),0):1.9,g=1-s.capability.priority/Math.max(r,1),m=1-h/Math.max(o-1,1),y=We(f,s.capability.priority,h,{maxPriority:r,totalSources:o,playerShortname:s.capability.shortname,mimeType:d.type,playbackMode:t});n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:y.total,compatible:!0,scoreBreakdown:{trackScore:p,trackTypes:Array.isArray(f)?f:["video","audio"],priorityScore:g,sourceScore:m,reliabilityScore:y.breakdown?.reliabilityScore??0,modeBonus:y.breakdown?.modeBonus??0,routingBonus:y.breakdown?.routingBonus??0,weights:{tracks:.5,priority:.1,source:.05,reliability:.1,mode:.12,routing:.08}}})}const d=this.players.get("mist-legacy");if(d&&e.source.length>0){const t=e.source[0],i={url:t.url,type:"mist/legacy",streamName:t.streamName,mistPlayerUrl:t.mistPlayerUrl};n.push({player:d.capability.shortname,playerName:d.capability.name,source:i,sourceIndex:0,sourceType:"mist/legacy",score:.1,compatible:!0,scoreBreakdown:{trackScore:2,trackTypes:["video","audio"],priorityScore:0,sourceScore:0,weights:{tracks:.5,priority:.1,source:.05}}})}return n.sort((e,t)=>e.compatible!==t.compatible?e.compatible?-1:1:e.compatible?t.score-e.score:e.playerName.localeCompare(t.playerName))}diagnoseNoPlayersAvailable(e,t){const n=e.source??[],i=n.filter(e=>qe(e.type)),r=Array.from(new Set(i.map(e=>e.type)));if(n.length>0&&i.length===n.length)return{code:Pe.ALL_PROTOCOLS_BLACKLISTED,message:`All ${n.length} protocols are blacklisted`,details:{blacklistedProtocols:r,incompatibilityReasons:[`All source protocols are blacklisted: ${r.join(", ")}`]}};const s=Array.from(new Set(t.filter(e=>!e.compatible&&e.incompatibleReason).map(e=>e.incompatibleReason)));return 0===n.length?{code:Pe.ALL_PROTOCOLS_EXHAUSTED,message:"No playback sources provided",details:{incompatibilityReasons:s,blacklistedProtocols:r}}:1===s.length?{code:Pe.ALL_PROTOCOLS_EXHAUSTED,message:s[0],details:{incompatibilityReasons:s,blacklistedProtocols:r}}:{code:Pe.ALL_PROTOCOLS_EXHAUSTED,message:"No compatible player/protocol combinations",details:{incompatibilityReasons:s.slice(0,5),blacklistedProtocols:r}}}pickBestFromCombinations(e){const t=e.filter(e=>e.compatible);if(0===t.length)return null;const n=t[0];return{score:n.score,player:n.player,source:n.source,source_index:n.sourceIndex}}hasSelectionChanged(e){return!(!this.cachedSelection&&!e)&&(!this.cachedSelection||!e||(this.cachedSelection.player!==e.player||this.cachedSelection.source?.type!==e.source?.type||(this.cachedSelection.source?.url??"")!==(e.source?.url??"")))}enqueueOp(e){const t=this.opQueue.then(e,e);return this.opQueue=t.then(()=>{},()=>{}),t}async initializePlayer(e,t,n={},i){return this.log("initializePlayer() called"),this.enqueueOp(async()=>(this.log("Inside enqueueOp - starting"),this.fallbackAttempts=0,this.excludedCombos.clear(),this.errorClassifier.reset(),this.lastContainer=e,this.lastStreamInfo=t,this.lastPlayerOptions=n,this.lastManagerOptions={playbackMode:i?.playbackMode,debug:i?.debug,autoFallback:i?.autoFallback,maxFallbackAttempts:i?.maxFallbackAttempts},this.tryInitializePlayer(e,t,n,i)))}async tryInitializePlayer(e,t,n,i,r=new Set){this.log("tryInitializePlayer() starting"),this.currentPlayer&&(this.log("Cleaning up previous player..."),await Promise.resolve(this.currentPlayer.destroy()),this.currentPlayer=null),e.innerHTML="";const s=this.getAllCombinations(t,i?.playbackMode),a=s.filter(e=>e.compatible&&!r.has(this.getComboKey(e.player,e.source)));this.errorClassifier.setAlternativesRemaining(Math.max(0,a.length-1));const o=t.source.filter((e,n)=>{if(0===r.size)return!0;const s=this.selectBestPlayer({...t,source:[t.source[n]]},i);return s&&!r.has(this.getComboKey(s.player,s.source))});if(0===o.length){this.log("No available sources after filtering");const e=this.diagnoseNoPlayersAvailable(t,s);if("fatal"===this.errorClassifier.classifyWithDetails(e.code,e.message,e.details).type)throw new Error(e.message);throw new Error(e.message)}this.log(`Available sources: ${o.length}`);const l={...t,source:o},u=this.selectBestPlayer(l,i);if(!u){this.log("No suitable player selected");const e=this.getAllCombinations(l,i?.playbackMode),t=this.diagnoseNoPlayersAvailable(l,e);throw this.errorClassifier.classifyWithDetails(t.code,t.message,t.details),new Error(t.message)}this.log(`Selected: ${u.player} for ${u.source.type}`);const d=this.players.get(u.player);if(!d)throw this.log(`Player ${u.player} not registered`),new Error(`Player ${u.player} not found`);this.log(`Calling ${u.player}.initialize()...`);try{const i=await d.initialize(e,u.source,n,t);return this.log(`${u.player}.initialize() completed successfully`),this.currentPlayer=d,this.errorClassifier.reset(),this.emit("playerInitialized",{player:d,videoElement:i}),i}catch(s){return this.handleInitError(s,u,e,t,n,i,r)}}async handleInitError(e,t,n,i,r,s,a){const o=Be.mapErrorToCode(e instanceof Error?e:new Error(String(e))),l=this.errorClassifier.classify(o,e instanceof Error?e:String(e));switch(this.log(`Error classified: ${o}, action: ${l.type}`),l.type){case"retry":return this.log(`Retrying in ${l.delayMs}ms...`),await this.delay(l.delayMs),this.tryInitializePlayer(n,i,r,s,a);case"swap":{const o=this.options.maxFallbackAttempts||3;if(!this.options.autoFallback||this.fallbackAttempts>=o)throw this.errorClassifier.classify(Pe.ALL_PROTOCOLS_EXHAUSTED),e;this.fallbackAttempts++;const u=t.player,d=t.source.type;a.add(this.getComboKey(t.player,t.source)),this.log(`Swapping from ${u} (attempt ${this.fallbackAttempts}/${o})`);try{const e=await this.tryInitializePlayer(n,i,r,s,a),t=this.currentPlayer?.capability.shortname||"unknown",o=this.cachedSelection?.source.type||"unknown";return this.errorClassifier.notifyProtocolSwap(u,t,d,o,l.reason),this.emit("fallbackAttempted",{fromPlayer:u,toPlayer:t}),e}catch(e){throw e}}default:throw e}}delay(e){return new Promise(t=>setTimeout(t,e))}async tryPlaybackFallback(){return this.enqueueOp(async()=>{if(!this.lastContainer||!this.lastStreamInfo)return this.log("Cannot attempt fallback: no previous init params"),!1;const e=this.options.maxFallbackAttempts||3;if(this.fallbackAttempts>=e)return this.log(`Fallback exhausted (${this.fallbackAttempts}/${e})`),this.errorClassifier.classify(Pe.ALL_PROTOCOLS_EXHAUSTED),!1;const t=this.currentPlayer?.capability.shortname||"unknown",n=this.cachedSelection?.source.type||"unknown";this.currentPlayer&&(this.cachedSelection&&this.excludedCombos.add(this.getComboKey(this.cachedSelection.player,this.cachedSelection.source)),await Promise.resolve(this.currentPlayer.destroy()),this.currentPlayer=null),this.fallbackAttempts++,this.lastContainer.innerHTML="",this.errorClassifier.reset();try{await this.tryInitializePlayer(this.lastContainer,this.lastStreamInfo,this.lastPlayerOptions,this.lastManagerOptions,this.excludedCombos);const e=this.getCurrentPlayer(),i=e?.capability.shortname||"unknown",r=this.cachedSelection?.source.type||"unknown";return this.errorClassifier.notifyProtocolSwap(t,i,n,r,"Playback fallback"),this.emit("fallbackAttempted",{fromPlayer:t,toPlayer:i}),!0}catch{return this.log("Playback fallback failed"),!1}})}reportError(e){const t=Be.mapErrorToCode(e);return this.errorClassifier.classify(t,e)}reportQualityChange(e,t){this.emit("qualityChanged",{direction:e,reason:t})}getErrorClassifier(){return this.errorClassifier}getRemainingFallbackAttempts(){return Math.max(0,(this.options.maxFallbackAttempts||3)-this.fallbackAttempts)}canAttemptFallback(){return this.getRemainingFallbackAttempts()>0&&null!==this.lastStreamInfo}getCurrentPlayer(){return this.currentPlayer}getBrowserCapabilities(){return{browser:Ae(),compatibility:Re(),supportedMimeTypes:this.getSupportedMimeTypes(),availablePlayers:this.getAvailablePlayerInfo()}}getSupportedMimeTypes(){const e=new Set;for(const t of this.players.values())t.capability.mimes.forEach(t=>e.add(t));return Array.from(e).sort()}getAvailablePlayerInfo(){return Array.from(this.players.values()).map(e=>({name:e.capability.name,shortname:e.capability.shortname,priority:e.capability.priority,mimes:e.capability.mimes})).sort((e,t)=>e.priority-t.priority)}async destroy(){await this.enqueueOp(async()=>{this.currentPlayer&&(await Promise.resolve(this.currentPlayer.destroy()),this.currentPlayer=null)})}removeAllListeners(){this.listeners.clear()}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){this.listeners.get(e)?.forEach(n=>{try{n(t)}catch(t){console.error(`Error in PlayerManager ${e} listener:`,t)}})}log(e){this.options.debug&&console.log(`[PlayerManager] ${e}`)}async testSource(e,t){const n={...t,source:[e]};if(!this.selectBestPlayer(n))return{canPlay:!1,players:[]};const i=[];for(const n of this.players.values())if(n.isMimeSupported(e.type)){n.isBrowserSupported(e.type,e,t)&&i.push(n.capability.shortname)}return{canPlay:!0,players:i}}}class Qe{constructor(){this.listeners=new Map}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}once(e,t){const n=i=>{this.off(e,n),t(i)};return this.on(e,n)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){this.listeners.get(e)?.forEach(n=>{try{n(t)}catch(t){console.error(`[EventEmitter] Error in ${String(e)} listener:`,t)}})}removeAllListeners(){this.listeners.clear()}removeListeners(e){this.listeners.delete(e)}hasListeners(e){return(this.listeners.get(e)?.size??0)>0}}const Xe=3,Je=500;class Ze extends Qe{constructor(e){super(),this.status="idle",this.endpoints=null,this.error=null,this.abortController=null,this.inFlightRequest=null,this.cacheTimestamp=0,this.circuitState="closed",this.consecutiveFailures=0,this.circuitOpenedAt=0,this.config=e,this.cacheTtlMs=1e4}async resolve(e=!1){if(!e&&this.endpoints&&this.isCacheValid())return this.endpoints;if(!this.canAttemptRequest())throw new Error("Circuit breaker is open - too many recent failures");if(this.inFlightRequest)return this.inFlightRequest;this.inFlightRequest=this.doResolve();try{const e=await this.inFlightRequest;return this.onSuccess(),e}catch(e){throw this.onFailure(),e}finally{this.inFlightRequest=null}}isCacheValid(){return Date.now()-this.cacheTimestamp<this.cacheTtlMs}setCacheTtl(e){this.cacheTtlMs=e}invalidateCache(){this.cacheTimestamp=0}canAttemptRequest(){switch(this.circuitState){case"closed":case"half-open":return!0;case"open":return Date.now()-this.circuitOpenedAt>=3e4&&(this.circuitState="half-open",!0)}}onSuccess(){this.consecutiveFailures=0,this.circuitState="closed"}onFailure(){this.consecutiveFailures++,"half-open"===this.circuitState?(this.circuitState="open",this.circuitOpenedAt=Date.now()):this.consecutiveFailures>=5&&(this.circuitState="open",this.circuitOpenedAt=Date.now(),console.warn(`[GatewayClient] Circuit breaker opened after ${this.consecutiveFailures} consecutive failures`))}getCircuitState(){return{state:this.circuitState,failures:this.consecutiveFailures,openedAt:"open"===this.circuitState?this.circuitOpenedAt:null}}resetCircuitBreaker(){this.circuitState="closed",this.consecutiveFailures=0,this.circuitOpenedAt=0}async doResolve(){this.abort();const{gatewayUrl:e,contentId:t,authToken:n,maxRetries:i=Xe,initialDelayMs:r=Je}=this.config;if(!e||!t){const e="Missing required parameters: gatewayUrl or contentId";throw this.setStatus("error",e),new Error(e)}this.setStatus("loading");const s=new AbortController;this.abortController=s;try{const a=e.replace(/\/$/,""),o=await async function(e,t,n,i){let r=null;for(let s=0;s<n;s++)try{return await fetch(e,t)}catch(e){if(r=e instanceof Error?e:new Error("Fetch failed"),t.signal?.aborted)throw r;if(s<n-1){const e=i*Math.pow(2,s);console.warn(`[GatewayClient] Retry ${s+1}/${n-1} after ${e}ms`),await new Promise(t=>setTimeout(t,e))}}throw r??new Error("Gateway unreachable after retries")}(a,{method:"POST",headers:{"Content-Type":"application/json",...n?{Authorization:`Bearer ${n}`}:{}},body:JSON.stringify({query:"\n query ResolveViewer($contentId: String!) {\n resolveViewerEndpoint(contentId: $contentId) {\n primary { nodeId baseUrl protocol url geoDistance loadScore outputs }\n fallbacks { nodeId baseUrl protocol url geoDistance loadScore outputs }\n metadata { contentType contentId title description durationSeconds status isLive viewers recordingSizeBytes clipSource createdAt }\n }\n }\n",variables:{contentId:t}}),signal:s.signal},i,r);if(!o.ok)throw new Error(`Gateway GQL error ${o.status}`);const l=await o.json();if(l.errors?.length)throw new Error(l.errors[0]?.message||"GraphQL error");const u=l.data?.resolveViewerEndpoint,d=u?.primary,c=Array.isArray(u?.fallbacks)?u.fallbacks:[];if(!d)throw new Error("No endpoints available");const h={primary:d,fallbacks:c,metadata:u?.metadata};return this.endpoints=h,this.cacheTimestamp=Date.now(),this.setStatus("ready"),this.emit("endpointsResolved",{endpoints:h}),h}catch(e){if(s.signal.aborted)throw new Error("Request aborted");const t=e instanceof Error?e.message:"Unknown gateway error";throw console.error("[GatewayClient] Gateway resolution failed:",t),this.setStatus("error",t),new Error(t)}}abort(){this.abortController&&(this.abortController.abort(),this.abortController=null)}getStatus(){return this.status}getEndpoints(){return this.endpoints}getError(){return this.error}updateConfig(e){this.abort(),this.config={...this.config,...e},this.endpoints=null,this.error=null,this.cacheTimestamp=0,this.inFlightRequest=null,this.resetCircuitBreaker(),this.setStatus("idle")}destroy(){this.abort(),this.removeAllListeners()}setStatus(e,t){this.status=e,this.error=t??null,this.emit("statusChange",{status:e,error:t})}}class et{constructor(e){this.timers=new Map,this.nextId=1,this.debug=e?.debug??!1}start(e,t,n){const i=this.nextId++,r=Date.now()+t,s=setTimeout(()=>{this.timers.delete(i);try{e()}catch(e){console.error("[TimerManager] Callback error:",e)}},t);return this.timers.set(i,{id:s,endTime:r,isInterval:!1,label:n}),this.debug&&console.debug(`[TimerManager] Started timeout ${i}${n?` (${n})`:""} for ${t}ms`),i}startInterval(e,t,n){const i=this.nextId++,r=setInterval(()=>{try{e()}catch(e){console.error("[TimerManager] Interval callback error:",e)}},t);return this.timers.set(i,{id:r,endTime:1/0,isInterval:!0,label:n}),this.debug&&console.debug(`[TimerManager] Started interval ${i}${n?` (${n})`:""} every ${t}ms`),i}stop(e){const t=this.timers.get(e);return!!t&&(t.isInterval?clearInterval(t.id):clearTimeout(t.id),this.timers.delete(e),this.debug&&console.debug(`[TimerManager] Stopped ${t.isInterval?"interval":"timeout"} ${e}${t.label?` (${t.label})`:""}`),!0)}stopAll(){const e=this.timers.size;for(const[e,t]of this.timers)t.isInterval?clearInterval(t.id):clearTimeout(t.id);this.timers.clear(),this.debug&&e>0&&console.debug(`[TimerManager] Stopped all ${e} timers`)}get activeCount(){return this.timers.size}isActive(e){return this.timers.has(e)}getRemainingTime(e){const t=this.timers.get(e);return!t||t.isInterval?0:Math.max(0,t.endTime-Date.now())}getDebugInfo(){const e=[];for(const[t,n]of this.timers)e.push({id:t,type:n.isInterval?"interval":"timeout",label:n.label,remainingMs:n.isInterval?void 0:Math.max(0,n.endTime-Date.now())});return e}destroy(){this.stopAll()}}const tt={status:"OFFLINE",isOnline:!1,message:"Connecting...",lastUpdate:0};class nt extends Qe{constructor(e){super(),this.state={...tt},this.ws=null,this.timers=new et,this.isRunning=!1,this.wasOnline=!1,this.connectionId=0,this.config={pollInterval:3e3,useWebSocket:!0,...e}}start(){if(this.isRunning)return;this.isRunning=!0;const{mistBaseUrl:e,streamName:t,useWebSocket:n}=this.config;if(!e||!t)return void console.warn("[StreamStateClient] Missing mistBaseUrl or streamName");this.setState({...tt,message:"Connecting...",lastUpdate:Date.now()});const i=++this.connectionId;this.timers.start(()=>{this.isRunning&&this.connectionId===i&&this.pollHttp().then(()=>{n&&this.isRunning&&this.connectionId===i&&this.connectWebSocket()})},nt.CONNECTION_DEBOUNCE_MS,"connect")}stop(){this.isRunning=!1,this.ws&&(this.ws.close(),this.ws=null),this.timers.destroy()}refresh(){this.config.useWebSocket&&this.ws?.readyState===WebSocket.OPEN||this.pollHttp()}getSocket(){return this.ws}isSocketReady(){return this.ws?.readyState===WebSocket.OPEN}getState(){return{...this.state}}isOnline(){return this.state.isOnline}updateConfig(e){const t=this.isRunning;this.stop(),this.config={...this.config,...e},t&&this.start()}destroy(){this.stop(),this.removeAllListeners()}connectWebSocket(){if(!this.isRunning)return;const{mistBaseUrl:e,streamName:t}=this.config;this.ws&&(this.ws.close(),this.ws=null);try{const n=e.replace(/^http:/,"ws:").replace(/^https:/,"wss:").replace(/\/$/,""),i=new WebSocket(`${n}/json_${encodeURIComponent(t)}.js?metaeverywhere=1&inclzero=1`);this.ws=i,i.onopen=()=>{console.debug("[StreamStateClient] WebSocket connected")},i.onmessage=e=>{try{const t=JSON.parse(e.data);this.processStreamInfo(t)}catch(e){console.warn("[StreamStateClient] Failed to parse WebSocket message:",e)}},i.onerror=()=>{console.warn("[StreamStateClient] WebSocket error, falling back to HTTP polling"),i.close()},i.onclose=()=>{this.ws=null,this.isRunning&&(this.config.useWebSocket=!1,console.debug("[StreamStateClient] WebSocket closed, switching to HTTP polling"),this.pollHttp())}}catch(e){console.warn("[StreamStateClient] WebSocket connection failed:",e),this.config.useWebSocket=!1,this.pollHttp()}}async pollHttp(){if(!this.isRunning)return;const{mistBaseUrl:e,streamName:t,pollInterval:n}=this.config;try{const n=`${e.replace(/\/$/,"")}/json_${encodeURIComponent(t)}.js?metaeverywhere=1&inclzero=1`,i=await fetch(n,{method:"GET",headers:{Accept:"application/json"}});if(!i.ok)throw new Error(`HTTP ${i.status}`);let r=await i.text();const s=r.match(/^[^(]+\(([\s\S]*)\);?$/);s&&(r=s[1]);const a=JSON.parse(r);this.processStreamInfo(a)}catch(e){if(!this.isRunning)return;const t=e instanceof Error?e.message:"Connection failed";this.setState({...this.state,status:"ERROR",isOnline:!1,message:t,lastUpdate:Date.now(),error:t}),this.emit("error",{error:t})}this.isRunning&&!this.config.useWebSocket&&this.timers.start(()=>this.pollHttp(),n,"poll")}processStreamInfo(e){if(!this.isRunning)return;let t;if(e.error){const n=function(e){const t=e.toLowerCase();return t.includes("offline")?"OFFLINE":t.includes("initializing")?"INITIALIZING":t.includes("booting")?"BOOTING":t.includes("waiting for data")?"WAITING_FOR_DATA":t.includes("shutting down")?"SHUTTING_DOWN":t.includes("invalid")?"INVALID":"ERROR"}(e.error),i=e.on_error||function(e,t){switch(e){case"ONLINE":return"Stream is online";case"OFFLINE":return"Stream is offline";case"INITIALIZING":return void 0!==t?`Initializing... ${Math.round(10*t)/10}%`:"Stream is initializing";case"BOOTING":return"Stream is starting up";case"WAITING_FOR_DATA":return"Waiting for stream data";case"SHUTTING_DOWN":return"Stream is shutting down";case"INVALID":return"Stream status is invalid";default:return"Stream error"}}(n,e.perc);t={status:n,isOnline:!1,message:i,percentage:e.perc,lastUpdate:Date.now(),error:e.error,streamInfo:this.state.streamInfo}}else{const n={...this.state.streamInfo,...e,source:e.source||this.state.streamInfo?.source,meta:{...this.state.streamInfo?.meta,...e.meta,tracks:e.meta?.tracks||this.state.streamInfo?.meta?.tracks}};t={status:"ONLINE",isOnline:!0,message:"Stream is online",lastUpdate:Date.now(),streamInfo:n}}this.setState(t),t.isOnline&&!this.wasOnline?this.emit("online",void 0):!t.isOnline&&this.wasOnline&&this.emit("offline",void 0),this.wasOnline=t.isOnline}setState(e){const t=this.state;this.state=e;(t.status!==e.status||t.isOnline!==e.isOnline||t.message!==e.message||t.streamInfo!==e.streamInfo||t.lastUpdate!==e.lastUpdate)&&this.emit("stateChange",{state:e})}}nt.CONNECTION_DEBOUNCE_MS=100;const it=[{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"]},load:()=>Promise.resolve().then(function(){return Dn}).then(e=>new e.NativePlayerImpl)},{capability:{name:"WebCodecs Player",shortname:"webcodecs",priority:0,mimes:["ws/video/raw","wss/video/raw","ws/video/h264","wss/video/h264"]},load:()=>Promise.resolve().then(function(){return Wn}).then(e=>new e.WebCodecsPlayerImpl)},{capability:{name:"MistServer WebRTC",shortname:"mist-webrtc",priority:2,mimes:["webrtc","mist/webrtc"]},load:()=>Promise.resolve().then(function(){return Kn}).then(e=>new e.MistWebRTCPlayerImpl)},{capability:{name:"Video.js Player",shortname:"videojs",priority:2,mimes:["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"]},load:()=>Promise.resolve().then(function(){return Qn}).then(e=>new e.VideoJsPlayerImpl)},{capability:{name:"HLS.js Player",shortname:"hlsjs",priority:3,mimes:["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"]},load:()=>Promise.resolve().then(function(){return Xn}).then(e=>new e.HlsJsPlayerImpl)},{capability:{name:"Dash.js Player",shortname:"dashjs",priority:100,mimes:["dash/video/mp4"]},load:()=>Promise.resolve().then(function(){return Jn}).then(e=>new e.DashJsPlayerImpl)},{capability:{name:"Legacy",shortname:"mist-legacy",priority:99,mimes:["mist/legacy"]},load:()=>Promise.resolve().then(function(){return Zn}).then(e=>new e.MistPlayerImpl)},{capability:{name:"MEWS WebSocket Player",shortname:"mews",priority:2,mimes:["ws/video/mp4","wss/video/mp4","ws/video/webm","wss/video/webm"]},load:()=>Promise.resolve().then(function(){return ri}).then(e=>new e.MewsWsPlayerImpl)}],rt=new WeakMap;function st(e){let t=rt.get(e);return t||(t=new Set,rt.set(e,t)),t}async function at(e,t){const n=st(e),i=it.filter(e=>!n.has(e.capability.shortname)&&e.capability.mimes.some(e=>t.includes(e)));if(0===i.length)return;const r=await Promise.all(i.map(e=>e.load()));for(const t of r){n.add(t.capability.shortname);const i=e.getRegisteredPlayers().some(e=>e.capability.shortname===t.capability.shortname);i||e.registerPlayer(t)}}const ot=new WeakMap;function lt(e=ct){if(st(e).size===it.length)return Promise.resolve();const t=ot.get(e);if(t)return t;const n=async function(e){const t=it.flatMap(e=>e.capability.mimes);return at(e,t)}(e).catch(t=>{throw console.error("[PlayerRegistry] Registration failed:",t),ot.delete(e),t});return ot.set(e,n),n}const ut=Ke.prototype.initializePlayer;Ke.prototype.initializePlayer=async function(...e){const[t,n,i,r]=e,s=n?.source?.map(e=>e.type)??[];return s.length>0?(await at(this,s),r?.forcePlayer&&await async function(e,t){const n=st(e);if(n.has(t))return;const i=it.find(e=>e.capability.shortname===t);if(!i)return;const r=await i.load();n.add(r.capability.shortname);const s=e.getRegisteredPlayers().some(e=>e.capability.shortname===r.capability.shortname);s||e.registerPlayer(r)}(this,r.forcePlayer)):await lt(this),ut.apply(this,e)};const dt=(()=>{try{const e=globalThis.process,t=e?.env;return"development"===t?.NODE_ENV}catch{return!1}})(),ct=new Ke({debug:dt,autoFallback:!0,maxFallbackAttempts:3}),ht={mode:"auto",maxResolution:{width:1920,height:1080},maxBitrate:8e6,minBufferForUpgrade:10,downgradeThreshold:60};class ft{constructor(e){this.videoElement=null,this.currentQualityId="auto",this.lastDecision="none",this.lastDecisionTime=0,this.resizeObserver=null,this.qualityChangeCallbacks=[],this.timers=new et,this.bandwidthHistory=[],this.lastUpgradeTime=0,this.lastDowngradeTime=0,this.currentQualityBitrate=0,this.options={...ht,...e.options},this.config=e,this.debug=e.debug??!1}start(e){this.stop(),this.videoElement=e,"manual"!==this.options.mode?("resize"!==this.options.mode&&"auto"!==this.options.mode||this.setupResizeObserver(),"bitrate"!==this.options.mode&&"auto"!==this.options.mode||this.startActiveMonitoring()):this.log("Manual mode - no automatic ABR")}stop(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.timers.destroy(),this.videoElement=null,this.bandwidthHistory=[]}startActiveMonitoring(){this.timers.startInterval(()=>this.checkBandwidthAndSwitch(),ft.MONITORING_INTERVAL_MS,"monitoring"),this.checkBandwidthAndSwitch()}async checkBandwidthAndSwitch(){if(!this.videoElement)return;const e=Date.now(),t=await this.getBandwidthEstimate();if(t<=0)return;this.bandwidthHistory.push(t),this.bandwidthHistory.length>ft.BANDWIDTH_HISTORY_SIZE&&this.bandwidthHistory.shift();const n=this.getSmoothedBandwidth();if(n<=0)return;const i=this.config.getQualities(),r=this.config.getCurrentQuality?.();if(!r||0===i.length)return;const s=r.bitrate||0;if(this.currentQualityBitrate!==s&&(this.currentQualityBitrate=s),e-this.lastDowngradeTime>=ft.DOWNGRADE_COOLDOWN_MS&&n<s*ft.DOWNGRADE_THRESHOLD){const t=this.findLowerQuality(i,r);if(t)return this.log(`ABR: bandwidth ${Math.round(n/1e3)}kbps < ${Math.round(s*ft.DOWNGRADE_THRESHOLD/1e3)}kbps threshold -> downgrading to ${t.label}`),this.lastDecision="downgrade",this.lastDecisionTime=e,this.lastDowngradeTime=e,void this.selectQuality(t.id)}if(e-this.lastUpgradeTime>=ft.UPGRADE_COOLDOWN_MS){const t=this.findHigherQuality(i,r);if(t&&this.isWithinConstraints(t)){const i=t.bitrate||0;if(n>=i*ft.UPGRADE_HEADROOM)return this.log(`ABR: bandwidth ${Math.round(n/1e3)}kbps >= ${Math.round(i*ft.UPGRADE_HEADROOM/1e3)}kbps headroom -> upgrading to ${t.label}`),this.lastDecision="upgrade",this.lastDecisionTime=e,this.lastUpgradeTime=e,void this.selectQuality(t.id)}}}async getBandwidthEstimate(){if(this.config.getBandwidthEstimate){const e=await this.config.getBandwidthEstimate();if(e>0)return e}const e=this.videoElement;return e&&e.buffered.length,0}getSmoothedBandwidth(){if(0===this.bandwidthHistory.length)return 0;if(this.bandwidthHistory.length<3)return 0;const e=this.bandwidthHistory.reduce((e,t)=>e+t,0);return e/this.bandwidthHistory.length}getCurrentBandwidth(){return this.getSmoothedBandwidth()}setupResizeObserver(){const e=this.videoElement;if(!e)return;this.resizeObserver=new ResizeObserver(e=>{for(const t of e){const{width:e,height:n}=t.contentRect;this.handleResize(e,n)}});const t=e.parentElement;t&&this.resizeObserver.observe(t);const n=e.getBoundingClientRect();this.handleResize(n.width,n.height)}handleResize(e,t){if("resize"!==this.options.mode&&"auto"!==this.options.mode)return;const n=this.config.getQualities();if(0===n.length)return;const i=Math.min(e*window.devicePixelRatio,this.options.maxResolution.width),r=Math.min(t*window.devicePixelRatio,this.options.maxResolution.height),s=this.findBestQualityForResolution(n,i,r);s&&s.id!==this.currentQualityId&&(this.log(`Resize ABR: ${e}x${t} -> selecting ${s.label}`),this.selectQuality(s.id))}handleQualityDegraded(e){if("bitrate"!==this.options.mode&&"auto"!==this.options.mode)return;const t=Date.now();if(!(t-this.lastDowngradeTime<ft.DOWNGRADE_COOLDOWN_MS)&&e.score<this.options.downgradeThreshold){const n=this.config.getQualities(),i=this.config.getCurrentQuality?.();if(i){const r=this.findLowerQuality(n,i);r&&(this.log(`Bitrate ABR: score ${e.score} -> downgrading to ${r.label}`),this.lastDecision="downgrade",this.lastDecisionTime=t,this.lastDowngradeTime=t,this.selectQuality(r.id))}}}handleQualityImproved(e){if("bitrate"!==this.options.mode&&"auto"!==this.options.mode)return;const t=Date.now();if(!(t-this.lastUpgradeTime<ft.UPGRADE_COOLDOWN_MS)&&e.score>=90&&e.bufferedAhead>=this.options.minBufferForUpgrade){const n=this.config.getQualities(),i=this.config.getCurrentQuality?.();if(i){const r=this.findHigherQuality(n,i);r&&this.isWithinConstraints(r)&&(this.log(`Bitrate ABR: score ${e.score} -> upgrading to ${r.label}`),this.lastDecision="upgrade",this.lastDecisionTime=t,this.lastUpgradeTime=t,this.selectQuality(r.id))}}}findBestQualityForResolution(e,t,n){const i=e.filter(e=>this.isWithinConstraints(e));if(0===i.length)return null;const r=[...i].sort((e,t)=>(e.width??0)*(e.height??0)-(t.width??0)*(t.height??0));for(const e of r){const i=e.width??0,r=e.height??0;if(i>=t&&r>=n)return e}return r[r.length-1]}findLowerQuality(e,t){const n=t.bitrate??0,i=[...e].sort((e,t)=>(t.bitrate??0)-(e.bitrate??0));for(const e of i)if((e.bitrate??0)<n)return e;return null}findHigherQuality(e,t){const n=t.bitrate??0,i=[...e].sort((e,t)=>(e.bitrate??0)-(t.bitrate??0));for(const e of i)if((e.bitrate??0)>n)return e;return null}isWithinConstraints(e){const{maxResolution:t,maxBitrate:n}=this.options;return!(e.width&&e.width>t.width)&&(!(e.height&&e.height>t.height)&&!(e.bitrate&&e.bitrate>n))}selectQuality(e){this.currentQualityId=e,this.config.selectQuality(e);const t=this.config.getQualities().find(t=>t.id===e);t&&this.qualityChangeCallbacks.forEach(e=>e(t))}onQualityChange(e){return this.qualityChangeCallbacks.push(e),()=>{const t=this.qualityChangeCallbacks.indexOf(e);t>=0&&this.qualityChangeCallbacks.splice(t,1)}}setQuality(e){this.selectQuality(e)}getMode(){return this.options.mode}setMode(e){if(this.options.mode!==e&&(this.options.mode=e,this.log(`Mode changed to: ${e}`),this.videoElement)){const e=this.videoElement;this.stop(),this.start(e)}}updateOptions(e){this.options={...this.options,...e}}getLastDecision(){return this.lastDecision}log(e){this.debug&&console.debug(`[ABRController] ${e}`)}}ft.BANDWIDTH_HISTORY_SIZE=10,ft.MONITORING_INTERVAL_MS=1e3,ft.UPGRADE_COOLDOWN_MS=5e3,ft.DOWNGRADE_COOLDOWN_MS=0,ft.UPGRADE_HEADROOM=1.5,ft.UPGRADE_HOLD_THRESHOLD=1.2,ft.DOWNGRADE_THRESHOLD=.8;class pt{constructor(e){this.isAttached=!1,this.spaceKeyDownTime=0,this.spaceIsHeld=!1,this.holdCheckTimeout=null,this.pointerDownTime=0,this.pointerIsHeld=!1,this.pointerHoldTimeout=null,this.lastTapTime=0,this.lastTapX=0,this.pendingTapTimeout=null,this.idleTimeout=null,this.lastInteractionTime=0,this.config=e,this.state={isHoldingSpeed:!1,previousSpeed:1,holdSpeed:e.speedHoldValue??2,isIdle:!1},this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this),this.boundPointerDown=this.handlePointerDown.bind(this),this.boundPointerUp=this.handlePointerUp.bind(this),this.boundPointerCancel=this.handlePointerCancel.bind(this),this.boundContextMenu=this.handleContextMenu.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundDoubleClick=this.handleDoubleClick.bind(this),this.boundDocumentKeyDown=this.handleKeyDown.bind(this),this.boundDocumentKeyUp=this.handleKeyUp.bind(this)}attach(){if(this.isAttached)return;const{container:e}=this.config;e.hasAttribute("tabindex")||e.setAttribute("tabindex","0"),e.addEventListener("keydown",this.boundKeyDown),e.addEventListener("keyup",this.boundKeyUp),document.addEventListener("keydown",this.boundDocumentKeyDown),document.addEventListener("keyup",this.boundDocumentKeyUp),e.addEventListener("pointerdown",this.boundPointerDown),e.addEventListener("pointerup",this.boundPointerUp),e.addEventListener("pointercancel",this.boundPointerCancel),e.addEventListener("pointerleave",this.boundPointerCancel),e.addEventListener("mousemove",this.boundMouseMove),e.addEventListener("dblclick",this.boundDoubleClick),e.addEventListener("contextmenu",this.boundContextMenu),this.resetIdleTimer(),this.isAttached=!0}detach(){if(!this.isAttached)return;const{container:e}=this.config;e.removeEventListener("keydown",this.boundKeyDown),e.removeEventListener("keyup",this.boundKeyUp),document.removeEventListener("keydown",this.boundDocumentKeyDown),document.removeEventListener("keyup",this.boundDocumentKeyUp),e.removeEventListener("pointerdown",this.boundPointerDown),e.removeEventListener("pointerup",this.boundPointerUp),e.removeEventListener("pointercancel",this.boundPointerCancel),e.removeEventListener("pointerleave",this.boundPointerCancel),e.removeEventListener("mousemove",this.boundMouseMove),e.removeEventListener("dblclick",this.boundDoubleClick),e.removeEventListener("contextmenu",this.boundContextMenu),this.holdCheckTimeout&&(clearTimeout(this.holdCheckTimeout),this.holdCheckTimeout=null),this.pointerHoldTimeout&&(clearTimeout(this.pointerHoldTimeout),this.pointerHoldTimeout=null),this.pendingTapTimeout&&(clearTimeout(this.pendingTapTimeout),this.pendingTapTimeout=null),this.idleTimeout&&(clearTimeout(this.idleTimeout),this.idleTimeout=null),this.state.isHoldingSpeed&&this.releaseSpeedHold(),this.isAttached=!1}isHoldingSpeed(){return this.state.isHoldingSpeed}isIdle(){return this.state.isIdle}getState(){return{...this.state}}updateConfig(e){this.config={...this.config,...e},e.isLive&&this.state.isHoldingSpeed&&this.releaseSpeedHold()}handleKeyDown(e){if(this.isInputElement(e.target))return;if(e.defaultPrevented)return;if(!this.shouldHandleKeyboard(e))return;this.recordInteraction();const{isLive:t}=this.config,n=this.config.isPaused?.()??this.config.videoElement?.paused??!1;switch(e.key){case" ":case"Spacebar":e.preventDefault(),this.handleSpaceDown();break;case"ArrowLeft":case"j":case"J":e.preventDefault(),t||this.config.onSeek(-10);break;case"ArrowRight":case"l":case"L":e.preventDefault(),t||this.config.onSeek(10);break;case"ArrowUp":e.preventDefault(),this.config.onVolumeChange(.1);break;case"ArrowDown":e.preventDefault(),this.config.onVolumeChange(-.1);break;case"m":case"M":e.preventDefault(),this.config.onMuteToggle();break;case"f":case"F":e.preventDefault(),this.config.onFullscreenToggle();break;case"c":case"C":e.preventDefault(),this.config.onCaptionsToggle?.();break;case"k":case"K":e.preventDefault(),this.config.onPlayPause();break;case"<":e.preventDefault(),t||this.adjustPlaybackSpeed(-.25);break;case">":e.preventDefault(),t||this.adjustPlaybackSpeed(.25);break;case",":(this.config.onFrameStep||!t&&n)&&(e.preventDefault(),this.stepFrame(-1));break;case".":(this.config.onFrameStep||!t&&n)&&(e.preventDefault(),this.stepFrame(1));break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":if(e.preventDefault(),!t&&this.config.onSeekPercent){const t=parseInt(e.key,10)/10;this.config.onSeekPercent(t)}}}handleKeyUp(e){this.isInputElement(e.target)||e.defaultPrevented||this.shouldHandleKeyboard(e)&&(" "!==e.key&&"Spacebar"!==e.key||(e.preventDefault(),this.handleSpaceUp()))}shouldHandleKeyboard(e){if(this.spaceKeyDownTime>0)return!0;const t=e.target;if(t&&this.config.container.contains(t))return!0;const n=document.activeElement;if(n&&this.config.container.contains(n))return!0;try{if(this.config.container.matches(":focus-within"))return!0;if(this.config.container.matches(":hover"))return!0}catch{}return Date.now()-this.lastInteractionTime<5e3}handleSpaceDown(){this.spaceKeyDownTime>0||(this.spaceKeyDownTime=Date.now(),this.spaceIsHeld=!1,this.config.isLive||(this.holdCheckTimeout=setTimeout(()=>{this.spaceIsHeld=!0,this.engageSpeedHold()},200)))}handleSpaceUp(){const e=this.spaceKeyDownTime;if(this.spaceKeyDownTime=0,this.holdCheckTimeout&&(clearTimeout(this.holdCheckTimeout),this.holdCheckTimeout=null),this.spaceIsHeld)this.releaseSpeedHold(),this.spaceIsHeld=!1;else{(Date.now()-e<200||this.config.isLive)&&this.config.onPlayPause()}}handleDoubleClick(e){this.isControlElement(e.target)||(this.recordInteraction(),e.preventDefault(),this.config.onFullscreenToggle())}stepFrame(e){const t=this.getFrameStepSeconds();if(!Number.isFinite(t)||t<=0)return;if(this.config.onFrameStep?.(e,t))return;const n=this.config.videoElement;if(!n)return;const i=n.currentTime+e*t;if(!Number.isFinite(i))return;const r=n.buffered;if(r&&r.length>0)for(let e=0;e<r.length;e++){const t=r.start(e),s=r.end(e);if(i>=t&&i<=s){try{n.currentTime=i}catch{}return}}}handlePointerDown(e){if(0!==e.button)return;if(this.isControlElement(e.target))return;this.recordInteraction(),this.config.container.focus();const t=Date.now(),n=this.config.container.getBoundingClientRect(),i=(e.clientX-n.left)/n.width,r="mouse"===e.pointerType;if(t-this.lastTapTime<300)return this.pendingTapTimeout&&(clearTimeout(this.pendingTapTimeout),this.pendingTapTimeout=null),r||this.config.isLive||(i<.33?this.config.onSeek(-10):i>.67?this.config.onSeek(10):this.config.onPlayPause()),void(this.lastTapTime=0);this.lastTapTime=t,this.lastTapX=i,this.pointerDownTime=t,this.pointerIsHeld=!1,this.config.isLive||(this.pointerHoldTimeout=setTimeout(()=>{this.pointerIsHeld=!0,this.engageSpeedHold()},300))}handlePointerUp(e){if(0!==e.button)return;const t=this.pointerIsHeld;this.cancelPointerHold(),t?this.releaseSpeedHold():this.pointerDownTime>0&&(this.pendingTapTimeout=setTimeout(()=>{this.pendingTapTimeout=null,this.config.onPlayPause()},300)),this.pointerDownTime=0}handlePointerCancel(e){this.pointerIsHeld&&this.releaseSpeedHold(),this.cancelPointerHold(),this.pointerDownTime=0}cancelPointerHold(){this.pointerHoldTimeout&&(clearTimeout(this.pointerHoldTimeout),this.pointerHoldTimeout=null),this.pointerIsHeld=!1}handleContextMenu(e){(this.pointerIsHeld||this.pointerDownTime>0)&&e.preventDefault()}engageSpeedHold(){this.state.isHoldingSpeed||this.config.isLive||(this.state.previousSpeed=this.config.videoElement.playbackRate,this.state.isHoldingSpeed=!0,this.config.onSpeedChange(this.state.holdSpeed,!0))}releaseSpeedHold(){this.state.isHoldingSpeed&&(this.state.isHoldingSpeed=!1,this.config.onSpeedChange(this.state.previousSpeed,!1))}adjustPlaybackSpeed(e){if(this.state.isHoldingSpeed)return;const t=this.config.videoElement.playbackRate,n=Math.max(.25,Math.min(4,t+e)),i=Math.round(100*n)/100;this.config.onSpeedChange(i,!1)}handleMouseMove(e){this.recordInteraction()}recordInteraction(){this.lastInteractionTime=Date.now(),this.state.isIdle&&(this.state.isIdle=!1,this.config.onActive?.()),this.resetIdleTimer()}resetIdleTimer(){this.idleTimeout&&(clearTimeout(this.idleTimeout),this.idleTimeout=null);const e=this.config.idleTimeout??5e3;e<=0||(this.idleTimeout=setTimeout(()=>{this.idleTimeout=null,this.state.isIdle||(this.state.isIdle=!0,this.config.onIdle?.())},e))}markActive(){this.recordInteraction()}pauseIdleTracking(){this.idleTimeout&&(clearTimeout(this.idleTimeout),this.idleTimeout=null)}resumeIdleTracking(){this.isAttached&&this.resetIdleTimer()}isInputElement(e){if(!(e&&e instanceof HTMLElement))return!1;const t=e.tagName.toLowerCase();return"input"===t||"textarea"===t||"select"===t||e.isContentEditable}isControlElement(e){if(!(e&&e instanceof HTMLElement))return!1;return["button",'[role="button"]','[role="slider"]',"input","select",".fw-player-controls","[data-player-controls]",".fw-controls-wrapper",".fw-control-bar",".fw-settings-menu",".fw-context-menu",".fw-stats-panel",".fw-dev-panel",".fw-error-overlay",".fw-error-popup",".fw-player-error"].some(t=>e.matches(t)||null!==e.closest(t))}getFrameStepSeconds(){const e=this.config.frameStepSeconds;return Number.isFinite(e)&&e>0?e:1/30}}class gt{constructor(e={}){this.socket=null,this.videoElement=null,this.containerElement=null,this.logs=[],this.waitingSince=0,this.stalledSince=0,this.unpausedSince=0,this.timeWaitingAccum=0,this.timeStalledAccum=0,this.timeUnpausedAccum=0,this.lastReported={},this.timers=new et,this.listeners=[],this.firstPlaybackRecorded=!1,this.pendingBatch={},this.hasPendingBatch=!1,this.lastFlushTime=0,this.batchFlushTimerId=null,this.offlineQueue=[],this.socket=e.socket??null,this.reportInterval=e.reportInterval??5e3,this.batchFlushInterval=e.batchFlushInterval??1e3,this.bootMs=e.bootMs??Date.now(),this.logs=e.logs??[],this._stats={_nWaiting:0,_nStalled:0,_nError:0,lastError:null,firstPlayback:null,playbackScore:1,autoplay:null,tracks:null},this.lastReported={nWaiting:0,timeWaiting:0,nStalled:0,timeStalled:0,timeUnpaused:0,nError:0,lastError:null,firstPlayback:null,playbackScore:1,autoplay:null,videoHeight:null,videoWidth:null,playerHeight:null,playerWidth:null,tracks:null,nLog:0}}setSocket(e){const t=!this.socket||this.socket.readyState!==WebSocket.OPEN;this.socket=e,t&&e?.readyState===WebSocket.OPEN&&this.flushOfflineQueue()}flushOfflineQueue(){if(0!==this.offlineQueue.length){for(const e of this.offlineQueue)this.sendReport(e);this.offlineQueue=[]}}getStats(){const e=performance.now();return{nWaiting:this._stats._nWaiting,timeWaiting:Math.round(this.timeWaitingAccum+(this.waitingSince>0?e-this.waitingSince:0)),nStalled:this._stats._nStalled,timeStalled:Math.round(this.timeStalledAccum+(this.stalledSince>0?e-this.stalledSince:0)),timeUnpaused:Math.round(this.timeUnpausedAccum+(this.unpausedSince>0?e-this.unpausedSince:0)),nError:this._stats._nError,lastError:this._stats.lastError,firstPlayback:this._stats.firstPlayback,playbackScore:Math.round(10*this._stats.playbackScore)/10,autoplay:this._stats.autoplay,videoHeight:this.videoElement?.videoHeight??null,videoWidth:this.videoElement?.videoWidth??null,playerHeight:this.containerElement?.clientHeight??null,playerWidth:this.containerElement?.clientWidth??null,tracks:this._stats.tracks,nLog:this.logs.length}}set(e,t){"nWaiting"===e?this._stats._nWaiting=t:"nStalled"===e?this._stats._nStalled=t:"nError"===e?this._stats._nError=t:"lastError"===e?this._stats.lastError=t:"firstPlayback"===e?this._stats.firstPlayback=t:"playbackScore"===e?this._stats.playbackScore=t:"autoplay"===e?this._stats.autoplay=t:"tracks"===e&&(this._stats.tracks=t)}add(e,t=1){"nWaiting"===e?this._stats._nWaiting+=t:"nStalled"===e?this._stats._nStalled+=t:"nError"===e&&(this._stats._nError+=t)}init(e,t){this.videoElement=e,this.containerElement=t??e.parentElement??null,this.firstPlaybackRecorded=!1;const n=()=>{const e=performance.now(),t=!this.firstPlaybackRecorded;t&&(this._stats.firstPlayback=Date.now()-this.bootMs,this.firstPlaybackRecorded=!0),this.waitingSince>0&&(this.timeWaitingAccum+=e-this.waitingSince,this.waitingSince=0),this.stalledSince>0&&(this.timeStalledAccum+=e-this.stalledSince,this.stalledSince=0),0===this.unpausedSince&&(this.unpausedSince=e),t&&(this.reportStats(),this.flushBatch())},i=()=>{this._stats._nWaiting++,0===this.waitingSince&&(this.waitingSince=performance.now())},r=()=>{this._stats._nStalled++,0===this.stalledSince&&(this.stalledSince=performance.now())},s=()=>{this.unpausedSince>0&&(this.timeUnpausedAccum+=performance.now()-this.unpausedSince,this.unpausedSince=0)},a=e=>{this._stats._nError++;const t=e.message||"Unknown error";this._stats.lastError=t,this.reportStats(),this.flushBatch()},o=()=>{this.waitingSince>0&&(this.timeWaitingAccum+=performance.now()-this.waitingSince,this.waitingSince=0)};e.addEventListener("playing",n),e.addEventListener("waiting",i),e.addEventListener("stalled",r),e.addEventListener("pause",s),e.addEventListener("error",a),e.addEventListener("canplay",o),this.listeners=[()=>e.removeEventListener("playing",n),()=>e.removeEventListener("waiting",i),()=>e.removeEventListener("stalled",r),()=>e.removeEventListener("pause",s),()=>e.removeEventListener("error",a),()=>e.removeEventListener("canplay",o)],this.startReporting()}sendInitialReport(e){this.report(e)}setPlaybackScore(e){this._stats.playbackScore=e}setAutoplayStatus(e){this._stats.autoplay=e}setTracks(e){this._stats.tracks=e.join(",")}sendReport(e){if(this.socket&&this.socket.readyState===WebSocket.OPEN)try{this.socket.send(JSON.stringify(e))}catch{this.offlineQueue.length<gt.MAX_OFFLINE_QUEUE_SIZE&&this.offlineQueue.push(e)}else this.offlineQueue.length<gt.MAX_OFFLINE_QUEUE_SIZE&&this.offlineQueue.push(e)}report(e){if(Object.assign(this.pendingBatch,e),this.hasPendingBatch=!0,null===this.batchFlushTimerId){const e=performance.now()-this.lastFlushTime,t=Math.max(0,this.batchFlushInterval-e);this.batchFlushTimerId=this.timers.start(()=>{this.batchFlushTimerId=null,this.flushBatch()},t,"batchFlush")}}flushBatch(){null!==this.batchFlushTimerId&&(this.timers.stop(this.batchFlushTimerId),this.batchFlushTimerId=null),this.hasPendingBatch&&(this.sendReport(this.pendingBatch),this.pendingBatch={},this.hasPendingBatch=!1,this.lastFlushTime=performance.now())}reportStats(){const e=this.getStats(),t={};let n=!1;const i=["nWaiting","timeWaiting","nStalled","timeStalled","timeUnpaused","nError","lastError","firstPlayback","playbackScore","autoplay","videoHeight","videoWidth","playerHeight","playerWidth","tracks","nLog"];for(const r of i){const i=e[r];i!==this.lastReported[r]&&(t[r]=i,this.lastReported[r]=i,n=!0)}const r=this.lastReported.nLog??0;if(this.logs.length>r){const e=this.logs.slice(r);e.length>0&&(t.logs=e,n=!0)}n&&this.report(t),this.scheduleNextReport()}startReporting(){this.scheduleNextReport()}scheduleNextReport(){this.timers.start(()=>{this.reportStats()},this.reportInterval,"report")}sendFinalReport(e){this.reportStats(),this.report({unload:e??null}),this.flushBatch()}destroy(){this.timers.destroy(),this.listeners.forEach(e=>e()),this.listeners=[],this.videoElement=null,this.containerElement=null}log(e){this.logs.push(e)}}gt.MAX_OFFLINE_QUEUE_SIZE=100;const mt={minScore:60,maxStalls:3,minBuffer:2},yt={webrtc:.95,hls:.75,dash:.75,html5:.75,unknown:.75};class bt{constructor(e={}){this.videoElement=null,this.timers=new et,this.stallCount=0,this.lastStallTime=0,this.totalStallMs=0,this.history=[],this.lastBytesLoaded=0,this.lastBytesTime=0,this.listeners=[],this.playbackScoreHistory=[],this.playbackScore=1,this.PLAYBACK_SCORE_AVERAGING_STEPS=10,this.consecutivePoorSamples=0,this.fallbackTriggered=!1,this.options={sampleInterval:e.sampleInterval??500,thresholds:e.thresholds??{},onQualityDegraded:e.onQualityDegraded??(()=>{}),onSample:e.onSample??(()=>{}),protocol:e.protocol??"unknown",playbackScoreThreshold:e.playbackScoreThreshold??null,onFallbackRequest:e.onFallbackRequest??(()=>{}),poorSamplesBeforeFallback:e.poorSamplesBeforeFallback??5},this.thresholds={...mt,...e.thresholds}}setProtocol(e){this.options.protocol=e}getProtocol(){return this.options.protocol}getPlaybackScoreThreshold(){return null!==this.options.playbackScoreThreshold?this.options.playbackScoreThreshold:yt[this.options.protocol]}setPlaybackScoreThreshold(e){this.options.playbackScoreThreshold=e}start(e){this.stop(),this.videoElement=e,this.stallCount=0,this.totalStallMs=0,this.lastStallTime=0,this.history=[],this.lastBytesLoaded=0,this.lastBytesTime=0,this.consecutivePoorSamples=0,this.fallbackTriggered=!1,this.playbackScoreHistory=[],this.playbackScore=1;const t=()=>{this.stallCount++,this.lastStallTime=performance.now()},n=()=>{this.lastStallTime>0&&(this.totalStallMs+=performance.now()-this.lastStallTime,this.lastStallTime=0)},i=()=>{this.lastStallTime>0&&(this.totalStallMs+=performance.now()-this.lastStallTime,this.lastStallTime=0)};e.addEventListener("waiting",t),e.addEventListener("playing",n),e.addEventListener("canplay",i),this.listeners=[()=>e.removeEventListener("waiting",t),()=>e.removeEventListener("playing",n),()=>e.removeEventListener("canplay",i)],this.timers.startInterval(()=>this.sample(),this.options.sampleInterval,"sampling"),this.sample()}stop(){this.timers.destroy(),this.listeners.forEach(e=>e()),this.listeners=[],this.videoElement=null}sample(){const e=this.videoElement;if(!e)return;this.updatePlaybackScore();const t=this.calculateQuality(e);this.history.push(t),this.history.length>20&&this.history.shift(),this.options.onSample(t),(t.score<this.thresholds.minScore||t.stallCount>this.thresholds.maxStalls||t.bufferedAhead<this.thresholds.minBuffer)&&this.options.onQualityDegraded(t),this.isPlaybackPoor()?(this.consecutivePoorSamples++,!this.fallbackTriggered&&this.consecutivePoorSamples>=this.options.poorSamplesBeforeFallback&&(this.fallbackTriggered=!0,console.warn(`[QualityMonitor] Poor playback detected: ${Math.round(100*this.playbackScore)}% (threshold: ${Math.round(100*this.getPlaybackScoreThreshold())}%, protocol: ${this.options.protocol})`),this.options.onFallbackRequest({score:this.playbackScore,consecutivePoorSamples:this.consecutivePoorSamples}))):(this.consecutivePoorSamples=0,this.fallbackTriggered=!1)}calculateQuality(e){const t=Date.now();let n=0;if(e.buffered.length>0)for(let t=0;t<e.buffered.length;t++)if(e.buffered.start(t)<=e.currentTime&&e.buffered.end(t)>e.currentTime){n=e.buffered.end(t)-e.currentTime;break}let i=0,r=0,s=0;if("getVideoPlaybackQuality"in e){const t=e.getVideoPlaybackQuality();i=t.totalVideoFrames,r=t.droppedVideoFrames,s=i>0?r/i*100:0}let a=0;if(e.buffered.length>0&&this.lastBytesTime>0){const n=(t-this.lastBytesTime)/1e3;if(n>0){const t=e.buffered.end(e.buffered.length-1)-e.currentTime;a=t>0?Math.round(1e6*t/n):0}}this.lastBytesTime=t;let o=0;if((e.duration===1/0||!isFinite(e.duration))&&e.buffered.length>0){o=1e3*(e.buffered.end(e.buffered.length-1)-e.currentTime)}return{score:this.calculateScore({bufferedAhead:n,stallCount:this.stallCount,stallDurationMs:this.totalStallMs,frameDropRate:s,latency:o}),bitrate:a,bufferedAhead:n,stallCount:this.stallCount,frameDropRate:s,latency:o,timestamp:t}}calculateScore(e){let t=100;if(e.bufferedAhead<this.thresholds.minBuffer){t-=Math.min(40,20*(this.thresholds.minBuffer-e.bufferedAhead))}const n=5*e.stallCount,i=e.stallDurationMs/1e3*2;t-=Math.min(30,n+i);if(t-=Math.min(20,2*e.frameDropRate),e.latency>5e3){t-=Math.min(10,(e.latency-5e3)/1e3)}return Math.max(0,Math.round(t))}getCurrentQuality(){return this.history.length>0?this.history[this.history.length-1]:null}getAverageQuality(){if(0===this.history.length)return null;const e={score:0,bitrate:0,bufferedAhead:0,stallCount:this.stallCount,frameDropRate:0,latency:0,timestamp:Date.now()};for(const t of this.history)e.score+=t.score,e.bitrate+=t.bitrate,e.bufferedAhead+=t.bufferedAhead,e.frameDropRate+=t.frameDropRate,e.latency+=t.latency;const t=this.history.length;return e.score=Math.round(e.score/t),e.bitrate=Math.round(e.bitrate/t),e.bufferedAhead=e.bufferedAhead/t,e.frameDropRate=e.frameDropRate/t,e.latency=e.latency/t,e}getHistory(){return[...this.history]}resetStallCounters(){this.stallCount=0,this.totalStallMs=0}getTotalStallMs(){return this.totalStallMs}isMonitoring(){return null!==this.videoElement&&this.timers.activeCount>0}getPlaybackScoreValue(){const e=this.videoElement,t={clock:performance.now()/1e3,video:e?.currentTime??0,score:1};if(this.playbackScoreHistory.length>0){const e=this.playbackScoreHistory[this.playbackScoreHistory.length-1];t.score=this.calculatePlaybackScoreFromEntries(e,t)}return t}calculatePlaybackScoreFromEntries(e,t){const n=this.videoElement;let i=1;n&&(i=n.playbackRate||1);const r=t.clock-e.clock,s=t.video-e.video;return r<=0?1:s/r/i}updatePlaybackScore(){const e=this.getPlaybackScoreValue();if(this.playbackScoreHistory.push(e),this.playbackScoreHistory.length<=1)return 1;const t=this.playbackScoreHistory[0],n=this.playbackScoreHistory[this.playbackScoreHistory.length-1];let i=this.calculatePlaybackScoreFromEntries(t,n);return this.playbackScoreHistory.length>this.PLAYBACK_SCORE_AVERAGING_STEPS&&this.playbackScoreHistory.shift(),i=Math.max(i,e.score),this.playbackScore=i,i}getPlaybackScore(){return this.playbackScore}isPlaybackPoor(){return this.playbackScore<this.getPlaybackScoreThreshold()}resetPlaybackScore(){this.playbackScoreHistory=[],this.playbackScore=1}resetFallbackState(){this.consecutivePoorSamples=0,this.fallbackTriggered=!1}getConsecutivePoorSamples(){return this.consecutivePoorSamples}hasFallbackTriggered(){return this.fallbackTriggered}}class vt{constructor(e){if(this.ws=null,this.state="disconnected",this.subscriptions=new Map,this.pendingSubscriptions=new Set,this.reconnectAttempt=0,this.timers=new et,this.messageBuffer=[],this.connectionId=0,this.currentPlaybackTime=0,this.lastFastForwardTime=0,this.timedEventBuffer=new Map,this.config=e,this.debug=e.debug??!1,this.bufferAhead=e.bufferAhead??5,this.maxMessageAge=e.maxMessageAge??5,this.fastForwardInterval=e.fastForwardInterval??5,e.subscriptions)for(const t of e.subscriptions)this.subscribe(t.trackId,t.callback)}connect(){if("connecting"===this.state||"connected"===this.state)return;this.state="connecting",this.log("Connecting...");const e=++this.connectionId;this.timers.start(()=>{"connecting"===this.state&&this.connectionId===e&&this.createWebSocket(e)},vt.CONNECTION_DEBOUNCE_MS,"connect")}createWebSocket(e){try{const t=this.buildWsUrl();this.ws=new WebSocket(t),this.ws.onopen=()=>{if(this.connectionId===e){this.log("Connected"),this.state="connected",this.reconnectAttempt=0;for(const e of this.pendingSubscriptions)this.subscriptions.has(e)||this.subscriptions.set(e,new Set);this.pendingSubscriptions.clear(),this.sendTracksUpdate(),this.sendSeek(this.currentPlaybackTime),this.flushMessageBuffer()}else this.ws?.close()},this.ws.onmessage=e=>{this.handleMessage(e.data)},this.ws.onerror=e=>{this.log("WebSocket error"),console.warn("[MetaTrackManager] WebSocket error:",e)},this.ws.onclose=()=>{this.log("Disconnected"),this.ws=null,"disconnected"!==this.state&&this.scheduleReconnect()}}catch(e){this.log(`Connection error: ${e}`),this.scheduleReconnect()}}disconnect(){this.state="disconnected",this.timers.destroy(),this.ws&&(this.ws.close(),this.ws=null)}subscribe(e,t){const n=!this.subscriptions.has(e);return n&&this.subscriptions.set(e,new Set),this.subscriptions.get(e).add(t),"connected"===this.state&&this.ws&&n?this.sendTracksUpdate():n&&this.pendingSubscriptions.add(e),()=>this.unsubscribe(e,t)}unsubscribe(e,t){const n=this.subscriptions.get(e);n&&(n.delete(t),0===n.size&&(this.subscriptions.delete(e),"connected"===this.state&&this.ws&&this.sendTracksUpdate()))}getSubscribedTracks(){return Array.from(this.subscriptions.keys())}getState(){return this.state}isConnected(){return"connected"===this.state}setPlaybackTime(e){this.currentPlaybackTime=e,this.processTimedEvents()}getPlaybackTime(){return this.currentPlaybackTime}onSeek(e){this.log(`Seek to ${e}s - clearing buffer and notifying server`),this.currentPlaybackTime=e,this.timedEventBuffer.clear(),this.lastFastForwardTime=0,this.sendSeek(e)}processTimedEvents(){const e=1e3*this.currentPlaybackTime;for(const[t,n]of this.timedEventBuffer){const i=[],r=[];for(const t of n)if(t.timestamp<=e){const n=(e-t.timestamp)/1e3;n<=this.maxMessageAge?i.push(t):this.log(`Filtering stale event (${n.toFixed(1)}s old)`)}else r.push(t);for(const e of i)this.dispatchEvent(e);r.length>0?this.timedEventBuffer.set(t,r):this.timedEventBuffer.delete(t)}}addToTimedBuffer(e){const t=e.trackId;this.timedEventBuffer.has(t)||this.timedEventBuffer.set(t,[]);const n=this.timedEventBuffer.get(t);let i=n.length;for(let t=0;t<n.length;t++)if(n[t].timestamp>e.timestamp){i=t;break}for(n.splice(i,0,e);n.length>vt.MESSAGE_BUFFER_SIZE;)n.shift()}needsMoreData(e){const t=this.timedEventBuffer.get(e);if(!t||0===t.length)return!0;return t[t.length-1].timestamp/1e3-this.currentPlaybackTime<this.bufferAhead}fastForward(){const e=Date.now();if(e-this.lastFastForwardTime<1e3*this.fastForwardInterval)return;this.lastFastForwardTime=e,this.log("Fast-forwarding through buffered events");const t=1e3*(this.currentPlaybackTime+this.bufferAhead);for(const[e,n]of this.timedEventBuffer){const i=[],r=[];for(const e of n)if(e.timestamp<=t){(1e3*this.currentPlaybackTime-e.timestamp)/1e3<=this.maxMessageAge&&i.push(e)}else r.push(e);for(const e of i)this.dispatchEvent(e);r.length>0?this.timedEventBuffer.set(e,r):this.timedEventBuffer.delete(e)}this.sendFastForward(this.currentPlaybackTime+this.bufferAhead)}getBufferStatus(){const e={};for(const[t,n]of this.timedEventBuffer)n.length>0&&(e[t]={count:n.length,oldestMs:n[0].timestamp,newestMs:n[n.length-1].timestamp});return e}buildWsUrl(){return`${this.config.mistBaseUrl.replace(/^http:/,"ws:").replace(/^https:/,"wss:").replace(/\/$/,"")}/json_${this.config.streamName}.js?rate=1`}sendTracksUpdate(){if(this.ws&&this.ws.readyState===WebSocket.OPEN){const e=Array.from(this.subscriptions.keys()),t=e.includes("all")?"all":e.join(","),n=JSON.stringify({type:"tracks",meta:t});this.ws.send(n),this.log(`Set tracks: ${t}`)}}sendSeek(e){if(this.ws&&this.ws.readyState===WebSocket.OPEN){const t=Math.round(1e3*e),n=Math.round(1e3*(e+this.bufferAhead)),i=JSON.stringify({type:"seek",seek_time:t,ff_to:n});this.ws.send(i),this.log(`Seek to ${e}s, buffer ahead to ${e+this.bufferAhead}s`)}}sendHold(){this.ws&&this.ws.readyState===WebSocket.OPEN&&(this.ws.send(JSON.stringify({type:"hold"})),this.log("Sent hold"))}sendPlay(){this.ws&&this.ws.readyState===WebSocket.OPEN&&(this.ws.send(JSON.stringify({type:"play"})),this.log("Sent play"))}sendFastForward(e){if(this.ws&&this.ws.readyState===WebSocket.OPEN){const t=JSON.stringify({type:"fast_forward",ff_to:Math.round(1e3*e)});this.ws.send(t),this.log(`Fast-forward to ${e}s`)}}handleMessage(e){try{const t=JSON.parse(e);if("time"in t&&"track"in t&&"data"in t){const e=this.parseMetaTrackEvent(t),n=String(t.track);return void((this.subscriptions.has(n)||this.subscriptions.has("all"))&&("subtitle"===e.type||"chapter"===e.type?(this.addToTimedBuffer(e),this.processTimedEvents()):this.dispatchEvent(e)))}if("type"in t)switch(t.type){case"on_time":if(t.data?.current){const e=t.data.current,n=e-1e3*this.currentPlaybackTime;n>6*this.bufferAhead*1e3&&(this.log(`Server ${n}ms ahead, sending hold`),this.sendHold())}break;case"seek":this.log("Server confirmed seek, clearing buffers"),this.timedEventBuffer.clear();break;default:this.log(`Unknown message type: ${t.type}`)}}catch(e){this.log(`Failed to parse message: ${e}`)}}parseMetaTrackEvent(e){const t=String(e.track),n=Number(e.time),i=e.data??e;return{type:this.detectEventType(i),timestamp:n,trackId:t,data:i}}detectEventType(e){if("object"!=typeof e||null===e)return"unknown";return"text"in e&&("startTime"in e||"start"in e)?"subtitle":"key"in e&&"value"in e?"score":"title"in e&&"startTime"in e?"chapter":"name"in e?"event":"unknown"}dispatchEvent(e){const t=this.subscriptions.get(e.trackId);if(t)for(const n of t)try{n(e)}catch(e){console.error("[MetaTrackManager] Callback error:",e)}}scheduleReconnect(){if("disconnected"===this.state)return;if(this.reconnectAttempt>=vt.MAX_RECONNECT_ATTEMPTS)return this.log("Max reconnect attempts reached"),void(this.state="disconnected");this.state="reconnecting",this.reconnectAttempt++;const e=Math.min(vt.INITIAL_RECONNECT_DELAY*Math.pow(2,this.reconnectAttempt-1),vt.MAX_RECONNECT_DELAY);this.log(`Reconnecting in ${e}ms (attempt ${this.reconnectAttempt})`),this.timers.start(()=>{this.connect()},e,"reconnect")}bufferMessage(e){for(this.messageBuffer.push(e);this.messageBuffer.length>vt.MESSAGE_BUFFER_SIZE;)this.messageBuffer.shift()}flushMessageBuffer(){const e=[...this.messageBuffer];this.messageBuffer=[];for(const t of e)this.dispatchEvent(t)}log(e){this.debug&&console.debug(`[MetaTrackManager] ${e}`)}}vt.CONNECTION_DEBOUNCE_MS=100,vt.MAX_RECONNECT_ATTEMPTS=5,vt.INITIAL_RECONNECT_DELAY=1e3,vt.MAX_RECONNECT_DELAY=3e4,vt.MESSAGE_BUFFER_SIZE=100;const Tt={"ultra-low":{exitLive:2,enterLive:.5},low:{exitLive:5,enterLive:1.5},medium:{exitLive:15,enterLive:5},high:{exitLive:30,enterLive:10}},_t=[.5,1,1.5,2];function Et(e){if(!e)return"medium";const t=e.toLowerCase();return"whep"===t||"webrtc"===t||t.includes("mist/webrtc")?"ultra-low":t.startsWith("ws/")||t.startsWith("wss/")?"low":(t.includes("mpegurl")||t.includes("dash")||t.includes("video/mp4")||t.includes("video/webm"),"medium")}function St(e){return!!e&&e.srcObject instanceof MediaStream}function wt(e){return!e||!St(e)}function kt(e){const{isLive:t,video:n,mistStreamInfo:i,currentTime:r,duration:s,allowMediaStreamDvr:a=!1}=e;if(!t)return{seekableStart:0,liveEdge:s};const o=St(n);if(n?.seekable&&n.seekable.length>0){const e=n.seekable.start(0),t=n.seekable.end(n.seekable.length-1);if(Number.isFinite(e)&&Number.isFinite(t)&&t>e)return{seekableStart:e,liveEdge:t}}if((a||!o)&&i?.meta?.tracks){const e=Object.values(i.meta.tracks);if(e.length>0){const t=e.map(e=>e.firstms).filter(e=>void 0!==e),n=e.map(e=>e.lastms).filter(e=>void 0!==e);if(t.length>0&&n.length>0){return{seekableStart:Math.max(...t)/1e3,liveEdge:Math.min(...n)/1e3}}}}const l=i?.meta?.buffer_window;if(l&&l>0&&r>0){const e=l/1e3;return{seekableStart:Math.max(0,r-e),liveEdge:r}}return{seekableStart:r,liveEdge:r}}function It(e){const{video:t,isLive:n,duration:i,bufferWindowMs:r,playerCanSeek:s}=e;return!(s&&!s())&&(s&&s()?!n||void 0!==r&&r>0:!!t&&(St(t)?void 0!==r&&r>0:!!(t.seekable&&t.seekable.length>0)||(!!(!n&&Number.isFinite(i)&&i>0)||!!(n&&void 0!==r&&r>0))))}function At(e,t,n){const i=e?Et(e):t?"ultra-low":"medium",r=Tt[i];if(("medium"===i||"high"===i)&&n&&n>0){const e=n/1e3;return{exitLive:Math.max(r.exitLive,Math.min(30,e/3)),enterLive:Math.max(r.enterLive,Math.min(10,e/10))}}return r}function Ct(e,t,n,i){if(!Number.isFinite(t)||t<=0)return!0;const r=t-e;return!(i&&r>n.exitLive+.5)&&(!i&&r<n.enterLive-.2||i)}const Dt={"html5/application/vnd.apple.mpegurl":{hrn:"HLS (TS)",player:"hlsjs",supported:!0},"html5/application/vnd.apple.mpegurl;version=7":{hrn:"HLS (CMAF)",player:"hlsjs",supported:!0},"dash/video/mp4":{hrn:"DASH",player:"dashjs",supported:!0},"html5/video/mp4":{hrn:"MP4 progressive",player:"native",supported:!0},"html5/video/webm":{hrn:"WebM progressive",player:"native",supported:!0},"ws/video/mp4":{hrn:"MP4 WebSocket",player:"mews",supported:!0},"wss/video/mp4":{hrn:"MP4 WebSocket (SSL)",player:"mews",supported:!0},"ws/video/webm":{hrn:"WebM WebSocket",player:"mews",supported:!0},"wss/video/webm":{hrn:"WebM WebSocket (SSL)",player:"mews",supported:!0},"ws/video/raw":{hrn:"Raw WebSocket",player:"webcodecs",supported:!0},"wss/video/raw":{hrn:"Raw WebSocket (SSL)",player:"webcodecs",supported:!0},"ws/video/h264":{hrn:"Annex B WebSocket",player:"webcodecs",supported:!0},"wss/video/h264":{hrn:"Annex B WebSocket (SSL)",player:"webcodecs",supported:!0},whep:{hrn:"WebRTC (WHEP)",player:"native",supported:!0},webrtc:{hrn:"WebRTC (WebSocket)",player:"mist-webrtc",supported:!0},"mist/webrtc":{hrn:"MistServer WebRTC",player:"mist-webrtc",supported:!0},"html5/audio/aac":{hrn:"AAC progressive",player:"native",supported:!0},"html5/audio/mp3":{hrn:"MP3 progressive",player:"native",supported:!0},"html5/audio/flac":{hrn:"FLAC progressive",player:"native",supported:!0},"html5/audio/wav":{hrn:"WAV progressive",player:"native",supported:!0},"html5/text/vtt":{hrn:"WebVTT subtitles",player:"track",supported:!0},"html5/text/plain":{hrn:"SRT subtitles",player:"track",supported:!0},"html5/image/jpeg":{hrn:"JPEG thumbnail",player:"image",supported:!0},"html5/text/javascript":{hrn:"JSON metadata",player:"fetch",supported:!0},"html5/video/mpeg":{hrn:"TS progressive",player:"none",supported:!1},"html5/video/h264":{hrn:"Annex B progressive",player:"none",supported:!1},"html5/application/sdp":{hrn:"SDP",player:"none",supported:!1},"html5/application/vnd.ms-sstr+xml":{hrn:"Smooth Streaming",player:"none",supported:!1},"flash/7":{hrn:"FLV",player:"none",supported:!1},"flash/10":{hrn:"RTMP",player:"none",supported:!1},"flash/11":{hrn:"HDS",player:"none",supported:!1},rtsp:{hrn:"RTSP",player:"none",supported:!1},srt:{hrn:"SRT",player:"none",supported:!1},dtsc:{hrn:"DTSC",player:"none",supported:!1}},Rt={HLS:"html5/application/vnd.apple.mpegurl",DASH:"dash/video/mp4",MP4:"html5/video/mp4",WEBM:"html5/video/webm",WHEP:"whep",WebRTC:"webrtc",MIST_WEBRTC:"mist/webrtc",MEWS:"ws/video/mp4",MEWS_WS:"ws/video/mp4",MEWS_WSS:"wss/video/mp4",MEWS_WEBM:"ws/video/webm",MEWS_WEBM_SSL:"wss/video/webm",RAW_WS:"ws/video/raw",RAW_WSS:"wss/video/raw",H264_WS:"ws/video/h264",H264_WSS:"wss/video/h264",AAC:"html5/audio/aac",MP3:"html5/audio/mp3",FLAC:"html5/audio/flac",WAV:"html5/audio/wav",VTT:"html5/text/vtt",SRT:"html5/text/plain",CMAF:"html5/application/vnd.apple.mpegurl;version=7",HLS_CMAF:"html5/application/vnd.apple.mpegurl;version=7",JPEG:"html5/image/jpeg",JPG:"html5/image/jpeg",HTTP:"html5/video/mp4",MIST_HTML:"mist/html",PLAYER_JS:"mist/html"};function xt(e){return Rt[e]||Rt[e.toUpperCase()]||e}function Lt(e){return Dt[e]}function Mt(e){const t=e.toLowerCase();return t.startsWith("avc1")?"H264":t.startsWith("hev1")||t.startsWith("hvc1")?"HEVC":t.startsWith("av01")?"AV1":t.startsWith("vp09")?"VP9":t.startsWith("vp8")?"VP8":t.startsWith("mp4a")?"AAC":t.includes("opus")?"Opus":t.includes("ec-3")||t.includes("ac3")?"AC3":e}function Nt(e,t){const n=e.primary;if(!n)return null;let i={};if(n.outputs)if("string"==typeof n.outputs)try{i=JSON.parse(n.outputs)}catch{console.warn("[buildStreamInfoFromEndpoints] Failed to parse outputs JSON"),i={}}else i=n.outputs;const r=[],s=Object.keys(i);if(s.length){const e=i.MIST_HTML?.url,n=i.PLAYER_JS?.url;((e,n)=>{if(!e&&!n)return;const i={url:e||n||"",type:"mist/html",streamName:t};n&&(i.mistPlayerUrl=n),r.push(i)})(e,n);const a=new Set(["MIST_HTML","PLAYER_JS"]);for(const e of s){if(a.has(e))continue;const t=i[e];if(!t?.url)continue;const n=xt(e),s=Lt(n);s&&!s.supported||r.push({url:t.url,type:n})}}else n&&r.push({url:n.url,type:n.protocol||"mist/html",streamName:t});const a=[];Object.values(i).forEach(e=>(e=>{if(!e)return;const t=e.codecs||[],n=(e,t)=>{a.push({type:e,codec:Mt(t),codecstring:t})};t.forEach(e=>{const t=e.toLowerCase();t.startsWith("avc1")||t.startsWith("hev1")||t.startsWith("hvc1")||t.startsWith("vp")||t.startsWith("av01")?n("video",e):(t.startsWith("mp4a")||t.includes("opus")||t.includes("vorbis")||t.includes("ac3")||t.includes("ec-3"))&&n("audio",e)}),t.length||(e.hasVideo&&a.push({type:"video",codec:"H264",codecstring:"avc1.42E01E"}),e.hasAudio&&a.push({type:"audio",codec:"AAC",codecstring:"mp4a.40.2"}))})(e.capabilities)),a.length||a.push({type:"video",codec:"H264",codecstring:"avc1.42E01E"});const o=!1===e.metadata?.isLive?"vod":"live";return r.length?{source:r,meta:{tracks:a},type:o}:null}class Pt extends Qe{constructor(e){super(),this.state="booting",this.lastEmittedState=null,this.suppressPlayPauseEventsUntil=0,this.gatewayClient=null,this.streamStateClient=null,this.currentPlayer=null,this.videoElement=null,this.container=null,this.endpoints=null,this.streamInfo=null,this.streamState=null,this.mistTracks=null,this.metadataSeed=null,this.metadata=null,this.cleanupFns=[],this.isDestroyed=!1,this.isAttached=!1,this._isBuffering=!1,this._hasPlaybackStarted=!1,this._errorText=null,this._isPassiveError=!1,this._isHoldingSpeed=!1,this._holdSpeed=2,this._isLoopEnabled=!1,this._currentPlayerInfo=null,this._currentSourceInfo=null,this._pendingForceOptions=null,this._errorShownAt=0,this._errorCleared=!1,this._isTransitioning=!1,this._errorCount=0,this._lastErrorTime=0,this._prevStreamIsOnline=void 0,this._isHovering=!1,this._hoverTimeout=null,this._subtitlesEnabled=!1,this._stallStartTime=0,this._seekableStart=0,this._liveEdge=0,this._canSeek=!1,this._isNearLive=!0,this._latencyTier="medium",this._liveThresholds={exitLive:15,enterLive:5},this._buffered=null,this._hasAudio=!0,this._lastVolume=1,this._supportsPlaybackRate=!0,this._isWebRTC=!1,this.abrController=null,this.interactionController=null,this.mistReporter=null,this.qualityMonitor=null,this.metaTrackManager=null,this._playbackQuality=null,this.bootMs=Date.now(),this.config=e,this.playerManager=e.playerManager||ct,this.playerManager.on("protocolSwapped",e=>this.emit("protocolSwapped",e)),this.playerManager.on("playbackFailed",e=>this.emit("playbackFailed",e));try{"undefined"!=typeof localStorage&&(this._isLoopEnabled="true"===localStorage.getItem("frameworks-player-loop"))}catch{}}async attach(e){if(this.isDestroyed)throw new Error("PlayerController is destroyed and cannot be reused");this.isAttached&&(this.log("Already attached, detaching first"),this.detach()),this.container=e,this.isAttached=!0,this.setState("booting");try{if(lt(),await this.resolveEndpoints(),this.isDestroyed||!this.container)return void this.log("[attach] Aborted - controller destroyed during endpoint resolution");if(!this.endpoints?.primary)return void this.setState("no_endpoint",{gatewayStatus:"error"});if(this.startStreamStatePolling(),this.streamInfo=this.buildStreamInfo(this.endpoints),!this.streamInfo||0===this.streamInfo.source.length)return this.setState("error",{error:"No playable sources found"}),void this.emit("error",{error:"No playable sources found"});if(this.isDestroyed||!this.container)return void this.log("[attach] Aborted - controller destroyed before player init");await this.initializePlayer()}catch(e){const t=e instanceof Error?e.message:"Unknown error";this.setState("error",{error:t}),this.emit("error",{error:t}),this.config.mistUrl&&!this.streamStateClient&&(this.log("[attach] Starting stream polling despite resolution failure"),this.startStreamStatePolling())}}detach(){this.cleanup(),this.clearHoverTimeout(),this.isAttached=!1,this.container=null,this.endpoints=null,this.streamInfo=null,this.streamState=null,this.metadataSeed=null,this.metadata=null,this.videoElement=null,this.currentPlayer=null,this.lastEmittedState=null,this._isHovering=!1}destroy(){this.isDestroyed||(this.detach(),this.setState("destroyed"),this.emit("destroyed",void 0),this.removeAllListeners(),this.isDestroyed=!0)}getState(){return this.state}getStreamState(){return this.streamState}getEndpoints(){return this.endpoints}getMetadata(){return this.metadata??null}setMetadataSeed(e){this.metadataSeed=e?{...e}:null,this.refreshMergedMetadata()}refreshMergedMetadata(){const e=this.metadataSeed?{...this.metadataSeed}:null,t=this.streamState?.streamInfo,n=this.streamState?.status;if(!e&&!t)return void(this.metadata=null);const i=e?{...e}:{};t&&(i.mist=this.sanitizeMistInfo(t),t.type&&(i.contentType=t.type,i.isLive="live"===t.type),n&&(i.status=n),t.meta?.duration&&(!i.durationSeconds||i.durationSeconds<=0)&&(i.durationSeconds=Math.round(t.meta.duration)),t.meta?.tracks&&(i.tracks=this.buildMetadataTracks(t.meta.tracks))),this.metadata=i}buildMetadataTracks(e){const t=[];for(const[,n]of Object.entries(e)){const e=n,i=e.type;if("video"!==i&&"audio"!==i&&"meta"!==i)continue;const r="number"==typeof e.bps?Math.round(e.bps):void 0,s="number"==typeof e.fpks?e.fpks/1e3:void 0;t.push({type:i,codec:e.codec,width:e.width,height:e.height,bitrate:r,fps:s,channels:e.channels,sampleRate:e.rate})}return t.length?t:void 0}sanitizeMistInfo(e){const t={error:e.error,on_error:e.on_error,perc:e.perc,type:e.type,hasVideo:e.hasVideo,hasAudio:e.hasAudio,unixoffset:e.unixoffset,lastms:e.lastms};if(e.source&&(t.source=e.source.map(e=>({url:e.url,type:e.type,priority:e.priority,simul_tracks:e.simul_tracks,relurl:e.relurl}))),e.meta&&(t.meta={buffer_window:e.meta.buffer_window,duration:e.meta.duration,mistUrl:e.meta.mistUrl},e.meta.tracks)){const n={};for(const[t,i]of Object.entries(e.meta.tracks))n[t]={type:i.type,codec:i.codec,width:i.width,height:i.height,bps:i.bps,fpks:i.fpks,codecstring:i.codecstring,firstms:i.firstms,lastms:i.lastms,lang:i.lang,idx:i.idx,channels:i.channels,rate:i.rate,size:i.size};t.meta.tracks=n}return t}getStreamInfo(){return this.streamInfo}getVideoElement(){return this.videoElement}getPlayer(){return this.currentPlayer}isReady(){return null!==this.videoElement}isPlaying(){return!(this.currentPlayer?.isPaused?.()??this.videoElement?.paused??!0)}isBuffering(){return this._isBuffering}getError(){return this._errorText}isPassiveError(){return this._isPassiveError}hasPlaybackStarted(){return this._hasPlaybackStarted}isHoldingSpeed(){return this._isHoldingSpeed}getHoldSpeed(){return this._holdSpeed}getCurrentPlayerInfo(){return this._currentPlayerInfo}getCurrentSourceInfo(){return this._currentSourceInfo}getVolume(){return this.videoElement?.volume??1}isLoopEnabled(){return this._isLoopEnabled}isSubtitlesEnabled(){return this._subtitlesEnabled}setSubtitlesEnabled(e){if(this._subtitlesEnabled!==e){if(this._subtitlesEnabled=e,this.videoElement){const t=this.videoElement.textTracks;for(let n=0;n<t.length;n++){const i=t[n];"subtitles"!==i.kind&&"captions"!==i.kind||(i.mode=e?"showing":"hidden")}}this.emit("captionsChange",{enabled:e})}}toggleSubtitles(){this.setSubtitlesEnabled(!this._subtitlesEnabled)}getSeekableStart(){return this._seekableStart}getLiveEdge(){return this._liveEdge}canSeekStream(){return this._canSeek}isNearLive(){return this._isNearLive}getBufferedRanges(){return this.currentPlayer&&"function"==typeof this.currentPlayer.getBufferedRanges?this.currentPlayer.getBufferedRanges():this.videoElement?.buffered??null}getLatencyTier(){return this._latencyTier}getLiveThresholds(){return this._liveThresholds}getBuffered(){return this._buffered}hasAudioTrack(){return this._hasAudio}canAdjustPlaybackRate(){return this._supportsPlaybackRate}getResolvedContentType(){if(this.config.contentType)return this.config.contentType;const e=this.getMetadata(),t=e?.contentType?.toLowerCase();if("live"===t||"clip"===t||"dvr"===t||"vod"===t)return t;const n=this.streamState?.streamInfo?.type;return"live"===n||"vod"===n?n:!0===e?.isLive?"live":!1===e?.isLive?"vod":null}isWebRTCSource(){return this._isWebRTC}isFullscreen(){return"undefined"!=typeof document&&document.fullscreenElement===this.container}isEffectivelyLive(){const e=this.getResolvedContentType()??"live",t=this.getMetadata();return"vod"!==e&&"clip"!==e&&(!1!==t?.isLive&&(("dvr"!==e||"completed"!==t?.dvrStatus)&&("live"===e||"dvr"===e&&"recording"===t?.dvrStatus||!Number.isFinite(this.getDuration()))))}isLive(){return"live"===(this.getResolvedContentType()??"live")}needsColdStart(){const e=this.getResolvedContentType();return!e||"live"!==e}shouldShowIdleScreen(){if(this._hasPlaybackStarted)return!1;if(this.needsColdStart()){return 0===(this.streamInfo?.source??[]).length}return!this.streamState?.isOnline||"ONLINE"!==this.streamState?.status||(!this.streamInfo||0===(this.streamInfo.source?.length??0))}getEffectiveContentType(){return this.isEffectivelyLive()?"live":"vod"}isHovering(){return this._isHovering}shouldShowControls(){return this._isHovering||this.isPaused()||null!==this._errorText}handleMouseEnter(){this.clearHoverTimeout(),this._isHovering||(this._isHovering=!0,this.emit("hoverStart",void 0))}handleMouseLeave(){this.clearHoverTimeout(),this._hoverTimeout=setTimeout(()=>{this._isHovering&&(this._isHovering=!1,this.emit("hoverEnd",void 0))},Pt.HOVER_LEAVE_DELAY_MS)}handleMouseMove(){this._isHovering||(this._isHovering=!0,this.emit("hoverStart",void 0)),this.clearHoverTimeout(),this._hoverTimeout=setTimeout(()=>{this._isHovering&&(this._isHovering=!1,this.emit("hoverEnd",void 0))},Pt.HOVER_HIDE_DELAY_MS)}handleTouchStart(){this.handleMouseEnter(),this.clearHoverTimeout(),this._hoverTimeout=setTimeout(()=>{this._isHovering&&(this._isHovering=!1,this.emit("hoverEnd",void 0))},Pt.HOVER_HIDE_DELAY_MS)}clearHoverTimeout(){this._hoverTimeout&&(clearTimeout(this._hoverTimeout),this._hoverTimeout=null)}getPlaybackRate(){return this.videoElement?.playbackRate??1}getPlaybackQuality(){return this._playbackQuality}getABRMode(){return this.abrController?.getMode()??"auto"}setABRMode(e){this.abrController?.setMode(e)}async play(){this.currentPlayer?.play?await this.currentPlayer.play():this.videoElement&&await this.videoElement.play()}pause(){this.currentPlayer?.pause?this.currentPlayer.pause():this.videoElement?.pause()}seek(e){this.currentPlayer?.seek?this.currentPlayer.seek(e):this.videoElement&&(this.videoElement.currentTime=e)}setVolume(e){if(!this.videoElement)return;const t=Math.max(0,Math.min(1,e));t>0&&(this._lastVolume=t);const n=0===t;this.videoElement.muted!==n&&(this.videoElement.muted=n,this.currentPlayer?.setMuted&&this.currentPlayer.setMuted(n)),this.videoElement.volume=t,this.emit("volumeChange",{volume:t,muted:n})}setMuted(e){this.videoElement&&(e&&this.videoElement.volume>0&&(this._lastVolume=this.videoElement.volume),this.currentPlayer?.setMuted?this.currentPlayer.setMuted(e):this.videoElement.muted=e,e||0!==this.videoElement.volume||(this.videoElement.volume=this._lastVolume),this.emit("volumeChange",{volume:e?0:this.videoElement.volume,muted:e}))}setPlaybackRate(e){this.currentPlayer?.setPlaybackRate?this.currentPlayer.setPlaybackRate(e):this.videoElement&&(this.videoElement.playbackRate=e),this.emit("speedChange",{rate:e})}jumpToLive(){if(this.currentPlayer?.jumpToLive){this.currentPlayer.jumpToLive();const e=this.videoElement;if(e&&!St(e)){const e=this._liveEdge;Number.isFinite(e)&&e>0&&setTimeout(()=>{if(!this.videoElement)return;const t=this.getEffectiveCurrentTime();if(e-t>1)try{this.videoElement.currentTime=e}catch{}},200)}return this._isNearLive=!0,void this.emitSeekingState()}const e=this.videoElement;if(e){if(St(e))return this._isNearLive=!0,void this.emitSeekingState();if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);if(Number.isFinite(t)&&t>0)return e.currentTime=t,this._isNearLive=!0,void this.emitSeekingState()}if(this._liveEdge>0&&Number.isFinite(this._liveEdge))return e.currentTime=this._liveEdge,this._isNearLive=!0,void this.emitSeekingState();Number.isFinite(e.duration)&&e.duration>0&&(e.currentTime=e.duration,this._isNearLive=!0,this.emitSeekingState())}}emitSeekingState(){this.emit("seekingStateChange",{seekableStart:this._seekableStart,liveEdge:this._liveEdge,canSeek:this._canSeek,isNearLive:this._isNearLive,isLive:this.isEffectivelyLive(),isWebRTC:this._isWebRTC,latencyTier:this._latencyTier,buffered:this._buffered,hasAudio:this._hasAudio,supportsPlaybackRate:this._supportsPlaybackRate})}async requestFullscreen(){this.container&&await this.container.requestFullscreen()}async requestPiP(){this.currentPlayer?.requestPiP?await this.currentPlayer.requestPiP():this.videoElement&&"requestPictureInPicture"in this.videoElement&&await this.videoElement.requestPictureInPicture()}getQualities(){return this.currentPlayer?.getQualities?.()??[]}selectQuality(e){this.currentPlayer?.selectQuality?.(e)}getTextTracks(){return this.currentPlayer?.getTextTracks?.()??[]}selectTextTrack(e){this.currentPlayer?.selectTextTrack?.(e)}getEffectiveCurrentTime(){if(this.currentPlayer&&"function"==typeof this.currentPlayer.getCurrentTime){const e=this.currentPlayer.getCurrentTime();if(Number.isFinite(e))return e}return this.videoElement?.currentTime??0}getEffectiveDuration(){if(this.currentPlayer&&"function"==typeof this.currentPlayer.getDuration){const e=this.currentPlayer.getDuration();if(Number.isFinite(e)||e===1/0)return e}return this.videoElement?.duration??NaN}getPlayerSeekableRange(){if(this.currentPlayer&&"function"==typeof this.currentPlayer.getSeekableRange){const e=this.currentPlayer.getSeekableRange();if(e&&Number.isFinite(e.start)&&Number.isFinite(e.end)&&e.end>=e.start)return e}return null}getFrameStepSecondsFromTracks(){const e=this.streamInfo?.meta?.tracks;if(!e||0===e.length)return;const t=e.filter(e=>"video"===e.type&&"number"==typeof e.fpks&&e.fpks>0);if(0===t.length)return;const n=Math.max(...t.map(e=>e.fpks));return!Number.isFinite(n)||n<=0?void 0:1e3/n}deriveBufferWindowMsFromTracks(e){if(!e)return;const t=Object.values(e);if(0===t.length)return;const n=t.map(e=>e.firstms).filter(e=>void 0!==e),i=t.map(e=>e.lastms).filter(e=>void 0!==e);if(0===n.length||0===i.length)return;const r=Math.max(...n),s=Math.min(...i)-r;return!Number.isFinite(s)||s<=0?void 0:s}getCurrentTime(){return this.getEffectiveCurrentTime()}getDuration(){return this.getEffectiveDuration()}isPaused(){return this.currentPlayer?.isPaused?.()??this.videoElement?.paused??!0}suppressPlayPauseEvents(e=200){this.suppressPlayPauseEventsUntil=Date.now()+e}shouldSuppressVideoEvents(){return Date.now()<this.suppressPlayPauseEventsUntil}isMuted(){return this.videoElement?.muted??!0}skipBack(e=10){this.seekBy(-e),this.emit("skipBackward",{seconds:e})}skipForward(e=10){this.seekBy(e),this.emit("skipForward",{seconds:e})}togglePlay(){this.currentPlayer?.isPaused?.()??this.videoElement?.paused??!0?this.currentPlayer?.play?this.currentPlayer.play().catch(()=>{}):this.videoElement?.play().catch(()=>{}):this.currentPlayer?.pause?this.currentPlayer.pause():this.videoElement?.pause()}toggleMute(){this.videoElement&&this.setMuted(!this.videoElement.muted)}seekBy(e){const t=this.getEffectiveCurrentTime(),n=this.getEffectiveDuration(),i=t+e,r=isFinite(n)?n:t+Math.abs(e);this.seek(Math.max(0,Math.min(r,i)))}seekPercent(e){const t=this.getEffectiveDuration();isFinite(t)&&this.seek(t*Math.max(0,Math.min(1,e)))}toggleLoop(){this._isLoopEnabled=!this._isLoopEnabled,this.videoElement&&(this.videoElement.loop=this._isLoopEnabled);try{"undefined"!=typeof localStorage&&localStorage.setItem("frameworks-player-loop",String(this._isLoopEnabled))}catch{}this.emit("loopChange",{isLoopEnabled:this._isLoopEnabled})}setLoopEnabled(e){if(this._isLoopEnabled!==e){this._isLoopEnabled=e,this.videoElement&&(this.videoElement.loop=e);try{"undefined"!=typeof localStorage&&localStorage.setItem("frameworks-player-loop",String(e))}catch{}this.emit("loopChange",{isLoopEnabled:e})}}clearError(){this._errorText=null,this._isPassiveError=!1,this._errorCleared=!0}updateSeekingState(){const e=this.videoElement;if(!e)return;const t=this.getEffectiveCurrentTime(),n=this.getEffectiveDuration(),i=this.isEffectivelyLive(),r=this._currentSourceInfo?.type,s=this.streamState?.streamInfo,a=this._isWebRTC;this._isWebRTC=St(e),this._supportsPlaybackRate=wt(e),this._latencyTier=r?Et(r):this._isWebRTC?"ultra-low":"medium";const o=s?.meta?.buffer_window??this.deriveBufferWindowMsFromTracks(s?.meta?.tracks);this._liveThresholds=At(r,this._isWebRTC,o);const l=this.getPlayerSeekableRange(),u=St(e)&&void 0!==o&&o>0&&"whep"!==r&&"webrtc"!==r,{seekableStart:d,liveEdge:c}=l?{seekableStart:l.start,liveEdge:l.end}:kt({isLive:i,video:e,mistStreamInfo:s,currentTime:t,duration:n,allowMediaStreamDvr:u}),h=this.currentPlayer&&"function"==typeof this.currentPlayer.canSeek?()=>this.currentPlayer.canSeek():void 0;this._canSeek=It({video:e,isLive:i,duration:n,bufferWindowMs:o,playerCanSeek:h}),this._buffered=e.buffered.length>0?e.buffered:null;const f=this._seekableStart!==d||this._liveEdge!==c;this._seekableStart=d,this._liveEdge=c;const p=i&&Number.isFinite(c)&&Number.isFinite(d)&&c>d,g=i&&!p;if(this.interactionController?.updateConfig({isLive:g,frameStepSeconds:this.getFrameStepSecondsFromTracks()}),i){const e=Ct(t,c,this._liveThresholds,this._isNearLive);e!==this._isNearLive&&(this._isNearLive=e)}else this._isNearLive=!0;(f||a!==this._isWebRTC)&&this.emit("seekingStateChange",{seekableStart:this._seekableStart,liveEdge:this._liveEdge,canSeek:this._canSeek,isNearLive:this._isNearLive,isLive:i,isWebRTC:this._isWebRTC,latencyTier:this._latencyTier,buffered:this._buffered,hasAudio:this._hasAudio,supportsPlaybackRate:this._supportsPlaybackRate})}detectAudioTracks(){const e=this.videoElement;if(!e)return;if(e.srcObject instanceof MediaStream){const t=e.srcObject.getAudioTracks();return void(this._hasAudio=t.length>0)}const t=e;t.audioTracks&&void 0!==t.audioTracks.length?this._hasAudio=t.audioTracks.length>0:this._hasAudio=!0}attemptClearError(){if(!this._errorText||this._errorCleared)return;Date.now()-this._errorShownAt>=Pt.AUTO_CLEAR_ERROR_DELAY_MS&&(this._errorCleared=!0,this._errorText=null,this._isPassiveError=!1,this.log("Error auto-cleared after playback resumed"),this.emit("errorCleared",void 0))}shouldAttemptFallback(e){const t=Date.now();if(t-this._lastErrorTime>Pt.HARD_FAILURE_ERROR_WINDOW_MS&&(this._errorCount=0),this._errorCount++,this._lastErrorTime=t,this._errorCount>=Pt.HARD_FAILURE_ERROR_THRESHOLD)return this.log(`Hard failure: repeated errors (${this._errorCount})`),!0;const n=e.toLowerCase();for(const e of Pt.FATAL_ERROR_KEYWORDS)if(n.includes(e))return this.log(`Hard failure: fatal keyword "${e}" detected`),!0;if(this._stallStartTime>0){const e=t-this._stallStartTime;if(e>=Pt.HARD_FAILURE_STALL_THRESHOLD_MS)return this.log(`Hard failure: sustained stall for ${e}ms`),!0}return!1}async setPassiveError(e){if(this._isTransitioning)return void this.log(`Ignoring error during player transition: ${e}`);const t=this.videoElement,n=t&&!t.paused&&t.currentTime>0;if(this.shouldAttemptFallback(e)&&this.playerManager.canAttemptFallback()){this.log("Attempting playback fallback..."),this._isTransitioning=!0;const e=await this.playerManager.tryPlaybackFallback();if(this._isTransitioning=!1,e)return this._errorCount=0,this._errorText=null,this._isPassiveError=!1,void this.log("Fallback succeeded");this.log("Fallback exhausted, showing error UI")}this._errorShownAt=Date.now(),this._errorCleared=!1,this._errorText=e,this._isPassiveError=n??!1,this.setState("error",{error:e}),this.emit("error",{error:e})}async retryWithFallback(){if(!this.playerManager.canAttemptFallback())return!1;this._isTransitioning=!0;const e=await this.playerManager.tryPlaybackFallback();return this._isTransitioning=!1,e&&(this._errorCount=0,this.clearError()),e}async toggleFullscreen(){"undefined"!=typeof document&&(document.fullscreenElement?await document.exitFullscreen().catch(()=>{}):this.container&&await this.container.requestFullscreen().catch(()=>{}))}async togglePictureInPicture(){"undefined"!=typeof document&&(document.pictureInPictureElement?await document.exitPictureInPicture().catch(()=>{}):this.videoElement&&"requestPictureInPicture"in this.videoElement&&await this.videoElement.requestPictureInPicture().catch(()=>{}))}isPiPSupported(){return"undefined"!=typeof document&&(document.pictureInPictureEnabled??!1)}isPiPActive(){return"undefined"!=typeof document&&document.pictureInPictureElement===this.videoElement}async retry(){if(this.container&&this.streamInfo){try{this.playerManager.destroy()}catch{}this.container.innerHTML="",this.videoElement=null,this.currentPlayer=null;try{await this.initializePlayer()}catch(e){const t=e instanceof Error?e.message:"Retry failed";this.setState("error",{error:t}),this.emit("error",{error:t})}}}async getStats(){return this.currentPlayer?.getStats?.()}async getLatency(){return this.currentPlayer?.getLatency?.()}updateConfig(e){void 0!==e.debug&&(this.config.debug=e.debug),void 0!==e.autoplay&&(this.config.autoplay=e.autoplay),void 0!==e.muted&&(this.config.muted=e.muted,this.videoElement&&(this.videoElement.muted=e.muted))}async reload(){if(!this.container||this.isDestroyed)return;const e=this.container;this.detach(),await this.attach(e)}async selectCombo(e){const t=this.container;t&&(this.log(`[selectCombo] One-shot selection: player=${e.forcePlayer}, type=${e.forceType}, source=${e.forceSource}`),this._pendingForceOptions={forcePlayer:e.forcePlayer,forceType:e.forceType,forceSource:e.forceSource},this.detach(),await this.attach(t))}setPlaybackMode(e){this.config.playbackMode=e,this.log(`[setPlaybackMode] Mode set to: ${e}`)}async setDevModeOptions(e){if(e.playbackMode&&this.setPlaybackMode(e.playbackMode),void 0!==e.forcePlayer||void 0!==e.forceType||void 0!==e.forceSource)await this.selectCombo({forcePlayer:e.forcePlayer,forceType:e.forceType,forceSource:e.forceSource});else if(e.playbackMode){const e=this.container;e&&(this.detach(),await this.attach(e))}}getMetadataPayload(){const e=this.videoElement,t=e&&e.buffered.length>0?e.buffered.end(e.buffered.length-1)-e.currentTime:0;return{currentTime:e?.currentTime??0,duration:e?.duration??NaN,bufferedAhead:Math.max(0,t),qualityScore:this._playbackQuality?.score,playerInfo:this._currentPlayerInfo??void 0,sourceInfo:this._currentSourceInfo??void 0,isLive:this.isEffectivelyLive(),isBuffering:this._isBuffering,isPaused:e?.paused??!0,volume:e?.volume??1,muted:e?.muted??!0}}emitMetadataUpdate(){this.emit("metadataUpdate",this.getMetadataPayload())}async resolveEndpoints(){const{endpoints:e,gatewayUrl:t,mistUrl:n,contentId:i,authToken:r}=this.config;if(e?.primary)return this.endpoints=e,this.setMetadataSeed(e.metadata??null),void this.setState("gateway_ready",{gatewayStatus:"ready"});if(n)await this.resolveFromMistServer(n,i);else{if(!t)throw new Error("No endpoints provided and no gatewayUrl or mistUrl configured");await this.resolveFromGateway(t,i,r)}}async resolveFromMistServer(e,t){this.setState("gateway_loading",{gatewayStatus:"loading"});try{let n=e;for(;n.endsWith("/");)n=n.slice(0,-1);const i=`${n}/json_${encodeURIComponent(t)}.js`;this.log(`[resolveFromMistServer] Fetching ${i}`);const r=await fetch(i,{cache:"no-store"});if(!r.ok)throw new Error(`MistServer HTTP ${r.status}`);let s=await r.text();const a=s.match(/^[^(]+\(([\s\S]*)\);?$/);a&&(s=a[1]);const o=JSON.parse(s);if(o.error)throw new Error(o.error);const l=Array.isArray(o.source)?o.source:[];if(0===l.length)throw new Error("No sources available from MistServer");const u={};for(const e of l){const t=this.mapMistTypeToProtocol(e.type);u[t]||(u[t]={protocol:t,url:e.url})}const d=l.filter(e=>!e.url.startsWith("ws://")),c=d.length>0?this.selectBestSource(d):l[0],h={nodeId:`mist-${t}`,protocol:this.mapMistTypeToProtocol(c.type),url:c.url,baseUrl:e,outputs:u};if(this.endpoints={primary:h,fallbacks:[]},this.setMetadataSeed(null),o.meta?.tracks&&"object"==typeof o.meta.tracks){const e=this.parseMistTracks(o.meta.tracks);this.mistTracks=e.length>0?e:null,this.log(`[resolveFromMistServer] Parsed ${e.length} tracks from MistServer`)}this.setState("gateway_ready",{gatewayStatus:"ready"}),this.log(`[resolveFromMistServer] Resolved: ${h.protocol} @ ${h.url}`)}catch(e){const t=e instanceof Error?e.message:"MistServer resolution failed";throw this.setState("gateway_error",{gatewayStatus:"error",error:t}),e}}mapMistTypeToProtocol(e){return"ws/video/raw"===e?"RAW_WS":"wss/video/raw"===e?"RAW_WSS":"ws/video/h264"===e?"H264_WS":"wss/video/h264"===e?"H264_WSS":"ws/video/webm"===e?"MEWS_WEBM":"wss/video/webm"===e?"MEWS_WEBM_SSL":e.startsWith("ws/")?"MEWS_WS":e.startsWith("wss/")?"MEWS_WSS":e.includes("webrtc")?"MIST_WEBRTC":e.includes("mpegurl")||e.includes("m3u8")?"HLS":e.includes("dash")||e.includes("mpd")?"DASH":e.includes("whep")?"WHEP":e.includes("mp4")?"MP4":e.includes("webm")?"WEBM":e}selectBestSource(e){const t={HLS:1,DASH:2,MP4:3,WEBM:4,WHEP:5,MIST_WEBRTC:6,MEWS_WS:99};return e.sort((e,n)=>(t[this.mapMistTypeToProtocol(e.type)]??50)-(t[this.mapMistTypeToProtocol(n.type)]??50))[0]}async resolveFromGateway(e,t,n){this.setState("gateway_loading",{gatewayStatus:"loading"}),this.gatewayClient=new Ze({gatewayUrl:e,contentId:t,authToken:n});const i=this.gatewayClient.on("statusChange",({status:e,error:t})=>{"error"===e&&this.setState("gateway_error",{gatewayStatus:e,error:t})});this.cleanupFns.push(i),this.cleanupFns.push(()=>this.gatewayClient?.destroy());try{this.endpoints=await this.gatewayClient.resolve(),this.setMetadataSeed(this.endpoints?.metadata??null),this.setState("gateway_ready",{gatewayStatus:"ready"})}catch(e){const t=e instanceof Error?e.message:"Gateway resolution failed";throw this.setState("gateway_error",{gatewayStatus:"error",error:t}),e}}startStreamStatePolling(){const{contentId:e,mistUrl:t}=this.config,n=this.getResolvedContentType();if(null==n){if(!t)return}else if("live"!==n&&"dvr"!==n)return;if("dvr"===n){const e=this.getMetadata()?.dvrStatus;if(e&&"recording"!==e)return}const i=this.endpoints?.primary?.baseUrl||t;if(!i)return;const r=this.getMetadata(),s=r?.contentId||e,a=this.isEffectivelyLive(),o=this.isEffectivelyLive()?3e3:5e3;this.streamStateClient=new nt({mistBaseUrl:i,streamName:s,useWebSocket:a,pollInterval:o});const l=this.streamStateClient.on("stateChange",({state:e})=>{const t=this._prevStreamIsOnline,n=e.isOnline;if(this.streamState=e,this._prevStreamIsOnline=n,e.streamInfo?.meta?.tracks&&this.streamInfo){const t=this.parseMistTracks(e.streamInfo.meta.tracks);t.length>0&&(this.streamInfo.meta.tracks=t,this.log(`[stateChange] Updated ${t.length} tracks from MistServer`))}this.refreshMergedMetadata(),this.emit("streamStateChange",{state:e}),!1===t&&!0===n&&this.isEffectivelyLive()&&(this.log("Stream came online, triggering auto-play"),this.videoElement?this.videoElement.play().catch(e=>this.log(`Auto-play on online transition failed: ${e}`)):this.container&&!this.endpoints?.primary&&(this.log("Stream came online, attempting late initialization"),this.initializeLateFromStreamState(e.streamInfo)))});this.cleanupFns.push(l),this.cleanupFns.push(()=>this.streamStateClient?.destroy()),this.streamStateClient.start()}async initializeLateFromStreamState(e){if(e?.source&&Array.isArray(e.source)&&0!==e.source.length)if(this.container&&this.config.mistUrl)try{const t=e.source,n=this.config.mistUrl,i=this.config.contentId,r={};for(const e of t){const t=this.mapMistTypeToProtocol(e.type);r[t]||(r[t]={protocol:t,url:e.url})}const s=t.filter(e=>!e.url.startsWith("ws://")),a=s.length>0?this.selectBestSource(s):t[0],o={nodeId:`mist-${i}`,protocol:this.mapMistTypeToProtocol(a.type),url:a.url,baseUrl:n,outputs:r};if(this.endpoints={primary:o,fallbacks:[]},this.setMetadataSeed(this.endpoints.metadata??null),e.meta?.tracks&&"object"==typeof e.meta.tracks){const t=this.parseMistTracks(e.meta.tracks);this.mistTracks=t.length>0?t:null,this.log(`[initializeLateFromStreamState] Parsed ${t.length} tracks`)}if(this.setState("gateway_ready",{gatewayStatus:"ready"}),this.log(`[initializeLateFromStreamState] Built endpoints from stream state: ${o.protocol}`),this.streamInfo=this.buildStreamInfo(this.endpoints),!this.streamInfo||0===this.streamInfo.source.length)return void this.setState("error",{error:"No playable sources found"});await this.initializePlayer(),this.log("[initializeLateFromStreamState] Player initialized successfully")}catch(e){const t=e instanceof Error?e.message:"Late initialization failed";this.log(`[initializeLateFromStreamState] Failed: ${t}`),this.setState("error",{error:t})}else this.log("[initializeLateFromStreamState] Missing container or mistUrl");else this.log("[initializeLateFromStreamState] No sources in stream info")}buildStreamInfo(e){const t=Nt(e,this.config.contentId);return t&&this.mistTracks&&this.mistTracks.length>0&&(t.meta.tracks=this.mistTracks,this.log(`[buildStreamInfo] Using ${this.mistTracks.length} tracks from MistServer`)),t}parseMistTracks(e){const t=[];for(const[,n]of Object.entries(e)){const e=n,i=e.type;"video"!==i&&"audio"!==i&&"meta"!==i||t.push({type:i,codec:e.codec,codecstring:e.codecstring,init:e.init,idx:e.idx,width:e.width,height:e.height,fpks:e.fpks,channels:e.channels,rate:e.rate,size:e.size})}return t}async initializePlayer(){const e=this.container,t=this.streamInfo;if(this.log(`[initializePlayer] Starting - container: ${!!e}, streamInfo: ${!!t}, sources: ${t?.source?.length??0}`),!e||!t)throw new Error("Container or streamInfo not available");this.log(`[initializePlayer] Sources: ${JSON.stringify(t.source.map(e=>({type:e.type,url:e.url.slice(0,60)+"..."})))}`),this.log(`[initializePlayer] Tracks: ${t.meta.tracks.map(e=>`${e.type}:${e.codec}`).join(", ")}`);const{autoplay:n,muted:i,controls:r,poster:s}=this.config;e.innerHTML="";const a=e=>{const t=this.playerManager.getRegisteredPlayers().find(t=>t.capability.shortname===e.player);t&&(this._currentPlayerInfo={name:t.capability.name,shortname:t.capability.shortname}),e.source&&(this._currentSourceInfo={url:e.source.url,type:e.source.type}),this.setState("connecting",{selectedPlayer:e.player,selectedProtocol:(e.source?.type||"").toString(),endpointUrl:e.source?.url}),this.emit("playerSelected",{player:e.player,source:e.source,score:e.score})};try{this.playerManager.on?.("playerSelected",a)}catch{}this.cleanupFns.push(()=>{try{this.playerManager.off?.("playerSelected",a)}catch{}}),this.setState("selecting_player");const o={autoplay:!1!==n,muted:!1!==i,controls:!1!==r,poster:s,debug:this.config.debug,onReady:e=>{if(!this.isDestroyed&&this.container){try{this.container&&!this.container.contains(e)&&(this.log("[initializePlayer] Video element was detached; re-attaching to container"),this.container.appendChild(e))}catch{}this.videoElement=e,this.currentPlayer=this.playerManager.getCurrentPlayer(),this.setupVideoEventListeners(e),this.initializeSubControllers(),this.emit("ready",{videoElement:e})}else this.log("[initializePlayer] onReady callback aborted - controller destroyed")},onTimeUpdate:e=>{if(!this.isDestroyed){try{this.container&&this.videoElement&&!this.container.contains(this.videoElement)&&(this.log("[initializePlayer] Video element was detached during playback; re-attaching to container"),this.container.appendChild(this.videoElement))}catch{}this.emit("timeUpdate",{currentTime:this.getEffectiveCurrentTime(),duration:this.getEffectiveDuration()})}},onError:e=>{if(this.isDestroyed)return;const t="string"==typeof e?e:String(e);this.setPassiveError(t)}},l=this._pendingForceOptions;this._pendingForceOptions=null;const u={forcePlayer:l?.forcePlayer??this.config.forcePlayer,forceType:l?.forceType??this.config.forceType,forceSource:l?.forceSource??this.config.forceSource,playbackMode:this.config.playbackMode};this.log("[initializePlayer] Calling playerManager.initializePlayer..."),this.log(`[initializePlayer] Manager options: ${JSON.stringify(u)} (pending force: ${l?"yes":"no"})`);try{await this.playerManager.initializePlayer(e,t,o,u),this.log("[initializePlayer] Player initialized successfully")}catch(e){throw this.log(`[initializePlayer] Player initialization FAILED: ${e}`),e}}setupVideoEventListeners(e){e.loop=this._isLoopEnabled;const t=()=>{this._isBuffering=!0,0===this._stallStartTime&&(this._stallStartTime=Date.now(),this.log("Stall started")),this.setState("buffering")},n=()=>{this.shouldSuppressVideoEvents()||(this._isBuffering=!1,this._hasPlaybackStarted=!0,this._stallStartTime>0&&(this.log(`Stall cleared after ${Date.now()-this._stallStartTime}ms`),this._stallStartTime=0),this.setState("playing"),this.attemptClearError())},i=()=>{this._isBuffering=!1,this._stallStartTime=0,this.setState("playing"),this.attemptClearError()},r=()=>{this.shouldSuppressVideoEvents()||this.setState("paused")},s=()=>this.setState("ended"),a=()=>{const t=e.error&&e.error.message||"Playback error";this.setPassiveError(t)},o=()=>{this.emit("timeUpdate",{currentTime:this.getEffectiveCurrentTime(),duration:this.getEffectiveDuration()}),this.updateSeekingState(),this.getEffectiveCurrentTime()>0&&this.attemptClearError()},l=()=>{this.emit("timeUpdate",{currentTime:this.getEffectiveCurrentTime(),duration:this.getEffectiveDuration()}),this.updateSeekingState()},u=()=>{this._buffered=e.buffered,this.updateSeekingState()},d=()=>{this.detectAudioTracks(),this._isWebRTC=St(e),this._supportsPlaybackRate=!this._isWebRTC,this.updateSeekingState()},c=()=>{const e=document.fullscreenElement===this.container;this.emit("fullscreenChange",{isFullscreen:e})},h=()=>this.emit("pipChange",{isPiP:!0}),f=()=>this.emit("pipChange",{isPiP:!1}),p=()=>{this.emit("volumeChange",{volume:e.volume,muted:e.muted})};e.addEventListener("waiting",t),e.addEventListener("playing",n),e.addEventListener("canplay",i),e.addEventListener("pause",r),e.addEventListener("ended",s),e.addEventListener("error",a),e.addEventListener("timeupdate",o),e.addEventListener("durationchange",l),e.addEventListener("progress",u),e.addEventListener("loadedmetadata",d),e.addEventListener("volumechange",p),e.addEventListener("enterpictureinpicture",h),e.addEventListener("leavepictureinpicture",f),document.addEventListener("fullscreenchange",c),this.cleanupFns.push(()=>{e.removeEventListener("waiting",t),e.removeEventListener("playing",n),e.removeEventListener("canplay",i),e.removeEventListener("pause",r),e.removeEventListener("ended",s),e.removeEventListener("error",a),e.removeEventListener("timeupdate",o),e.removeEventListener("durationchange",l),e.removeEventListener("progress",u),e.removeEventListener("loadedmetadata",d),e.removeEventListener("volumechange",p),e.removeEventListener("enterpictureinpicture",h),e.removeEventListener("leavepictureinpicture",f),document.removeEventListener("fullscreenchange",c)})}initializeSubControllers(){this.videoElement&&this.container&&(this.initializeABRController(),this.initializeQualityMonitor(),this.initializeInteractionController(),this.initializeMistReporter(),this.initializeMetaTrackManager())}initializeABRController(){const e=this.currentPlayer;e&&this.videoElement&&(this.abrController=new ft({options:{mode:"auto"},getQualities:()=>e.getQualities?.()??[],selectQuality:t=>e.selectQuality?.(t),getCurrentQuality:()=>{const t=e.getQualities?.()??[],n=e.getCurrentQuality?.();return t.find(e=>e.id===n)??null},getBandwidthEstimate:async()=>{if(!this.currentPlayer?.getStats)return 0;try{const e=await this.currentPlayer.getStats();return e?.bandwidthEstimate?e.bandwidthEstimate:e?.averageThroughput?e.averageThroughput:0}catch{return 0}},debug:this.config.debug}),this.abrController.start(this.videoElement),this.cleanupFns.push(()=>{this.abrController?.stop(),this.abrController=null}))}initializeQualityMonitor(){if(!this.videoElement)return;this.qualityMonitor=new bt({sampleInterval:1e3}),this.qualityMonitor.start(this.videoElement);const e=setInterval(()=>{if(this.qualityMonitor&&(this._playbackQuality=this.qualityMonitor.getCurrentQuality(),this.mistReporter&&this._playbackQuality)){const e=this._playbackQuality.score/100;this.mistReporter.setPlaybackScore(e)}},1e3);this.cleanupFns.push(()=>{clearInterval(e),this.qualityMonitor?.stop(),this.qualityMonitor=null})}initializeInteractionController(){if(!this.container||!this.videoElement)return;const e=this.isEffectivelyLive(),t=e&&Number.isFinite(this._liveEdge)&&Number.isFinite(this._seekableStart)&&this._liveEdge>this._seekableStart,n=e&&!t,i=this.container.closest('[data-player-container="true"]')??this.container;this.interactionController=new pt({container:i,videoElement:this.videoElement,isLive:n,isPaused:()=>this.currentPlayer?.isPaused?.()??this.videoElement?.paused??!0,frameStepSeconds:this.getFrameStepSecondsFromTracks(),onFrameStep:(e,t)=>{const n=this.currentPlayer??this.playerManager.getCurrentPlayer(),i=n?.capability?.shortname??this._currentPlayerInfo?.shortname??"unknown",r="function"==typeof n?.frameStep;return this.log(`[interaction] frameStep dir=${e} player=${i} hasFrameStep=${r}`),"webcodecs"===i&&this.suppressPlayPauseEvents(250),!!(r&&n&&n.frameStep)&&(n.frameStep(e,t),!0)},onPlayPause:()=>this.togglePlay(),onSeek:e=>{this._isHoldingSpeed&&(this._isHoldingSpeed=!1,this.emit("holdSpeedEnd",void 0)),this.seekBy(e),e>0?this.emit("skipForward",{seconds:e}):this.emit("skipBackward",{seconds:Math.abs(e)})},onVolumeChange:e=>{if(this.videoElement){const t=Math.max(0,Math.min(1,this.videoElement.volume+e));this.videoElement.volume=t,this.emit("volumeChange",{volume:t,muted:this.videoElement.muted})}},onMuteToggle:()=>this.toggleMute(),onFullscreenToggle:()=>this.toggleFullscreen(),onCaptionsToggle:()=>{this.toggleSubtitles()},onSpeedChange:(e,t)=>{const n=this._isHoldingSpeed;this._isHoldingSpeed=t,this._holdSpeed=e,this.setPlaybackRate(e),t&&!n?this.emit("holdSpeedStart",{speed:e}):!t&&n&&this.emit("holdSpeedEnd",void 0)},onSeekPercent:e=>this.seekPercent(e),speedHoldValue:this._holdSpeed}),this.interactionController.attach(),this.cleanupFns.push(()=>{this.interactionController?.detach(),this.interactionController=null})}initializeMistReporter(){if(!this.streamStateClient)return;const e=this.streamStateClient.getSocket();e&&(this.mistReporter=new gt({socket:e,bootMs:this.bootMs,reportInterval:5e3}),this.videoElement&&this.mistReporter.init(this.videoElement,this.container??void 0),this._currentSourceInfo&&this.mistReporter.sendInitialReport({player:this._currentPlayerInfo?.shortname||"unknown",sourceType:this._currentSourceInfo.type,sourceUrl:this._currentSourceInfo.url,pageUrl:"undefined"!=typeof window?window.location.href:""}),this.cleanupFns.push(()=>{this.mistReporter?.sendFinalReport("unmount"),this.mistReporter?.destroy(),this.mistReporter=null}))}initializeMetaTrackManager(){const e=this.endpoints?.primary?.baseUrl;if(e){if(this.metaTrackManager=new vt({mistBaseUrl:e,streamName:this.config.contentId,debug:this.config.debug}),this.metaTrackManager.connect(),this.videoElement){const e=()=>{this.videoElement&&this.metaTrackManager&&this.metaTrackManager.setPlaybackTime(this.videoElement.currentTime)},t=()=>{this.videoElement&&this.metaTrackManager&&this.metaTrackManager.onSeek(this.videoElement.currentTime)};this.videoElement.addEventListener("timeupdate",e),this.videoElement.addEventListener("seeking",t),this.cleanupFns.push(()=>{this.videoElement?.removeEventListener("timeupdate",e),this.videoElement?.removeEventListener("seeking",t)})}this.cleanupFns.push(()=>{this.metaTrackManager?.disconnect(),this.metaTrackManager=null})}}cleanup(){this.cleanupFns.forEach(e=>{try{e()}catch{}}),this.cleanupFns=[];try{this.playerManager.destroy()}catch{}}setState(e,t){this.state=e,this.lastEmittedState!==e&&(this.lastEmittedState=e,this.emit("stateChange",{state:e,context:t}))}log(e){this.config.debug&&console.log(`[PlayerController] ${e}`)}}Pt.HOVER_HIDE_DELAY_MS=3e3,Pt.HOVER_LEAVE_DELAY_MS=200,Pt.HARD_FAILURE_STALL_THRESHOLD_MS=3e4,Pt.AUTO_CLEAR_ERROR_DELAY_MS=2e3,Pt.HARD_FAILURE_ERROR_THRESHOLD=5,Pt.HARD_FAILURE_ERROR_WINDOW_MS=6e4,Pt.FATAL_ERROR_KEYWORDS=["fatal","network error","media error","decode error","source not supported"];class Ot extends Qe{constructor(e){super(),this.ws=null,this.timeoutId=null,this._state="disconnected",this.seekPromise=null,this.url=e.url.replace(/^http/,"ws"),this.timeout=e.timeout??5e3,this.onLog=e.onLog??(()=>{})}get state(){return this._state}get isConnected(){return"connected"===this._state}connect(){if(!this.ws||this.ws.readyState!==WebSocket.OPEN&&this.ws.readyState!==WebSocket.CONNECTING){this._state="connecting",this.onLog(`Connecting to ${this.url}`);try{this.ws=new WebSocket(this.url)}catch(e){return this.onLog(`Failed to create WebSocket: ${e}`),void(this._state="disconnected")}this.timeoutId=setTimeout(()=>{this.ws&&this.ws.readyState===WebSocket.CONNECTING&&(this.onLog("WebSocket connection timeout"),this.ws.close(),this._state="disconnected",this.emit("error",{message:"Connection timeout"}))},this.timeout),this.ws.onopen=()=>{this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),this._state="connected",this.onLog("WebSocket connected"),this.emit("connected",void 0)},this.ws.onmessage=e=>{try{const t=JSON.parse(e.data);this.handleMessage(t)}catch(e){this.onLog(`Failed to parse message: ${e}`)}},this.ws.onclose=e=>{this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),this._state="closed",this.onLog(`WebSocket closed (code: ${e.code})`),this.emit("disconnected",{code:e.code})},this.ws.onerror=e=>{this.onLog(`WebSocket error: ${e}`)}}else this.onLog("Already connected or connecting")}handleMessage(e){const t=e.type;switch(t){case"on_connected":break;case"on_disconnected":this._state="disconnected",this.emit("disconnected",{code:e.code||0});break;case"on_answer_sdp":this.emit("answer_sdp",{result:e.result,answer_sdp:e.answer_sdp});break;case"on_time":this.emit("time_update",{current:e.current,end:e.end,begin:e.begin,tracks:e.tracks,paused:e.paused,live_point:e.live_point});break;case"seek":this.emit("seeked",{live_point:e.live_point}),this.seekPromise&&(this.seekPromise.resolve("Seeked"),this.seekPromise=null);break;case"set_speed":this.emit("speed_changed",{play_rate:e.play_rate,play_rate_curr:e.play_rate_curr});break;case"on_stop":this.emit("stopped",void 0);break;case"on_error":this.emit("error",{message:e.message});break;default:this.onLog(`Unhandled message type: ${t}`)}}send(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)return this.onLog("Cannot send: WebSocket not connected"),!1;try{return this.ws.send(JSON.stringify(e)),!0}catch(e){return this.onLog(`Failed to send message: ${e}`),!1}}sendOfferSDP(e){return this.send({type:"offer_sdp",offer_sdp:e})}seek(e){return new Promise((t,n)=>{if(!this.isConnected)return void n("Not connected");this.seekPromise&&this.seekPromise.reject("New seek requested");const i="live"===e?"live":1e3*e;this.send({type:"seek",seek_time:i}),this.seekPromise={resolve:t,reject:n}})}pause(){return this.send({type:"hold"})}stop(){return this.send({type:"stop"})}setTracks(e){return this.send({type:"tracks",...e})}setSpeed(e){return this.send({type:"set_speed",play_rate:e})}close(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),this.seekPromise&&(this.seekPromise.reject("Connection closed"),this.seekPromise=null),this.ws&&(this._state="closed",this.ws.close(),this.ws=null)}destroy(){this.close(),this.removeAllListeners()}}class Ft{constructor(e,t={}){this.lastProgressTime=0,this.lastBufferEnd=0,this.listeners=[],this._calculatedDuration=0,this.video=e,this.options={constrainSeek:t.constrainSeek??!0,liveOffset:t.liveOffset??0,onDurationChange:t.onDurationChange??(()=>{})},this.setupListeners(),this.updateDuration()}isLive(){const e=this.video.duration;return!isFinite(e)||e===1/0}getDuration(){return this.isLive()?this._calculatedDuration:this.video.duration}getBufferEnd(){const e=this.video.buffered;if(0===e.length)return 0;for(let t=0;t<e.length;t++)if(e.start(t)<=this.video.currentTime&&e.end(t)>this.video.currentTime)return e.end(t);return e.end(e.length-1)}getLiveEdge(){return this.getBufferEnd()-this.options.liveOffset}getLatency(){return this.isLive()?Math.max(0,this.getLiveEdge()-this.video.currentTime):0}seek(e){if(!this.isLive()||!this.options.constrainSeek)return void(this.video.currentTime=e);const t=this.video.buffered;if(0===t.length)return void(this.video.currentTime=e);const n=t.start(0),i=this.getLiveEdge(),r=Math.max(n,Math.min(e,i));this.video.currentTime=r}jumpToLive(){this.isLive()&&(this.video.currentTime=this.getLiveEdge())}isAtLiveEdge(e=2){return!!this.isLive()&&this.getLatency()<=e}getState(){return{duration:this.getDuration(),isLive:this.isLive(),bufferEnd:this.getBufferEnd(),elapsed:this.lastProgressTime>0?(Date.now()-this.lastProgressTime)/1e3:0}}updateDuration(){if(!this.isLive())return void(this._calculatedDuration=this.video.duration);const e=this.getBufferEnd(),t=Date.now(),n=e+(this.lastProgressTime>0?(t-this.lastProgressTime)/1e3:0);Math.abs(n-this._calculatedDuration)>.1&&(this._calculatedDuration=n,this.options.onDurationChange(n)),this.lastBufferEnd=e}setupListeners(){const e=()=>{this.lastProgressTime=Date.now(),this.updateDuration()},t=()=>{this.updateDuration()},n=()=>{this.updateDuration()},i=()=>{this.updateDuration()};this.video.addEventListener("progress",e),this.video.addEventListener("timeupdate",t),this.video.addEventListener("durationchange",n),this.video.addEventListener("loadedmetadata",i),this.listeners=[()=>this.video.removeEventListener("progress",e),()=>this.video.removeEventListener("timeupdate",t),()=>this.video.removeEventListener("durationchange",n),()=>this.video.removeEventListener("loadedmetadata",i)]}destroy(){this.listeners.forEach(e=>e()),this.listeners=[]}}function Ut(e,t){if(!t)return e;let n;if("object"==typeof t){const i=Object.entries(t).filter(([,e])=>null!=e).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(String(t))}`);if(0===i.length)return e;n=i.join("&")}else n=t,(n.startsWith("?")||n.startsWith("&"))&&(n=n.slice(1));if(!n)return e;const i=e.includes("?")?"&":"?";return`${e}${i}${n}`}function zt(e){const t={};try{new URL(e).searchParams.forEach((e,n)=>{t[n]=e})}catch{const n=e.indexOf("?");if(-1===n)return t;const i=e.slice(n+1).split("&");for(const e of i){const[n,i]=e.split("=");n&&(t[decodeURIComponent(n)]=i?decodeURIComponent(i):"")}}return t}function Bt(e){const t=e.indexOf("?");return-1===t?e:e.slice(0,t)}function jt(e){if(!Number.isFinite(e)||e<0)return"LIVE";const t=Math.floor(e),n=Math.floor(t/3600),i=Math.floor(t%3600/60),r=t%60;return n>0?`${n}:${String(i).padStart(2,"0")}:${String(r).padStart(2,"0")}`:`${String(i).padStart(2,"0")}:${String(r).padStart(2,"0")}`}function $t(e){const{isLive:t,currentTime:n,duration:i,liveEdge:r,seekableStart:s,unixoffset:a}=e;if(t){if(a&&a>0){const e=new Date(a+1e3*n);return o=e,`${String(o.getHours()).padStart(2,"0")}:${String(o.getMinutes()).padStart(2,"0")}:${String(o.getSeconds()).padStart(2,"0")}`}if(r-s>0){const e=r-n;return e<1?"LIVE":`-${jt(Math.abs(e))}`}return"LIVE"}var o;return Number.isFinite(i)&&i>0?`${jt(n)} / ${jt(i)}`:jt(n)}const qt={state:"booting",streamState:null,endpoints:null,metadata:null,videoElement:null,currentTime:0,duration:NaN,isPlaying:!1,isPaused:!0,isBuffering:!1,isMuted:!0,volume:1,error:null,errorDetails:null,isPassiveError:!1,hasPlaybackStarted:!1,isHoldingSpeed:!1,holdSpeed:2,isHovering:!1,shouldShowControls:!1,isLoopEnabled:!1,isFullscreen:!1,isPiPActive:!1,isEffectivelyLive:!1,shouldShowIdleScreen:!0,currentPlayerInfo:null,currentSourceInfo:null,playbackQuality:null,subtitlesEnabled:!1,qualities:[],textTracks:[],streamInfo:null,toast:null};class Ht{constructor(e){this.controller=null,this.unsubs=[],this.currentConfig=null,this.s={...qt},this.host=e,e.addController(this)}configure(e){this.currentConfig=e}async attach(e){if(!this.currentConfig)return;this.teardown();const t=new Pt({contentId:this.currentConfig.contentId,contentType:this.currentConfig.contentType,endpoints:this.currentConfig.endpoints,gatewayUrl:this.currentConfig.gatewayUrl,mistUrl:this.currentConfig.mistUrl,authToken:this.currentConfig.authToken,autoplay:this.currentConfig.autoplay,muted:this.currentConfig.muted,controls:this.currentConfig.controls,poster:this.currentConfig.poster,debug:this.currentConfig.debug});this.controller=t,this.subscribeToEvents(t),this.update({isLoopEnabled:t.isLoopEnabled()});try{await t.attach(e)}catch(e){console.warn("[PlayerControllerHost] Attach failed:",e)}}hostConnected(){}hostDisconnected(){this.teardown(),this.s={...qt}}teardown(){this.unsubs.forEach(e=>e()),this.unsubs=[],this.controller?.destroy(),this.controller=null}update(e){Object.assign(this.s,e),this.host.requestUpdate()}syncState(){if(!this.controller)return;const e=this.controller;this.update({isPlaying:e.isPlaying(),isPaused:e.isPaused(),isBuffering:e.isBuffering(),isMuted:e.isMuted(),volume:e.getVolume(),hasPlaybackStarted:e.hasPlaybackStarted(),shouldShowControls:e.shouldShowControls(),shouldShowIdleScreen:e.shouldShowIdleScreen(),playbackQuality:e.getPlaybackQuality(),isLoopEnabled:e.isLoopEnabled(),subtitlesEnabled:e.isSubtitlesEnabled(),qualities:e.getQualities(),textTracks:e.getTextTracks(),streamInfo:e.getStreamInfo()})}subscribeToEvents(e){const t=this.unsubs;t.push(e.on("stateChange",({state:e})=>{this.update({state:e}),this.dispatchEvent("fw-state-change",{state:e})})),t.push(e.on("streamStateChange",({state:t})=>{this.update({streamState:t,metadata:e.getMetadata(),isEffectivelyLive:e.isEffectivelyLive(),shouldShowIdleScreen:e.shouldShowIdleScreen()}),this.dispatchEvent("fw-stream-state",{state:t})})),t.push(e.on("timeUpdate",({currentTime:e,duration:t})=>{this.update({currentTime:e,duration:t}),this.dispatchEvent("fw-time-update",{currentTime:e,duration:t})})),t.push(e.on("error",({error:t})=>{this.update({error:t,isPassiveError:e.isPassiveError()}),this.dispatchEvent("fw-error",{error:t})})),t.push(e.on("errorCleared",()=>{this.update({error:null,isPassiveError:!1})})),t.push(e.on("ready",({videoElement:n})=>{this.update({videoElement:n,endpoints:e.getEndpoints(),metadata:e.getMetadata(),streamInfo:e.getStreamInfo(),isEffectivelyLive:e.isEffectivelyLive(),shouldShowIdleScreen:e.shouldShowIdleScreen(),currentPlayerInfo:e.getCurrentPlayerInfo(),currentSourceInfo:e.getCurrentSourceInfo(),qualities:e.getQualities(),textTracks:e.getTextTracks()}),this.dispatchEvent("fw-ready",{videoElement:n});const i=()=>{this.controller?.shouldSuppressVideoEvents?.()||this.syncState()};n.addEventListener("play",i),n.addEventListener("pause",i),n.addEventListener("waiting",i),n.addEventListener("playing",i),t.push(()=>{n.removeEventListener("play",i),n.removeEventListener("pause",i),n.removeEventListener("waiting",i),n.removeEventListener("playing",i)})})),t.push(e.on("playerSelected",({player:t,source:n})=>{this.update({currentPlayerInfo:e.getCurrentPlayerInfo(),currentSourceInfo:{url:n.url,type:n.type},qualities:e.getQualities(),textTracks:e.getTextTracks()})})),t.push(e.on("volumeChange",({volume:e,muted:t})=>{this.update({volume:e,isMuted:t}),this.dispatchEvent("fw-volume-change",{volume:e,muted:t})})),t.push(e.on("loopChange",({isLoopEnabled:e})=>{this.update({isLoopEnabled:e})})),t.push(e.on("fullscreenChange",({isFullscreen:e})=>{this.update({isFullscreen:e}),this.dispatchEvent("fw-fullscreen-change",{isFullscreen:e})})),t.push(e.on("pipChange",({isPiP:e})=>{this.update({isPiPActive:e}),this.dispatchEvent("fw-pip-change",{isPiP:e})})),t.push(e.on("holdSpeedStart",({speed:e})=>{this.update({isHoldingSpeed:!0,holdSpeed:e})})),t.push(e.on("holdSpeedEnd",()=>{this.update({isHoldingSpeed:!1})})),t.push(e.on("hoverStart",()=>{this.update({isHovering:!0,shouldShowControls:!0})})),t.push(e.on("hoverEnd",()=>{this.update({isHovering:!1,shouldShowControls:e.shouldShowControls()})})),t.push(e.on("captionsChange",({enabled:t})=>{this.update({subtitlesEnabled:t,textTracks:e.getTextTracks()})})),t.push(e.on("protocolSwapped",e=>{const t=`Switched to ${e.toProtocol}`;this.update({toast:{message:t,timestamp:Date.now()}}),this.dispatchEvent("fw-protocol-swapped",e)})),t.push(e.on("playbackFailed",e=>{this.update({error:e.message,errorDetails:e.details??null,isPassiveError:!1}),this.dispatchEvent("fw-playback-failed",{code:e.code,message:e.message})}))}dispatchEvent(e,t){this.host.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}async play(){await(this.controller?.play())}pause(){this.controller?.pause()}togglePlay(){this.controller?.togglePlay()}seek(e){this.controller?.seek(e)}seekBy(e){this.controller?.seekBy(e)}jumpToLive(){this.controller?.jumpToLive()}setVolume(e){this.controller?.setVolume(e)}toggleMute(){this.controller?.toggleMute()}toggleLoop(){this.controller?.toggleLoop()}async toggleFullscreen(){await(this.controller?.toggleFullscreen())}async togglePiP(){await(this.controller?.togglePictureInPicture())}toggleSubtitles(){this.controller?.toggleSubtitles()}clearError(){this.controller?.clearError(),this.update({error:null,errorDetails:null,isPassiveError:!1})}dismissToast(){this.update({toast:null})}async retry(){await(this.controller?.retry())}async reload(){await(this.controller?.reload())}getQualities(){return this.controller?.getQualities()??[]}selectQuality(e){this.controller?.selectQuality(e)}getTextTracks(){return this.controller?.getTextTracks()??[]}selectTextTrack(e){this.controller?.selectTextTrack(e)}setPlaybackRate(e){this.controller?.setPlaybackRate(e)}getSeekableStart(){return this.controller?.getSeekableStart()??0}getLiveEdge(){return this.controller?.getLiveEdge()??0}canSeekStream(){return this.controller?.canSeekStream()??!1}getBufferedRanges(){return this.controller?.getBufferedRanges()??null}async getStats(){return this.controller?.getStats()}handleMouseEnter(){this.controller?.handleMouseEnter()}handleMouseLeave(){this.controller?.handleMouseLeave()}handleMouseMove(){this.controller?.handleMouseMove()}handleTouchStart(){this.controller?.handleTouchStart()}async setDevModeOptions(e){await(this.controller?.setDevModeOptions(e))}getController(){return this.controller}}const Gt=d`
|
|
60
|
+
*/const Se=_e(class extends Ee{constructor(e){if(super(e),e.type!==Te||"class"!==e.name||e.strings?.length>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(e){return" "+Object.keys(e).filter(t=>e[t]).join(" ")+" "}update(e,[t]){if(void 0===this.st){this.st=new Set,void 0!==e.strings&&(this.nt=new Set(e.strings.join(" ").split(/\s/).filter(e=>""!==e)));for(const e in t)t[e]&&!this.nt?.has(e)&&this.st.add(e);return this.render(t)}const n=e.element.classList;for(const e of this.st)e in t||(n.remove(e),this.st.delete(e));for(const e in t){const i=!!t[e];i===this.st.has(e)||this.nt?.has(e)||(i?(n.add(e),this.st.add(e)):(n.remove(e),this.st.delete(e)))}return Q}});function we(e){const t=e.codec.toUpperCase();if(e.codecstring)return e.codecstring;if("audio"===e.type)switch(t){case"AAC":case"MP4A":return"mp4a.40.2";case"MP3":return"mp4a.40.34";case"AC3":case"AC-3":return"ac-3";case"EAC3":case"EC3":case"E-AC3":case"EC-3":return"ec-3";case"OPUS":return"opus";case"VORBIS":return"vorbis";case"FLAC":return"flac";case"PCM":case"PCMS16LE":return"pcm";default:return t.toLowerCase()}if("video"===e.type)switch(t){case"H264":case"AVC":case"AVC1":{const t=function(e){if(!e)return null;try{const t=Ie(e);for(let e=0;e<t.length-4;e++)if(0===t[e]&&0===t[e+1]){let n=e+2;0===t[n]&&n++,1===t[n]&&n++;if(7===(31&t[n])&&n+3<t.length){const e=t[n+1],i=t[n+2],r=t[n+3];return`avc1.${ke(e)}${ke(i)}${ke(r)}`}}if(t.length>=4){const e=t[0],n=t[1],i=t[2];if(e>0&&e<255&&i>0&&i<100)return`avc1.${ke(e)}${ke(n)}${ke(i)}`}}catch{}return null}(e.init);return t||"avc1.42E01E"}case"H265":case"HEVC":case"HEV1":case"HVC1":{const t=function(e){if(!e)return null;try{const t=Ie(e);if(t.length>0)for(let e=0;e<t.length-3;e++){const n=t[e];if(n>=1&&n<=5){return`hev1.${n}.6.L${t[e+1]||93}.B0`}}}catch{}return null}(e.init);return t||"hev1.1.6.L93.B0"}case"VP8":return"vp8";case"VP9":return"vp09.00.10.08";case"AV1":return"av01.0.01M.08";case"THEORA":return"theora";default:return t.toLowerCase()}return t.toLowerCase()}function ke(e){return e.toString(16).padStart(2,"0").toUpperCase()}function Ie(e){const t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}function Ae(){const e=navigator.userAgent.toLowerCase();return{isChrome:/chrome|crios/.test(e)&&!/edge|edg/.test(e),isFirefox:/firefox/.test(e),isSafari:/safari/.test(e)&&!/chrome|crios/.test(e),isEdge:/edge|edg/.test(e),isAndroid:/android/.test(e),isIOS:/iphone|ipad|ipod/.test(e),isMobile:/mobile|android|iphone|ipad|ipod/.test(e),supportsMediaSource:"MediaSource"in window,supportsWebRTC:"RTCPeerConnection"in window,supportsWebSocket:"WebSocket"in window}}function Ce(e){const t=window.location.protocol,n=new URL(e).protocol;return("file:"!==t||"http:"!==n)&&t!==n}function De(){return"file:"===window.location.protocol}function Re(){const e=Ae(),t=function(){const e=navigator.userAgent.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);return e?parseInt(e[1],10)+(e[2]?parseInt(e[2],10):0)/10:null}();return{supportsNativeHLS:e.isSafari||e.isIOS||t&&t>=7,supportsMSE:e.supportsMediaSource,supportsWebSocket:e.supportsWebSocket,supportsWebRTC:e.supportsWebRTC&&"RTCRtpReceiver"in window,preferVideoJs:t&&t<7,avoidMEWSOnMac:e.isSafari,fileProtocolLimitations:De()}}const xe={video:["H264","VP8","VP9","AV1"],audio:["OPUS","PCMU","PCMA","G711","G722"]};function Le(e,t){if("undefined"!=typeof RTCRtpReceiver&&RTCRtpReceiver.getCapabilities)try{const n=RTCRtpReceiver.getCapabilities(e);if(n?.codecs){const i=`${e}/${t}`.toLowerCase();return n.codecs.some(e=>e.mimeType.toLowerCase()===i)}}catch{}return xe[e].includes(t.toUpperCase())}function Me(e){const t=e.filter(e=>"video"===e.type),n=e.filter(e=>"audio"===e.type),i=[],r=[],s=[];for(const e of t)Le("video",e.codec)?i.push(e.codec):s.push(`video:${e.codec}`);for(const e of n)Le("audio",e.codec)?r.push(e.codec):s.push(`audio:${e.codec}`);const a=0===t.length||i.length>0,o=0===n.length||r.length>0;return{videoCompatible:a,audioCompatible:o,compatible:a&&o,incompatibleCodecs:s,details:{videoTracks:t.length,audioTracks:n.length,compatibleVideoCodecs:i,compatibleAudioCodecs:r}}}var Ne,Pe;!function(e){e[e.TRANSIENT=1]="TRANSIENT",e[e.RECOVERABLE=2]="RECOVERABLE",e[e.DEGRADED=3]="DEGRADED",e[e.FATAL=4]="FATAL"}(Ne||(Ne={})),function(e){e.NETWORK_TIMEOUT="NETWORK_TIMEOUT",e.WEBSOCKET_DISCONNECT="WEBSOCKET_DISCONNECT",e.SEGMENT_LOAD_ERROR="SEGMENT_LOAD_ERROR",e.ICE_DISCONNECTED="ICE_DISCONNECTED",e.BUFFER_UNDERRUN="BUFFER_UNDERRUN",e.CODEC_DECODE_ERROR="CODEC_DECODE_ERROR",e.PROTOCOL_UNSUPPORTED="PROTOCOL_UNSUPPORTED",e.CODEC_INCOMPATIBLE="CODEC_INCOMPATIBLE",e.ICE_FAILED="ICE_FAILED",e.MANIFEST_STALE="MANIFEST_STALE",e.PLAYER_INIT_FAILED="PLAYER_INIT_FAILED",e.QUALITY_DROPPED="QUALITY_DROPPED",e.BANDWIDTH_LIMITED="BANDWIDTH_LIMITED",e.ALL_PROTOCOLS_EXHAUSTED="ALL_PROTOCOLS_EXHAUSTED",e.ALL_PROTOCOLS_BLACKLISTED="ALL_PROTOCOLS_BLACKLISTED",e.STREAM_OFFLINE="STREAM_OFFLINE",e.AUTH_REQUIRED="AUTH_REQUIRED",e.GEO_BLOCKED="GEO_BLOCKED",e.DRM_ERROR="DRM_ERROR",e.CONTENT_UNAVAILABLE="CONTENT_UNAVAILABLE",e.UNKNOWN="UNKNOWN"}(Pe||(Pe={}));class Oe{constructor(){this.listeners=new Map,this.videoElement=null}getVideoElement(){return this.videoElement}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){const n=this.listeners.get(e);n&&n.delete(t)}emit(e,t){const n=this.listeners.get(e);n&&n.forEach(n=>{try{n(t)}catch(t){console.error(`Error in ${e} listener:`,t)}})}setupVideoEventListeners(e,t){const n=(t,n)=>{e.addEventListener(t,()=>{n(),this.emit(t,void 0)})};n("play",()=>t.onPlay?.()),n("pause",()=>t.onPause?.()),n("ended",()=>t.onEnded?.()),e.addEventListener("waiting",()=>t.onWaiting?.()),e.addEventListener("playing",()=>t.onPlaying?.()),e.addEventListener("canplay",()=>t.onCanPlay?.()),e.addEventListener("durationchange",()=>{t.onDurationChange?.(e.duration)}),e.addEventListener("timeupdate",()=>{const n=e.currentTime;t.onTimeUpdate?.(n),this.emit("timeupdate",n)}),e.addEventListener("error",()=>{const n=e.error?`Video error: ${e.error.message}`:"Unknown video error";t.onError?.(n),this.emit("error",n)}),this.emit("ready",e),t.onReady&&t.onReady(e)}getCurrentTime(){return this.videoElement?.currentTime||0}getDuration(){return this.videoElement?.duration||0}getSeekableRange(){return null}getBufferedRanges(){return this.videoElement?.buffered??null}isPaused(){return this.videoElement?.paused??!0}isMuted(){return this.videoElement?.muted??!1}async play(){if(this.videoElement)return this.videoElement.play()}pause(){this.videoElement?.pause()}seek(e){this.videoElement&&(this.videoElement.currentTime=e)}setVolume(e){this.videoElement&&(this.videoElement.volume=Math.max(0,Math.min(1,e)))}setMuted(e){this.videoElement&&(this.videoElement.muted=e)}setPlaybackRate(e){this.videoElement&&(this.videoElement.playbackRate=e)}getTextTracks(){const e=this.videoElement;if(!e||!e.textTracks)return[];const t=[],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})}return t}selectTextTrack(e){const t=this.videoElement;if(!t||!t.textTracks)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"}}isLive(){const e=this.videoElement;return!!e&&(!isFinite(e.duration)||e.duration===1/0)}jumpToLive(){const e=this.videoElement;if(!e)return;const t=e.seekable;if(t&&t.length>0)try{e.currentTime=t.end(t.length-1)}catch{}}async requestPiP(){const e=this.videoElement;if(e)if(document.pictureInPictureElement!==e)try{e.requestPictureInPicture?await e.requestPictureInPicture():e.webkitSetPresentationMode&&e.webkitSetPresentationMode("picture-in-picture")}catch{}else try{await(document.exitPictureInPicture?.())}catch{}}setSize(e,t){this.videoElement&&(this.videoElement.style.width=`${e}px`,this.videoElement.style.height=`${t}px`)}async getStats(){}async getLatency(){}}const Fe={[Pe.NETWORK_TIMEOUT]:{maxAttempts:3,baseDelayMs:500,maxDelayMs:4e3,jitterPercent:20},[Pe.WEBSOCKET_DISCONNECT]:{maxAttempts:5,baseDelayMs:500,maxDelayMs:5e3,jitterPercent:20},[Pe.SEGMENT_LOAD_ERROR]:{maxAttempts:3,baseDelayMs:200,maxDelayMs:2e3,jitterPercent:10},[Pe.ICE_DISCONNECTED]:{maxAttempts:3,baseDelayMs:500,maxDelayMs:3e3,jitterPercent:20},[Pe.BUFFER_UNDERRUN]:{maxAttempts:1,baseDelayMs:5e3,maxDelayMs:5e3,jitterPercent:0},[Pe.CODEC_DECODE_ERROR]:{maxAttempts:3,baseDelayMs:100,maxDelayMs:1e3,jitterPercent:10},[Pe.PROTOCOL_UNSUPPORTED]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.CODEC_INCOMPATIBLE]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.ICE_FAILED]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.MANIFEST_STALE]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.PLAYER_INIT_FAILED]:{maxAttempts:1,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.QUALITY_DROPPED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.BANDWIDTH_LIMITED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.ALL_PROTOCOLS_EXHAUSTED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.ALL_PROTOCOLS_BLACKLISTED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.STREAM_OFFLINE]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.AUTH_REQUIRED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.GEO_BLOCKED]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.DRM_ERROR]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.CONTENT_UNAVAILABLE]:{maxAttempts:0,baseDelayMs:0,maxDelayMs:0,jitterPercent:0},[Pe.UNKNOWN]:{maxAttempts:1,baseDelayMs:1e3,maxDelayMs:1e3,jitterPercent:0}},Ue={[Pe.NETWORK_TIMEOUT]:Ne.TRANSIENT,[Pe.WEBSOCKET_DISCONNECT]:Ne.TRANSIENT,[Pe.SEGMENT_LOAD_ERROR]:Ne.TRANSIENT,[Pe.ICE_DISCONNECTED]:Ne.TRANSIENT,[Pe.BUFFER_UNDERRUN]:Ne.TRANSIENT,[Pe.CODEC_DECODE_ERROR]:Ne.TRANSIENT,[Pe.PROTOCOL_UNSUPPORTED]:Ne.RECOVERABLE,[Pe.CODEC_INCOMPATIBLE]:Ne.RECOVERABLE,[Pe.ICE_FAILED]:Ne.RECOVERABLE,[Pe.MANIFEST_STALE]:Ne.RECOVERABLE,[Pe.PLAYER_INIT_FAILED]:Ne.RECOVERABLE,[Pe.QUALITY_DROPPED]:Ne.DEGRADED,[Pe.BANDWIDTH_LIMITED]:Ne.DEGRADED,[Pe.ALL_PROTOCOLS_EXHAUSTED]:Ne.FATAL,[Pe.ALL_PROTOCOLS_BLACKLISTED]:Ne.FATAL,[Pe.STREAM_OFFLINE]:Ne.FATAL,[Pe.AUTH_REQUIRED]:Ne.FATAL,[Pe.GEO_BLOCKED]:Ne.FATAL,[Pe.DRM_ERROR]:Ne.FATAL,[Pe.CONTENT_UNAVAILABLE]:Ne.FATAL,[Pe.UNKNOWN]:Ne.FATAL},ze={[Pe.NETWORK_TIMEOUT]:"Network timeout",[Pe.WEBSOCKET_DISCONNECT]:"Connection lost",[Pe.SEGMENT_LOAD_ERROR]:"Failed to load video segment",[Pe.ICE_DISCONNECTED]:"Connection interrupted",[Pe.BUFFER_UNDERRUN]:"Buffering",[Pe.CODEC_DECODE_ERROR]:"Decode error",[Pe.PROTOCOL_UNSUPPORTED]:"Protocol not supported",[Pe.CODEC_INCOMPATIBLE]:"Codec not supported",[Pe.ICE_FAILED]:"Connection failed",[Pe.MANIFEST_STALE]:"Stream manifest outdated",[Pe.PLAYER_INIT_FAILED]:"Player initialization failed",[Pe.QUALITY_DROPPED]:"Quality reduced",[Pe.BANDWIDTH_LIMITED]:"Bandwidth limited",[Pe.ALL_PROTOCOLS_EXHAUSTED]:"Unable to play video",[Pe.ALL_PROTOCOLS_BLACKLISTED]:"No compatible playback protocols available",[Pe.STREAM_OFFLINE]:"Stream is offline",[Pe.AUTH_REQUIRED]:"Sign in to watch",[Pe.GEO_BLOCKED]:"Not available in your region",[Pe.DRM_ERROR]:"Playback not supported",[Pe.CONTENT_UNAVAILABLE]:"Content unavailable",[Pe.UNKNOWN]:"Playback error"};class Be{constructor(e={}){this.retryCounts=new Map,this.lastErrorTime=new Map,this.listeners=new Map,this.lastQualityToastTime=0,this.alternativesRemaining=e.alternativesCount??0,this.debug=e.debug??!1}setAlternativesRemaining(e){this.alternativesRemaining=e}reset(){this.retryCounts.clear(),this.lastErrorTime.clear(),this.lastQualityToastTime=0,this.log("Error state reset")}classify(e,t){const n=Fe[e],i=(this.retryCounts.get(e)??0)+1,r=Math.max(0,n.maxAttempts-i);this.retryCounts.set(e,i),this.lastErrorTime.set(e,Date.now());const s={severity:Ue[e],code:e,message:ze[e],retriesRemaining:r,alternativesRemaining:this.alternativesRemaining,originalError:t,timestamp:Date.now()};if(this.log(`Classified error: ${e}, attempt ${i}/${n.maxAttempts}, severity ${s.severity}`),s.severity===Ne.TRANSIENT&&r>0){const t=this.calculateBackoff(e,i);return this.emit("recoveryAttempted",{code:e,attempt:i,maxAttempts:n.maxAttempts}),{type:"retry",delayMs:t}}if(s.severity===Ne.TRANSIENT&&0===r||s.severity===Ne.RECOVERABLE){if(this.alternativesRemaining>0)return{type:"swap",reason:s.message};const e=s.code,t=s.message;s.severity=Ne.FATAL,s.code=Pe.ALL_PROTOCOLS_EXHAUSTED,s.message=`${t} (no alternatives remaining)`,s.details={...s.details,originalCode:e,originalMessage:t}}if(s.severity===Ne.DEGRADED){const e=Date.now();return e-this.lastQualityToastTime>=Be.QUALITY_TOAST_DEBOUNCE_MS?(this.lastQualityToastTime=e,this.emit("qualityChanged",{direction:"down",reason:s.message}),{type:"toast",message:s.message}):{type:"toast",message:""}}return this.emit("playbackFailed",s),{type:"fatal",error:s}}classifyWithDetails(e,t,n,i){if(Ue[e]===Ne.FATAL){const r={severity:Ne.FATAL,code:e,message:t,retriesRemaining:0,alternativesRemaining:this.alternativesRemaining,originalError:i,timestamp:Date.now(),details:n};return this.emit("playbackFailed",r),{type:"fatal",error:r}}const r=this.classify(e,i);return"fatal"===r.type&&(r.error.message=t,r.error.details=n),r}notifyProtocolSwap(e,t,n,i,r){this.emit("protocolSwapped",{fromPlayer:e,toPlayer:t,fromProtocol:n,toProtocol:i,reason:r})}calculateBackoff(e,t){const n=Fe[e],i=n.baseDelayMs*Math.pow(2,t-1),r=Math.min(i,n.maxDelayMs),s=r*(n.jitterPercent/100),a=(2*Math.random()-1)*s;return Math.round(r+a)}static mapErrorToCode(e){const t=("string"==typeof e?e:e.message).toLowerCase();return t.includes("timeout")||t.includes("timed out")?Pe.NETWORK_TIMEOUT:t.includes("websocket")||t.includes("socket")?Pe.WEBSOCKET_DISCONNECT:t.includes("fetch")||t.includes("network")?Pe.NETWORK_TIMEOUT:t.includes("offline")||t.includes("not found")||t.includes("stream not found")?Pe.STREAM_OFFLINE:t.includes("segment")?Pe.SEGMENT_LOAD_ERROR:t.includes("manifest")||t.includes("playlist")?t.includes("404")?Pe.STREAM_OFFLINE:Pe.MANIFEST_STALE:t.includes("ice")&&t.includes("disconnect")?Pe.ICE_DISCONNECTED:t.includes("ice")&&t.includes("fail")?Pe.ICE_FAILED:t.includes("codec")||t.includes("decode")?Pe.CODEC_DECODE_ERROR:t.includes("not supported")||t.includes("unsupported")?Pe.PROTOCOL_UNSUPPORTED:t.includes("buffer")||t.includes("underrun")?Pe.BUFFER_UNDERRUN:t.includes("401")||t.includes("auth")||t.includes("unauthorized")?Pe.AUTH_REQUIRED:t.includes("403")||t.includes("forbidden")||t.includes("geo")?Pe.GEO_BLOCKED:t.includes("drm")||t.includes("eme")||t.includes("key")?Pe.DRM_ERROR:Pe.UNKNOWN}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){const n=this.listeners.get(e);n&&n.delete(t)}emit(e,t){const n=this.listeners.get(e);n&&n.forEach(n=>{try{n(t)}catch(t){console.error(`Error in ${e} listener:`,t)}})}log(e){this.debug&&console.log(`[ErrorClassifier] ${e}`)}}Be.QUALITY_TOAST_DEBOUNCE_MS=1e4;const je={video:2,audio:1,subtitle:.5};const $e=new Set(["flash/7","flash/10","flash/11","silverlight","html5/application/sdp","sdp","html5/video/mpeg","html5/application/vnd.ms-sstr+xml","srt","rtsp","rtmp","dtsc","html5/image/jpeg","html5/text/javascript","html5/text/vtt","html5/text/plain"]);function qe(e){return $e.has(e)}const He={"html5/video/webm":.8,"html5/audio/webm":.6,"ws/video/webm":.8,"wss/video/webm":.8,"ws/video/mp4":.5,"wss/video/mp4":.5,webrtc:.5,"mist/webrtc":.5,"dash/video/mp4":.9,"dash/video/webm":.95,"html5/application/vnd.apple.mpegurl;version=7":.2,"ll-hls":.2,cmaf:.2};const Ge={webcodecs:.95,videojs:.95,hlsjs:.9,native:.85,"mist-webrtc":.85,mews:.75,"mist-legacy":.7,dashjs:.5};const Ve={"low-latency":{"ws/video/raw":.55,"wss/video/raw":.55,"ws/video/h264":.52,"wss/video/h264":.52,whep:.5,webrtc:.25,"mist/webrtc":.25,"ws/video/mp4":.3,"wss/video/mp4":.3,"html5/video/mp4":.15,"html5/application/vnd.apple.mpegurl":.05},quality:{"ws/video/mp4":.45,"wss/video/mp4":.45,"ws/video/raw":.4,"wss/video/raw":.4,"ws/video/h264":.38,"wss/video/h264":.38,"html5/application/vnd.apple.mpegurl":.3,"html5/video/mp4":.2,whep:.05,webrtc:.05,"mist/webrtc":.05},vod:{"html5/video/mp4":.5,"html5/application/vnd.apple.mpegurl":.45,"dash/video/mp4":.4,"ws/video/mp4":.35,"wss/video/mp4":.35,whep:-1,webrtc:-1,"mist/webrtc":-1},auto:{"ws/video/raw":.5,"wss/video/raw":.5,"ws/video/h264":.48,"wss/video/h264":.48,"html5/video/mp4":.42,whep:.38,webrtc:.2,"mist/webrtc":.2,"ws/video/mp4":.3,"wss/video/mp4":.3,"html5/application/vnd.apple.mpegurl":.2}};const Ye={whep:{prefer:["native"]},webrtc:{prefer:["mist-webrtc","native"]},"mist/webrtc":{prefer:["mist-webrtc"]},"ws/video/raw":{prefer:["webcodecs"]},"wss/video/raw":{prefer:["webcodecs"]},"ws/video/h264":{prefer:["webcodecs"]},"wss/video/h264":{prefer:["webcodecs"]},"ws/video/mp4":{prefer:["mews"]},"wss/video/mp4":{prefer:["mews"]},"ws/video/webm":{prefer:["mews"]},"wss/video/webm":{prefer:["mews"]},"html5/application/vnd.apple.mpegurl":{prefer:["videojs","hlsjs"],avoid:["native"]},"html5/application/vnd.apple.mpegurl;version=7":{prefer:["videojs","hlsjs"],avoid:["native"]},"dash/video/mp4":{prefer:["dashjs","videojs"]},"html5/video/mp4":{prefer:["native"]},"html5/video/webm":{prefer:["native"]},"html5/audio/aac":{prefer:["native"]},"html5/audio/mp3":{prefer:["native"]},"html5/audio/flac":{prefer:["native"]},"html5/audio/wav":{prefer:["native"]}};function We(e,t,n,i={}){const{maxPriority:r=10,totalSources:s=1,trackScores:a={},bandwidth:o,targetBandwidth:l,playerShortname:u,mimeType:d,playbackMode:c="auto",weights:h={tracks:.5,priority:.1,source:.05,quality:.05,reliability:.1,mode:.1,routing:.08,protocolPenalty:1}}=i,f=function(e,t=je){if(!0===e)return 1.9;if(!1===e||0===e.length)return 0;let n=0;for(const i of e){const e=t[i];void 0!==e&&(n+=e)}return n}(e,{...je,...a}),p=function(e,t){return 1-e/Math.max(t,1)}(t,r),g=function(e,t){return 1-e/Math.max(t-1,1)}(n,s),m=function(e,t){return e&&t?Math.min(e,t)/Math.max(e,t):1}(o,l),y=u?function(e){return Ge[e]??.5}(u):.5,b=d?function(e,t){return t?Ve[t]?.[e]??0:0}(d,c):0,v=d&&u?function(e,t){const n=Ye[e];if(!n)return 0;if(n.avoid?.includes(t))return-.1;if(n.prefer?.includes(t))return.15-.05*n.prefer.indexOf(t);return 0}(d,u):0,T=d?function(e){if(He[e])return He[e];const t=e.toLowerCase();return t.includes("webm")?.5:t.startsWith("dash/")?.4:t.includes("cmaf")||t.includes("ll-hls")?.2:0}(d):0,_=f*h.tracks+p*h.priority+g*h.source+m*h.quality+y*(h.reliability??0)+b*(h.mode??0)+v*(h.routing??0)-T*(h.protocolPenalty??1);return{base:f,trackTypes:Array.isArray(e)?e:[],total:_,breakdown:{trackScore:f,priorityScore:p,sourceScore:g,reliabilityScore:y,modeBonus:b,routingBonus:v,protocolPenalty:T}}}class Ke{constructor(e={}){this.players=new Map,this.currentPlayer=null,this.listeners=new Map,this.fallbackAttempts=0,this.cachedCombinations=null,this.cachedSelection=null,this.cacheKey=null,this.lastLoggedWinner=null,this.lastContainer=null,this.lastStreamInfo=null,this.lastPlayerOptions={},this.lastManagerOptions={},this.excludedCombos=new Set,this.opQueue=Promise.resolve(),this.options={debug:!1,autoFallback:!0,maxFallbackAttempts:3,...e},this.errorClassifier=new Be({alternativesCount:0,debug:this.options.debug}),this.errorClassifier.on("recoveryAttempted",e=>this.emit("recoveryAttempted",e)),this.errorClassifier.on("protocolSwapped",e=>this.emit("protocolSwapped",e)),this.errorClassifier.on("qualityChanged",e=>this.emit("qualityChanged",e)),this.errorClassifier.on("playbackFailed",e=>this.emit("playbackFailed",e))}registerPlayer(e){this.players.set(e.capability.shortname,e),this.invalidateCache(),this.log(`Registered player: ${e.capability.name}`)}unregisterPlayer(e){const t=this.players.get(e);t&&(t.destroy(),this.players.delete(e),this.invalidateCache(),this.log(`Unregistered player: ${e}`))}getRegisteredPlayers(){return Array.from(this.players.values())}computeCacheKey(e,t){return JSON.stringify({sources:e.source.map(e=>`${e.type}:${e.url??""}`).sort(),tracks:e.meta?.tracks?.map(e=>e.codec).sort()??[],mode:t,forcePlayer:this.options.forcePlayer,forceSource:this.options.forceSource,forceType:this.options.forceType})}getComboKey(e,t){return`${e}:${t.type}:${t.url??""}`}invalidateCache(){this.cachedCombinations=null,this.cachedSelection=null,this.cacheKey=null}getCurrentSelection(){return this.cachedSelection}getCachedCombinations(){return this.cachedCombinations}getAllCombinations(e,t){const n=t||this.options.playbackMode,i=n&&"auto"!==n?n:"vod"===e.type?"vod":"auto",r=this.computeCacheKey(e,i);if(r===this.cacheKey&&this.cachedCombinations)return this.cachedCombinations;const s=this.computeAllCombinations(e,i);this.cachedCombinations=s,this.cacheKey=r;const a=this.pickBestFromCombinations(s);if(this.hasSelectionChanged(a)){if(this.cachedSelection=a,this.options.debug&&a){const e=`${a.player}:${a.source?.type}`;e!==this.lastLoggedWinner&&(console.log(`[PlayerManager] Selection: ${a.player} + ${a.source?.type} (score: ${a.score.toFixed(3)})`),this.lastLoggedWinner=e)}this.emit("selection-changed",a)}return this.emit("combinations-updated",s),s}selectBestPlayer(e,t){const n={...this.options,...t};if("mist-legacy"===n.forcePlayer||"mist/legacy"===n.forceType){if(this.players.get("mist-legacy")&&e.source.length>0){const t=e.source[0],n={score:.1,player:"mist-legacy",source:{url:t.url,type:"mist/legacy",streamName:t.streamName,mistPlayerUrl:t.mistPlayerUrl},source_index:0};return this.emit("playerSelected",{player:n.player,source:n.source,score:n.score}),n}}let i=this.getAllCombinations(e,n.playbackMode).filter(e=>e.compatible);if(n.forcePlayer&&(i=i.filter(e=>e.player===n.forcePlayer)),n.forceType&&(i=i.filter(e=>e.sourceType===n.forceType)),void 0!==n.forceSource&&(i=i.filter(e=>e.sourceIndex===n.forceSource)),0===i.length)return this.log("No suitable player found"),!1;const r=i[0],s={score:r.score,player:r.player,source:r.source,source_index:r.sourceIndex};return this.emit("playerSelected",{player:s.player,source:s.source,score:s.score}),s}computeAllCombinations(e,t){const n=[],i=Array.from(this.players.values()),r=Math.max(...i.map(e=>e.capability.priority),1),s=e.source.filter(e=>!qe(e.type)),a=new Map;s.forEach((e,t)=>a.set(e,t));const o=s.length,l=[];e.meta.tracks.some(e=>"video"===e.type)&&l.push("video"),e.meta.tracks.some(e=>"audio"===e.type)&&l.push("audio");const u=new Set;for(const s of i)for(let i=0;i<e.source.length;i++){const d=e.source[i],c=this.getComboKey(s.capability.shortname,d);if(u.has(c))continue;u.add(c);const h=a.get(d);if(void 0===h){n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:0,compatible:!1,incompatibleReason:`Protocol "${d.type}" is blacklisted`});continue}if(!s.isMimeSupported(d.type)){n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:0,compatible:!1,incompatibleReason:`MIME type "${d.type}" not supported`});continue}const f=s.isBrowserSupported(d.type,d,e);if(!f){const e=1-s.capability.priority/Math.max(r,1),a=1-h/Math.max(o-1,1),l=We(["video","audio"],s.capability.priority,h,{maxPriority:r,totalSources:o,playerShortname:s.capability.shortname,mimeType:d.type,playbackMode:t});n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:l.total,compatible:!1,codecIncompatible:!0,incompatibleReason:"Codec not supported by browser",scoreBreakdown:{trackScore:0,trackTypes:[],priorityScore:e,sourceScore:a,weights:{tracks:.5,priority:.1,source:.05}}});continue}if(Array.isArray(f)&&l.length>0){const e=l.filter(e=>!f.includes(e));if(e.length>0){const a=1-s.capability.priority/Math.max(r,1),l=1-h/Math.max(o-1,1),u=We(f,s.capability.priority,h,{maxPriority:r,totalSources:o,playerShortname:s.capability.shortname,mimeType:d.type,playbackMode:t});n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:u.total,compatible:!1,incompatibleReason:`Missing required tracks: ${e.join(", ")}`,scoreBreakdown:{trackScore:0,trackTypes:f,priorityScore:a,sourceScore:l,weights:{tracks:.5,priority:.1,source:.05}}});continue}}const p=Array.isArray(f)?f.reduce((e,t)=>e+({video:2,audio:1,subtitle:.5}[t]||0),0):1.9,g=1-s.capability.priority/Math.max(r,1),m=1-h/Math.max(o-1,1),y=We(f,s.capability.priority,h,{maxPriority:r,totalSources:o,playerShortname:s.capability.shortname,mimeType:d.type,playbackMode:t});n.push({player:s.capability.shortname,playerName:s.capability.name,source:d,sourceIndex:i,sourceType:d.type,score:y.total,compatible:!0,scoreBreakdown:{trackScore:p,trackTypes:Array.isArray(f)?f:["video","audio"],priorityScore:g,sourceScore:m,reliabilityScore:y.breakdown?.reliabilityScore??0,modeBonus:y.breakdown?.modeBonus??0,routingBonus:y.breakdown?.routingBonus??0,weights:{tracks:.5,priority:.1,source:.05,reliability:.1,mode:.12,routing:.08}}})}const d=this.players.get("mist-legacy");if(d&&e.source.length>0){const t=e.source[0],i={url:t.url,type:"mist/legacy",streamName:t.streamName,mistPlayerUrl:t.mistPlayerUrl};n.push({player:d.capability.shortname,playerName:d.capability.name,source:i,sourceIndex:0,sourceType:"mist/legacy",score:.1,compatible:!0,scoreBreakdown:{trackScore:2,trackTypes:["video","audio"],priorityScore:0,sourceScore:0,weights:{tracks:.5,priority:.1,source:.05}}})}return n.sort((e,t)=>e.compatible!==t.compatible?e.compatible?-1:1:e.compatible?t.score-e.score:e.playerName.localeCompare(t.playerName))}diagnoseNoPlayersAvailable(e,t){const n=e.source??[],i=n.filter(e=>qe(e.type)),r=Array.from(new Set(i.map(e=>e.type)));if(n.length>0&&i.length===n.length)return{code:Pe.ALL_PROTOCOLS_BLACKLISTED,message:`All ${n.length} protocols are blacklisted`,details:{blacklistedProtocols:r,incompatibilityReasons:[`All source protocols are blacklisted: ${r.join(", ")}`]}};const s=Array.from(new Set(t.filter(e=>!e.compatible&&e.incompatibleReason).map(e=>e.incompatibleReason)));return 0===n.length?{code:Pe.ALL_PROTOCOLS_EXHAUSTED,message:"No playback sources provided",details:{incompatibilityReasons:s,blacklistedProtocols:r}}:1===s.length?{code:Pe.ALL_PROTOCOLS_EXHAUSTED,message:s[0],details:{incompatibilityReasons:s,blacklistedProtocols:r}}:{code:Pe.ALL_PROTOCOLS_EXHAUSTED,message:"No compatible player/protocol combinations",details:{incompatibilityReasons:s.slice(0,5),blacklistedProtocols:r}}}pickBestFromCombinations(e){const t=e.filter(e=>e.compatible);if(0===t.length)return null;const n=t[0];return{score:n.score,player:n.player,source:n.source,source_index:n.sourceIndex}}hasSelectionChanged(e){return!(!this.cachedSelection&&!e)&&(!this.cachedSelection||!e||(this.cachedSelection.player!==e.player||this.cachedSelection.source?.type!==e.source?.type||(this.cachedSelection.source?.url??"")!==(e.source?.url??"")))}enqueueOp(e){const t=this.opQueue.then(e,e);return this.opQueue=t.then(()=>{},()=>{}),t}async initializePlayer(e,t,n={},i){return this.log("initializePlayer() called"),this.enqueueOp(async()=>(this.log("Inside enqueueOp - starting"),this.fallbackAttempts=0,this.excludedCombos.clear(),this.errorClassifier.reset(),this.lastContainer=e,this.lastStreamInfo=t,this.lastPlayerOptions=n,this.lastManagerOptions={playbackMode:i?.playbackMode,debug:i?.debug,autoFallback:i?.autoFallback,maxFallbackAttempts:i?.maxFallbackAttempts},this.tryInitializePlayer(e,t,n,i)))}async tryInitializePlayer(e,t,n,i,r=new Set){this.log("tryInitializePlayer() starting"),this.currentPlayer&&(this.log("Cleaning up previous player..."),await Promise.resolve(this.currentPlayer.destroy()),this.currentPlayer=null),e.innerHTML="";const s=this.getAllCombinations(t,i?.playbackMode),a=s.filter(e=>e.compatible&&!r.has(this.getComboKey(e.player,e.source)));this.errorClassifier.setAlternativesRemaining(Math.max(0,a.length-1));const o=t.source.filter((e,n)=>{if(0===r.size)return!0;const s=this.selectBestPlayer({...t,source:[t.source[n]]},i);return s&&!r.has(this.getComboKey(s.player,s.source))});if(0===o.length){this.log("No available sources after filtering");const e=this.diagnoseNoPlayersAvailable(t,s);if("fatal"===this.errorClassifier.classifyWithDetails(e.code,e.message,e.details).type)throw new Error(e.message);throw new Error(e.message)}this.log(`Available sources: ${o.length}`);const l={...t,source:o},u=this.selectBestPlayer(l,i);if(!u){this.log("No suitable player selected");const e=this.getAllCombinations(l,i?.playbackMode),t=this.diagnoseNoPlayersAvailable(l,e);throw this.errorClassifier.classifyWithDetails(t.code,t.message,t.details),new Error(t.message)}this.log(`Selected: ${u.player} for ${u.source.type}`);const d=this.players.get(u.player);if(!d)throw this.log(`Player ${u.player} not registered`),new Error(`Player ${u.player} not found`);this.log(`Calling ${u.player}.initialize()...`);try{const i=await d.initialize(e,u.source,n,t);return this.log(`${u.player}.initialize() completed successfully`),this.currentPlayer=d,this.errorClassifier.reset(),this.emit("playerInitialized",{player:d,videoElement:i}),i}catch(s){return this.handleInitError(s,u,e,t,n,i,r)}}async handleInitError(e,t,n,i,r,s,a){const o=Be.mapErrorToCode(e instanceof Error?e:new Error(String(e))),l=this.errorClassifier.classify(o,e instanceof Error?e:String(e));switch(this.log(`Error classified: ${o}, action: ${l.type}`),l.type){case"retry":return this.log(`Retrying in ${l.delayMs}ms...`),await this.delay(l.delayMs),this.tryInitializePlayer(n,i,r,s,a);case"swap":{const o=this.options.maxFallbackAttempts||3;if(!this.options.autoFallback||this.fallbackAttempts>=o)throw this.errorClassifier.classify(Pe.ALL_PROTOCOLS_EXHAUSTED),e;this.fallbackAttempts++;const u=t.player,d=t.source.type;a.add(this.getComboKey(t.player,t.source)),this.log(`Swapping from ${u} (attempt ${this.fallbackAttempts}/${o})`);try{const e=await this.tryInitializePlayer(n,i,r,s,a),t=this.currentPlayer?.capability.shortname||"unknown",o=this.cachedSelection?.source.type||"unknown";return this.errorClassifier.notifyProtocolSwap(u,t,d,o,l.reason),this.emit("fallbackAttempted",{fromPlayer:u,toPlayer:t}),e}catch(e){throw e}}default:throw e}}delay(e){return new Promise(t=>setTimeout(t,e))}async tryPlaybackFallback(){return this.enqueueOp(async()=>{if(!this.lastContainer||!this.lastStreamInfo)return this.log("Cannot attempt fallback: no previous init params"),!1;const e=this.options.maxFallbackAttempts||3;if(this.fallbackAttempts>=e)return this.log(`Fallback exhausted (${this.fallbackAttempts}/${e})`),this.errorClassifier.classify(Pe.ALL_PROTOCOLS_EXHAUSTED),!1;const t=this.currentPlayer?.capability.shortname||"unknown",n=this.cachedSelection?.source.type||"unknown";this.currentPlayer&&(this.cachedSelection&&this.excludedCombos.add(this.getComboKey(this.cachedSelection.player,this.cachedSelection.source)),await Promise.resolve(this.currentPlayer.destroy()),this.currentPlayer=null),this.fallbackAttempts++,this.lastContainer.innerHTML="",this.errorClassifier.reset();try{await this.tryInitializePlayer(this.lastContainer,this.lastStreamInfo,this.lastPlayerOptions,this.lastManagerOptions,this.excludedCombos);const e=this.getCurrentPlayer(),i=e?.capability.shortname||"unknown",r=this.cachedSelection?.source.type||"unknown";return this.errorClassifier.notifyProtocolSwap(t,i,n,r,"Playback fallback"),this.emit("fallbackAttempted",{fromPlayer:t,toPlayer:i}),!0}catch{return this.log("Playback fallback failed"),!1}})}reportError(e){const t=Be.mapErrorToCode(e);return this.errorClassifier.classify(t,e)}reportQualityChange(e,t){this.emit("qualityChanged",{direction:e,reason:t})}getErrorClassifier(){return this.errorClassifier}getRemainingFallbackAttempts(){return Math.max(0,(this.options.maxFallbackAttempts||3)-this.fallbackAttempts)}canAttemptFallback(){return this.getRemainingFallbackAttempts()>0&&null!==this.lastStreamInfo}getCurrentPlayer(){return this.currentPlayer}getBrowserCapabilities(){return{browser:Ae(),compatibility:Re(),supportedMimeTypes:this.getSupportedMimeTypes(),availablePlayers:this.getAvailablePlayerInfo()}}getSupportedMimeTypes(){const e=new Set;for(const t of this.players.values())t.capability.mimes.forEach(t=>e.add(t));return Array.from(e).sort()}getAvailablePlayerInfo(){return Array.from(this.players.values()).map(e=>({name:e.capability.name,shortname:e.capability.shortname,priority:e.capability.priority,mimes:e.capability.mimes})).sort((e,t)=>e.priority-t.priority)}async destroy(){await this.enqueueOp(async()=>{this.currentPlayer&&(await Promise.resolve(this.currentPlayer.destroy()),this.currentPlayer=null)})}removeAllListeners(){this.listeners.clear()}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){this.listeners.get(e)?.forEach(n=>{try{n(t)}catch(t){console.error(`Error in PlayerManager ${e} listener:`,t)}})}log(e){this.options.debug&&console.log(`[PlayerManager] ${e}`)}async testSource(e,t){const n={...t,source:[e]};if(!this.selectBestPlayer(n))return{canPlay:!1,players:[]};const i=[];for(const n of this.players.values())if(n.isMimeSupported(e.type)){n.isBrowserSupported(e.type,e,t)&&i.push(n.capability.shortname)}return{canPlay:!0,players:i}}}class Qe{constructor(){this.listeners=new Map}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}once(e,t){const n=i=>{this.off(e,n),t(i)};return this.on(e,n)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){this.listeners.get(e)?.forEach(n=>{try{n(t)}catch(t){console.error(`[EventEmitter] Error in ${String(e)} listener:`,t)}})}removeAllListeners(){this.listeners.clear()}removeListeners(e){this.listeners.delete(e)}hasListeners(e){return(this.listeners.get(e)?.size??0)>0}}const Xe=3,Je=500;class Ze extends Qe{constructor(e){super(),this.status="idle",this.endpoints=null,this.error=null,this.abortController=null,this.inFlightRequest=null,this.cacheTimestamp=0,this.circuitState="closed",this.consecutiveFailures=0,this.circuitOpenedAt=0,this.config=e,this.cacheTtlMs=1e4}async resolve(e=!1){if(!e&&this.endpoints&&this.isCacheValid())return this.endpoints;if(!this.canAttemptRequest())throw new Error("Circuit breaker is open - too many recent failures");if(this.inFlightRequest)return this.inFlightRequest;this.inFlightRequest=this.doResolve();try{const e=await this.inFlightRequest;return this.onSuccess(),e}catch(e){throw this.onFailure(),e}finally{this.inFlightRequest=null}}isCacheValid(){return Date.now()-this.cacheTimestamp<this.cacheTtlMs}setCacheTtl(e){this.cacheTtlMs=e}invalidateCache(){this.cacheTimestamp=0}canAttemptRequest(){switch(this.circuitState){case"closed":case"half-open":return!0;case"open":return Date.now()-this.circuitOpenedAt>=3e4&&(this.circuitState="half-open",!0)}}onSuccess(){this.consecutiveFailures=0,this.circuitState="closed"}onFailure(){this.consecutiveFailures++,"half-open"===this.circuitState?(this.circuitState="open",this.circuitOpenedAt=Date.now()):this.consecutiveFailures>=5&&(this.circuitState="open",this.circuitOpenedAt=Date.now(),console.warn(`[GatewayClient] Circuit breaker opened after ${this.consecutiveFailures} consecutive failures`))}getCircuitState(){return{state:this.circuitState,failures:this.consecutiveFailures,openedAt:"open"===this.circuitState?this.circuitOpenedAt:null}}resetCircuitBreaker(){this.circuitState="closed",this.consecutiveFailures=0,this.circuitOpenedAt=0}async doResolve(){this.abort();const{gatewayUrl:e,contentId:t,authToken:n,maxRetries:i=Xe,initialDelayMs:r=Je}=this.config;if(!e||!t){const e="Missing required parameters: gatewayUrl or contentId";throw this.setStatus("error",e),new Error(e)}this.setStatus("loading");const s=new AbortController;this.abortController=s;try{const a=e.replace(/\/$/,""),o=await async function(e,t,n,i){let r=null;for(let s=0;s<n;s++)try{return await fetch(e,t)}catch(e){if(r=e instanceof Error?e:new Error("Fetch failed"),t.signal?.aborted)throw r;if(s<n-1){const e=i*Math.pow(2,s);console.warn(`[GatewayClient] Retry ${s+1}/${n-1} after ${e}ms`),await new Promise(t=>setTimeout(t,e))}}throw r??new Error("Gateway unreachable after retries")}(a,{method:"POST",headers:{"Content-Type":"application/json",...n?{Authorization:`Bearer ${n}`}:{}},body:JSON.stringify({query:"\n query ResolveViewer($contentId: String!) {\n resolveViewerEndpoint(contentId: $contentId) {\n primary { nodeId baseUrl protocol url geoDistance loadScore outputs }\n fallbacks { nodeId baseUrl protocol url geoDistance loadScore outputs }\n metadata { contentType contentId title description durationSeconds status isLive viewers recordingSizeBytes clipSource createdAt }\n }\n }\n",variables:{contentId:t}}),signal:s.signal},i,r);if(!o.ok)throw new Error(`Gateway GQL error ${o.status}`);const l=await o.json();if(l.errors?.length)throw new Error(l.errors[0]?.message||"GraphQL error");const u=l.data?.resolveViewerEndpoint,d=u?.primary,c=Array.isArray(u?.fallbacks)?u.fallbacks:[];if(!d)throw new Error("No endpoints available");const h={primary:d,fallbacks:c,metadata:u?.metadata};return this.endpoints=h,this.cacheTimestamp=Date.now(),this.setStatus("ready"),this.emit("endpointsResolved",{endpoints:h}),h}catch(e){if(s.signal.aborted)throw new Error("Request aborted");const t=e instanceof Error?e.message:"Unknown gateway error";throw console.error("[GatewayClient] Gateway resolution failed:",t),this.setStatus("error",t),new Error(t)}}abort(){this.abortController&&(this.abortController.abort(),this.abortController=null)}getStatus(){return this.status}getEndpoints(){return this.endpoints}getError(){return this.error}updateConfig(e){this.abort(),this.config={...this.config,...e},this.endpoints=null,this.error=null,this.cacheTimestamp=0,this.inFlightRequest=null,this.resetCircuitBreaker(),this.setStatus("idle")}destroy(){this.abort(),this.removeAllListeners()}setStatus(e,t){this.status=e,this.error=t??null,this.emit("statusChange",{status:e,error:t})}}class et{constructor(e){this.timers=new Map,this.nextId=1,this.debug=e?.debug??!1}start(e,t,n){const i=this.nextId++,r=Date.now()+t,s=setTimeout(()=>{this.timers.delete(i);try{e()}catch(e){console.error("[TimerManager] Callback error:",e)}},t);return this.timers.set(i,{id:s,endTime:r,isInterval:!1,label:n}),this.debug&&console.debug(`[TimerManager] Started timeout ${i}${n?` (${n})`:""} for ${t}ms`),i}startInterval(e,t,n){const i=this.nextId++,r=setInterval(()=>{try{e()}catch(e){console.error("[TimerManager] Interval callback error:",e)}},t);return this.timers.set(i,{id:r,endTime:1/0,isInterval:!0,label:n}),this.debug&&console.debug(`[TimerManager] Started interval ${i}${n?` (${n})`:""} every ${t}ms`),i}stop(e){const t=this.timers.get(e);return!!t&&(t.isInterval?clearInterval(t.id):clearTimeout(t.id),this.timers.delete(e),this.debug&&console.debug(`[TimerManager] Stopped ${t.isInterval?"interval":"timeout"} ${e}${t.label?` (${t.label})`:""}`),!0)}stopAll(){const e=this.timers.size;for(const[e,t]of this.timers)t.isInterval?clearInterval(t.id):clearTimeout(t.id);this.timers.clear(),this.debug&&e>0&&console.debug(`[TimerManager] Stopped all ${e} timers`)}get activeCount(){return this.timers.size}isActive(e){return this.timers.has(e)}getRemainingTime(e){const t=this.timers.get(e);return!t||t.isInterval?0:Math.max(0,t.endTime-Date.now())}getDebugInfo(){const e=[];for(const[t,n]of this.timers)e.push({id:t,type:n.isInterval?"interval":"timeout",label:n.label,remainingMs:n.isInterval?void 0:Math.max(0,n.endTime-Date.now())});return e}destroy(){this.stopAll()}}const tt={status:"OFFLINE",isOnline:!1,message:"Connecting...",lastUpdate:0};class nt extends Qe{constructor(e){super(),this.state={...tt},this.ws=null,this.timers=new et,this.isRunning=!1,this.wasOnline=!1,this.connectionId=0,this.config={pollInterval:3e3,useWebSocket:!0,...e}}start(){if(this.isRunning)return;this.isRunning=!0;const{mistBaseUrl:e,streamName:t,useWebSocket:n}=this.config;if(!e||!t)return void console.warn("[StreamStateClient] Missing mistBaseUrl or streamName");this.setState({...tt,message:"Connecting...",lastUpdate:Date.now()});const i=++this.connectionId;this.timers.start(()=>{this.isRunning&&this.connectionId===i&&this.pollHttp().then(()=>{n&&this.isRunning&&this.connectionId===i&&this.connectWebSocket()})},nt.CONNECTION_DEBOUNCE_MS,"connect")}stop(){this.isRunning=!1,this.ws&&(this.ws.close(),this.ws=null),this.timers.destroy()}refresh(){this.config.useWebSocket&&this.ws?.readyState===WebSocket.OPEN||this.pollHttp()}getSocket(){return this.ws}isSocketReady(){return this.ws?.readyState===WebSocket.OPEN}getState(){return{...this.state}}isOnline(){return this.state.isOnline}updateConfig(e){const t=this.isRunning;this.stop(),this.config={...this.config,...e},t&&this.start()}destroy(){this.stop(),this.removeAllListeners()}connectWebSocket(){if(!this.isRunning)return;const{mistBaseUrl:e,streamName:t}=this.config;this.ws&&(this.ws.close(),this.ws=null);try{const n=e.replace(/^http:/,"ws:").replace(/^https:/,"wss:").replace(/\/$/,""),i=new WebSocket(`${n}/json_${encodeURIComponent(t)}.js?metaeverywhere=1&inclzero=1`);this.ws=i,i.onopen=()=>{console.debug("[StreamStateClient] WebSocket connected")},i.onmessage=e=>{try{const t=JSON.parse(e.data);this.processStreamInfo(t)}catch(e){console.warn("[StreamStateClient] Failed to parse WebSocket message:",e)}},i.onerror=()=>{console.warn("[StreamStateClient] WebSocket error, falling back to HTTP polling"),i.close()},i.onclose=()=>{this.ws=null,this.isRunning&&(this.config.useWebSocket=!1,console.debug("[StreamStateClient] WebSocket closed, switching to HTTP polling"),this.pollHttp())}}catch(e){console.warn("[StreamStateClient] WebSocket connection failed:",e),this.config.useWebSocket=!1,this.pollHttp()}}async pollHttp(){if(!this.isRunning)return;const{mistBaseUrl:e,streamName:t,pollInterval:n}=this.config;try{const n=`${e.replace(/\/$/,"")}/json_${encodeURIComponent(t)}.js?metaeverywhere=1&inclzero=1`,i=await fetch(n,{method:"GET",headers:{Accept:"application/json"}});if(!i.ok)throw new Error(`HTTP ${i.status}`);let r=await i.text();const s=r.match(/^[^(]+\(([\s\S]*)\);?$/);s&&(r=s[1]);const a=JSON.parse(r);this.processStreamInfo(a)}catch(e){if(!this.isRunning)return;const t=e instanceof Error?e.message:"Connection failed";this.setState({...this.state,status:"ERROR",isOnline:!1,message:t,lastUpdate:Date.now(),error:t}),this.emit("error",{error:t})}this.isRunning&&!this.config.useWebSocket&&this.timers.start(()=>this.pollHttp(),n,"poll")}processStreamInfo(e){if(!this.isRunning)return;let t;if(e.error){const n=function(e){const t=e.toLowerCase();return t.includes("offline")?"OFFLINE":t.includes("initializing")?"INITIALIZING":t.includes("booting")?"BOOTING":t.includes("waiting for data")?"WAITING_FOR_DATA":t.includes("shutting down")?"SHUTTING_DOWN":t.includes("invalid")?"INVALID":"ERROR"}(e.error),i=e.on_error||function(e,t){switch(e){case"ONLINE":return"Stream is online";case"OFFLINE":return"Stream is offline";case"INITIALIZING":return void 0!==t?`Initializing... ${Math.round(10*t)/10}%`:"Stream is initializing";case"BOOTING":return"Stream is starting up";case"WAITING_FOR_DATA":return"Waiting for stream data";case"SHUTTING_DOWN":return"Stream is shutting down";case"INVALID":return"Stream status is invalid";default:return"Stream error"}}(n,e.perc);t={status:n,isOnline:!1,message:i,percentage:e.perc,lastUpdate:Date.now(),error:e.error,streamInfo:this.state.streamInfo}}else{const n={...this.state.streamInfo,...e,source:e.source||this.state.streamInfo?.source,meta:{...this.state.streamInfo?.meta,...e.meta,tracks:e.meta?.tracks||this.state.streamInfo?.meta?.tracks}};t={status:"ONLINE",isOnline:!0,message:"Stream is online",lastUpdate:Date.now(),streamInfo:n}}this.setState(t),t.isOnline&&!this.wasOnline?this.emit("online",void 0):!t.isOnline&&this.wasOnline&&this.emit("offline",void 0),this.wasOnline=t.isOnline}setState(e){const t=this.state;this.state=e;(t.status!==e.status||t.isOnline!==e.isOnline||t.message!==e.message||t.streamInfo!==e.streamInfo||t.lastUpdate!==e.lastUpdate)&&this.emit("stateChange",{state:e})}}nt.CONNECTION_DEBOUNCE_MS=100;const it=[{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"]},load:()=>Promise.resolve().then(function(){return Dn}).then(e=>new e.NativePlayerImpl)},{capability:{name:"WebCodecs Player",shortname:"webcodecs",priority:0,mimes:["ws/video/raw","wss/video/raw","ws/video/h264","wss/video/h264"]},load:()=>Promise.resolve().then(function(){return Wn}).then(e=>new e.WebCodecsPlayerImpl)},{capability:{name:"MistServer WebRTC",shortname:"mist-webrtc",priority:2,mimes:["webrtc","mist/webrtc"]},load:()=>Promise.resolve().then(function(){return Kn}).then(e=>new e.MistWebRTCPlayerImpl)},{capability:{name:"Video.js Player",shortname:"videojs",priority:2,mimes:["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"]},load:()=>Promise.resolve().then(function(){return Qn}).then(e=>new e.VideoJsPlayerImpl)},{capability:{name:"HLS.js Player",shortname:"hlsjs",priority:3,mimes:["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"]},load:()=>Promise.resolve().then(function(){return Xn}).then(e=>new e.HlsJsPlayerImpl)},{capability:{name:"Dash.js Player",shortname:"dashjs",priority:100,mimes:["dash/video/mp4"]},load:()=>Promise.resolve().then(function(){return Jn}).then(e=>new e.DashJsPlayerImpl)},{capability:{name:"Legacy",shortname:"mist-legacy",priority:99,mimes:["mist/legacy"]},load:()=>Promise.resolve().then(function(){return Zn}).then(e=>new e.MistPlayerImpl)},{capability:{name:"MEWS WebSocket Player",shortname:"mews",priority:2,mimes:["ws/video/mp4","wss/video/mp4","ws/video/webm","wss/video/webm"]},load:()=>Promise.resolve().then(function(){return ri}).then(e=>new e.MewsWsPlayerImpl)}],rt=new WeakMap;function st(e){let t=rt.get(e);return t||(t=new Set,rt.set(e,t)),t}async function at(e,t){const n=st(e),i=it.filter(e=>!n.has(e.capability.shortname)&&e.capability.mimes.some(e=>t.includes(e)));if(0===i.length)return;const r=await Promise.all(i.map(e=>e.load()));for(const t of r){n.add(t.capability.shortname);const i=e.getRegisteredPlayers().some(e=>e.capability.shortname===t.capability.shortname);i||e.registerPlayer(t)}}const ot=new WeakMap;function lt(e=ct){if(st(e).size===it.length)return Promise.resolve();const t=ot.get(e);if(t)return t;const n=async function(e){const t=it.flatMap(e=>e.capability.mimes);return at(e,t)}(e).catch(t=>{throw console.error("[PlayerRegistry] Registration failed:",t),ot.delete(e),t});return ot.set(e,n),n}const ut=Ke.prototype.initializePlayer;Ke.prototype.initializePlayer=async function(...e){const[t,n,i,r]=e,s=n?.source?.map(e=>e.type)??[];return s.length>0?(await at(this,s),r?.forcePlayer&&await async function(e,t){const n=st(e);if(n.has(t))return;const i=it.find(e=>e.capability.shortname===t);if(!i)return;const r=await i.load();n.add(r.capability.shortname);const s=e.getRegisteredPlayers().some(e=>e.capability.shortname===r.capability.shortname);s||e.registerPlayer(r)}(this,r.forcePlayer)):await lt(this),ut.apply(this,e)};const dt=(()=>{try{const e=globalThis.process,t=e?.env;return"development"===t?.NODE_ENV}catch{return!1}})(),ct=new Ke({debug:dt,autoFallback:!0,maxFallbackAttempts:3}),ht={mode:"auto",maxResolution:{width:1920,height:1080},maxBitrate:8e6,minBufferForUpgrade:10,downgradeThreshold:60};class ft{constructor(e){this.videoElement=null,this.currentQualityId="auto",this.lastDecision="none",this.lastDecisionTime=0,this.resizeObserver=null,this.qualityChangeCallbacks=[],this.timers=new et,this.bandwidthHistory=[],this.lastUpgradeTime=0,this.lastDowngradeTime=0,this.currentQualityBitrate=0,this.options={...ht,...e.options},this.config=e,this.debug=e.debug??!1}start(e){this.stop(),this.videoElement=e,"manual"!==this.options.mode?("resize"!==this.options.mode&&"auto"!==this.options.mode||this.setupResizeObserver(),"bitrate"!==this.options.mode&&"auto"!==this.options.mode||this.startActiveMonitoring()):this.log("Manual mode - no automatic ABR")}stop(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.timers.destroy(),this.videoElement=null,this.bandwidthHistory=[]}startActiveMonitoring(){this.timers.startInterval(()=>this.checkBandwidthAndSwitch(),ft.MONITORING_INTERVAL_MS,"monitoring"),this.checkBandwidthAndSwitch()}async checkBandwidthAndSwitch(){if(!this.videoElement)return;const e=Date.now(),t=await this.getBandwidthEstimate();if(t<=0)return;this.bandwidthHistory.push(t),this.bandwidthHistory.length>ft.BANDWIDTH_HISTORY_SIZE&&this.bandwidthHistory.shift();const n=this.getSmoothedBandwidth();if(n<=0)return;const i=this.config.getQualities(),r=this.config.getCurrentQuality?.();if(!r||0===i.length)return;const s=r.bitrate||0;if(this.currentQualityBitrate!==s&&(this.currentQualityBitrate=s),e-this.lastDowngradeTime>=ft.DOWNGRADE_COOLDOWN_MS&&n<s*ft.DOWNGRADE_THRESHOLD){const t=this.findLowerQuality(i,r);if(t)return this.log(`ABR: bandwidth ${Math.round(n/1e3)}kbps < ${Math.round(s*ft.DOWNGRADE_THRESHOLD/1e3)}kbps threshold -> downgrading to ${t.label}`),this.lastDecision="downgrade",this.lastDecisionTime=e,this.lastDowngradeTime=e,void this.selectQuality(t.id)}if(e-this.lastUpgradeTime>=ft.UPGRADE_COOLDOWN_MS){const t=this.findHigherQuality(i,r);if(t&&this.isWithinConstraints(t)){const i=t.bitrate||0;if(n>=i*ft.UPGRADE_HEADROOM)return this.log(`ABR: bandwidth ${Math.round(n/1e3)}kbps >= ${Math.round(i*ft.UPGRADE_HEADROOM/1e3)}kbps headroom -> upgrading to ${t.label}`),this.lastDecision="upgrade",this.lastDecisionTime=e,this.lastUpgradeTime=e,void this.selectQuality(t.id)}}}async getBandwidthEstimate(){if(this.config.getBandwidthEstimate){const e=await this.config.getBandwidthEstimate();if(e>0)return e}const e=this.videoElement;return e&&e.buffered.length,0}getSmoothedBandwidth(){if(0===this.bandwidthHistory.length)return 0;if(this.bandwidthHistory.length<3)return 0;const e=this.bandwidthHistory.reduce((e,t)=>e+t,0);return e/this.bandwidthHistory.length}getCurrentBandwidth(){return this.getSmoothedBandwidth()}setupResizeObserver(){const e=this.videoElement;if(!e)return;this.resizeObserver=new ResizeObserver(e=>{for(const t of e){const{width:e,height:n}=t.contentRect;this.handleResize(e,n)}});const t=e.parentElement;t&&this.resizeObserver.observe(t);const n=e.getBoundingClientRect();this.handleResize(n.width,n.height)}handleResize(e,t){if("resize"!==this.options.mode&&"auto"!==this.options.mode)return;const n=this.config.getQualities();if(0===n.length)return;const i=Math.min(e*window.devicePixelRatio,this.options.maxResolution.width),r=Math.min(t*window.devicePixelRatio,this.options.maxResolution.height),s=this.findBestQualityForResolution(n,i,r);s&&s.id!==this.currentQualityId&&(this.log(`Resize ABR: ${e}x${t} -> selecting ${s.label}`),this.selectQuality(s.id))}handleQualityDegraded(e){if("bitrate"!==this.options.mode&&"auto"!==this.options.mode)return;const t=Date.now();if(!(t-this.lastDowngradeTime<ft.DOWNGRADE_COOLDOWN_MS)&&e.score<this.options.downgradeThreshold){const n=this.config.getQualities(),i=this.config.getCurrentQuality?.();if(i){const r=this.findLowerQuality(n,i);r&&(this.log(`Bitrate ABR: score ${e.score} -> downgrading to ${r.label}`),this.lastDecision="downgrade",this.lastDecisionTime=t,this.lastDowngradeTime=t,this.selectQuality(r.id))}}}handleQualityImproved(e){if("bitrate"!==this.options.mode&&"auto"!==this.options.mode)return;const t=Date.now();if(!(t-this.lastUpgradeTime<ft.UPGRADE_COOLDOWN_MS)&&e.score>=90&&e.bufferedAhead>=this.options.minBufferForUpgrade){const n=this.config.getQualities(),i=this.config.getCurrentQuality?.();if(i){const r=this.findHigherQuality(n,i);r&&this.isWithinConstraints(r)&&(this.log(`Bitrate ABR: score ${e.score} -> upgrading to ${r.label}`),this.lastDecision="upgrade",this.lastDecisionTime=t,this.lastUpgradeTime=t,this.selectQuality(r.id))}}}findBestQualityForResolution(e,t,n){const i=e.filter(e=>this.isWithinConstraints(e));if(0===i.length)return null;const r=[...i].sort((e,t)=>(e.width??0)*(e.height??0)-(t.width??0)*(t.height??0));for(const e of r){const i=e.width??0,r=e.height??0;if(i>=t&&r>=n)return e}return r[r.length-1]}findLowerQuality(e,t){const n=t.bitrate??0,i=[...e].sort((e,t)=>(t.bitrate??0)-(e.bitrate??0));for(const e of i)if((e.bitrate??0)<n)return e;return null}findHigherQuality(e,t){const n=t.bitrate??0,i=[...e].sort((e,t)=>(e.bitrate??0)-(t.bitrate??0));for(const e of i)if((e.bitrate??0)>n)return e;return null}isWithinConstraints(e){const{maxResolution:t,maxBitrate:n}=this.options;return!(e.width&&e.width>t.width)&&(!(e.height&&e.height>t.height)&&!(e.bitrate&&e.bitrate>n))}selectQuality(e){this.currentQualityId=e,this.config.selectQuality(e);const t=this.config.getQualities().find(t=>t.id===e);t&&this.qualityChangeCallbacks.forEach(e=>e(t))}onQualityChange(e){return this.qualityChangeCallbacks.push(e),()=>{const t=this.qualityChangeCallbacks.indexOf(e);t>=0&&this.qualityChangeCallbacks.splice(t,1)}}setQuality(e){this.selectQuality(e)}getMode(){return this.options.mode}setMode(e){if(this.options.mode!==e&&(this.options.mode=e,this.log(`Mode changed to: ${e}`),this.videoElement)){const e=this.videoElement;this.stop(),this.start(e)}}updateOptions(e){this.options={...this.options,...e}}getLastDecision(){return this.lastDecision}log(e){this.debug&&console.debug(`[ABRController] ${e}`)}}ft.BANDWIDTH_HISTORY_SIZE=10,ft.MONITORING_INTERVAL_MS=1e3,ft.UPGRADE_COOLDOWN_MS=5e3,ft.DOWNGRADE_COOLDOWN_MS=0,ft.UPGRADE_HEADROOM=1.5,ft.UPGRADE_HOLD_THRESHOLD=1.2,ft.DOWNGRADE_THRESHOLD=.8;class pt{constructor(e){this.isAttached=!1,this.spaceKeyDownTime=0,this.spaceIsHeld=!1,this.holdCheckTimeout=null,this.pointerDownTime=0,this.pointerIsHeld=!1,this.pointerHoldTimeout=null,this.lastTapTime=0,this.lastTapX=0,this.pendingTapTimeout=null,this.idleTimeout=null,this.lastInteractionTime=0,this.config=e,this.state={isHoldingSpeed:!1,previousSpeed:1,holdSpeed:e.speedHoldValue??2,isIdle:!1},this.boundKeyDown=this.handleKeyDown.bind(this),this.boundKeyUp=this.handleKeyUp.bind(this),this.boundPointerDown=this.handlePointerDown.bind(this),this.boundPointerUp=this.handlePointerUp.bind(this),this.boundPointerCancel=this.handlePointerCancel.bind(this),this.boundContextMenu=this.handleContextMenu.bind(this),this.boundMouseMove=this.handleMouseMove.bind(this),this.boundDoubleClick=this.handleDoubleClick.bind(this),this.boundDocumentKeyDown=this.handleKeyDown.bind(this),this.boundDocumentKeyUp=this.handleKeyUp.bind(this)}attach(){if(this.isAttached)return;const{container:e}=this.config;e.hasAttribute("tabindex")||e.setAttribute("tabindex","0"),e.addEventListener("keydown",this.boundKeyDown),e.addEventListener("keyup",this.boundKeyUp),document.addEventListener("keydown",this.boundDocumentKeyDown),document.addEventListener("keyup",this.boundDocumentKeyUp),e.addEventListener("pointerdown",this.boundPointerDown),e.addEventListener("pointerup",this.boundPointerUp),e.addEventListener("pointercancel",this.boundPointerCancel),e.addEventListener("pointerleave",this.boundPointerCancel),e.addEventListener("mousemove",this.boundMouseMove),e.addEventListener("dblclick",this.boundDoubleClick),e.addEventListener("contextmenu",this.boundContextMenu),this.resetIdleTimer(),this.isAttached=!0}detach(){if(!this.isAttached)return;const{container:e}=this.config;e.removeEventListener("keydown",this.boundKeyDown),e.removeEventListener("keyup",this.boundKeyUp),document.removeEventListener("keydown",this.boundDocumentKeyDown),document.removeEventListener("keyup",this.boundDocumentKeyUp),e.removeEventListener("pointerdown",this.boundPointerDown),e.removeEventListener("pointerup",this.boundPointerUp),e.removeEventListener("pointercancel",this.boundPointerCancel),e.removeEventListener("pointerleave",this.boundPointerCancel),e.removeEventListener("mousemove",this.boundMouseMove),e.removeEventListener("dblclick",this.boundDoubleClick),e.removeEventListener("contextmenu",this.boundContextMenu),this.holdCheckTimeout&&(clearTimeout(this.holdCheckTimeout),this.holdCheckTimeout=null),this.pointerHoldTimeout&&(clearTimeout(this.pointerHoldTimeout),this.pointerHoldTimeout=null),this.pendingTapTimeout&&(clearTimeout(this.pendingTapTimeout),this.pendingTapTimeout=null),this.idleTimeout&&(clearTimeout(this.idleTimeout),this.idleTimeout=null),this.state.isHoldingSpeed&&this.releaseSpeedHold(),this.isAttached=!1}isHoldingSpeed(){return this.state.isHoldingSpeed}isIdle(){return this.state.isIdle}getState(){return{...this.state}}updateConfig(e){this.config={...this.config,...e},e.isLive&&this.state.isHoldingSpeed&&this.releaseSpeedHold()}handleKeyDown(e){if(this.isInputElement(e.target))return;if(e.defaultPrevented)return;if(!this.shouldHandleKeyboard(e))return;this.recordInteraction();const{isLive:t}=this.config,n=this.config.isPaused?.()??this.config.videoElement?.paused??!1;switch(e.key){case" ":case"Spacebar":e.preventDefault(),this.handleSpaceDown();break;case"ArrowLeft":case"j":case"J":e.preventDefault(),t||this.config.onSeek(-10);break;case"ArrowRight":case"l":case"L":e.preventDefault(),t||this.config.onSeek(10);break;case"ArrowUp":e.preventDefault(),this.config.onVolumeChange(.1);break;case"ArrowDown":e.preventDefault(),this.config.onVolumeChange(-.1);break;case"m":case"M":e.preventDefault(),this.config.onMuteToggle();break;case"f":case"F":e.preventDefault(),this.config.onFullscreenToggle();break;case"c":case"C":e.preventDefault(),this.config.onCaptionsToggle?.();break;case"k":case"K":e.preventDefault(),this.config.onPlayPause();break;case"<":e.preventDefault(),t||this.adjustPlaybackSpeed(-.25);break;case">":e.preventDefault(),t||this.adjustPlaybackSpeed(.25);break;case",":(this.config.onFrameStep||!t&&n)&&(e.preventDefault(),this.stepFrame(-1));break;case".":(this.config.onFrameStep||!t&&n)&&(e.preventDefault(),this.stepFrame(1));break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":if(e.preventDefault(),!t&&this.config.onSeekPercent){const t=parseInt(e.key,10)/10;this.config.onSeekPercent(t)}}}handleKeyUp(e){this.isInputElement(e.target)||e.defaultPrevented||this.shouldHandleKeyboard(e)&&(" "!==e.key&&"Spacebar"!==e.key||(e.preventDefault(),this.handleSpaceUp()))}shouldHandleKeyboard(e){if(this.spaceKeyDownTime>0)return!0;const t=e.target;if(t&&this.config.container.contains(t))return!0;const n=document.activeElement;if(n&&this.config.container.contains(n))return!0;try{if(this.config.container.matches(":focus-within"))return!0;if(this.config.container.matches(":hover"))return!0}catch{}return Date.now()-this.lastInteractionTime<5e3}handleSpaceDown(){this.spaceKeyDownTime>0||(this.spaceKeyDownTime=Date.now(),this.spaceIsHeld=!1,this.config.isLive||(this.holdCheckTimeout=setTimeout(()=>{this.spaceIsHeld=!0,this.engageSpeedHold()},200)))}handleSpaceUp(){const e=this.spaceKeyDownTime;if(this.spaceKeyDownTime=0,this.holdCheckTimeout&&(clearTimeout(this.holdCheckTimeout),this.holdCheckTimeout=null),this.spaceIsHeld)this.releaseSpeedHold(),this.spaceIsHeld=!1;else{(Date.now()-e<200||this.config.isLive)&&this.config.onPlayPause()}}handleDoubleClick(e){this.isControlElement(e.target)||(this.recordInteraction(),e.preventDefault(),this.config.onFullscreenToggle())}stepFrame(e){const t=this.getFrameStepSeconds();if(!Number.isFinite(t)||t<=0)return;if(this.config.onFrameStep?.(e,t))return;const n=this.config.videoElement;if(!n)return;const i=n.currentTime+e*t;if(!Number.isFinite(i))return;const r=n.buffered;if(r&&r.length>0)for(let e=0;e<r.length;e++){const t=r.start(e),s=r.end(e);if(i>=t&&i<=s){try{n.currentTime=i}catch{}return}}}handlePointerDown(e){if(0!==e.button)return;if(this.isControlElement(e.target))return;this.recordInteraction(),this.config.container.focus();const t=Date.now(),n=this.config.container.getBoundingClientRect(),i=(e.clientX-n.left)/n.width,r="mouse"===e.pointerType;if(t-this.lastTapTime<300)return this.pendingTapTimeout&&(clearTimeout(this.pendingTapTimeout),this.pendingTapTimeout=null),r||this.config.isLive||(i<.33?this.config.onSeek(-10):i>.67?this.config.onSeek(10):this.config.onPlayPause()),void(this.lastTapTime=0);this.lastTapTime=t,this.lastTapX=i,this.pointerDownTime=t,this.pointerIsHeld=!1,this.config.isLive||(this.pointerHoldTimeout=setTimeout(()=>{this.pointerIsHeld=!0,this.engageSpeedHold()},300))}handlePointerUp(e){if(0!==e.button)return;const t=this.pointerIsHeld;this.cancelPointerHold(),t?this.releaseSpeedHold():this.pointerDownTime>0&&(this.pendingTapTimeout=setTimeout(()=>{this.pendingTapTimeout=null,this.config.onPlayPause()},300)),this.pointerDownTime=0}handlePointerCancel(e){this.pointerIsHeld&&this.releaseSpeedHold(),this.cancelPointerHold(),this.pointerDownTime=0}cancelPointerHold(){this.pointerHoldTimeout&&(clearTimeout(this.pointerHoldTimeout),this.pointerHoldTimeout=null),this.pointerIsHeld=!1}handleContextMenu(e){(this.pointerIsHeld||this.pointerDownTime>0)&&e.preventDefault()}engageSpeedHold(){this.state.isHoldingSpeed||this.config.isLive||(this.state.previousSpeed=this.config.videoElement.playbackRate,this.state.isHoldingSpeed=!0,this.config.onSpeedChange(this.state.holdSpeed,!0))}releaseSpeedHold(){this.state.isHoldingSpeed&&(this.state.isHoldingSpeed=!1,this.config.onSpeedChange(this.state.previousSpeed,!1))}adjustPlaybackSpeed(e){if(this.state.isHoldingSpeed)return;const t=this.config.videoElement.playbackRate,n=Math.max(.25,Math.min(4,t+e)),i=Math.round(100*n)/100;this.config.onSpeedChange(i,!1)}handleMouseMove(e){this.recordInteraction()}recordInteraction(){this.lastInteractionTime=Date.now(),this.state.isIdle&&(this.state.isIdle=!1,this.config.onActive?.()),this.resetIdleTimer()}resetIdleTimer(){this.idleTimeout&&(clearTimeout(this.idleTimeout),this.idleTimeout=null);const e=this.config.idleTimeout??5e3;e<=0||(this.idleTimeout=setTimeout(()=>{this.idleTimeout=null,this.state.isIdle||(this.state.isIdle=!0,this.config.onIdle?.())},e))}markActive(){this.recordInteraction()}pauseIdleTracking(){this.idleTimeout&&(clearTimeout(this.idleTimeout),this.idleTimeout=null)}resumeIdleTracking(){this.isAttached&&this.resetIdleTimer()}isInputElement(e){if(!(e&&e instanceof HTMLElement))return!1;const t=e.tagName.toLowerCase();return"input"===t||"textarea"===t||"select"===t||e.isContentEditable}isControlElement(e){if(!(e&&e instanceof HTMLElement))return!1;return["button",'[role="button"]','[role="slider"]',"input","select",".fw-player-controls","[data-player-controls]",".fw-controls-wrapper",".fw-control-bar",".fw-settings-menu",".fw-context-menu",".fw-stats-panel",".fw-dev-panel",".fw-error-overlay",".fw-error-popup",".fw-player-error"].some(t=>e.matches(t)||null!==e.closest(t))}getFrameStepSeconds(){const e=this.config.frameStepSeconds;return Number.isFinite(e)&&e>0?e:1/30}}class gt{constructor(e={}){this.socket=null,this.videoElement=null,this.containerElement=null,this.logs=[],this.waitingSince=0,this.stalledSince=0,this.unpausedSince=0,this.timeWaitingAccum=0,this.timeStalledAccum=0,this.timeUnpausedAccum=0,this.lastReported={},this.timers=new et,this.listeners=[],this.firstPlaybackRecorded=!1,this.pendingBatch={},this.hasPendingBatch=!1,this.lastFlushTime=0,this.batchFlushTimerId=null,this.offlineQueue=[],this.socket=e.socket??null,this.reportInterval=e.reportInterval??5e3,this.batchFlushInterval=e.batchFlushInterval??1e3,this.bootMs=e.bootMs??Date.now(),this.logs=e.logs??[],this._stats={_nWaiting:0,_nStalled:0,_nError:0,lastError:null,firstPlayback:null,playbackScore:1,autoplay:null,tracks:null},this.lastReported={nWaiting:0,timeWaiting:0,nStalled:0,timeStalled:0,timeUnpaused:0,nError:0,lastError:null,firstPlayback:null,playbackScore:1,autoplay:null,videoHeight:null,videoWidth:null,playerHeight:null,playerWidth:null,tracks:null,nLog:0}}setSocket(e){const t=!this.socket||this.socket.readyState!==WebSocket.OPEN;this.socket=e,t&&e?.readyState===WebSocket.OPEN&&this.flushOfflineQueue()}flushOfflineQueue(){if(0!==this.offlineQueue.length){for(const e of this.offlineQueue)this.sendReport(e);this.offlineQueue=[]}}getStats(){const e=performance.now();return{nWaiting:this._stats._nWaiting,timeWaiting:Math.round(this.timeWaitingAccum+(this.waitingSince>0?e-this.waitingSince:0)),nStalled:this._stats._nStalled,timeStalled:Math.round(this.timeStalledAccum+(this.stalledSince>0?e-this.stalledSince:0)),timeUnpaused:Math.round(this.timeUnpausedAccum+(this.unpausedSince>0?e-this.unpausedSince:0)),nError:this._stats._nError,lastError:this._stats.lastError,firstPlayback:this._stats.firstPlayback,playbackScore:Math.round(10*this._stats.playbackScore)/10,autoplay:this._stats.autoplay,videoHeight:this.videoElement?.videoHeight??null,videoWidth:this.videoElement?.videoWidth??null,playerHeight:this.containerElement?.clientHeight??null,playerWidth:this.containerElement?.clientWidth??null,tracks:this._stats.tracks,nLog:this.logs.length}}set(e,t){"nWaiting"===e?this._stats._nWaiting=t:"nStalled"===e?this._stats._nStalled=t:"nError"===e?this._stats._nError=t:"lastError"===e?this._stats.lastError=t:"firstPlayback"===e?this._stats.firstPlayback=t:"playbackScore"===e?this._stats.playbackScore=t:"autoplay"===e?this._stats.autoplay=t:"tracks"===e&&(this._stats.tracks=t)}add(e,t=1){"nWaiting"===e?this._stats._nWaiting+=t:"nStalled"===e?this._stats._nStalled+=t:"nError"===e&&(this._stats._nError+=t)}init(e,t){this.videoElement=e,this.containerElement=t??e.parentElement??null,this.firstPlaybackRecorded=!1;const n=()=>{const e=performance.now(),t=!this.firstPlaybackRecorded;t&&(this._stats.firstPlayback=Date.now()-this.bootMs,this.firstPlaybackRecorded=!0),this.waitingSince>0&&(this.timeWaitingAccum+=e-this.waitingSince,this.waitingSince=0),this.stalledSince>0&&(this.timeStalledAccum+=e-this.stalledSince,this.stalledSince=0),0===this.unpausedSince&&(this.unpausedSince=e),t&&(this.reportStats(),this.flushBatch())},i=()=>{this._stats._nWaiting++,0===this.waitingSince&&(this.waitingSince=performance.now())},r=()=>{this._stats._nStalled++,0===this.stalledSince&&(this.stalledSince=performance.now())},s=()=>{this.unpausedSince>0&&(this.timeUnpausedAccum+=performance.now()-this.unpausedSince,this.unpausedSince=0)},a=e=>{this._stats._nError++;const t=e.message||"Unknown error";this._stats.lastError=t,this.reportStats(),this.flushBatch()},o=()=>{this.waitingSince>0&&(this.timeWaitingAccum+=performance.now()-this.waitingSince,this.waitingSince=0)};e.addEventListener("playing",n),e.addEventListener("waiting",i),e.addEventListener("stalled",r),e.addEventListener("pause",s),e.addEventListener("error",a),e.addEventListener("canplay",o),this.listeners=[()=>e.removeEventListener("playing",n),()=>e.removeEventListener("waiting",i),()=>e.removeEventListener("stalled",r),()=>e.removeEventListener("pause",s),()=>e.removeEventListener("error",a),()=>e.removeEventListener("canplay",o)],this.startReporting()}sendInitialReport(e){this.report(e)}setPlaybackScore(e){this._stats.playbackScore=e}setAutoplayStatus(e){this._stats.autoplay=e}setTracks(e){this._stats.tracks=e.join(",")}sendReport(e){if(this.socket&&this.socket.readyState===WebSocket.OPEN)try{this.socket.send(JSON.stringify(e))}catch{this.offlineQueue.length<gt.MAX_OFFLINE_QUEUE_SIZE&&this.offlineQueue.push(e)}else this.offlineQueue.length<gt.MAX_OFFLINE_QUEUE_SIZE&&this.offlineQueue.push(e)}report(e){if(Object.assign(this.pendingBatch,e),this.hasPendingBatch=!0,null===this.batchFlushTimerId){const e=performance.now()-this.lastFlushTime,t=Math.max(0,this.batchFlushInterval-e);this.batchFlushTimerId=this.timers.start(()=>{this.batchFlushTimerId=null,this.flushBatch()},t,"batchFlush")}}flushBatch(){null!==this.batchFlushTimerId&&(this.timers.stop(this.batchFlushTimerId),this.batchFlushTimerId=null),this.hasPendingBatch&&(this.sendReport(this.pendingBatch),this.pendingBatch={},this.hasPendingBatch=!1,this.lastFlushTime=performance.now())}reportStats(){const e=this.getStats(),t={};let n=!1;const i=["nWaiting","timeWaiting","nStalled","timeStalled","timeUnpaused","nError","lastError","firstPlayback","playbackScore","autoplay","videoHeight","videoWidth","playerHeight","playerWidth","tracks","nLog"];for(const r of i){const i=e[r];i!==this.lastReported[r]&&(t[r]=i,this.lastReported[r]=i,n=!0)}const r=this.lastReported.nLog??0;if(this.logs.length>r){const e=this.logs.slice(r);e.length>0&&(t.logs=e,n=!0)}n&&this.report(t),this.scheduleNextReport()}startReporting(){this.scheduleNextReport()}scheduleNextReport(){this.timers.start(()=>{this.reportStats()},this.reportInterval,"report")}sendFinalReport(e){this.reportStats(),this.report({unload:e??null}),this.flushBatch()}destroy(){this.timers.destroy(),this.listeners.forEach(e=>e()),this.listeners=[],this.videoElement=null,this.containerElement=null}log(e){this.logs.push(e)}}gt.MAX_OFFLINE_QUEUE_SIZE=100;const mt={minScore:60,maxStalls:3,minBuffer:2},yt={webrtc:.95,hls:.75,dash:.75,html5:.75,unknown:.75};class bt{constructor(e={}){this.videoElement=null,this.timers=new et,this.stallCount=0,this.lastStallTime=0,this.totalStallMs=0,this.history=[],this.lastBytesLoaded=0,this.lastBytesTime=0,this.listeners=[],this.playbackScoreHistory=[],this.playbackScore=1,this.PLAYBACK_SCORE_AVERAGING_STEPS=10,this.consecutivePoorSamples=0,this.fallbackTriggered=!1,this.options={sampleInterval:e.sampleInterval??500,thresholds:e.thresholds??{},onQualityDegraded:e.onQualityDegraded??(()=>{}),onSample:e.onSample??(()=>{}),protocol:e.protocol??"unknown",playbackScoreThreshold:e.playbackScoreThreshold??null,onFallbackRequest:e.onFallbackRequest??(()=>{}),poorSamplesBeforeFallback:e.poorSamplesBeforeFallback??5},this.thresholds={...mt,...e.thresholds}}setProtocol(e){this.options.protocol=e}getProtocol(){return this.options.protocol}getPlaybackScoreThreshold(){return null!==this.options.playbackScoreThreshold?this.options.playbackScoreThreshold:yt[this.options.protocol]}setPlaybackScoreThreshold(e){this.options.playbackScoreThreshold=e}start(e){this.stop(),this.videoElement=e,this.stallCount=0,this.totalStallMs=0,this.lastStallTime=0,this.history=[],this.lastBytesLoaded=0,this.lastBytesTime=0,this.consecutivePoorSamples=0,this.fallbackTriggered=!1,this.playbackScoreHistory=[],this.playbackScore=1;const t=()=>{this.stallCount++,this.lastStallTime=performance.now()},n=()=>{this.lastStallTime>0&&(this.totalStallMs+=performance.now()-this.lastStallTime,this.lastStallTime=0)},i=()=>{this.lastStallTime>0&&(this.totalStallMs+=performance.now()-this.lastStallTime,this.lastStallTime=0)};e.addEventListener("waiting",t),e.addEventListener("playing",n),e.addEventListener("canplay",i),this.listeners=[()=>e.removeEventListener("waiting",t),()=>e.removeEventListener("playing",n),()=>e.removeEventListener("canplay",i)],this.timers.startInterval(()=>this.sample(),this.options.sampleInterval,"sampling"),this.sample()}stop(){this.timers.destroy(),this.listeners.forEach(e=>e()),this.listeners=[],this.videoElement=null}sample(){const e=this.videoElement;if(!e)return;this.updatePlaybackScore();const t=this.calculateQuality(e);this.history.push(t),this.history.length>20&&this.history.shift(),this.options.onSample(t),(t.score<this.thresholds.minScore||t.stallCount>this.thresholds.maxStalls||t.bufferedAhead<this.thresholds.minBuffer)&&this.options.onQualityDegraded(t),this.isPlaybackPoor()?(this.consecutivePoorSamples++,!this.fallbackTriggered&&this.consecutivePoorSamples>=this.options.poorSamplesBeforeFallback&&(this.fallbackTriggered=!0,console.warn(`[QualityMonitor] Poor playback detected: ${Math.round(100*this.playbackScore)}% (threshold: ${Math.round(100*this.getPlaybackScoreThreshold())}%, protocol: ${this.options.protocol})`),this.options.onFallbackRequest({score:this.playbackScore,consecutivePoorSamples:this.consecutivePoorSamples}))):(this.consecutivePoorSamples=0,this.fallbackTriggered=!1)}calculateQuality(e){const t=Date.now();let n=0;if(e.buffered.length>0)for(let t=0;t<e.buffered.length;t++)if(e.buffered.start(t)<=e.currentTime&&e.buffered.end(t)>e.currentTime){n=e.buffered.end(t)-e.currentTime;break}let i=0,r=0,s=0;if("getVideoPlaybackQuality"in e){const t=e.getVideoPlaybackQuality();i=t.totalVideoFrames,r=t.droppedVideoFrames,s=i>0?r/i*100:0}let a=0;if(e.buffered.length>0&&this.lastBytesTime>0){const n=(t-this.lastBytesTime)/1e3;if(n>0){const t=e.buffered.end(e.buffered.length-1)-e.currentTime;a=t>0?Math.round(1e6*t/n):0}}this.lastBytesTime=t;let o=0;if((e.duration===1/0||!isFinite(e.duration))&&e.buffered.length>0){o=1e3*(e.buffered.end(e.buffered.length-1)-e.currentTime)}return{score:this.calculateScore({bufferedAhead:n,stallCount:this.stallCount,stallDurationMs:this.totalStallMs,frameDropRate:s,latency:o}),bitrate:a,bufferedAhead:n,stallCount:this.stallCount,frameDropRate:s,latency:o,timestamp:t}}calculateScore(e){let t=100;if(e.bufferedAhead<this.thresholds.minBuffer){t-=Math.min(40,20*(this.thresholds.minBuffer-e.bufferedAhead))}const n=5*e.stallCount,i=e.stallDurationMs/1e3*2;t-=Math.min(30,n+i);if(t-=Math.min(20,2*e.frameDropRate),e.latency>5e3){t-=Math.min(10,(e.latency-5e3)/1e3)}return Math.max(0,Math.round(t))}getCurrentQuality(){return this.history.length>0?this.history[this.history.length-1]:null}getAverageQuality(){if(0===this.history.length)return null;const e={score:0,bitrate:0,bufferedAhead:0,stallCount:this.stallCount,frameDropRate:0,latency:0,timestamp:Date.now()};for(const t of this.history)e.score+=t.score,e.bitrate+=t.bitrate,e.bufferedAhead+=t.bufferedAhead,e.frameDropRate+=t.frameDropRate,e.latency+=t.latency;const t=this.history.length;return e.score=Math.round(e.score/t),e.bitrate=Math.round(e.bitrate/t),e.bufferedAhead=e.bufferedAhead/t,e.frameDropRate=e.frameDropRate/t,e.latency=e.latency/t,e}getHistory(){return[...this.history]}resetStallCounters(){this.stallCount=0,this.totalStallMs=0}getTotalStallMs(){return this.totalStallMs}isMonitoring(){return null!==this.videoElement&&this.timers.activeCount>0}getPlaybackScoreValue(){const e=this.videoElement,t={clock:performance.now()/1e3,video:e?.currentTime??0,score:1};if(this.playbackScoreHistory.length>0){const e=this.playbackScoreHistory[this.playbackScoreHistory.length-1];t.score=this.calculatePlaybackScoreFromEntries(e,t)}return t}calculatePlaybackScoreFromEntries(e,t){const n=this.videoElement;let i=1;n&&(i=n.playbackRate||1);const r=t.clock-e.clock,s=t.video-e.video;return r<=0?1:s/r/i}updatePlaybackScore(){const e=this.getPlaybackScoreValue();if(this.playbackScoreHistory.push(e),this.playbackScoreHistory.length<=1)return 1;const t=this.playbackScoreHistory[0],n=this.playbackScoreHistory[this.playbackScoreHistory.length-1];let i=this.calculatePlaybackScoreFromEntries(t,n);return this.playbackScoreHistory.length>this.PLAYBACK_SCORE_AVERAGING_STEPS&&this.playbackScoreHistory.shift(),i=Math.max(i,e.score),this.playbackScore=i,i}getPlaybackScore(){return this.playbackScore}isPlaybackPoor(){return this.playbackScore<this.getPlaybackScoreThreshold()}resetPlaybackScore(){this.playbackScoreHistory=[],this.playbackScore=1}resetFallbackState(){this.consecutivePoorSamples=0,this.fallbackTriggered=!1}getConsecutivePoorSamples(){return this.consecutivePoorSamples}hasFallbackTriggered(){return this.fallbackTriggered}}class vt{constructor(e){if(this.ws=null,this.state="disconnected",this.subscriptions=new Map,this.pendingSubscriptions=new Set,this.reconnectAttempt=0,this.timers=new et,this.messageBuffer=[],this.connectionId=0,this.currentPlaybackTime=0,this.lastFastForwardTime=0,this.timedEventBuffer=new Map,this.config=e,this.debug=e.debug??!1,this.bufferAhead=e.bufferAhead??5,this.maxMessageAge=e.maxMessageAge??5,this.fastForwardInterval=e.fastForwardInterval??5,e.subscriptions)for(const t of e.subscriptions)this.subscribe(t.trackId,t.callback)}connect(){if("connecting"===this.state||"connected"===this.state)return;this.state="connecting",this.log("Connecting...");const e=++this.connectionId;this.timers.start(()=>{"connecting"===this.state&&this.connectionId===e&&this.createWebSocket(e)},vt.CONNECTION_DEBOUNCE_MS,"connect")}createWebSocket(e){try{const t=this.buildWsUrl();this.ws=new WebSocket(t),this.ws.onopen=()=>{if(this.connectionId===e){this.log("Connected"),this.state="connected",this.reconnectAttempt=0;for(const e of this.pendingSubscriptions)this.subscriptions.has(e)||this.subscriptions.set(e,new Set);this.pendingSubscriptions.clear(),this.sendTracksUpdate(),this.sendSeek(this.currentPlaybackTime),this.flushMessageBuffer()}else this.ws?.close()},this.ws.onmessage=e=>{this.handleMessage(e.data)},this.ws.onerror=e=>{this.log("WebSocket error"),console.warn("[MetaTrackManager] WebSocket error:",e)},this.ws.onclose=()=>{this.log("Disconnected"),this.ws=null,"disconnected"!==this.state&&this.scheduleReconnect()}}catch(e){this.log(`Connection error: ${e}`),this.scheduleReconnect()}}disconnect(){this.state="disconnected",this.timers.destroy(),this.ws&&(this.ws.close(),this.ws=null)}subscribe(e,t){const n=!this.subscriptions.has(e);return n&&this.subscriptions.set(e,new Set),this.subscriptions.get(e).add(t),"connected"===this.state&&this.ws&&n?this.sendTracksUpdate():n&&this.pendingSubscriptions.add(e),()=>this.unsubscribe(e,t)}unsubscribe(e,t){const n=this.subscriptions.get(e);n&&(n.delete(t),0===n.size&&(this.subscriptions.delete(e),"connected"===this.state&&this.ws&&this.sendTracksUpdate()))}getSubscribedTracks(){return Array.from(this.subscriptions.keys())}getState(){return this.state}isConnected(){return"connected"===this.state}setPlaybackTime(e){this.currentPlaybackTime=e,this.processTimedEvents()}getPlaybackTime(){return this.currentPlaybackTime}onSeek(e){this.log(`Seek to ${e}s - clearing buffer and notifying server`),this.currentPlaybackTime=e,this.timedEventBuffer.clear(),this.lastFastForwardTime=0,this.sendSeek(e)}processTimedEvents(){const e=1e3*this.currentPlaybackTime;for(const[t,n]of this.timedEventBuffer){const i=[],r=[];for(const t of n)if(t.timestamp<=e){const n=(e-t.timestamp)/1e3;n<=this.maxMessageAge?i.push(t):this.log(`Filtering stale event (${n.toFixed(1)}s old)`)}else r.push(t);for(const e of i)this.dispatchEvent(e);r.length>0?this.timedEventBuffer.set(t,r):this.timedEventBuffer.delete(t)}}addToTimedBuffer(e){const t=e.trackId;this.timedEventBuffer.has(t)||this.timedEventBuffer.set(t,[]);const n=this.timedEventBuffer.get(t);let i=n.length;for(let t=0;t<n.length;t++)if(n[t].timestamp>e.timestamp){i=t;break}for(n.splice(i,0,e);n.length>vt.MESSAGE_BUFFER_SIZE;)n.shift()}needsMoreData(e){const t=this.timedEventBuffer.get(e);if(!t||0===t.length)return!0;return t[t.length-1].timestamp/1e3-this.currentPlaybackTime<this.bufferAhead}fastForward(){const e=Date.now();if(e-this.lastFastForwardTime<1e3*this.fastForwardInterval)return;this.lastFastForwardTime=e,this.log("Fast-forwarding through buffered events");const t=1e3*(this.currentPlaybackTime+this.bufferAhead);for(const[e,n]of this.timedEventBuffer){const i=[],r=[];for(const e of n)if(e.timestamp<=t){(1e3*this.currentPlaybackTime-e.timestamp)/1e3<=this.maxMessageAge&&i.push(e)}else r.push(e);for(const e of i)this.dispatchEvent(e);r.length>0?this.timedEventBuffer.set(e,r):this.timedEventBuffer.delete(e)}this.sendFastForward(this.currentPlaybackTime+this.bufferAhead)}getBufferStatus(){const e={};for(const[t,n]of this.timedEventBuffer)n.length>0&&(e[t]={count:n.length,oldestMs:n[0].timestamp,newestMs:n[n.length-1].timestamp});return e}buildWsUrl(){return`${this.config.mistBaseUrl.replace(/^http:/,"ws:").replace(/^https:/,"wss:").replace(/\/$/,"")}/json_${this.config.streamName}.js?rate=1`}sendTracksUpdate(){if(this.ws&&this.ws.readyState===WebSocket.OPEN){const e=Array.from(this.subscriptions.keys()),t=e.includes("all")?"all":e.join(","),n=JSON.stringify({type:"tracks",meta:t});this.ws.send(n),this.log(`Set tracks: ${t}`)}}sendSeek(e){if(this.ws&&this.ws.readyState===WebSocket.OPEN){const t=Math.round(1e3*e),n=Math.round(1e3*(e+this.bufferAhead)),i=JSON.stringify({type:"seek",seek_time:t,ff_to:n});this.ws.send(i),this.log(`Seek to ${e}s, buffer ahead to ${e+this.bufferAhead}s`)}}sendHold(){this.ws&&this.ws.readyState===WebSocket.OPEN&&(this.ws.send(JSON.stringify({type:"hold"})),this.log("Sent hold"))}sendPlay(){this.ws&&this.ws.readyState===WebSocket.OPEN&&(this.ws.send(JSON.stringify({type:"play"})),this.log("Sent play"))}sendFastForward(e){if(this.ws&&this.ws.readyState===WebSocket.OPEN){const t=JSON.stringify({type:"fast_forward",ff_to:Math.round(1e3*e)});this.ws.send(t),this.log(`Fast-forward to ${e}s`)}}handleMessage(e){try{const t=JSON.parse(e);if("time"in t&&"track"in t&&"data"in t){const e=this.parseMetaTrackEvent(t),n=String(t.track);return void((this.subscriptions.has(n)||this.subscriptions.has("all"))&&("subtitle"===e.type||"chapter"===e.type?(this.addToTimedBuffer(e),this.processTimedEvents()):this.dispatchEvent(e)))}if("type"in t)switch(t.type){case"on_time":if(t.data?.current){const e=t.data.current,n=e-1e3*this.currentPlaybackTime;n>6*this.bufferAhead*1e3&&(this.log(`Server ${n}ms ahead, sending hold`),this.sendHold())}break;case"seek":this.log("Server confirmed seek, clearing buffers"),this.timedEventBuffer.clear();break;default:this.log(`Unknown message type: ${t.type}`)}}catch(e){this.log(`Failed to parse message: ${e}`)}}parseMetaTrackEvent(e){const t=String(e.track),n=Number(e.time),i=e.data??e;return{type:this.detectEventType(i),timestamp:n,trackId:t,data:i}}detectEventType(e){if("object"!=typeof e||null===e)return"unknown";return"text"in e&&("startTime"in e||"start"in e)?"subtitle":"key"in e&&"value"in e?"score":"title"in e&&"startTime"in e?"chapter":"name"in e?"event":"unknown"}dispatchEvent(e){const t=this.subscriptions.get(e.trackId);if(t)for(const n of t)try{n(e)}catch(e){console.error("[MetaTrackManager] Callback error:",e)}}scheduleReconnect(){if("disconnected"===this.state)return;if(this.reconnectAttempt>=vt.MAX_RECONNECT_ATTEMPTS)return this.log("Max reconnect attempts reached"),void(this.state="disconnected");this.state="reconnecting",this.reconnectAttempt++;const e=Math.min(vt.INITIAL_RECONNECT_DELAY*Math.pow(2,this.reconnectAttempt-1),vt.MAX_RECONNECT_DELAY);this.log(`Reconnecting in ${e}ms (attempt ${this.reconnectAttempt})`),this.timers.start(()=>{this.connect()},e,"reconnect")}bufferMessage(e){for(this.messageBuffer.push(e);this.messageBuffer.length>vt.MESSAGE_BUFFER_SIZE;)this.messageBuffer.shift()}flushMessageBuffer(){const e=[...this.messageBuffer];this.messageBuffer=[];for(const t of e)this.dispatchEvent(t)}log(e){this.debug&&console.debug(`[MetaTrackManager] ${e}`)}}vt.CONNECTION_DEBOUNCE_MS=100,vt.MAX_RECONNECT_ATTEMPTS=5,vt.INITIAL_RECONNECT_DELAY=1e3,vt.MAX_RECONNECT_DELAY=3e4,vt.MESSAGE_BUFFER_SIZE=100;const Tt={"ultra-low":{exitLive:2,enterLive:.5},low:{exitLive:5,enterLive:1.5},medium:{exitLive:15,enterLive:5},high:{exitLive:30,enterLive:10}},_t=[.5,1,1.5,2];function Et(e){if(!e)return"medium";const t=e.toLowerCase();return"whep"===t||"webrtc"===t||t.includes("mist/webrtc")?"ultra-low":t.startsWith("ws/")||t.startsWith("wss/")?"low":(t.includes("mpegurl")||t.includes("dash")||t.includes("video/mp4")||t.includes("video/webm"),"medium")}function St(e){return!!e&&e.srcObject instanceof MediaStream}function wt(e){return!e||!St(e)}function kt(e){const{isLive:t,video:n,mistStreamInfo:i,currentTime:r,duration:s,allowMediaStreamDvr:a=!1}=e;if(!t)return{seekableStart:0,liveEdge:s};const o=St(n);if(n?.seekable&&n.seekable.length>0){const e=n.seekable.start(0),t=n.seekable.end(n.seekable.length-1);if(Number.isFinite(e)&&Number.isFinite(t)&&t>e)return{seekableStart:e,liveEdge:t}}if((a||!o)&&i?.meta?.tracks){const e=Object.values(i.meta.tracks);if(e.length>0){const t=e.map(e=>e.firstms).filter(e=>void 0!==e),n=e.map(e=>e.lastms).filter(e=>void 0!==e);if(t.length>0&&n.length>0){return{seekableStart:Math.max(...t)/1e3,liveEdge:Math.min(...n)/1e3}}}}const l=i?.meta?.buffer_window;if(l&&l>0&&r>0){const e=l/1e3;return{seekableStart:Math.max(0,r-e),liveEdge:r}}return{seekableStart:r,liveEdge:r}}function It(e){const{video:t,isLive:n,duration:i,bufferWindowMs:r,playerCanSeek:s}=e;return!(s&&!s())&&(s&&s()?!n||void 0!==r&&r>0:!!t&&(St(t)?void 0!==r&&r>0:!!(t.seekable&&t.seekable.length>0)||(!!(!n&&Number.isFinite(i)&&i>0)||!!(n&&void 0!==r&&r>0))))}function At(e,t,n){const i=e?Et(e):t?"ultra-low":"medium",r=Tt[i];if(("medium"===i||"high"===i)&&n&&n>0){const e=n/1e3;return{exitLive:Math.max(r.exitLive,Math.min(30,e/3)),enterLive:Math.max(r.enterLive,Math.min(10,e/10))}}return r}function Ct(e,t,n,i){if(!Number.isFinite(t)||t<=0)return!0;const r=t-e;return!(i&&r>n.exitLive+.5)&&(!i&&r<n.enterLive-.2||i)}const Dt={"html5/application/vnd.apple.mpegurl":{hrn:"HLS (TS)",player:"hlsjs",supported:!0},"html5/application/vnd.apple.mpegurl;version=7":{hrn:"HLS (CMAF)",player:"hlsjs",supported:!0},"dash/video/mp4":{hrn:"DASH",player:"dashjs",supported:!0},"html5/video/mp4":{hrn:"MP4 progressive",player:"native",supported:!0},"html5/video/webm":{hrn:"WebM progressive",player:"native",supported:!0},"ws/video/mp4":{hrn:"MP4 WebSocket",player:"mews",supported:!0},"wss/video/mp4":{hrn:"MP4 WebSocket (SSL)",player:"mews",supported:!0},"ws/video/webm":{hrn:"WebM WebSocket",player:"mews",supported:!0},"wss/video/webm":{hrn:"WebM WebSocket (SSL)",player:"mews",supported:!0},"ws/video/raw":{hrn:"Raw WebSocket",player:"webcodecs",supported:!0},"wss/video/raw":{hrn:"Raw WebSocket (SSL)",player:"webcodecs",supported:!0},"ws/video/h264":{hrn:"Annex B WebSocket",player:"webcodecs",supported:!0},"wss/video/h264":{hrn:"Annex B WebSocket (SSL)",player:"webcodecs",supported:!0},whep:{hrn:"WebRTC (WHEP)",player:"native",supported:!0},webrtc:{hrn:"WebRTC (WebSocket)",player:"mist-webrtc",supported:!0},"mist/webrtc":{hrn:"MistServer WebRTC",player:"mist-webrtc",supported:!0},"html5/audio/aac":{hrn:"AAC progressive",player:"native",supported:!0},"html5/audio/mp3":{hrn:"MP3 progressive",player:"native",supported:!0},"html5/audio/flac":{hrn:"FLAC progressive",player:"native",supported:!0},"html5/audio/wav":{hrn:"WAV progressive",player:"native",supported:!0},"html5/text/vtt":{hrn:"WebVTT subtitles",player:"track",supported:!0},"html5/text/plain":{hrn:"SRT subtitles",player:"track",supported:!0},"html5/image/jpeg":{hrn:"JPEG thumbnail",player:"image",supported:!0},"html5/text/javascript":{hrn:"JSON metadata",player:"fetch",supported:!0},"html5/video/mpeg":{hrn:"TS progressive",player:"none",supported:!1},"html5/video/h264":{hrn:"Annex B progressive",player:"none",supported:!1},"html5/application/sdp":{hrn:"SDP",player:"none",supported:!1},"html5/application/vnd.ms-sstr+xml":{hrn:"Smooth Streaming",player:"none",supported:!1},"flash/7":{hrn:"FLV",player:"none",supported:!1},"flash/10":{hrn:"RTMP",player:"none",supported:!1},"flash/11":{hrn:"HDS",player:"none",supported:!1},rtsp:{hrn:"RTSP",player:"none",supported:!1},srt:{hrn:"SRT",player:"none",supported:!1},dtsc:{hrn:"DTSC",player:"none",supported:!1}},Rt={HLS:"html5/application/vnd.apple.mpegurl",DASH:"dash/video/mp4",MP4:"html5/video/mp4",WEBM:"html5/video/webm",WHEP:"whep",WebRTC:"webrtc",MIST_WEBRTC:"mist/webrtc",MEWS:"ws/video/mp4",MEWS_WS:"ws/video/mp4",MEWS_WSS:"wss/video/mp4",MEWS_WEBM:"ws/video/webm",MEWS_WEBM_SSL:"wss/video/webm",RAW_WS:"ws/video/raw",RAW_WSS:"wss/video/raw",H264_WS:"ws/video/h264",H264_WSS:"wss/video/h264",AAC:"html5/audio/aac",MP3:"html5/audio/mp3",FLAC:"html5/audio/flac",WAV:"html5/audio/wav",VTT:"html5/text/vtt",SRT:"html5/text/plain",CMAF:"html5/application/vnd.apple.mpegurl;version=7",HLS_CMAF:"html5/application/vnd.apple.mpegurl;version=7",JPEG:"html5/image/jpeg",JPG:"html5/image/jpeg",HTTP:"html5/video/mp4",MIST_HTML:"mist/html",PLAYER_JS:"mist/html"};function xt(e){return Rt[e]||Rt[e.toUpperCase()]||e}function Lt(e){return Dt[e]}function Mt(e){const t=e.toLowerCase();return t.startsWith("avc1")?"H264":t.startsWith("hev1")||t.startsWith("hvc1")?"HEVC":t.startsWith("av01")?"AV1":t.startsWith("vp09")?"VP9":t.startsWith("vp8")?"VP8":t.startsWith("mp4a")?"AAC":t.includes("opus")?"Opus":t.includes("ec-3")||t.includes("ac3")?"AC3":e}function Nt(e,t){const n=e.primary;if(!n)return null;let i={};if(n.outputs)if("string"==typeof n.outputs)try{i=JSON.parse(n.outputs)}catch{console.warn("[buildStreamInfoFromEndpoints] Failed to parse outputs JSON"),i={}}else i=n.outputs;const r=[],s=Object.keys(i);if(s.length){const e=i.MIST_HTML?.url,n=i.PLAYER_JS?.url;((e,n)=>{if(!e&&!n)return;const i={url:e||n||"",type:"mist/html",streamName:t};n&&(i.mistPlayerUrl=n),r.push(i)})(e,n);const a=new Set(["MIST_HTML","PLAYER_JS"]);for(const e of s){if(a.has(e))continue;const t=i[e];if(!t?.url)continue;const n=xt(e),s=Lt(n);s&&!s.supported||r.push({url:t.url,type:n})}}else n&&r.push({url:n.url,type:n.protocol||"mist/html",streamName:t});const a=[];Object.values(i).forEach(e=>(e=>{if(!e)return;const t=e.codecs||[],n=(e,t)=>{a.push({type:e,codec:Mt(t),codecstring:t})};t.forEach(e=>{const t=e.toLowerCase();t.startsWith("avc1")||t.startsWith("hev1")||t.startsWith("hvc1")||t.startsWith("vp")||t.startsWith("av01")?n("video",e):(t.startsWith("mp4a")||t.includes("opus")||t.includes("vorbis")||t.includes("ac3")||t.includes("ec-3"))&&n("audio",e)}),t.length||(e.hasVideo&&a.push({type:"video",codec:"H264",codecstring:"avc1.42E01E"}),e.hasAudio&&a.push({type:"audio",codec:"AAC",codecstring:"mp4a.40.2"}))})(e.capabilities)),a.length||a.push({type:"video",codec:"H264",codecstring:"avc1.42E01E"});const o=!1===e.metadata?.isLive?"vod":"live";return r.length?{source:r,meta:{tracks:a},type:o}:null}class Pt extends Qe{constructor(e){super(),this.state="booting",this.lastEmittedState=null,this.suppressPlayPauseEventsUntil=0,this.gatewayClient=null,this.streamStateClient=null,this.currentPlayer=null,this.videoElement=null,this.container=null,this.endpoints=null,this.streamInfo=null,this.streamState=null,this.mistTracks=null,this.metadataSeed=null,this.metadata=null,this.cleanupFns=[],this.isDestroyed=!1,this.isAttached=!1,this._isBuffering=!1,this._hasPlaybackStarted=!1,this._errorText=null,this._isPassiveError=!1,this._isHoldingSpeed=!1,this._holdSpeed=2,this._isLoopEnabled=!1,this._currentPlayerInfo=null,this._currentSourceInfo=null,this._pendingForceOptions=null,this._errorShownAt=0,this._errorCleared=!1,this._isTransitioning=!1,this._errorCount=0,this._lastErrorTime=0,this._prevStreamIsOnline=void 0,this._isHovering=!1,this._hoverTimeout=null,this._subtitlesEnabled=!1,this._stallStartTime=0,this._seekableStart=0,this._liveEdge=0,this._canSeek=!1,this._isNearLive=!0,this._latencyTier="medium",this._liveThresholds={exitLive:15,enterLive:5},this._buffered=null,this._hasAudio=!0,this._lastVolume=1,this._supportsPlaybackRate=!0,this._isWebRTC=!1,this.abrController=null,this.interactionController=null,this.mistReporter=null,this.qualityMonitor=null,this.metaTrackManager=null,this._playbackQuality=null,this.bootMs=Date.now(),this.config=e,this.playerManager=e.playerManager||ct,this.playerManager.on("protocolSwapped",e=>this.emit("protocolSwapped",e)),this.playerManager.on("playbackFailed",e=>this.emit("playbackFailed",e));try{"undefined"!=typeof localStorage&&(this._isLoopEnabled="true"===localStorage.getItem("frameworks-player-loop"))}catch{}}async attach(e){if(this.isDestroyed)throw new Error("PlayerController is destroyed and cannot be reused");this.isAttached&&(this.log("Already attached, detaching first"),this.detach()),this.container=e,this.isAttached=!0,this.setState("booting");try{if(lt(),await this.resolveEndpoints(),this.isDestroyed||!this.container)return void this.log("[attach] Aborted - controller destroyed during endpoint resolution");if(!this.endpoints?.primary)return void this.setState("no_endpoint",{gatewayStatus:"error"});if(this.startStreamStatePolling(),this.streamInfo=this.buildStreamInfo(this.endpoints),!this.streamInfo||0===this.streamInfo.source.length)return this.setState("error",{error:"No playable sources found"}),void this.emit("error",{error:"No playable sources found"});if(this.isDestroyed||!this.container)return void this.log("[attach] Aborted - controller destroyed before player init");await this.initializePlayer()}catch(e){const t=e instanceof Error?e.message:"Unknown error";this.setState("error",{error:t}),this.emit("error",{error:t}),this.config.mistUrl&&!this.streamStateClient&&(this.log("[attach] Starting stream polling despite resolution failure"),this.startStreamStatePolling())}}detach(){this.cleanup(),this.clearHoverTimeout(),this.isAttached=!1,this.container=null,this.endpoints=null,this.streamInfo=null,this.streamState=null,this.metadataSeed=null,this.metadata=null,this.videoElement=null,this.currentPlayer=null,this.lastEmittedState=null,this._isHovering=!1}destroy(){this.isDestroyed||(this.detach(),this.setState("destroyed"),this.emit("destroyed",void 0),this.removeAllListeners(),this.isDestroyed=!0)}getState(){return this.state}getStreamState(){return this.streamState}getEndpoints(){return this.endpoints}getMetadata(){return this.metadata??null}setMetadataSeed(e){this.metadataSeed=e?{...e}:null,this.refreshMergedMetadata()}refreshMergedMetadata(){const e=this.metadataSeed?{...this.metadataSeed}:null,t=this.streamState?.streamInfo,n=this.streamState?.status;if(!e&&!t)return void(this.metadata=null);const i=e?{...e}:{};t&&(i.mist=this.sanitizeMistInfo(t),t.type&&(i.contentType=t.type,i.isLive="live"===t.type),n&&(i.status=n),t.meta?.duration&&(!i.durationSeconds||i.durationSeconds<=0)&&(i.durationSeconds=Math.round(t.meta.duration)),t.meta?.tracks&&(i.tracks=this.buildMetadataTracks(t.meta.tracks))),this.metadata=i}buildMetadataTracks(e){const t=[];for(const[,n]of Object.entries(e)){const e=n,i=e.type;if("video"!==i&&"audio"!==i&&"meta"!==i)continue;const r="number"==typeof e.bps?Math.round(e.bps):void 0,s="number"==typeof e.fpks?e.fpks/1e3:void 0;t.push({type:i,codec:e.codec,width:e.width,height:e.height,bitrate:r,fps:s,channels:e.channels,sampleRate:e.rate})}return t.length?t:void 0}sanitizeMistInfo(e){const t={error:e.error,on_error:e.on_error,perc:e.perc,type:e.type,hasVideo:e.hasVideo,hasAudio:e.hasAudio,unixoffset:e.unixoffset,lastms:e.lastms};if(e.source&&(t.source=e.source.map(e=>({url:e.url,type:e.type,priority:e.priority,simul_tracks:e.simul_tracks,relurl:e.relurl}))),e.meta&&(t.meta={buffer_window:e.meta.buffer_window,duration:e.meta.duration,mistUrl:e.meta.mistUrl},e.meta.tracks)){const n={};for(const[t,i]of Object.entries(e.meta.tracks))n[t]={type:i.type,codec:i.codec,width:i.width,height:i.height,bps:i.bps,fpks:i.fpks,codecstring:i.codecstring,firstms:i.firstms,lastms:i.lastms,lang:i.lang,idx:i.idx,channels:i.channels,rate:i.rate,size:i.size};t.meta.tracks=n}return t}getStreamInfo(){return this.streamInfo}getVideoElement(){return this.videoElement}getPlayer(){return this.currentPlayer}isReady(){return null!==this.videoElement}isPlaying(){return!(this.currentPlayer?.isPaused?.()??this.videoElement?.paused??!0)}isBuffering(){return this._isBuffering}getError(){return this._errorText}isPassiveError(){return this._isPassiveError}hasPlaybackStarted(){return this._hasPlaybackStarted}isHoldingSpeed(){return this._isHoldingSpeed}getHoldSpeed(){return this._holdSpeed}getCurrentPlayerInfo(){return this._currentPlayerInfo}getCurrentSourceInfo(){return this._currentSourceInfo}getVolume(){return this.videoElement?.volume??1}isLoopEnabled(){return this._isLoopEnabled}isSubtitlesEnabled(){return this._subtitlesEnabled}setSubtitlesEnabled(e){if(this._subtitlesEnabled!==e){if(this._subtitlesEnabled=e,this.videoElement){const t=this.videoElement.textTracks;for(let n=0;n<t.length;n++){const i=t[n];"subtitles"!==i.kind&&"captions"!==i.kind||(i.mode=e?"showing":"hidden")}}this.emit("captionsChange",{enabled:e})}}toggleSubtitles(){this.setSubtitlesEnabled(!this._subtitlesEnabled)}getSeekableStart(){return this._seekableStart}getLiveEdge(){return this._liveEdge}canSeekStream(){return this._canSeek}isNearLive(){return this._isNearLive}getBufferedRanges(){return this.currentPlayer&&"function"==typeof this.currentPlayer.getBufferedRanges?this.currentPlayer.getBufferedRanges():this.videoElement?.buffered??null}getLatencyTier(){return this._latencyTier}getLiveThresholds(){return this._liveThresholds}getBuffered(){return this._buffered}hasAudioTrack(){return this._hasAudio}canAdjustPlaybackRate(){return this._supportsPlaybackRate}getResolvedContentType(){if(this.config.contentType)return this.config.contentType;const e=this.getMetadata(),t=e?.contentType?.toLowerCase();if("live"===t||"clip"===t||"dvr"===t||"vod"===t)return t;const n=this.streamState?.streamInfo?.type;return"live"===n||"vod"===n?n:!0===e?.isLive?"live":!1===e?.isLive?"vod":null}isWebRTCSource(){return this._isWebRTC}isFullscreen(){return"undefined"!=typeof document&&document.fullscreenElement===this.container}isEffectivelyLive(){const e=this.getResolvedContentType()??"live",t=this.getMetadata();return"vod"!==e&&"clip"!==e&&(!1!==t?.isLive&&(("dvr"!==e||"completed"!==t?.dvrStatus)&&("live"===e||"dvr"===e&&"recording"===t?.dvrStatus||!Number.isFinite(this.getDuration()))))}isLive(){return"live"===(this.getResolvedContentType()??"live")}needsColdStart(){const e=this.getResolvedContentType();return!e||"live"!==e}shouldShowIdleScreen(){if(this._hasPlaybackStarted)return!1;if(this.needsColdStart()){return 0===(this.streamInfo?.source??[]).length}return!this.streamState?.isOnline||"ONLINE"!==this.streamState?.status||(!this.streamInfo||0===(this.streamInfo.source?.length??0))}getEffectiveContentType(){return this.isEffectivelyLive()?"live":"vod"}isHovering(){return this._isHovering}shouldShowControls(){return this._isHovering||this.isPaused()||null!==this._errorText}handleMouseEnter(){this.clearHoverTimeout(),this._isHovering||(this._isHovering=!0,this.emit("hoverStart",void 0))}handleMouseLeave(){this.clearHoverTimeout(),this._hoverTimeout=setTimeout(()=>{this._isHovering&&(this._isHovering=!1,this.emit("hoverEnd",void 0))},Pt.HOVER_LEAVE_DELAY_MS)}handleMouseMove(){this._isHovering||(this._isHovering=!0,this.emit("hoverStart",void 0)),this.clearHoverTimeout(),this._hoverTimeout=setTimeout(()=>{this._isHovering&&(this._isHovering=!1,this.emit("hoverEnd",void 0))},Pt.HOVER_HIDE_DELAY_MS)}handleTouchStart(){this.handleMouseEnter(),this.clearHoverTimeout(),this._hoverTimeout=setTimeout(()=>{this._isHovering&&(this._isHovering=!1,this.emit("hoverEnd",void 0))},Pt.HOVER_HIDE_DELAY_MS)}clearHoverTimeout(){this._hoverTimeout&&(clearTimeout(this._hoverTimeout),this._hoverTimeout=null)}getPlaybackRate(){return this.videoElement?.playbackRate??1}getPlaybackQuality(){return this._playbackQuality}getABRMode(){return this.abrController?.getMode()??"auto"}setABRMode(e){this.abrController?.setMode(e)}async play(){this.currentPlayer?.play?await this.currentPlayer.play():this.videoElement&&await this.videoElement.play()}pause(){this.currentPlayer?.pause?this.currentPlayer.pause():this.videoElement?.pause()}seek(e){this.currentPlayer?.seek?this.currentPlayer.seek(e):this.videoElement&&(this.videoElement.currentTime=e)}setVolume(e){if(!this.videoElement)return;const t=Math.max(0,Math.min(1,e));t>0&&(this._lastVolume=t);const n=0===t;this.videoElement.muted!==n&&(this.videoElement.muted=n,this.currentPlayer?.setMuted&&this.currentPlayer.setMuted(n)),this.videoElement.volume=t,this.emit("volumeChange",{volume:t,muted:n})}setMuted(e){this.videoElement&&(e&&this.videoElement.volume>0&&(this._lastVolume=this.videoElement.volume),this.currentPlayer?.setMuted?this.currentPlayer.setMuted(e):this.videoElement.muted=e,e||0!==this.videoElement.volume||(this.videoElement.volume=this._lastVolume),this.emit("volumeChange",{volume:e?0:this.videoElement.volume,muted:e}))}setPlaybackRate(e){this.currentPlayer?.setPlaybackRate?this.currentPlayer.setPlaybackRate(e):this.videoElement&&(this.videoElement.playbackRate=e),this.emit("speedChange",{rate:e})}jumpToLive(){if(this.currentPlayer?.jumpToLive){this.currentPlayer.jumpToLive();const e=this.videoElement;if(e&&!St(e)){const e=this._liveEdge;Number.isFinite(e)&&e>0&&setTimeout(()=>{if(!this.videoElement)return;const t=this.getEffectiveCurrentTime();if(e-t>1)try{this.videoElement.currentTime=e}catch{}},200)}return this._isNearLive=!0,void this.emitSeekingState()}const e=this.videoElement;if(e){if(St(e))return this._isNearLive=!0,void this.emitSeekingState();if(e.seekable&&e.seekable.length>0){const t=e.seekable.end(e.seekable.length-1);if(Number.isFinite(t)&&t>0)return e.currentTime=t,this._isNearLive=!0,void this.emitSeekingState()}if(this._liveEdge>0&&Number.isFinite(this._liveEdge))return e.currentTime=this._liveEdge,this._isNearLive=!0,void this.emitSeekingState();Number.isFinite(e.duration)&&e.duration>0&&(e.currentTime=e.duration,this._isNearLive=!0,this.emitSeekingState())}}emitSeekingState(){this.emit("seekingStateChange",{seekableStart:this._seekableStart,liveEdge:this._liveEdge,canSeek:this._canSeek,isNearLive:this._isNearLive,isLive:this.isEffectivelyLive(),isWebRTC:this._isWebRTC,latencyTier:this._latencyTier,buffered:this._buffered,hasAudio:this._hasAudio,supportsPlaybackRate:this._supportsPlaybackRate})}async requestFullscreen(){this.container&&await this.container.requestFullscreen()}async requestPiP(){this.currentPlayer?.requestPiP?await this.currentPlayer.requestPiP():this.videoElement&&"requestPictureInPicture"in this.videoElement&&await this.videoElement.requestPictureInPicture()}getQualities(){return this.currentPlayer?.getQualities?.()??[]}selectQuality(e){this.currentPlayer?.selectQuality?.(e)}getTextTracks(){return this.currentPlayer?.getTextTracks?.()??[]}selectTextTrack(e){this.currentPlayer?.selectTextTrack?.(e)}getEffectiveCurrentTime(){if(this.currentPlayer&&"function"==typeof this.currentPlayer.getCurrentTime){const e=this.currentPlayer.getCurrentTime();if(Number.isFinite(e))return e}return this.videoElement?.currentTime??0}getEffectiveDuration(){if(this.currentPlayer&&"function"==typeof this.currentPlayer.getDuration){const e=this.currentPlayer.getDuration();if(Number.isFinite(e)||e===1/0)return e}return this.videoElement?.duration??NaN}getPlayerSeekableRange(){if(this.currentPlayer&&"function"==typeof this.currentPlayer.getSeekableRange){const e=this.currentPlayer.getSeekableRange();if(e&&Number.isFinite(e.start)&&Number.isFinite(e.end)&&e.end>=e.start)return e}return null}getFrameStepSecondsFromTracks(){const e=this.streamInfo?.meta?.tracks;if(!e||0===e.length)return;const t=e.filter(e=>"video"===e.type&&"number"==typeof e.fpks&&e.fpks>0);if(0===t.length)return;const n=Math.max(...t.map(e=>e.fpks));return!Number.isFinite(n)||n<=0?void 0:1e3/n}deriveBufferWindowMsFromTracks(e){if(!e)return;const t=Object.values(e);if(0===t.length)return;const n=t.map(e=>e.firstms).filter(e=>void 0!==e),i=t.map(e=>e.lastms).filter(e=>void 0!==e);if(0===n.length||0===i.length)return;const r=Math.max(...n),s=Math.min(...i)-r;return!Number.isFinite(s)||s<=0?void 0:s}getCurrentTime(){return this.getEffectiveCurrentTime()}getDuration(){return this.getEffectiveDuration()}isPaused(){return this.currentPlayer?.isPaused?.()??this.videoElement?.paused??!0}suppressPlayPauseEvents(e=200){this.suppressPlayPauseEventsUntil=Date.now()+e}shouldSuppressVideoEvents(){return Date.now()<this.suppressPlayPauseEventsUntil}isMuted(){return this.videoElement?.muted??!0}skipBack(e=10){this.seekBy(-e),this.emit("skipBackward",{seconds:e})}skipForward(e=10){this.seekBy(e),this.emit("skipForward",{seconds:e})}togglePlay(){this.currentPlayer?.isPaused?.()??this.videoElement?.paused??!0?this.currentPlayer?.play?this.currentPlayer.play().catch(()=>{}):this.videoElement?.play().catch(()=>{}):this.currentPlayer?.pause?this.currentPlayer.pause():this.videoElement?.pause()}toggleMute(){this.videoElement&&this.setMuted(!this.videoElement.muted)}seekBy(e){const t=this.getEffectiveCurrentTime(),n=this.getEffectiveDuration(),i=t+e,r=isFinite(n)?n:t+Math.abs(e);this.seek(Math.max(0,Math.min(r,i)))}seekPercent(e){const t=this.getEffectiveDuration();isFinite(t)&&this.seek(t*Math.max(0,Math.min(1,e)))}toggleLoop(){this._isLoopEnabled=!this._isLoopEnabled,this.videoElement&&(this.videoElement.loop=this._isLoopEnabled);try{"undefined"!=typeof localStorage&&localStorage.setItem("frameworks-player-loop",String(this._isLoopEnabled))}catch{}this.emit("loopChange",{isLoopEnabled:this._isLoopEnabled})}setLoopEnabled(e){if(this._isLoopEnabled!==e){this._isLoopEnabled=e,this.videoElement&&(this.videoElement.loop=e);try{"undefined"!=typeof localStorage&&localStorage.setItem("frameworks-player-loop",String(e))}catch{}this.emit("loopChange",{isLoopEnabled:e})}}clearError(){this._errorText=null,this._isPassiveError=!1,this._errorCleared=!0}updateSeekingState(){const e=this.videoElement;if(!e)return;const t=this.getEffectiveCurrentTime(),n=this.getEffectiveDuration(),i=this.isEffectivelyLive(),r=this._currentSourceInfo?.type,s=this.streamState?.streamInfo,a=this._isWebRTC;this._isWebRTC=St(e),this._supportsPlaybackRate=wt(e),this._latencyTier=r?Et(r):this._isWebRTC?"ultra-low":"medium";const o=s?.meta?.buffer_window??this.deriveBufferWindowMsFromTracks(s?.meta?.tracks);this._liveThresholds=At(r,this._isWebRTC,o);const l=this.getPlayerSeekableRange(),u=St(e)&&void 0!==o&&o>0&&"whep"!==r&&"webrtc"!==r,{seekableStart:d,liveEdge:c}=l?{seekableStart:l.start,liveEdge:l.end}:kt({isLive:i,video:e,mistStreamInfo:s,currentTime:t,duration:n,allowMediaStreamDvr:u}),h=this.currentPlayer&&"function"==typeof this.currentPlayer.canSeek?()=>this.currentPlayer.canSeek():void 0;this._canSeek=It({video:e,isLive:i,duration:n,bufferWindowMs:o,playerCanSeek:h}),this._buffered=e.buffered.length>0?e.buffered:null;const f=this._seekableStart!==d||this._liveEdge!==c;this._seekableStart=d,this._liveEdge=c;const p=i&&Number.isFinite(c)&&Number.isFinite(d)&&c>d,g=i&&!p;if(this.interactionController?.updateConfig({isLive:g,frameStepSeconds:this.getFrameStepSecondsFromTracks()}),i){const e=Ct(t,c,this._liveThresholds,this._isNearLive);e!==this._isNearLive&&(this._isNearLive=e)}else this._isNearLive=!0;(f||a!==this._isWebRTC)&&this.emit("seekingStateChange",{seekableStart:this._seekableStart,liveEdge:this._liveEdge,canSeek:this._canSeek,isNearLive:this._isNearLive,isLive:i,isWebRTC:this._isWebRTC,latencyTier:this._latencyTier,buffered:this._buffered,hasAudio:this._hasAudio,supportsPlaybackRate:this._supportsPlaybackRate})}detectAudioTracks(){const e=this.videoElement;if(!e)return;if(e.srcObject instanceof MediaStream){const t=e.srcObject.getAudioTracks();return void(this._hasAudio=t.length>0)}const t=e;t.audioTracks&&void 0!==t.audioTracks.length?this._hasAudio=t.audioTracks.length>0:this._hasAudio=!0}attemptClearError(){if(!this._errorText||this._errorCleared)return;Date.now()-this._errorShownAt>=Pt.AUTO_CLEAR_ERROR_DELAY_MS&&(this._errorCleared=!0,this._errorText=null,this._isPassiveError=!1,this.log("Error auto-cleared after playback resumed"),this.emit("errorCleared",void 0))}shouldAttemptFallback(e){const t=Date.now();if(t-this._lastErrorTime>Pt.HARD_FAILURE_ERROR_WINDOW_MS&&(this._errorCount=0),this._errorCount++,this._lastErrorTime=t,this._errorCount>=Pt.HARD_FAILURE_ERROR_THRESHOLD)return this.log(`Hard failure: repeated errors (${this._errorCount})`),!0;const n=e.toLowerCase();for(const e of Pt.FATAL_ERROR_KEYWORDS)if(n.includes(e))return this.log(`Hard failure: fatal keyword "${e}" detected`),!0;if(this._stallStartTime>0){const e=t-this._stallStartTime;if(e>=Pt.HARD_FAILURE_STALL_THRESHOLD_MS)return this.log(`Hard failure: sustained stall for ${e}ms`),!0}return!1}async setPassiveError(e){if(this._isTransitioning)return void this.log(`Ignoring error during player transition: ${e}`);const t=this.videoElement,n=t&&!t.paused&&t.currentTime>0;if(this.shouldAttemptFallback(e)&&this.playerManager.canAttemptFallback()){this.log("Attempting playback fallback..."),this._isTransitioning=!0;const e=await this.playerManager.tryPlaybackFallback();if(this._isTransitioning=!1,e)return this._errorCount=0,this._errorText=null,this._isPassiveError=!1,void this.log("Fallback succeeded");this.log("Fallback exhausted, showing error UI")}this._errorShownAt=Date.now(),this._errorCleared=!1,this._errorText=e,this._isPassiveError=n??!1,this.setState("error",{error:e}),this.emit("error",{error:e})}async retryWithFallback(){if(!this.playerManager.canAttemptFallback())return!1;this._isTransitioning=!0;const e=await this.playerManager.tryPlaybackFallback();return this._isTransitioning=!1,e&&(this._errorCount=0,this.clearError()),e}async toggleFullscreen(){"undefined"!=typeof document&&(document.fullscreenElement?await document.exitFullscreen().catch(()=>{}):this.container&&await this.container.requestFullscreen().catch(()=>{}))}async togglePictureInPicture(){"undefined"!=typeof document&&(document.pictureInPictureElement?await document.exitPictureInPicture().catch(()=>{}):this.videoElement&&"requestPictureInPicture"in this.videoElement&&await this.videoElement.requestPictureInPicture().catch(()=>{}))}isPiPSupported(){return"undefined"!=typeof document&&(document.pictureInPictureEnabled??!1)}isPiPActive(){return"undefined"!=typeof document&&document.pictureInPictureElement===this.videoElement}async retry(){if(this.container&&this.streamInfo){try{this.playerManager.destroy()}catch{}this.container.innerHTML="",this.videoElement=null,this.currentPlayer=null;try{await this.initializePlayer()}catch(e){const t=e instanceof Error?e.message:"Retry failed";this.setState("error",{error:t}),this.emit("error",{error:t})}}}async getStats(){return this.currentPlayer?.getStats?.()}async getLatency(){return this.currentPlayer?.getLatency?.()}updateConfig(e){void 0!==e.debug&&(this.config.debug=e.debug),void 0!==e.autoplay&&(this.config.autoplay=e.autoplay),void 0!==e.muted&&(this.config.muted=e.muted,this.videoElement&&(this.videoElement.muted=e.muted))}async reload(){if(!this.container||this.isDestroyed)return;const e=this.container;this.detach(),await this.attach(e)}async selectCombo(e){const t=this.container;t&&(this.log(`[selectCombo] One-shot selection: player=${e.forcePlayer}, type=${e.forceType}, source=${e.forceSource}`),this._pendingForceOptions={forcePlayer:e.forcePlayer,forceType:e.forceType,forceSource:e.forceSource},this.detach(),await this.attach(t))}setPlaybackMode(e){this.config.playbackMode=e,this.log(`[setPlaybackMode] Mode set to: ${e}`)}async setDevModeOptions(e){if(e.playbackMode&&this.setPlaybackMode(e.playbackMode),void 0!==e.forcePlayer||void 0!==e.forceType||void 0!==e.forceSource)await this.selectCombo({forcePlayer:e.forcePlayer,forceType:e.forceType,forceSource:e.forceSource});else if(e.playbackMode){const e=this.container;e&&(this.detach(),await this.attach(e))}}getMetadataPayload(){const e=this.videoElement,t=e&&e.buffered.length>0?e.buffered.end(e.buffered.length-1)-e.currentTime:0;return{currentTime:e?.currentTime??0,duration:e?.duration??NaN,bufferedAhead:Math.max(0,t),qualityScore:this._playbackQuality?.score,playerInfo:this._currentPlayerInfo??void 0,sourceInfo:this._currentSourceInfo??void 0,isLive:this.isEffectivelyLive(),isBuffering:this._isBuffering,isPaused:e?.paused??!0,volume:e?.volume??1,muted:e?.muted??!0}}emitMetadataUpdate(){this.emit("metadataUpdate",this.getMetadataPayload())}async resolveEndpoints(){const{endpoints:e,gatewayUrl:t,mistUrl:n,contentId:i,authToken:r}=this.config;if(e?.primary)return this.endpoints=e,this.setMetadataSeed(e.metadata??null),void this.setState("gateway_ready",{gatewayStatus:"ready"});if(n)await this.resolveFromMistServer(n,i);else{if(!t)throw new Error("No endpoints provided and no gatewayUrl or mistUrl configured");await this.resolveFromGateway(t,i,r)}}async resolveFromMistServer(e,t){this.setState("gateway_loading",{gatewayStatus:"loading"});try{let n=e;for(;n.endsWith("/");)n=n.slice(0,-1);const i=`${n}/json_${encodeURIComponent(t)}.js`;this.log(`[resolveFromMistServer] Fetching ${i}`);const r=await fetch(i,{cache:"no-store"});if(!r.ok)throw new Error(`MistServer HTTP ${r.status}`);let s=await r.text();const a=s.match(/^[^(]+\(([\s\S]*)\);?$/);a&&(s=a[1]);const o=JSON.parse(s);if(o.error)throw new Error(o.error);const l=Array.isArray(o.source)?o.source:[];if(0===l.length)throw new Error("No sources available from MistServer");const u={};for(const e of l){const t=this.mapMistTypeToProtocol(e.type);u[t]||(u[t]={protocol:t,url:e.url})}const d=l.filter(e=>!e.url.startsWith("ws://")),c=d.length>0?this.selectBestSource(d):l[0],h={nodeId:`mist-${t}`,protocol:this.mapMistTypeToProtocol(c.type),url:c.url,baseUrl:e,outputs:u};if(this.endpoints={primary:h,fallbacks:[]},this.setMetadataSeed(null),o.meta?.tracks&&"object"==typeof o.meta.tracks){const e=this.parseMistTracks(o.meta.tracks);this.mistTracks=e.length>0?e:null,this.log(`[resolveFromMistServer] Parsed ${e.length} tracks from MistServer`)}this.setState("gateway_ready",{gatewayStatus:"ready"}),this.log(`[resolveFromMistServer] Resolved: ${h.protocol} @ ${h.url}`)}catch(e){const t=e instanceof Error?e.message:"MistServer resolution failed";throw this.setState("gateway_error",{gatewayStatus:"error",error:t}),e}}mapMistTypeToProtocol(e){return"ws/video/raw"===e?"RAW_WS":"wss/video/raw"===e?"RAW_WSS":"ws/video/h264"===e?"H264_WS":"wss/video/h264"===e?"H264_WSS":"ws/video/webm"===e?"MEWS_WEBM":"wss/video/webm"===e?"MEWS_WEBM_SSL":e.startsWith("ws/")?"MEWS_WS":e.startsWith("wss/")?"MEWS_WSS":e.includes("webrtc")?"MIST_WEBRTC":e.includes("mpegurl")||e.includes("m3u8")?"HLS":e.includes("dash")||e.includes("mpd")?"DASH":e.includes("whep")?"WHEP":e.includes("mp4")?"MP4":e.includes("webm")?"WEBM":e}selectBestSource(e){const t={HLS:1,DASH:2,MP4:3,WEBM:4,WHEP:5,MIST_WEBRTC:6,MEWS_WS:99};return e.sort((e,n)=>(t[this.mapMistTypeToProtocol(e.type)]??50)-(t[this.mapMistTypeToProtocol(n.type)]??50))[0]}async resolveFromGateway(e,t,n){this.setState("gateway_loading",{gatewayStatus:"loading"}),this.gatewayClient=new Ze({gatewayUrl:e,contentId:t,authToken:n});const i=this.gatewayClient.on("statusChange",({status:e,error:t})=>{"error"===e&&this.setState("gateway_error",{gatewayStatus:e,error:t})});this.cleanupFns.push(i),this.cleanupFns.push(()=>this.gatewayClient?.destroy());try{this.endpoints=await this.gatewayClient.resolve(),this.setMetadataSeed(this.endpoints?.metadata??null),this.setState("gateway_ready",{gatewayStatus:"ready"})}catch(e){const t=e instanceof Error?e.message:"Gateway resolution failed";throw this.setState("gateway_error",{gatewayStatus:"error",error:t}),e}}startStreamStatePolling(){const{contentId:e,mistUrl:t}=this.config,n=this.getResolvedContentType();if(null==n){if(!t)return}else if("live"!==n&&"dvr"!==n)return;if("dvr"===n){const e=this.getMetadata()?.dvrStatus;if(e&&"recording"!==e)return}const i=this.endpoints?.primary?.baseUrl||t;if(!i)return;const r=this.getMetadata(),s=r?.contentId||e,a=this.isEffectivelyLive(),o=this.isEffectivelyLive()?3e3:5e3;this.streamStateClient=new nt({mistBaseUrl:i,streamName:s,useWebSocket:a,pollInterval:o});const l=this.streamStateClient.on("stateChange",({state:e})=>{const t=this._prevStreamIsOnline,n=e.isOnline;if(this.streamState=e,this._prevStreamIsOnline=n,e.streamInfo?.meta?.tracks&&this.streamInfo){const t=this.parseMistTracks(e.streamInfo.meta.tracks);t.length>0&&(this.streamInfo.meta.tracks=t,this.log(`[stateChange] Updated ${t.length} tracks from MistServer`))}this.refreshMergedMetadata(),this.emit("streamStateChange",{state:e}),!1===t&&!0===n&&this.isEffectivelyLive()&&(this.log("Stream came online, triggering auto-play"),this.videoElement?this.videoElement.play().catch(e=>this.log(`Auto-play on online transition failed: ${e}`)):this.container&&!this.endpoints?.primary&&(this.log("Stream came online, attempting late initialization"),this.initializeLateFromStreamState(e.streamInfo)))});this.cleanupFns.push(l),this.cleanupFns.push(()=>this.streamStateClient?.destroy()),this.streamStateClient.start()}async initializeLateFromStreamState(e){if(e?.source&&Array.isArray(e.source)&&0!==e.source.length)if(this.container&&this.config.mistUrl)try{const t=e.source,n=this.config.mistUrl,i=this.config.contentId,r={};for(const e of t){const t=this.mapMistTypeToProtocol(e.type);r[t]||(r[t]={protocol:t,url:e.url})}const s=t.filter(e=>!e.url.startsWith("ws://")),a=s.length>0?this.selectBestSource(s):t[0],o={nodeId:`mist-${i}`,protocol:this.mapMistTypeToProtocol(a.type),url:a.url,baseUrl:n,outputs:r};if(this.endpoints={primary:o,fallbacks:[]},this.setMetadataSeed(this.endpoints.metadata??null),e.meta?.tracks&&"object"==typeof e.meta.tracks){const t=this.parseMistTracks(e.meta.tracks);this.mistTracks=t.length>0?t:null,this.log(`[initializeLateFromStreamState] Parsed ${t.length} tracks`)}if(this.setState("gateway_ready",{gatewayStatus:"ready"}),this.log(`[initializeLateFromStreamState] Built endpoints from stream state: ${o.protocol}`),this.streamInfo=this.buildStreamInfo(this.endpoints),!this.streamInfo||0===this.streamInfo.source.length)return void this.setState("error",{error:"No playable sources found"});await this.initializePlayer(),this.log("[initializeLateFromStreamState] Player initialized successfully")}catch(e){const t=e instanceof Error?e.message:"Late initialization failed";this.log(`[initializeLateFromStreamState] Failed: ${t}`),this.setState("error",{error:t})}else this.log("[initializeLateFromStreamState] Missing container or mistUrl");else this.log("[initializeLateFromStreamState] No sources in stream info")}buildStreamInfo(e){const t=Nt(e,this.config.contentId);return t&&this.mistTracks&&this.mistTracks.length>0&&(t.meta.tracks=this.mistTracks,this.log(`[buildStreamInfo] Using ${this.mistTracks.length} tracks from MistServer`)),t}parseMistTracks(e){const t=[];for(const[,n]of Object.entries(e)){const e=n,i=e.type;"video"!==i&&"audio"!==i&&"meta"!==i||t.push({type:i,codec:e.codec,codecstring:e.codecstring,init:e.init,idx:e.idx,width:e.width,height:e.height,fpks:e.fpks,channels:e.channels,rate:e.rate,size:e.size})}return t}async initializePlayer(){const e=this.container,t=this.streamInfo;if(this.log(`[initializePlayer] Starting - container: ${!!e}, streamInfo: ${!!t}, sources: ${t?.source?.length??0}`),!e||!t)throw new Error("Container or streamInfo not available");this.log(`[initializePlayer] Sources: ${JSON.stringify(t.source.map(e=>({type:e.type,url:e.url.slice(0,60)+"..."})))}`),this.log(`[initializePlayer] Tracks: ${t.meta.tracks.map(e=>`${e.type}:${e.codec}`).join(", ")}`);const{autoplay:n,muted:i,controls:r,poster:s}=this.config;e.innerHTML="";const a=e=>{const t=this.playerManager.getRegisteredPlayers().find(t=>t.capability.shortname===e.player);t&&(this._currentPlayerInfo={name:t.capability.name,shortname:t.capability.shortname}),e.source&&(this._currentSourceInfo={url:e.source.url,type:e.source.type}),this.setState("connecting",{selectedPlayer:e.player,selectedProtocol:(e.source?.type||"").toString(),endpointUrl:e.source?.url}),this.emit("playerSelected",{player:e.player,source:e.source,score:e.score})};try{this.playerManager.on?.("playerSelected",a)}catch{}this.cleanupFns.push(()=>{try{this.playerManager.off?.("playerSelected",a)}catch{}}),this.setState("selecting_player");const o={autoplay:!1!==n,muted:!1!==i,controls:!1!==r,poster:s,debug:this.config.debug,onReady:e=>{if(!this.isDestroyed&&this.container){try{this.container&&!this.container.contains(e)&&(this.log("[initializePlayer] Video element was detached; re-attaching to container"),this.container.appendChild(e))}catch{}this.videoElement=e,this.currentPlayer=this.playerManager.getCurrentPlayer(),this.setupVideoEventListeners(e),this.initializeSubControllers(),this.emit("ready",{videoElement:e})}else this.log("[initializePlayer] onReady callback aborted - controller destroyed")},onTimeUpdate:e=>{if(!this.isDestroyed){try{this.container&&this.videoElement&&!this.container.contains(this.videoElement)&&(this.log("[initializePlayer] Video element was detached during playback; re-attaching to container"),this.container.appendChild(this.videoElement))}catch{}this.emit("timeUpdate",{currentTime:this.getEffectiveCurrentTime(),duration:this.getEffectiveDuration()})}},onError:e=>{if(this.isDestroyed)return;const t="string"==typeof e?e:String(e);this.setPassiveError(t)}},l=this._pendingForceOptions;this._pendingForceOptions=null;const u={forcePlayer:l?.forcePlayer??this.config.forcePlayer,forceType:l?.forceType??this.config.forceType,forceSource:l?.forceSource??this.config.forceSource,playbackMode:this.config.playbackMode};this.log("[initializePlayer] Calling playerManager.initializePlayer..."),this.log(`[initializePlayer] Manager options: ${JSON.stringify(u)} (pending force: ${l?"yes":"no"})`);try{await this.playerManager.initializePlayer(e,t,o,u),this.log("[initializePlayer] Player initialized successfully")}catch(e){throw this.log(`[initializePlayer] Player initialization FAILED: ${e}`),e}}setupVideoEventListeners(e){e.loop=this._isLoopEnabled;const t=()=>{this._isBuffering=!0,0===this._stallStartTime&&(this._stallStartTime=Date.now(),this.log("Stall started")),this.setState("buffering")},n=()=>{this.shouldSuppressVideoEvents()||(this._isBuffering=!1,this._hasPlaybackStarted=!0,this._stallStartTime>0&&(this.log(`Stall cleared after ${Date.now()-this._stallStartTime}ms`),this._stallStartTime=0),this.setState("playing"),this.attemptClearError())},i=()=>{this._isBuffering=!1,this._stallStartTime=0,this.setState("playing"),this.attemptClearError()},r=()=>{this.shouldSuppressVideoEvents()||this.setState("paused")},s=()=>this.setState("ended"),a=()=>{const t=e.error&&e.error.message||"Playback error";this.setPassiveError(t)},o=()=>{this.emit("timeUpdate",{currentTime:this.getEffectiveCurrentTime(),duration:this.getEffectiveDuration()}),this.updateSeekingState(),this.getEffectiveCurrentTime()>0&&this.attemptClearError()},l=()=>{this.emit("timeUpdate",{currentTime:this.getEffectiveCurrentTime(),duration:this.getEffectiveDuration()}),this.updateSeekingState()},u=()=>{this._buffered=e.buffered,this.updateSeekingState()},d=()=>{this.detectAudioTracks(),this._isWebRTC=St(e),this._supportsPlaybackRate=!this._isWebRTC,this.updateSeekingState()},c=()=>{const e=document.fullscreenElement===this.container;this.emit("fullscreenChange",{isFullscreen:e})},h=()=>this.emit("pipChange",{isPiP:!0}),f=()=>this.emit("pipChange",{isPiP:!1}),p=()=>{this.emit("volumeChange",{volume:e.volume,muted:e.muted})};e.addEventListener("waiting",t),e.addEventListener("playing",n),e.addEventListener("canplay",i),e.addEventListener("pause",r),e.addEventListener("ended",s),e.addEventListener("error",a),e.addEventListener("timeupdate",o),e.addEventListener("durationchange",l),e.addEventListener("progress",u),e.addEventListener("loadedmetadata",d),e.addEventListener("volumechange",p),e.addEventListener("enterpictureinpicture",h),e.addEventListener("leavepictureinpicture",f),document.addEventListener("fullscreenchange",c),this.cleanupFns.push(()=>{e.removeEventListener("waiting",t),e.removeEventListener("playing",n),e.removeEventListener("canplay",i),e.removeEventListener("pause",r),e.removeEventListener("ended",s),e.removeEventListener("error",a),e.removeEventListener("timeupdate",o),e.removeEventListener("durationchange",l),e.removeEventListener("progress",u),e.removeEventListener("loadedmetadata",d),e.removeEventListener("volumechange",p),e.removeEventListener("enterpictureinpicture",h),e.removeEventListener("leavepictureinpicture",f),document.removeEventListener("fullscreenchange",c)})}initializeSubControllers(){this.videoElement&&this.container&&(this.initializeABRController(),this.initializeQualityMonitor(),this.initializeInteractionController(),this.initializeMistReporter(),this.initializeMetaTrackManager())}initializeABRController(){const e=this.currentPlayer;e&&this.videoElement&&(this.abrController=new ft({options:{mode:"auto"},getQualities:()=>e.getQualities?.()??[],selectQuality:t=>e.selectQuality?.(t),getCurrentQuality:()=>{const t=e.getQualities?.()??[],n=e.getCurrentQuality?.();return t.find(e=>e.id===n)??null},getBandwidthEstimate:async()=>{if(!this.currentPlayer?.getStats)return 0;try{const e=await this.currentPlayer.getStats();return e?.bandwidthEstimate?e.bandwidthEstimate:e?.averageThroughput?e.averageThroughput:0}catch{return 0}},debug:this.config.debug}),this.abrController.start(this.videoElement),this.cleanupFns.push(()=>{this.abrController?.stop(),this.abrController=null}))}initializeQualityMonitor(){if(!this.videoElement)return;this.qualityMonitor=new bt({sampleInterval:1e3}),this.qualityMonitor.start(this.videoElement);const e=setInterval(()=>{if(this.qualityMonitor&&(this._playbackQuality=this.qualityMonitor.getCurrentQuality(),this.mistReporter&&this._playbackQuality)){const e=this._playbackQuality.score/100;this.mistReporter.setPlaybackScore(e)}},1e3);this.cleanupFns.push(()=>{clearInterval(e),this.qualityMonitor?.stop(),this.qualityMonitor=null})}initializeInteractionController(){if(!this.container||!this.videoElement)return;const e=this.isEffectivelyLive(),t=e&&Number.isFinite(this._liveEdge)&&Number.isFinite(this._seekableStart)&&this._liveEdge>this._seekableStart,n=e&&!t,i=this.container.closest('[data-player-container="true"]')??this.container;this.interactionController=new pt({container:i,videoElement:this.videoElement,isLive:n,isPaused:()=>this.currentPlayer?.isPaused?.()??this.videoElement?.paused??!0,frameStepSeconds:this.getFrameStepSecondsFromTracks(),onFrameStep:(e,t)=>{const n=this.currentPlayer??this.playerManager.getCurrentPlayer(),i=n?.capability?.shortname??this._currentPlayerInfo?.shortname??"unknown",r="function"==typeof n?.frameStep;return this.log(`[interaction] frameStep dir=${e} player=${i} hasFrameStep=${r}`),"webcodecs"===i&&this.suppressPlayPauseEvents(250),!!(r&&n&&n.frameStep)&&(n.frameStep(e,t),!0)},onPlayPause:()=>this.togglePlay(),onSeek:e=>{this._isHoldingSpeed&&(this._isHoldingSpeed=!1,this.emit("holdSpeedEnd",void 0)),this.seekBy(e),e>0?this.emit("skipForward",{seconds:e}):this.emit("skipBackward",{seconds:Math.abs(e)})},onVolumeChange:e=>{if(this.videoElement){const t=Math.max(0,Math.min(1,this.videoElement.volume+e));this.videoElement.volume=t,this.emit("volumeChange",{volume:t,muted:this.videoElement.muted})}},onMuteToggle:()=>this.toggleMute(),onFullscreenToggle:()=>this.toggleFullscreen(),onCaptionsToggle:()=>{this.toggleSubtitles()},onSpeedChange:(e,t)=>{const n=this._isHoldingSpeed;this._isHoldingSpeed=t,this._holdSpeed=e,this.setPlaybackRate(e),t&&!n?this.emit("holdSpeedStart",{speed:e}):!t&&n&&this.emit("holdSpeedEnd",void 0)},onSeekPercent:e=>this.seekPercent(e),speedHoldValue:this._holdSpeed}),this.interactionController.attach(),this.cleanupFns.push(()=>{this.interactionController?.detach(),this.interactionController=null})}initializeMistReporter(){if(!this.streamStateClient)return;const e=this.streamStateClient.getSocket();e&&(this.mistReporter=new gt({socket:e,bootMs:this.bootMs,reportInterval:5e3}),this.videoElement&&this.mistReporter.init(this.videoElement,this.container??void 0),this._currentSourceInfo&&this.mistReporter.sendInitialReport({player:this._currentPlayerInfo?.shortname||"unknown",sourceType:this._currentSourceInfo.type,sourceUrl:this._currentSourceInfo.url,pageUrl:"undefined"!=typeof window?window.location.href:""}),this.cleanupFns.push(()=>{this.mistReporter?.sendFinalReport("unmount"),this.mistReporter?.destroy(),this.mistReporter=null}))}initializeMetaTrackManager(){const e=this.endpoints?.primary?.baseUrl;if(e){if(this.metaTrackManager=new vt({mistBaseUrl:e,streamName:this.config.contentId,debug:this.config.debug}),this.metaTrackManager.connect(),this.videoElement){const e=()=>{this.videoElement&&this.metaTrackManager&&this.metaTrackManager.setPlaybackTime(this.videoElement.currentTime)},t=()=>{this.videoElement&&this.metaTrackManager&&this.metaTrackManager.onSeek(this.videoElement.currentTime)};this.videoElement.addEventListener("timeupdate",e),this.videoElement.addEventListener("seeking",t),this.cleanupFns.push(()=>{this.videoElement?.removeEventListener("timeupdate",e),this.videoElement?.removeEventListener("seeking",t)})}this.cleanupFns.push(()=>{this.metaTrackManager?.disconnect(),this.metaTrackManager=null})}}cleanup(){this.cleanupFns.forEach(e=>{try{e()}catch{}}),this.cleanupFns=[];try{this.playerManager.destroy()}catch{}}setState(e,t){this.state=e,this.lastEmittedState!==e&&(this.lastEmittedState=e,this.emit("stateChange",{state:e,context:t}))}log(e){this.config.debug&&console.log(`[PlayerController] ${e}`)}}Pt.HOVER_HIDE_DELAY_MS=3e3,Pt.HOVER_LEAVE_DELAY_MS=200,Pt.HARD_FAILURE_STALL_THRESHOLD_MS=3e4,Pt.AUTO_CLEAR_ERROR_DELAY_MS=2e3,Pt.HARD_FAILURE_ERROR_THRESHOLD=5,Pt.HARD_FAILURE_ERROR_WINDOW_MS=6e4,Pt.FATAL_ERROR_KEYWORDS=["fatal","network error","media error","decode error","source not supported"];class Ot extends Qe{constructor(e){super(),this.ws=null,this.timeoutId=null,this._state="disconnected",this.seekPromise=null,this.url=e.url.replace(/^http/,"ws"),this.timeout=e.timeout??5e3,this.onLog=e.onLog??(()=>{})}get state(){return this._state}get isConnected(){return"connected"===this._state}connect(){if(!this.ws||this.ws.readyState!==WebSocket.OPEN&&this.ws.readyState!==WebSocket.CONNECTING){this._state="connecting",this.onLog(`Connecting to ${this.url}`);try{this.ws=new WebSocket(this.url)}catch(e){return this.onLog(`Failed to create WebSocket: ${e}`),void(this._state="disconnected")}this.timeoutId=setTimeout(()=>{this.ws&&this.ws.readyState===WebSocket.CONNECTING&&(this.onLog("WebSocket connection timeout"),this.ws.close(),this._state="disconnected",this.emit("error",{message:"Connection timeout"}))},this.timeout),this.ws.onopen=()=>{this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),this._state="connected",this.onLog("WebSocket connected"),this.emit("connected",void 0)},this.ws.onmessage=e=>{try{const t=JSON.parse(e.data);this.handleMessage(t)}catch(e){this.onLog(`Failed to parse message: ${e}`)}},this.ws.onclose=e=>{this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),this._state="closed",this.onLog(`WebSocket closed (code: ${e.code})`),this.emit("disconnected",{code:e.code})},this.ws.onerror=e=>{this.onLog(`WebSocket error: ${e}`)}}else this.onLog("Already connected or connecting")}handleMessage(e){const t=e.type;switch(t){case"on_connected":break;case"on_disconnected":this._state="disconnected",this.emit("disconnected",{code:e.code||0});break;case"on_answer_sdp":this.emit("answer_sdp",{result:e.result,answer_sdp:e.answer_sdp});break;case"on_time":this.emit("time_update",{current:e.current,end:e.end,begin:e.begin,tracks:e.tracks,paused:e.paused,live_point:e.live_point});break;case"seek":this.emit("seeked",{live_point:e.live_point}),this.seekPromise&&(this.seekPromise.resolve("Seeked"),this.seekPromise=null);break;case"set_speed":this.emit("speed_changed",{play_rate:e.play_rate,play_rate_curr:e.play_rate_curr});break;case"on_stop":this.emit("stopped",void 0);break;case"on_error":this.emit("error",{message:e.message});break;default:this.onLog(`Unhandled message type: ${t}`)}}send(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)return this.onLog("Cannot send: WebSocket not connected"),!1;try{return this.ws.send(JSON.stringify(e)),!0}catch(e){return this.onLog(`Failed to send message: ${e}`),!1}}sendOfferSDP(e){return this.send({type:"offer_sdp",offer_sdp:e})}seek(e){return new Promise((t,n)=>{if(!this.isConnected)return void n("Not connected");this.seekPromise&&this.seekPromise.reject("New seek requested");const i="live"===e?"live":1e3*e;this.send({type:"seek",seek_time:i}),this.seekPromise={resolve:t,reject:n}})}pause(){return this.send({type:"hold"})}stop(){return this.send({type:"stop"})}setTracks(e){return this.send({type:"tracks",...e})}setSpeed(e){return this.send({type:"set_speed",play_rate:e})}close(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),this.seekPromise&&(this.seekPromise.reject("Connection closed"),this.seekPromise=null),this.ws&&(this._state="closed",this.ws.close(),this.ws=null)}destroy(){this.close(),this.removeAllListeners()}}class Ft{constructor(e,t={}){this.lastProgressTime=0,this.lastBufferEnd=0,this.listeners=[],this._calculatedDuration=0,this.video=e,this.options={constrainSeek:t.constrainSeek??!0,liveOffset:t.liveOffset??0,onDurationChange:t.onDurationChange??(()=>{})},this.setupListeners(),this.updateDuration()}isLive(){const e=this.video.duration;return!isFinite(e)||e===1/0}getDuration(){return this.isLive()?this._calculatedDuration:this.video.duration}getBufferEnd(){const e=this.video.buffered;if(0===e.length)return 0;for(let t=0;t<e.length;t++)if(e.start(t)<=this.video.currentTime&&e.end(t)>this.video.currentTime)return e.end(t);return e.end(e.length-1)}getLiveEdge(){return this.getBufferEnd()-this.options.liveOffset}getLatency(){return this.isLive()?Math.max(0,this.getLiveEdge()-this.video.currentTime):0}seek(e){if(!this.isLive()||!this.options.constrainSeek)return void(this.video.currentTime=e);const t=this.video.buffered;if(0===t.length)return void(this.video.currentTime=e);const n=t.start(0),i=this.getLiveEdge(),r=Math.max(n,Math.min(e,i));this.video.currentTime=r}jumpToLive(){this.isLive()&&(this.video.currentTime=this.getLiveEdge())}isAtLiveEdge(e=2){return!!this.isLive()&&this.getLatency()<=e}getState(){return{duration:this.getDuration(),isLive:this.isLive(),bufferEnd:this.getBufferEnd(),elapsed:this.lastProgressTime>0?(Date.now()-this.lastProgressTime)/1e3:0}}updateDuration(){if(!this.isLive())return void(this._calculatedDuration=this.video.duration);const e=this.getBufferEnd(),t=Date.now(),n=e+(this.lastProgressTime>0?(t-this.lastProgressTime)/1e3:0);Math.abs(n-this._calculatedDuration)>.1&&(this._calculatedDuration=n,this.options.onDurationChange(n)),this.lastBufferEnd=e}setupListeners(){const e=()=>{this.lastProgressTime=Date.now(),this.updateDuration()},t=()=>{this.updateDuration()},n=()=>{this.updateDuration()},i=()=>{this.updateDuration()};this.video.addEventListener("progress",e),this.video.addEventListener("timeupdate",t),this.video.addEventListener("durationchange",n),this.video.addEventListener("loadedmetadata",i),this.listeners=[()=>this.video.removeEventListener("progress",e),()=>this.video.removeEventListener("timeupdate",t),()=>this.video.removeEventListener("durationchange",n),()=>this.video.removeEventListener("loadedmetadata",i)]}destroy(){this.listeners.forEach(e=>e()),this.listeners=[]}}function Ut(e,t){if(!t)return e;let n;if("object"==typeof t){const i=Object.entries(t).filter(([,e])=>null!=e).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(String(t))}`);if(0===i.length)return e;n=i.join("&")}else n=t,(n.startsWith("?")||n.startsWith("&"))&&(n=n.slice(1));if(!n)return e;const i=e.includes("?")?"&":"?";return`${e}${i}${n}`}function zt(e){const t={};try{new URL(e).searchParams.forEach((e,n)=>{t[n]=e})}catch{const n=e.indexOf("?");if(-1===n)return t;const i=e.slice(n+1).split("&");for(const e of i){const[n,i]=e.split("=");n&&(t[decodeURIComponent(n)]=i?decodeURIComponent(i):"")}}return t}function Bt(e){const t=e.indexOf("?");return-1===t?e:e.slice(0,t)}function jt(e){if(!Number.isFinite(e)||e<0)return"LIVE";const t=Math.floor(e),n=Math.floor(t/3600),i=Math.floor(t%3600/60),r=t%60;return n>0?`${n}:${String(i).padStart(2,"0")}:${String(r).padStart(2,"0")}`:`${String(i).padStart(2,"0")}:${String(r).padStart(2,"0")}`}function $t(e){const{isLive:t,currentTime:n,duration:i,liveEdge:r,seekableStart:s,unixoffset:a}=e;if(t){if(a&&a>0){const e=new Date(a+1e3*n);return o=e,`${String(o.getHours()).padStart(2,"0")}:${String(o.getMinutes()).padStart(2,"0")}:${String(o.getSeconds()).padStart(2,"0")}`}if(r-s>0){const e=r-n;return e<1?"LIVE":`-${jt(Math.abs(e))}`}return"LIVE"}var o;return Number.isFinite(i)&&i>0?`${jt(n)} / ${jt(i)}`:jt(n)}const qt={state:"booting",streamState:null,endpoints:null,metadata:null,videoElement:null,currentTime:0,duration:NaN,isPlaying:!1,isPaused:!0,isBuffering:!1,isMuted:!0,volume:1,error:null,errorDetails:null,isPassiveError:!1,hasPlaybackStarted:!1,isHoldingSpeed:!1,holdSpeed:2,isHovering:!1,shouldShowControls:!1,isLoopEnabled:!1,isFullscreen:!1,isPiPActive:!1,isEffectivelyLive:!1,shouldShowIdleScreen:!0,currentPlayerInfo:null,currentSourceInfo:null,playbackQuality:null,subtitlesEnabled:!1,qualities:[],textTracks:[],streamInfo:null,toast:null};class Ht{constructor(e){this.controller=null,this.unsubs=[],this.currentConfig=null,this.s={...qt},this.host=e,e.addController(this)}configure(e){this.currentConfig=e}async attach(e){if(!this.currentConfig)return;this.teardown();const t=new Pt({contentId:this.currentConfig.contentId,contentType:this.currentConfig.contentType,endpoints:this.currentConfig.endpoints,gatewayUrl:this.currentConfig.gatewayUrl,mistUrl:this.currentConfig.mistUrl,authToken:this.currentConfig.authToken,autoplay:this.currentConfig.autoplay,muted:this.currentConfig.muted,controls:this.currentConfig.controls,poster:this.currentConfig.poster,debug:this.currentConfig.debug});this.controller=t,this.subscribeToEvents(t),this.update({isLoopEnabled:t.isLoopEnabled()});try{await t.attach(e)}catch(e){console.warn("[PlayerControllerHost] Attach failed:",e)}}hostConnected(){}hostDisconnected(){this.teardown(),this.s={...qt}}teardown(){this.unsubs.forEach(e=>e()),this.unsubs=[],this.controller?.destroy(),this.controller=null}update(e){Object.assign(this.s,e),this.host.requestUpdate()}syncState(){if(!this.controller)return;const e=this.controller;this.update({isPlaying:e.isPlaying(),isPaused:e.isPaused(),isBuffering:e.isBuffering(),isMuted:e.isMuted(),volume:e.getVolume(),hasPlaybackStarted:e.hasPlaybackStarted(),shouldShowControls:e.shouldShowControls(),shouldShowIdleScreen:e.shouldShowIdleScreen(),playbackQuality:e.getPlaybackQuality(),isLoopEnabled:e.isLoopEnabled(),subtitlesEnabled:e.isSubtitlesEnabled(),qualities:e.getQualities(),textTracks:e.getTextTracks(),streamInfo:e.getStreamInfo()})}subscribeToEvents(e){const t=this.unsubs;t.push(e.on("stateChange",({state:e})=>{this.update({state:e}),this.dispatchEvent("fw-state-change",{state:e})})),t.push(e.on("streamStateChange",({state:t})=>{this.update({streamState:t,metadata:e.getMetadata(),isEffectivelyLive:e.isEffectivelyLive(),shouldShowIdleScreen:e.shouldShowIdleScreen()}),this.dispatchEvent("fw-stream-state",{state:t})})),t.push(e.on("timeUpdate",({currentTime:t,duration:n})=>{const i={currentTime:t,duration:n,shouldShowControls:e.shouldShowControls()};if(0===this.s.qualities.length){const t=e.getQualities();t.length>0&&(i.qualities=t)}this.update(i),this.dispatchEvent("fw-time-update",{currentTime:t,duration:n})})),t.push(e.on("error",({error:t})=>{this.update({error:t,isPassiveError:e.isPassiveError()}),this.dispatchEvent("fw-error",{error:t})})),t.push(e.on("errorCleared",()=>{this.update({error:null,isPassiveError:!1})})),t.push(e.on("ready",({videoElement:n})=>{this.update({videoElement:n,endpoints:e.getEndpoints(),metadata:e.getMetadata(),streamInfo:e.getStreamInfo(),isEffectivelyLive:e.isEffectivelyLive(),shouldShowIdleScreen:e.shouldShowIdleScreen(),currentPlayerInfo:e.getCurrentPlayerInfo(),currentSourceInfo:e.getCurrentSourceInfo(),qualities:e.getQualities(),textTracks:e.getTextTracks()}),this.dispatchEvent("fw-ready",{videoElement:n}),this.syncState();const i=()=>{this.controller?.shouldSuppressVideoEvents?.()||this.syncState()};n.addEventListener("play",i),n.addEventListener("pause",i),n.addEventListener("waiting",i),n.addEventListener("playing",i),t.push(()=>{n.removeEventListener("play",i),n.removeEventListener("pause",i),n.removeEventListener("waiting",i),n.removeEventListener("playing",i)})})),t.push(e.on("playerSelected",({player:t,source:n})=>{this.update({currentPlayerInfo:e.getCurrentPlayerInfo(),currentSourceInfo:{url:n.url,type:n.type},qualities:e.getQualities(),textTracks:e.getTextTracks()}),this.syncState()})),t.push(e.on("volumeChange",({volume:e,muted:t})=>{this.update({volume:e,isMuted:t}),this.dispatchEvent("fw-volume-change",{volume:e,muted:t})})),t.push(e.on("loopChange",({isLoopEnabled:e})=>{this.update({isLoopEnabled:e})})),t.push(e.on("fullscreenChange",({isFullscreen:e})=>{this.update({isFullscreen:e}),this.dispatchEvent("fw-fullscreen-change",{isFullscreen:e})})),t.push(e.on("pipChange",({isPiP:e})=>{this.update({isPiPActive:e}),this.dispatchEvent("fw-pip-change",{isPiP:e})})),t.push(e.on("holdSpeedStart",({speed:e})=>{this.update({isHoldingSpeed:!0,holdSpeed:e})})),t.push(e.on("holdSpeedEnd",()=>{this.update({isHoldingSpeed:!1})})),t.push(e.on("hoverStart",()=>{this.update({isHovering:!0,shouldShowControls:!0})})),t.push(e.on("hoverEnd",()=>{this.update({isHovering:!1,shouldShowControls:e.shouldShowControls()})})),t.push(e.on("captionsChange",({enabled:t})=>{this.update({subtitlesEnabled:t,textTracks:e.getTextTracks()})})),t.push(e.on("protocolSwapped",e=>{const t=`Switched to ${e.toProtocol}`;this.update({toast:{message:t,timestamp:Date.now()}}),this.dispatchEvent("fw-protocol-swapped",e)})),t.push(e.on("playbackFailed",e=>{this.update({error:e.message,errorDetails:e.details??null,isPassiveError:!1}),this.dispatchEvent("fw-playback-failed",{code:e.code,message:e.message})}))}dispatchEvent(e,t){this.host.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}async play(){await(this.controller?.play())}pause(){this.controller?.pause()}togglePlay(){this.controller?.togglePlay()}seek(e){this.controller?.seek(e)}seekBy(e){this.controller?.seekBy(e)}jumpToLive(){this.controller?.jumpToLive()}setVolume(e){this.controller?.setVolume(e)}toggleMute(){this.controller?.toggleMute()}toggleLoop(){this.controller?.toggleLoop()}async toggleFullscreen(){await(this.controller?.toggleFullscreen())}async togglePiP(){await(this.controller?.togglePictureInPicture())}toggleSubtitles(){this.controller?.toggleSubtitles()}clearError(){this.controller?.clearError(),this.update({error:null,errorDetails:null,isPassiveError:!1})}dismissToast(){this.update({toast:null})}async retry(){await(this.controller?.retry())}async reload(){await(this.controller?.reload())}getQualities(){return this.controller?.getQualities()??[]}selectQuality(e){this.controller?.selectQuality(e)}getTextTracks(){return this.controller?.getTextTracks()??[]}selectTextTrack(e){this.controller?.selectTextTrack(e)}setPlaybackRate(e){this.controller?.setPlaybackRate(e)}getSeekableStart(){return this.controller?.getSeekableStart()??0}getLiveEdge(){return this.controller?.getLiveEdge()??0}canSeekStream(){return this.controller?.canSeekStream()??!1}getBufferedRanges(){return this.controller?.getBufferedRanges()??null}async getStats(){return this.controller?.getStats()}handleMouseEnter(){this.controller?.handleMouseEnter(),this.update({isHovering:!0,shouldShowControls:!0})}handleMouseLeave(){this.controller?.handleMouseLeave(),this.update({isHovering:!1,shouldShowControls:this.controller?.shouldShowControls()??!1})}handleMouseMove(){this.controller?.handleMouseMove(),this.controller&&this.update({shouldShowControls:this.controller.shouldShowControls()})}handleTouchStart(){this.controller?.handleTouchStart(),this.update({shouldShowControls:!0})}async setDevModeOptions(e){await(this.controller?.setDevModeOptions(e))}getController(){return this.controller}}const Gt=d`
|
|
61
61
|
/*
|
|
62
62
|
* FrameWorks Player CSS
|
|
63
63
|
* Plain CSS - no build step required (just copy to dist).
|
|
@@ -497,11 +497,20 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
497
497
|
.fw-context-menu-item {
|
|
498
498
|
position: relative;
|
|
499
499
|
display: flex;
|
|
500
|
+
width: 100%;
|
|
501
|
+
justify-content: flex-start;
|
|
502
|
+
gap: 0.5rem;
|
|
500
503
|
cursor: pointer;
|
|
501
504
|
user-select: none;
|
|
502
505
|
align-items: center;
|
|
503
506
|
padding: 0.5rem 0.75rem;
|
|
504
507
|
font-size: 0.875rem;
|
|
508
|
+
text-align: left;
|
|
509
|
+
font: inherit;
|
|
510
|
+
border: none;
|
|
511
|
+
background: transparent;
|
|
512
|
+
appearance: none;
|
|
513
|
+
-webkit-appearance: none;
|
|
505
514
|
outline: none;
|
|
506
515
|
color: hsl(var(--tn-fg));
|
|
507
516
|
transition:
|
|
@@ -540,11 +549,20 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
540
549
|
.fw-context-menu-checkbox {
|
|
541
550
|
position: relative;
|
|
542
551
|
display: flex;
|
|
552
|
+
width: 100%;
|
|
553
|
+
justify-content: flex-start;
|
|
554
|
+
gap: 0.5rem;
|
|
543
555
|
cursor: pointer;
|
|
544
556
|
user-select: none;
|
|
545
557
|
align-items: center;
|
|
546
558
|
padding: 0.5rem 0.5rem 0.5rem 2rem;
|
|
547
559
|
font-size: 0.875rem;
|
|
560
|
+
text-align: left;
|
|
561
|
+
font: inherit;
|
|
562
|
+
border: none;
|
|
563
|
+
background: transparent;
|
|
564
|
+
appearance: none;
|
|
565
|
+
-webkit-appearance: none;
|
|
548
566
|
outline: none;
|
|
549
567
|
color: hsl(var(--tn-fg));
|
|
550
568
|
transition:
|
|
@@ -2753,7 +2771,7 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
2753
2771
|
<svg width="${e}" height="${e}" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
2754
2772
|
<path d="M9 3L3 9M3 3L9 9" stroke="${t}" stroke-width="1.5" stroke-linecap="round" />
|
|
2755
2773
|
</svg>
|
|
2756
|
-
`;e.FwPlayer=class extends he{constructor(){super(...arguments),this.contentId="",this.autoplay=!0,this.muted=!0,this.controls=!1,this.debug=!1,this.devMode=!1,this.playbackMode="auto",this._isStatsOpen=!1,this._isDevPanelOpen=!1,this._skipDirection=null,this._contextMenuOpen=!1,this._contextMenuMounted=!1,this._contextMenuState="closed",this._contextMenuSide="bottom",this._contextMenuActiveLevel="root",this._contextMenuOpenSubmenu=null,this._contextMenuSubmenuSide="right",this._contextMenuX=0,this._contextMenuY=0,this.pc=new Ht(this),this._contextMenuTypeahead="",this._resetContextMenuTypeahead=()=>{this._contextMenuTypeahead="",this._contextMenuTypeaheadTimer&&(clearTimeout(this._contextMenuTypeaheadTimer),this._contextMenuTypeaheadTimer=void 0)},this._resolveContextMenuSide=(e,t,n,i)=>{const r=Math.abs(e-n),s=Math.abs(t-i);return 0===r&&0===s?"bottom":s>=r?t>i?"top":"bottom":e>n?"left":"right"},this._closeContextMenu=(e=!1)=>{if(this._contextMenuOpen=!1,this._contextMenuState="closed",this._contextMenuActiveLevel="root",this._contextMenuOpenSubmenu=null,this._resetContextMenuTypeahead(),this._contextMenuCloseTimer&&clearTimeout(this._contextMenuCloseTimer),this._contextMenuCloseTimer=setTimeout(()=>{this._contextMenuOpen||(this._contextMenuMounted=!1)},170),e){const e=this.shadowRoot?.querySelector('[part="root"]');e?.focus()}},this._getQueryRoot=()=>this.shadowRoot??this.renderRoot??null,this._getContextMenuElement=()=>this._getQueryRoot()?.querySelector('[data-context-menu="true"]')??null,this._getContextMenuItems=(e=this._contextMenuActiveLevel)=>Array.from(this._getQueryRoot()?.querySelectorAll(`[data-context-menu-item="true"][data-context-menu-level="${e}"]:not([data-disabled="true"])`)??[]),this._focusFirstContextMenuItem=(e=this._contextMenuActiveLevel)=>{const[t]=this._getContextMenuItems(e);t?.focus()},this._focusPlaybackModeTrigger=()=>{const e=this._getQueryRoot()?.querySelector('[data-context-menu-trigger="playback-mode"]');e?.focus()},this._openPlaybackModeSubmenu=()=>{this._contextMenuOpenSubmenu="playback-mode",this._contextMenuActiveLevel="submenu",this._resetContextMenuTypeahead(),queueMicrotask(()=>{this._syncPlaybackModeSubmenuSide(),this._focusFirstContextMenuItem("submenu")})},this._closePlaybackModeSubmenu=(e=!1)=>{this._contextMenuOpenSubmenu=null,this._contextMenuActiveLevel="root",this._resetContextMenuTypeahead(),e&&this._focusPlaybackModeTrigger()},this._clampContextMenuPosition=(e,t,n,i)=>{const r=Math.max(8,
|
|
2774
|
+
`;e.FwPlayer=class extends he{constructor(){super(...arguments),this.contentId="",this.autoplay=!0,this.muted=!0,this.controls=!1,this.stockControls=!1,this.nativeControls=!1,this.debug=!1,this.devMode=!1,this.playbackMode="auto",this._isStatsOpen=!1,this._isDevPanelOpen=!1,this._skipDirection=null,this._contextMenuOpen=!1,this._contextMenuMounted=!1,this._contextMenuState="closed",this._contextMenuSide="bottom",this._contextMenuActiveLevel="root",this._contextMenuOpenSubmenu=null,this._contextMenuSubmenuSide="right",this._contextMenuX=0,this._contextMenuY=0,this.pc=new Ht(this),this._contextMenuTypeahead="",this._resetContextMenuTypeahead=()=>{this._contextMenuTypeahead="",this._contextMenuTypeaheadTimer&&(clearTimeout(this._contextMenuTypeaheadTimer),this._contextMenuTypeaheadTimer=void 0)},this._resolveContextMenuSide=(e,t,n,i)=>{const r=Math.abs(e-n),s=Math.abs(t-i);return 0===r&&0===s?"bottom":s>=r?t>i?"top":"bottom":e>n?"left":"right"},this._closeContextMenu=(e=!1)=>{if(this._contextMenuOpen=!1,this._contextMenuState="closed",this._contextMenuActiveLevel="root",this._contextMenuOpenSubmenu=null,this._resetContextMenuTypeahead(),this._contextMenuCloseTimer&&clearTimeout(this._contextMenuCloseTimer),this._contextMenuCloseTimer=setTimeout(()=>{this._contextMenuOpen||(this._contextMenuMounted=!1)},170),e){const e=this.shadowRoot?.querySelector('[part="root"]');e?.focus()}},this._getQueryRoot=()=>this.shadowRoot??this.renderRoot??null,this._getContextMenuElement=()=>this._getQueryRoot()?.querySelector('[data-context-menu="true"]')??null,this._getContextMenuBounds=()=>{const e=this._getQueryRoot()?.querySelector('[part="root"]'),t=e?.getBoundingClientRect()??this.getBoundingClientRect(),n=t.width>0?t.width:window.innerWidth,i=t.height>0?t.height:window.innerHeight;return{left:t.left,top:t.top,right:t.left+n,bottom:t.top+i,width:n,height:i}},this._toLocalContextMenuPoint=(e,t)=>{const n=this._getContextMenuBounds();return{x:e-n.left,y:t-n.top}},this._getContextMenuItems=(e=this._contextMenuActiveLevel)=>Array.from(this._getQueryRoot()?.querySelectorAll(`[data-context-menu-item="true"][data-context-menu-level="${e}"]:not([data-disabled="true"])`)??[]),this._focusFirstContextMenuItem=(e=this._contextMenuActiveLevel)=>{const[t]=this._getContextMenuItems(e);t?.focus()},this._focusPlaybackModeTrigger=()=>{const e=this._getQueryRoot()?.querySelector('[data-context-menu-trigger="playback-mode"]');e?.focus()},this._openPlaybackModeSubmenu=()=>{this._contextMenuOpenSubmenu="playback-mode",this._contextMenuActiveLevel="submenu",this._resetContextMenuTypeahead(),queueMicrotask(()=>{this._syncPlaybackModeSubmenuSide(),this._focusFirstContextMenuItem("submenu")})},this._closePlaybackModeSubmenu=(e=!1)=>{this._contextMenuOpenSubmenu=null,this._contextMenuActiveLevel="root",this._resetContextMenuTypeahead(),e&&this._focusPlaybackModeTrigger()},this._clampContextMenuPosition=(e,t,n,i)=>{const r=this._getContextMenuBounds(),s=Math.max(8,r.width-n-8),a=Math.max(8,r.height-i-8);return{x:Math.max(8,Math.min(e,s)),y:Math.max(8,Math.min(t,a))}},this._syncContextMenuPosition=()=>{if(!this._contextMenuMounted)return;const e=this._getContextMenuElement();if(!e)return;const t=e.getBoundingClientRect(),n=this._clampContextMenuPosition(this._contextMenuX,this._contextMenuY,t.width,t.height);this._contextMenuSide=this._resolveContextMenuSide(this._contextMenuX,this._contextMenuY,n.x,n.y),n.x===this._contextMenuX&&n.y===this._contextMenuY||(this._contextMenuX=n.x,this._contextMenuY=n.y)},this._syncPlaybackModeSubmenuSide=()=>{if("playback-mode"!==this._contextMenuOpenSubmenu)return;const e=this._getContextMenuElement();if(!e)return;const t=this._getContextMenuBounds(),n=e.getBoundingClientRect();this._contextMenuSubmenuSide=n.right+190>t.right-8?"left":"right"},this._openContextMenu=(e,t)=>{const n=this._toLocalContextMenuPoint(e,t),i=this._clampContextMenuPosition(n.x,n.y,220,200);this._contextMenuSide=this._resolveContextMenuSide(n.x,n.y,i.x,i.y),this._contextMenuX=i.x,this._contextMenuY=i.y,this._contextMenuMounted=!0,this._contextMenuState="open",this._contextMenuActiveLevel="root",this._contextMenuOpenSubmenu=null,this._contextMenuCloseTimer&&(clearTimeout(this._contextMenuCloseTimer),this._contextMenuCloseTimer=void 0),this._resetContextMenuTypeahead(),this._contextMenuOpen=!0},this._handleContextMenu=e=>{const t=e.target;t?.closest('[data-context-menu="true"]')?e.preventDefault():(e.preventDefault(),this._openContextMenu(e.clientX,e.clientY))},this._handleContextMenuShortcut=e=>{const t="ContextMenu"===e.key,n="F10"===e.key&&e.shiftKey;if(!t&&!n)return;e.preventDefault();const i=this.getBoundingClientRect(),r=i.left+i.width/2,s=i.top+i.height/2;this._openContextMenu(r,s)},this._handleDocumentPointerDown=e=>{if(!this._contextMenuOpen)return;const t=this._getContextMenuElement(),n=e.composedPath();t&&n.includes(t)||this._closeContextMenu()},this._handleDocumentContextMenu=e=>{this._contextMenuOpen&&(this.contains(e.target)||this._closeContextMenu())},this._handleDocumentKeyDown=e=>{"Escape"===e.key&&this._contextMenuOpen&&(e.preventDefault(),this._closeContextMenu(!0))},this._handleContextMenuKeyDown=e=>{if(!this._contextMenuOpen)return;const t=this.shadowRoot?.activeElement;if("Escape"===e.key)return e.preventDefault(),void("submenu"===this._contextMenuActiveLevel?this._closePlaybackModeSubmenu(!0):this._closeContextMenu(!0));if("Tab"===e.key)return void this._closeContextMenu();if("ArrowRight"===e.key&&"root"===this._contextMenuActiveLevel)return void("playback-mode"===t?.dataset.contextMenuTrigger&&(e.preventDefault(),this._openPlaybackModeSubmenu()));if("ArrowLeft"===e.key&&"submenu"===this._contextMenuActiveLevel)return e.preventDefault(),void this._closePlaybackModeSubmenu(!0);const n=this._getContextMenuItems(this._contextMenuActiveLevel);if(0===n.length)return;const i=n.findIndex(e=>e===t);if("Home"===e.key)return e.preventDefault(),void this._focusFirstContextMenuItem(this._contextMenuActiveLevel);if("End"===e.key)return e.preventDefault(),void n[n.length-1]?.focus();if("ArrowDown"===e.key||"ArrowUp"===e.key){e.preventDefault();const t="ArrowDown"===e.key?1:-1,r=((-1===i?1===t?0:n.length-1:i)+t+n.length)%n.length;return void n[r]?.focus()}if("Enter"!==e.key&&" "!==e.key){if(1===e.key.length&&!e.metaKey&&!e.ctrlKey&&!e.altKey){e.preventDefault(),this._contextMenuTypeahead+=e.key.toLowerCase(),this._contextMenuTypeaheadTimer&&clearTimeout(this._contextMenuTypeaheadTimer),this._contextMenuTypeaheadTimer=setTimeout(()=>{this._resetContextMenuTypeahead()},700);const t=-1===i?0:i+1,r=[...n.slice(t),...n.slice(0,t)].find(e=>e.textContent?.trim().toLowerCase().startsWith(this._contextMenuTypeahead));r?.focus()}}else t&&(e.preventDefault(),t.click())}}willUpdate(e){(e.has("contentId")||e.has("contentType")||e.has("gatewayUrl")||e.has("mistUrl")||e.has("authToken")||e.has("autoplay")||e.has("muted")||e.has("stockControls")||e.has("nativeControls")||e.has("debug")||e.has("thumbnailUrl")||e.has("endpoints"))&&this.pc.configure({contentId:this.contentId,contentType:this.contentType,endpoints:this.endpoints,gatewayUrl:this.gatewayUrl,mistUrl:this.mistUrl,authToken:this.authToken,autoplay:this.autoplay,muted:this.muted,controls:this.stockControls||this.nativeControls,poster:this.thumbnailUrl,debug:this.debug})}firstUpdated(){this.pc.attach(this._containerEl),document.addEventListener("pointerdown",this._handleDocumentPointerDown),document.addEventListener("contextmenu",this._handleDocumentContextMenu),document.addEventListener("keydown",this._handleDocumentKeyDown)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("pointerdown",this._handleDocumentPointerDown),document.removeEventListener("contextmenu",this._handleDocumentContextMenu),document.removeEventListener("keydown",this._handleDocumentKeyDown),this._contextMenuCloseTimer&&(clearTimeout(this._contextMenuCloseTimer),this._contextMenuCloseTimer=void 0),this._resetContextMenuTypeahead()}updated(e){this.pc.s.toast&&(clearTimeout(this._toastTimer),this._toastTimer=setTimeout(()=>this.pc.dismissToast(),3e3)),(e.has("_contextMenuOpen")||e.has("_contextMenuMounted"))&&this._contextMenuOpen&&queueMicrotask(()=>{this._syncContextMenuPosition(),this._focusFirstContextMenuItem("root")}),e.has("_contextMenuOpenSubmenu")&&"playback-mode"===this._contextMenuOpenSubmenu&&queueMicrotask(()=>{this._syncPlaybackModeSubmenuSide()})}get _showTitleOverlay(){const e=this.pc.s;return(e.isHovering||e.isPaused)&&!e.shouldShowIdleScreen&&!e.isBuffering&&!e.error}get _showBufferingSpinner(){const e=this.pc.s;return!e.shouldShowIdleScreen&&e.isBuffering&&!e.error&&e.hasPlaybackStarted}get _showWaitingForEndpoint(){const e=this.pc.s;return!e.endpoints?.primary&&"booting"!==e.state}get _waitingMessage(){const e=this.pc.s;return this.gatewayUrl&&"gateway_loading"===e.state?"Resolving viewing endpoint...":"Waiting for endpoint..."}get _useStockControls(){return this.stockControls||this.nativeControls||"mist-legacy"===this.pc.s.currentPlayerInfo?.shortname}async play(){await this.pc.play()}pause(){this.pc.pause()}togglePlay(){this.pc.togglePlay()}seek(e){this.pc.seek(e)}seekBy(e){this.pc.seekBy(e)}jumpToLive(){this.pc.jumpToLive()}setVolume(e){this.pc.setVolume(e)}toggleMute(){this.pc.toggleMute()}toggleLoop(){this.pc.toggleLoop()}async toggleFullscreen(){await this.pc.toggleFullscreen()}async togglePiP(){await this.pc.togglePiP()}toggleSubtitles(){this.pc.toggleSubtitles()}async retry(){await this.pc.retry()}async reload(){await this.pc.reload()}getQualities(){return this.pc.getQualities()}selectQuality(e){this.pc.selectQuality(e)}destroy(){this.pc.hostDisconnected()}render(){const e=this.pc.s;return W`
|
|
2757
2775
|
<div
|
|
2758
2776
|
part="root"
|
|
2759
2777
|
class=${Se({"fw-player-surface":!0,"fw-player-root":!0,"w-full":!0,"h-full":!0,"overflow-hidden":!0,flex:this.devMode})}
|
|
@@ -2918,6 +2936,7 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
2918
2936
|
.pc=${this.pc}
|
|
2919
2937
|
.playbackMode=${this.playbackMode}
|
|
2920
2938
|
.isContentLive=${e.isEffectivelyLive}
|
|
2939
|
+
.devMode=${this.devMode}
|
|
2921
2940
|
.isStatsOpen=${this._isStatsOpen}
|
|
2922
2941
|
@fw-stats-toggle=${()=>{this._isStatsOpen=!this._isStatsOpen}}
|
|
2923
2942
|
@fw-mode-change=${e=>{this.playbackMode=e.detail.mode}}
|
|
@@ -2947,7 +2966,7 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
2947
2966
|
role="menu"
|
|
2948
2967
|
aria-label="Player options"
|
|
2949
2968
|
tabindex="-1"
|
|
2950
|
-
style="position:
|
|
2969
|
+
style="position: absolute; left: ${this._contextMenuX}px; top: ${this._contextMenuY}px;"
|
|
2951
2970
|
@contextmenu=${e=>e.preventDefault()}
|
|
2952
2971
|
@keydown=${this._handleContextMenuKeyDown}
|
|
2953
2972
|
>
|
|
@@ -3135,10 +3154,11 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
3135
3154
|
.player-area--dev {
|
|
3136
3155
|
flex: 1;
|
|
3137
3156
|
min-width: 0;
|
|
3157
|
+
min-height: 0;
|
|
3138
3158
|
}
|
|
3139
|
-
`],n([ye({attribute:"content-id"})],e.FwPlayer.prototype,"contentId",void 0),n([ye({attribute:"content-type"})],e.FwPlayer.prototype,"contentType",void 0),n([ye({attribute:"gateway-url"})],e.FwPlayer.prototype,"gatewayUrl",void 0),n([ye({attribute:"mist-url"})],e.FwPlayer.prototype,"mistUrl",void 0),n([ye({attribute:"auth-token"})],e.FwPlayer.prototype,"authToken",void 0),n([ye({type:Boolean})],e.FwPlayer.prototype,"autoplay",void 0),n([ye({type:Boolean})],e.FwPlayer.prototype,"muted",void 0),n([ye({type:Boolean})],e.FwPlayer.prototype,"controls",void 0),n([ye({type:Boolean})],e.FwPlayer.prototype,"debug",void 0),n([ye({type:Boolean,attribute:"dev-mode"})],e.FwPlayer.prototype,"devMode",void 0),n([ye({attribute:"thumbnail-url"})],e.FwPlayer.prototype,"thumbnailUrl",void 0),n([ye({attribute:"playback-mode"})],e.FwPlayer.prototype,"playbackMode",void 0),n([ye({attribute:!1})],e.FwPlayer.prototype,"endpoints",void 0),n([be()],e.FwPlayer.prototype,"_isStatsOpen",void 0),n([be()],e.FwPlayer.prototype,"_isDevPanelOpen",void 0),n([be()],e.FwPlayer.prototype,"_skipDirection",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuOpen",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuMounted",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuState",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuSide",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuActiveLevel",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuOpenSubmenu",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuSubmenuSide",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuX",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuY",void 0),n([ve("#container")],e.FwPlayer.prototype,"_containerEl",void 0),e.FwPlayer=n([pe("fw-player")],e.FwPlayer);let Qt=class extends he{constructor(){super(...arguments),this.playbackMode="auto",this.isContentLive=!1,this.showStatsButton=!1,this.isStatsOpen=!1,this._settingsOpen=!1,this._isNearLiveState=!0,this._buffered=null,this._boundVideo=null,this._onBufferedUpdate=null,this._onWindowClick=e=>{e.composedPath().some(e=>e instanceof HTMLElement&&(e.classList.contains("fw-settings-anchor")||e.classList.contains("fw-settings-menu")))||(this._settingsOpen=!1)}}connectedCallback(){super.connectedCallback()}disconnectedCallback(){super.disconnectedCallback(),this._unbindVideoEvents(),this._detachWindowClickListener()}updated(e){this._bindVideoEvents(),this._reconcileNearLiveState(),e.has("_settingsOpen")&&(this._settingsOpen?this._attachWindowClickListener():this._detachWindowClickListener())}_bindVideoEvents(){const e=this.pc?.s.videoElement??null;if(e===this._boundVideo)return;if(this._unbindVideoEvents(),this._boundVideo=e,!e)return void(this._buffered=null);const t=()=>{this._buffered=this.pc.getBufferedRanges()??e.buffered};t(),e.addEventListener("progress",t),e.addEventListener("loadeddata",t),this._onBufferedUpdate=t}_unbindVideoEvents(){if(!this._boundVideo)return;const e=this._onBufferedUpdate;e&&(this._boundVideo.removeEventListener("progress",e),this._boundVideo.removeEventListener("loadeddata",e)),this._boundVideo=null,this._onBufferedUpdate=null}_attachWindowClickListener(){window.setTimeout(()=>{this._settingsOpen&&window.addEventListener("click",this._onWindowClick)},0)}_detachWindowClickListener(){window.removeEventListener("click",this._onWindowClick)}_deriveBufferWindowMs(e){if(!e)return;const t=Object.values(e);if(0===t.length)return;const n=t.map(e=>e.firstms).filter(e=>"number"==typeof e),i=t.map(e=>e.lastms).filter(e=>"number"==typeof e);if(0===n.length||0===i.length)return;const r=Math.max(...n),s=Math.min(...i)-r;return!Number.isFinite(s)||s<=0?void 0:s}_getSeekingContext(){const e=this.pc.s,t=this.pc.getController(),n=e.currentSourceInfo?.type,i=e.streamState?.streamInfo,r=function(e,t,n){return void 0!==e?e:t?.type?"live"===t.type:!Number.isFinite(n)}(this.isContentLive,i,e.duration),s=i?.meta?.buffer_window??this._deriveBufferWindowMs(i?.meta?.tracks),a=St(e.videoElement),o=St(e.videoElement)&&void 0!==s&&s>0&&"whep"!==n&&"webrtc"!==n,l=kt({isLive:r,video:e.videoElement,mistStreamInfo:i,currentTime:e.currentTime,duration:e.duration,allowMediaStreamDvr:o}),u=this.pc.getSeekableStart(),d=this.pc.getLiveEdge(),c=Number.isFinite(u)&&Number.isFinite(d)&&d>=u&&(d>0||u>0),h=c?u:l.seekableStart,f=c?d:l.liveEdge,p=r&&Number.isFinite(f)&&Number.isFinite(h)&&f>h;return{mistStreamInfo:i,isLive:r,sourceType:n,seekableStart:h,liveEdge:f,hasDvrWindow:p,canSeek:(t?.canSeekStream?.()??It({video:e.videoElement,isLive:r,duration:e.duration,bufferWindowMs:s}))&&(!r||p),commitOnRelease:r,liveThresholds:At(n,a,s)}}_reconcileNearLiveState(){const e=this._getSeekingContext();if(!e.isLive)return void(this._isNearLiveState||(this._isNearLiveState=!0));const t=Ct(this.pc.s.currentTime,e.liveEdge,e.liveThresholds,this._isNearLiveState);t!==this._isNearLiveState&&(this._isNearLiveState=t)}_handleModeChange(e){const{mode:t}=e.detail;this.dispatchEvent(new CustomEvent("fw-mode-change",{detail:{mode:t},bubbles:!0,composed:!0}))}render(){const e=this.pc.s,t=!e.videoElement,n=this._getSeekingContext(),i=$t({isLive:n.isLive,currentTime:e.currentTime,duration:e.duration,liveEdge:n.liveEdge,seekableStart:n.seekableStart,unixoffset:n.mistStreamInfo?.unixoffset}),
|
|
3159
|
+
`],n([ye({attribute:"content-id"})],e.FwPlayer.prototype,"contentId",void 0),n([ye({attribute:"content-type"})],e.FwPlayer.prototype,"contentType",void 0),n([ye({attribute:"gateway-url"})],e.FwPlayer.prototype,"gatewayUrl",void 0),n([ye({attribute:"mist-url"})],e.FwPlayer.prototype,"mistUrl",void 0),n([ye({attribute:"auth-token"})],e.FwPlayer.prototype,"authToken",void 0),n([ye({type:Boolean})],e.FwPlayer.prototype,"autoplay",void 0),n([ye({type:Boolean})],e.FwPlayer.prototype,"muted",void 0),n([ye({type:Boolean})],e.FwPlayer.prototype,"controls",void 0),n([ye({type:Boolean,attribute:"stock-controls"})],e.FwPlayer.prototype,"stockControls",void 0),n([ye({type:Boolean,attribute:"native-controls"})],e.FwPlayer.prototype,"nativeControls",void 0),n([ye({type:Boolean})],e.FwPlayer.prototype,"debug",void 0),n([ye({type:Boolean,attribute:"dev-mode"})],e.FwPlayer.prototype,"devMode",void 0),n([ye({attribute:"thumbnail-url"})],e.FwPlayer.prototype,"thumbnailUrl",void 0),n([ye({attribute:"playback-mode"})],e.FwPlayer.prototype,"playbackMode",void 0),n([ye({attribute:!1})],e.FwPlayer.prototype,"endpoints",void 0),n([be()],e.FwPlayer.prototype,"_isStatsOpen",void 0),n([be()],e.FwPlayer.prototype,"_isDevPanelOpen",void 0),n([be()],e.FwPlayer.prototype,"_skipDirection",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuOpen",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuMounted",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuState",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuSide",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuActiveLevel",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuOpenSubmenu",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuSubmenuSide",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuX",void 0),n([be()],e.FwPlayer.prototype,"_contextMenuY",void 0),n([ve("#container")],e.FwPlayer.prototype,"_containerEl",void 0),e.FwPlayer=n([pe("fw-player")],e.FwPlayer);let Qt=class extends he{constructor(){super(...arguments),this.playbackMode="auto",this.isContentLive=!1,this.devMode=!1,this.showStatsButton=!1,this.isStatsOpen=!1,this._settingsOpen=!1,this._isNearLiveState=!0,this._buffered=null,this._boundVideo=null,this._onBufferedUpdate=null,this._onWindowClick=e=>{e.composedPath().some(e=>e instanceof HTMLElement&&(e.classList.contains("fw-settings-anchor")||e.classList.contains("fw-settings-menu")))||(this._settingsOpen=!1)}}connectedCallback(){super.connectedCallback()}disconnectedCallback(){super.disconnectedCallback(),this._unbindVideoEvents(),this._detachWindowClickListener()}updated(e){this._bindVideoEvents(),this._reconcileNearLiveState(),e.has("_settingsOpen")&&(this._settingsOpen?this._attachWindowClickListener():this._detachWindowClickListener())}_bindVideoEvents(){const e=this.pc?.s.videoElement??null;if(e===this._boundVideo)return;if(this._unbindVideoEvents(),this._boundVideo=e,!e)return void(this._buffered=null);const t=()=>{this._buffered=this.pc.getBufferedRanges()??e.buffered};t(),e.addEventListener("progress",t),e.addEventListener("loadeddata",t),this._onBufferedUpdate=t}_unbindVideoEvents(){if(!this._boundVideo)return;const e=this._onBufferedUpdate;e&&(this._boundVideo.removeEventListener("progress",e),this._boundVideo.removeEventListener("loadeddata",e)),this._boundVideo=null,this._onBufferedUpdate=null}_attachWindowClickListener(){window.setTimeout(()=>{this._settingsOpen&&window.addEventListener("click",this._onWindowClick)},0)}_detachWindowClickListener(){window.removeEventListener("click",this._onWindowClick)}_deriveBufferWindowMs(e){if(!e)return;const t=Object.values(e);if(0===t.length)return;const n=t.map(e=>e.firstms).filter(e=>"number"==typeof e),i=t.map(e=>e.lastms).filter(e=>"number"==typeof e);if(0===n.length||0===i.length)return;const r=Math.max(...n),s=Math.min(...i)-r;return!Number.isFinite(s)||s<=0?void 0:s}_getSeekingContext(){const e=this.pc.s,t=this.pc.getController(),n=e.currentSourceInfo?.type,i=e.streamState?.streamInfo,r=function(e,t,n){return void 0!==e?e:t?.type?"live"===t.type:!Number.isFinite(n)}(this.isContentLive,i,e.duration),s=i?.meta?.buffer_window??this._deriveBufferWindowMs(i?.meta?.tracks),a=St(e.videoElement),o=St(e.videoElement)&&void 0!==s&&s>0&&"whep"!==n&&"webrtc"!==n,l=kt({isLive:r,video:e.videoElement,mistStreamInfo:i,currentTime:e.currentTime,duration:e.duration,allowMediaStreamDvr:o}),u=this.pc.getSeekableStart(),d=this.pc.getLiveEdge(),c=Number.isFinite(u)&&Number.isFinite(d)&&d>=u&&(d>0||u>0),h=c?u:l.seekableStart,f=c?d:l.liveEdge,p=r&&Number.isFinite(f)&&Number.isFinite(h)&&f>h;return{mistStreamInfo:i,isLive:r,sourceType:n,seekableStart:h,liveEdge:f,hasDvrWindow:p,canSeek:(t?.canSeekStream?.()??It({video:e.videoElement,isLive:r,duration:e.duration,bufferWindowMs:s}))&&(!r||p),commitOnRelease:r,liveThresholds:At(n,a,s)}}_reconcileNearLiveState(){const e=this._getSeekingContext();if(!e.isLive)return void(this._isNearLiveState||(this._isNearLiveState=!0));const t=Ct(this.pc.s.currentTime,e.liveEdge,e.liveThresholds,this._isNearLiveState);t!==this._isNearLiveState&&(this._isNearLiveState=t)}_handleModeChange(e){const{mode:t}=e.detail;this.dispatchEvent(new CustomEvent("fw-mode-change",{detail:{mode:t},bubbles:!0,composed:!0}))}render(){const e=this.pc.s,t=!e.videoElement,n=this._getSeekingContext(),i=e.shouldShowControls||e.isPaused||!e.hasPlaybackStarted||e.shouldShowIdleScreen||!!e.error||this._settingsOpen,r=$t({isLive:n.isLive,currentTime:e.currentTime,duration:e.duration,liveEdge:n.liveEdge,seekableStart:n.seekableStart,unixoffset:n.mistStreamInfo?.unixoffset}),s=!n.hasDvrWindow||this._isNearLiveState;return W`
|
|
3140
3160
|
<div
|
|
3141
|
-
class=${Se({"fw-player-surface":!0,"fw-controls-wrapper":!0,"fw-controls-wrapper--visible":
|
|
3161
|
+
class=${Se({"fw-player-surface":!0,"fw-controls-wrapper":!0,"fw-controls-wrapper--visible":i,"fw-controls-wrapper--hidden":!i})}
|
|
3142
3162
|
>
|
|
3143
3163
|
<div class="fw-control-bar" @click=${e=>e.stopPropagation()}>
|
|
3144
3164
|
${n.canSeek?W`
|
|
@@ -3222,7 +3242,7 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
3222
3242
|
</div>
|
|
3223
3243
|
|
|
3224
3244
|
<div class="fw-control-group">
|
|
3225
|
-
<span class="fw-time-display">${
|
|
3245
|
+
<span class="fw-time-display">${r}</span>
|
|
3226
3246
|
</div>
|
|
3227
3247
|
|
|
3228
3248
|
${n.isLive?W`
|
|
@@ -3230,8 +3250,8 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
3230
3250
|
<button
|
|
3231
3251
|
type="button"
|
|
3232
3252
|
@click=${()=>this.pc.jumpToLive()}
|
|
3233
|
-
?disabled=${
|
|
3234
|
-
class=${Se({"fw-live-badge":!0,"fw-live-badge--active":
|
|
3253
|
+
?disabled=${s}
|
|
3254
|
+
class=${Se({"fw-live-badge":!0,"fw-live-badge--active":s,"fw-live-badge--behind":!s})}
|
|
3235
3255
|
title=${n.hasDvrWindow?this._isNearLiveState?"At live edge":"Jump to live":"Live only"}
|
|
3236
3256
|
>
|
|
3237
3257
|
LIVE
|
|
@@ -3260,7 +3280,6 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
3260
3280
|
</button>
|
|
3261
3281
|
</div>
|
|
3262
3282
|
`:X}
|
|
3263
|
-
|
|
3264
3283
|
<div class="fw-control-group fw-settings-anchor">
|
|
3265
3284
|
<button
|
|
3266
3285
|
type="button"
|
|
@@ -3328,7 +3347,7 @@ function ve(e,t){return(t,n,i)=>((e,t,n)=>(n.configurable=!0,n.enumerable=!0,Ref
|
|
|
3328
3347
|
.fw-settings-anchor {
|
|
3329
3348
|
position: relative;
|
|
3330
3349
|
}
|
|
3331
|
-
`],n([ye({attribute:!1})],Qt.prototype,"pc",void 0),n([ye({type:String})],Qt.prototype,"playbackMode",void 0),n([ye({type:Boolean,attribute:"is-content-live"})],Qt.prototype,"isContentLive",void 0),n([ye({type:Boolean,attribute:"show-stats-button"})],Qt.prototype,"showStatsButton",void 0),n([ye({type:Boolean,attribute:"is-stats-open"})],Qt.prototype,"isStatsOpen",void 0),n([be()],Qt.prototype,"_settingsOpen",void 0),n([be()],Qt.prototype,"_isNearLiveState",void 0),n([be()],Qt.prototype,"_buffered",void 0),Qt=n([pe("fw-player-controls")],Qt);
|
|
3350
|
+
`],n([ye({attribute:!1})],Qt.prototype,"pc",void 0),n([ye({type:String})],Qt.prototype,"playbackMode",void 0),n([ye({type:Boolean,attribute:"is-content-live"})],Qt.prototype,"isContentLive",void 0),n([ye({type:Boolean,attribute:"dev-mode"})],Qt.prototype,"devMode",void 0),n([ye({type:Boolean,attribute:"show-stats-button"})],Qt.prototype,"showStatsButton",void 0),n([ye({type:Boolean,attribute:"is-stats-open"})],Qt.prototype,"isStatsOpen",void 0),n([be()],Qt.prototype,"_settingsOpen",void 0),n([be()],Qt.prototype,"_isNearLiveState",void 0),n([be()],Qt.prototype,"_buffered",void 0),Qt=n([pe("fw-player-controls")],Qt);
|
|
3332
3351
|
/**
|
|
3333
3352
|
* @license
|
|
3334
3353
|
* Copyright 2018 Google LLC
|
|
@@ -3497,7 +3516,7 @@ const Xt="important",Jt=" !"+Xt,Zt=_e(class extends Ee{constructor(e){if(super(e
|
|
|
3497
3516
|
transform: translate(-50%, -50%);
|
|
3498
3517
|
pointer-events: none;
|
|
3499
3518
|
}
|
|
3500
|
-
`],n([ye({attribute:!1})],tn.prototype,"pc",void 0),n([be()],tn.prototype,"_hovered",void 0),n([be()],tn.prototype,"_focused",void 0),n([be()],tn.prototype,"_hasAudio",void 0),tn=n([pe("fw-volume-control")],tn);let nn=class extends he{constructor(){super(...arguments),this.open=!1,this.playbackMode="auto",this.isContentLive=!0,this._playbackRate=1}updated(){if(!this.open)return;if(Number.isFinite(this.playbackRate))return void(this._playbackRate=this.playbackRate);const e=this.pc?.s.videoElement;e&&Number.isFinite(e.playbackRate)&&(this._playbackRate=e.playbackRate)}_close(){this.dispatchEvent(new CustomEvent("fw-close",{bubbles:!0,composed:!0}))}_handleModeChange(e){this.pc.setDevModeOptions({playbackMode:e}),this.dispatchEvent(new CustomEvent("fw-mode-change",{detail:{mode:e},bubbles:!0,composed:!0})),this._close()}_handleSpeedChange(e){this._playbackRate=e,this.pc.setPlaybackRate(e),this.dispatchEvent(new CustomEvent("fw-speed-change",{detail:{rate:e},bubbles:!0,composed:!0})),this._close()}_handleQualityChange(e){this.pc.selectQuality(e),this.dispatchEvent(new CustomEvent("fw-quality-change",{detail:{quality:e},bubbles:!0,composed:!0})),this._close()}_handleCaptionChange(e){"none"===e?this.pc.selectTextTrack(null):this.pc.selectTextTrack(e),this.dispatchEvent(new CustomEvent("fw-caption-change",{detail:{caption:e},bubbles:!0,composed:!0})),this._close()}render(){if(!this.open)return X;const e=this.pc.s,t=e.qualities??[],n=e.textTracks??[],
|
|
3519
|
+
`],n([ye({attribute:!1})],tn.prototype,"pc",void 0),n([be()],tn.prototype,"_hovered",void 0),n([be()],tn.prototype,"_focused",void 0),n([be()],tn.prototype,"_hasAudio",void 0),tn=n([pe("fw-volume-control")],tn);let nn=class extends he{constructor(){super(...arguments),this.open=!1,this.playbackMode="auto",this.isContentLive=!0,this._playbackRate=1}updated(){if(!this.open)return;if(Number.isFinite(this.playbackRate))return void(this._playbackRate=this.playbackRate);const e=this.pc?.s.videoElement;e&&Number.isFinite(e.playbackRate)&&(this._playbackRate=e.playbackRate)}_close(){this.dispatchEvent(new CustomEvent("fw-close",{bubbles:!0,composed:!0}))}_handleModeChange(e){this.pc.setDevModeOptions({playbackMode:e}),this.dispatchEvent(new CustomEvent("fw-mode-change",{detail:{mode:e},bubbles:!0,composed:!0})),this._close()}_handleSpeedChange(e){this._playbackRate=e,this.pc.setPlaybackRate(e),this.dispatchEvent(new CustomEvent("fw-speed-change",{detail:{rate:e},bubbles:!0,composed:!0})),this._close()}_handleQualityChange(e){this.pc.selectQuality(e),this.dispatchEvent(new CustomEvent("fw-quality-change",{detail:{quality:e},bubbles:!0,composed:!0})),this._close()}_handleCaptionChange(e){"none"===e?this.pc.selectTextTrack(null):this.pc.selectTextTrack(e),this.dispatchEvent(new CustomEvent("fw-caption-change",{detail:{caption:e},bubbles:!0,composed:!0})),this._close()}_deriveFallbackQualities(){const e=this.pc?.s.streamState?.streamInfo?.meta?.tracks;return e?Object.entries(e).filter(([,e])=>"video"===e?.type).map(([e,t])=>({id:e,label:t.height?`${t.height}p`:t.codec??e,width:t.width,height:t.height,bitrate:t.bps})).sort((e,t)=>(t.height??0)-(e.height??0)):[]}render(){if(!this.open)return X;const e=this.pc.s,t=e.qualities??[],n=t.length>0?t:this._deriveFallbackQualities(),i=e.textTracks??[],r=this.qualityValue??n.find(e=>e.active)?.id??"auto",s=this.captionValue??i.find(e=>e.active)?.id??"none",a=this.supportsPlaybackRate??wt(e.videoElement);return W`
|
|
3501
3520
|
<div class="fw-player-surface fw-settings-menu" role="menu" aria-label="Player settings">
|
|
3502
3521
|
${this.isContentLive?W`
|
|
3503
3522
|
<div class="fw-settings-section">
|
|
@@ -3515,7 +3534,7 @@ const Xt="important",Jt=" !"+Xt,Zt=_e(class extends Ee{constructor(e){if(super(e
|
|
|
3515
3534
|
</div>
|
|
3516
3535
|
</div>
|
|
3517
3536
|
`:X}
|
|
3518
|
-
${
|
|
3537
|
+
${a?W`
|
|
3519
3538
|
<div class="fw-settings-section">
|
|
3520
3539
|
<div class="fw-settings-label">Speed</div>
|
|
3521
3540
|
<div class="fw-settings-options fw-settings-options--wrap">
|
|
@@ -3531,21 +3550,21 @@ const Xt="important",Jt=" !"+Xt,Zt=_e(class extends Ee{constructor(e){if(super(e
|
|
|
3531
3550
|
</div>
|
|
3532
3551
|
</div>
|
|
3533
3552
|
`:X}
|
|
3534
|
-
${
|
|
3553
|
+
${n.length>0?W`
|
|
3535
3554
|
<div class="fw-settings-section">
|
|
3536
3555
|
<div class="fw-settings-label">Quality</div>
|
|
3537
3556
|
<div class="fw-settings-list">
|
|
3538
3557
|
<button
|
|
3539
3558
|
type="button"
|
|
3540
|
-
class=${Se({"fw-settings-list-item":!0,"fw-settings-list-item--active":"auto"===
|
|
3559
|
+
class=${Se({"fw-settings-list-item":!0,"fw-settings-list-item--active":"auto"===r})}
|
|
3541
3560
|
@click=${()=>this._handleQualityChange("auto")}
|
|
3542
3561
|
>
|
|
3543
3562
|
Auto
|
|
3544
3563
|
</button>
|
|
3545
|
-
${
|
|
3564
|
+
${n.map(e=>W`
|
|
3546
3565
|
<button
|
|
3547
3566
|
type="button"
|
|
3548
|
-
class=${Se({"fw-settings-list-item":!0,"fw-settings-list-item--active":
|
|
3567
|
+
class=${Se({"fw-settings-list-item":!0,"fw-settings-list-item--active":r===e.id})}
|
|
3549
3568
|
@click=${()=>this._handleQualityChange(e.id)}
|
|
3550
3569
|
>
|
|
3551
3570
|
${e.label}
|
|
@@ -3554,21 +3573,21 @@ const Xt="important",Jt=" !"+Xt,Zt=_e(class extends Ee{constructor(e){if(super(e
|
|
|
3554
3573
|
</div>
|
|
3555
3574
|
</div>
|
|
3556
3575
|
`:X}
|
|
3557
|
-
${
|
|
3576
|
+
${i.length>0?W`
|
|
3558
3577
|
<div class="fw-settings-section">
|
|
3559
3578
|
<div class="fw-settings-label">Captions</div>
|
|
3560
3579
|
<div class="fw-settings-list">
|
|
3561
3580
|
<button
|
|
3562
3581
|
type="button"
|
|
3563
|
-
class=${Se({"fw-settings-list-item":!0,"fw-settings-list-item--active":"none"===
|
|
3582
|
+
class=${Se({"fw-settings-list-item":!0,"fw-settings-list-item--active":"none"===s})}
|
|
3564
3583
|
@click=${()=>this._handleCaptionChange("none")}
|
|
3565
3584
|
>
|
|
3566
3585
|
Off
|
|
3567
3586
|
</button>
|
|
3568
|
-
${
|
|
3587
|
+
${i.map(e=>W`
|
|
3569
3588
|
<button
|
|
3570
3589
|
type="button"
|
|
3571
|
-
class=${Se({"fw-settings-list-item":!0,"fw-settings-list-item--active":
|
|
3590
|
+
class=${Se({"fw-settings-list-item":!0,"fw-settings-list-item--active":s===e.id})}
|
|
3572
3591
|
@click=${()=>this._handleCaptionChange(e.id)}
|
|
3573
3592
|
>
|
|
3574
3593
|
${e.label||e.id}
|
|
@@ -5357,6 +5376,7 @@ const Xt="important",Jt=" !"+Xt,Zt=_e(class extends Ee{constructor(e){if(super(e
|
|
|
5357
5376
|
:host {
|
|
5358
5377
|
display: block;
|
|
5359
5378
|
height: 100%;
|
|
5379
|
+
min-height: 0;
|
|
5360
5380
|
}
|
|
5361
5381
|
`],n([ye({attribute:!1})],_n.prototype,"pc",void 0),n([ye({type:String})],_n.prototype,"playbackMode",void 0),n([be()],_n.prototype,"_activeTab",void 0),n([be()],_n.prototype,"_hoveredComboIndex",void 0),n([be()],_n.prototype,"_tooltipAbove",void 0),n([be()],_n.prototype,"_showDisabledPlayers",void 0),n([be()],_n.prototype,"_playbackScore",void 0),n([be()],_n.prototype,"_qualityScore",void 0),n([be()],_n.prototype,"_stallCount",void 0),n([be()],_n.prototype,"_frameDropRate",void 0),n([be()],_n.prototype,"_videoStats",void 0),n([be()],_n.prototype,"_playerStats",void 0),_n=n([pe("fw-dev-mode-panel")],_n);const En={fontSize:"1.5rem",fontFamily:"system-ui, -apple-system, sans-serif",color:"white",backgroundColor:"rgba(0, 0, 0, 0.75)",textShadow:"2px 2px 4px rgba(0, 0, 0, 0.5)",bottom:"5%",maxWidth:"90%",padding:"0.5em 1em",borderRadius:"4px"};let Sn=class extends he{constructor(){super(...arguments),this.currentTime=0,this.enabled=!0,this.cues=[],this.className="",this._liveCues=[],this._displayedText="",this._unsubscribe=null,this._handleMetaEvent=e=>{if("subtitle"!==e.type)return;const t=this._parseSubtitleCue(e.data);t&&(this._liveCues=(()=>this._liveCues.find(e=>e.id===t.id)?this._liveCues:[...this._liveCues,t].slice(-50))())}}disconnectedCallback(){super.disconnectedCallback(),this._teardownSubscription()}updated(e){(e.has("enabled")||e.has("subscribeToMetaTrack")||e.has("metaTrackId"))&&this._syncSubscription(),(e.has("currentTime")||e.has("_liveCues"))&&this._pruneExpiredLiveCues(),(e.has("enabled")||e.has("currentTime")||e.has("cues")||e.has("_liveCues"))&&this._syncDisplayedCue()}_syncSubscription(){this._teardownSubscription(),this.enabled&&this.subscribeToMetaTrack&&this.metaTrackId&&(this._unsubscribe=this.subscribeToMetaTrack(this.metaTrackId,this._handleMetaEvent))}_teardownSubscription(){this._unsubscribe&&(this._unsubscribe(),this._unsubscribe=null)}_parseSubtitleCue(e){if("object"!=typeof e||null===e)return null;const t=e,n="string"==typeof t.text?t.text:String(t.text??"");if(!n)return null;const i="startTime"in t?Number(t.startTime):"start"in t?Number(t.start):0,r="endTime"in t?Number(t.endTime):"end"in t?Number(t.end):1/0,s=Number.isFinite(i)?i:0,a=Number.isFinite(r)?r:1/0;return{id:"string"==typeof t.id?t.id:String(Date.now()+Math.random()),text:n,startTime:s,endTime:a,lang:"string"==typeof t.lang?t.lang:void 0}}_getAllCues(){return[...this.cues??[],...this._liveCues]}_syncDisplayedCue(){if(!this.enabled)return void(this._displayedText&&(this._displayedText=""));const e=1e3*this.currentTime,t=this._getAllCues().find(t=>e>=t.startTime&&e<t.endTime),n=t?.text??"";n!==this._displayedText&&(this._displayedText=n)}_pruneExpiredLiveCues(){if(0===this._liveCues.length)return;const e=1e3*this.currentTime,t=this._liveCues.filter(t=>(t.endTime===1/0?t.startTime+1e4:t.endTime)>=e-3e4);t.length!==this._liveCues.length&&(this._liveCues=t)}render(){if(!this.enabled||!this._displayedText)return X;const e={...En,...this.subtitleStyle??{}};return W`
|
|
5362
5382
|
<div
|