stormcloud-video-player 0.3.17 → 0.3.18
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/stormcloud-vp.min.js +1 -1
- package/lib/index.cjs +314 -142
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +7 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +314 -142
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +303 -139
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +7 -0
- package/lib/players/HlsPlayer.cjs +303 -139
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +303 -139
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +6 -0
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/ima.cjs +4 -0
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +314 -142
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24/Dev/stormcloud-vp/lib/index.js","../src/ui/StormcloudVideoPlayer.tsx","../src/player/StormcloudVideoPlayer.ts","../src/utils/browserCompat.ts","../src/sdk/ima.ts","../src/sdk/hlsAdPlayer.ts","../src/utils/tracking.ts","../src/utils/polyfills.ts","../src/StormcloudPlayer.tsx","../src/props.ts","../src/utils.ts","../src/patterns.ts","../src/players/HlsPlayer.tsx","../src/players/FilePlayer.tsx","../src/players/index.ts","../src/Player.tsx"],"names":["React","useEffect","useRef","useMemo","Hls","getChromeVersion","ua","match","parseInt","getWebKitVersion","getPlatform","navigator","userAgentData","platform","userAgent","test","detectBrowser","name","version","majorVersion","isSmartTV","isLegacyTV","supportsIMA","supportsModernJS","recommendedAdPlayer","parts","split","chromeVersion","webkitVersion","toString","Promise","Map","Set","URLSearchParams","supportsGoogleIMA","browser","document","createElement","video","e","getRecommendedAdPlayer","Array","from","Object","assign","prototype","forEach","String","includes","logBrowserInfo","debug","imaSupport","console","log","getBrowserConfigOverrides","overrides","adPlayerType","allowNativeHls","supportsFeature","feature","TextEncoder","fetch","crypto","subtle","createImaController","options","adPlaying","contentVideoHidden","originalMutedState","originalVolume","volume","Number","isNaN","Math","max","min","listeners","preloadedVast","preloadingVast","adVideoElement","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","hideContentVideo","style","transition","opacity","setTimeout","visibility","muted","showContentVideo","offsetHeight","createAdVideoElement","adVideo","position","top","left","width","height","objectFit","backgroundColor","zIndex","playsInline","addEventListener","once","emit","event","payload","set","get","fn","ensureImaLoaded","window","warn","reject","Error","frameEl","frameElement","sandboxAttr","getAttribute","tokens","map","t","trim","filter","length","allowsScripts","has","error","google","ima","resolve","existing","querySelector","timeout","clearTimeout","script","src","async","defer","setAttribute","onload","onerror","head","appendChild","adsManager","adsLoader","adDisplayContainer","adContainerEl","lastAdTagUrl","retryAttempts","maxRetries","backoffBaseMs","adsLoadedPromise","adsLoadedResolve","adsLoadedReject","makeAdsRequest","vastTagUrl","adsRequest","AdsRequest","adTagUrl","videoWidth","offsetWidth","clientWidth","videoHeight","clientHeight","linearAdSlotWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","setAdWillAutoPlay","willAutoPlay","paused","autoplay","setAdWillPlayMuted","willPlayMuted","vastLoadTimeout","requestAds","ensurePlaceholderContainer","container","right","bottom","display","alignItems","justifyContent","pointerEvents","parentElement","fetchVastDocument","response","mode","ok","status","text","destroyAdsManager","destroy","initialize","then","AdDisplayContainer","catch","currentReject","adsLoaderCls","message","URL","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","evt","adsRenderingSettings","AdsRenderingSettings","enablePreloading","getAdsManager","AdEvent","AdErrorEvent","AD_ERROR","errorEvent","getError","getMessage","delay","pow","continueLiveStreamDuringAds","play","CONTENT_PAUSE_REQUESTED","pause","STARTED","CONTENT_RESUME_REQUESTED","ALL_ADS_COMPLETED","adErrorEvent","preloadAds","inflight","preloadPromise","xml","delete","finally","hasPreloadedAd","adVolume","init","ViewMode","NORMAL","setVolume","start","stop","removeChild","clear","isAdPlaying","resize","on","listener","add","off","updateOriginalMutedState","nextVolume","getOriginalMutedState","getOriginalVolume","setAdVolume","clampedVolume","getAdVolume","getVolume","showPlaceholder","hidePlaceholder","createHlsAdPlayer","contentVideo","licenseKey","mainHlsInstance","adHls","currentAd","sessionId","preloadedAds","preloadingAds","destroyed","pendingTimeouts","trackingFired","impression","firstQuartile","midpoint","thirdQuartile","complete","generateSessionId","Date","now","random","substr","fireTrackingPixels","urls","url","trackingUrl","img","Image","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","bitrate","selectBestMediaFile","mediaFiles","firstFile","mainQuality","scoredFiles","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","sort","a","b","bestMatch","resolution","parseVastXml","xmlString","xmlDoc","parser","DOMParser","parseFromString","parserError","textContent","adElement","adId","title","isNoAdAvailable","toLowerCase","durationText","durationParts","duration","mediaFileElements","querySelectorAll","mf","index","type","bitrateAttr","bitrateValue","push","trackingUrls","mute","unmute","resume","fullscreen","exitFullscreen","skip","el","eventKey","clickThrough","id","fetchAndParseVastAd","vastXml","statusText","substring","setupAdEventListeners","progress","currentTime","handleAdComplete","handleAdError","ended","timeoutId","stillInPod","idx","indexOf","splice","previousMutedState","ad","contentVolume","mediaFile","isSupported","enableWorker","lowLatencyMode","loadSource","attachMedia","Events","MANIFEST_PARSED","ERROR","data","fatal","canPlayType","remove","cachedBrowserId","getClientInfo","screen","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isAndroid","isWebView","isWebApp","webosMatch","tizenMatch","tvMatch","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","location","hostname","origin","path","pathname","language","languages","join","cookieEnabled","doNotTrack","referrer","visibilityState","getBrowserID","clientInfo","fingerprintString","encodedData","utf8","buffer","i","hashBuffer","hashArray","hashHex","hash","char","fallbackHash","timestamp","JSON","stringify","digest","Uint8Array","encode","unescape","encodeURIComponent","charCodeAt","padStart","padEnd","sendInitialTracking","browserId","trackingData","headers","method","body","json","sendHeartbeat","heartbeatData","toISOString","polyfillURLSearchParams","URLSearchParamsPolyfill","params","parseQueryString","value","key","append","query","cleanQuery","startsWith","slice","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","replace","values","getAll","callback","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","constructor","reason","polyfillObjectAssign","target","sources","TypeError","to","nextSource","nextKey","hasOwnProperty","call","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","len","result","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","endsWith","polyfillStringIncludes","initializePolyfills","StormcloudVideoPlayer","config","attached","inAdBreak","ptsDriftEmaMs","adPodQueue","lastHeartbeatTime","currentAdIndex","totalAdsInBreak","showAds","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","adPodAllUrls","preloadingAdUrls","vastToMediaUrlMap","preloadedMediaUrls","preloadingMediaUrls","adRequestTokenCounter","activeAdRequestToken","adRequestWatchdogToken","adFailsafeToken","fetchedAdDurations","targetAdBreakDurationMs","isAdaptiveMode","failedVastUrls","continuousFetchingActive","adRequestQueue","successfulAdRequests","maxPlaceholderDurationMs","placeholderStartTimeMs","isShowingPlaceholder","browserOverrides","videoElement","debugAdTiming","createAdPlayer","vastMode","hls","load","attach","fetchAdConfiguration","initializeTracking","shouldUseNativeHls","isLive","adBehavior","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","_","minSegments","some","details","live","shouldContinueLiveStreamDuringAds","minSegmentsBeforePlay","FRAG_BUFFERED","_evt","err","FRAG_PARSING_METADATA","id3Tags","samples","s","ptsSeconds","pts","tag","onId3Tag","FRAG_CHANGED","frag","tagList","isArray","entry","durationSeconds","parseCueOutDuration","marker","raw","onScte35Marker","prog","parseCueOutCont","elapsed","attrs","parseAttributeList","hasScteOut","hasScteIn","klass","toNumber","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","handleAdPodComplete","errorPayload","remaining","getRemainingAdMs","nextPreloaded","findNextPreloadedAd","playSingleAd","handleAdFailure","clearAdFailsafeTimer","clearAdRequestWatchdog","tryNextAvailableAd","timeUpdateHandler","onTimeUpdate","emptiedHandler","wasPaused","streamType","getStreamType","canNative","updatePtsDrift","parseScte35FromId3","decodeId3ValueToText","cueOutMatch","arg","dur","id3","cueOutContMatch","cont","cueInMatch","daterangeMatch","bin","parseScte35Binary","decoder","TextDecoder","decode","out","fromCharCode","durationMs","expectedAdBreakDurationMs","currentAdBreakStartWallClockMs","isManifestMarker","isManifestBasedMarker","forceImmediate","immediateManifestAds","hasPts","clearAdStartTimer","handleAdStart","tol","driftToleranceMs","nowMs","estCurrentPtsMs","deltaMs","floor","markerPtsMs","tolerance","scheduleAdStartIn","scheduleAdStopCountdown","elapsedMs","remainingMs","scheduled","findCurrentOrNextBreak","tags","selectVastTagsForBreak","apiVastTagUrl","first","rest","clearAdStopTimer","num","parseFloat","dStr","d","elapsedMatch","durationMatch","res","regex","exec","rawVal","val","n","splice_command_type","BitReader","buf","bytePos","bitPos","readBits","numBits","remainingInByte","toRead","currentByte","shift","mask","bits","skipBits","r","tableId","sectionLength","ptsAdjHigh","ptsAdjLow","spliceCommandLength","spliceCommandType","cancel","outOfNetwork","programSpliceFlag","durationFlag","spliceImmediateFlag","timeSpecifiedFlag","componentCount","high","low","durationTicks","heartbeatInterval","setInterval","sendHeartbeatIfNeeded","vastEndpoint","apiUrl","imaPayload","numberAds","vast","cue_tones","number_ads","apiNumberAds","getCurrentAdIndex","getTotalAdsInBreak","generateVastUrlsWithCorrelators","baseUrl","count","uniqueCorrelator","searchParams","isShowingAds","shouldShowNativeControls","showCustomControls","_marker","baseVastUrl","adBreakDurationMs","currentMuted","currentVolume","firstAdUrlArray","firstAdUrl","startContinuousFetching","continuousFetchLoop","maxQueueSize","newAdUrl","xmlText","stopContinuousFetching","retryCount","nextAdUrl","showPlaceholderAndWaitForAds","waitTime","checkInterval","maxChecks","schedule","candidate","startTimeMs","currentTimeSec","breakToPlay","findBreakForTime","handleMidAdJoin","adBreak","endMs","ms","ensureAdStoppedByTimer","adStopTimerId","pendingAds","checkIntervalMs","adBreakCheckIntervalMs","maxExtensionMsConfig","maxAdBreakExtensionMs","maxExtensionMs","elapsedSinceStartMs","expectedDurationMs","overrunMs","shouldExtendAdBreak","delayMs","adStartTimerId","ptsSecondsSample","sampleMs","isFinite","alpha","requestToken","playError","startAdRequestWatchdog","startAdFailsafeTimer","restoredMuted","restoredVolume","size","token","timeoutMs","adFailsafeTimeoutMs","adRequestWatchdogId","logAdState","failsafeMs","adFailsafeTimerId","videoPaused","imaAdPlaying","extra","fetchAndParseVastXml","extractMediaUrlsFromVast","mediaUrls","lowerUrl","fetchVastDuration","calculateAdditionalAdsNeeded","totalFetchedDurationMs","fetchedCount","averageDurationMs","queuedButNotFetched","estimatedQueuedDurationMs","estimatedTotalDurationMs","remainingTimeMs","additionalAds","ceil","addAdaptiveAdsToQueue","newUrls","preloadMediaFile","mediaUrl","Range","preloadAllAdsInBackground","processedUrls","nextUrl","preloadPromises","find","preloadSingleAd","all","primaryMediaUrl","hasImaPreload","hasMediaPreload","end","toggleMute","currentPerceptualState","isMuted","newMutedState","toggleFullscreen","fullscreenElement","requestFullscreen","setMuted","isFullscreen","removeEventListener","clearInterval","FaPlay","FaPause","FaVolumeUp","FaVolumeMute","FaVolumeDown","FaExpand","FaCompress","FaSpinner","Fragment","jsx","jsxs","CRITICAL_PROPS","StormcloudVideoPlayerComponent","memo","props","hideLoadingIndicator","onVolumeToggle","onFullscreenToggle","onControlClick","onReady","wrapperClassName","wrapperStyle","className","controls","preload","poster","children","restVideoAttrs","videoRef","playerRef","bufferingTimeoutRef","useState","currentIndex","totalAds","adStatus","setAdStatus","setShouldShowNativeControls","setIsMuted","setIsFullscreen","setIsPlaying","setCurrentTime","setDuration","playbackRate","setPlaybackRate","showVolumeSlider","setShowVolumeSlider","showSpeedMenu","setShowSpeedMenu","isLoading","setIsLoading","isBuffering","setIsBuffering","showCenterPlay","setShowCenterPlay","showLicenseWarning","setShowLicenseWarning","innerWidth","viewportWidth","setViewportWidth","innerHeight","isPortrait","setIsPortrait","getResponsiveScale","responsiveScale","formatTime","seconds","hours","minutes","remainingSeconds","handlePlayPause","current","hasValidSource","currentSrc","readyState","handleCenterPlayClick","handleTimelineSeek","rect","currentTarget","getBoundingClientRect","clickX","clientX","newTime","handleVolumeChange","newVolume","handlePlaybackRateChange","rate","isHlsStream","shouldShowEnhancedControls","criticalPropsKey","prop","cfg","player","showNative","checkAdStatus","prev","interval","handleResize","updateStates","currentTimeValue","durationValue","volumeValue","rateValue","handleFullscreenChange","handleLoadedMetadata","handleLoadedData","handleLoadStart","handleCanPlay","handleCanPlayThrough","handleWaiting","handlePlaying","handlePause","handleEnded","overflow","minHeight","maxWidth","maxHeight","borderRadius","boxShadow","ref","aspectRatio","color","animation","transform","background","padding","backdropFilter","border","textAlign","margin","fontSize","fontWeight","marginBottom","textShadow","lineHeight","onClick","cursor","onMouseEnter","borderColor","onMouseLeave","marginLeft","flexWrap","gap","minWidth","flexDirection","onMouseDown","preventDefault","sliderElement","handleMouseMove","moveEvent","y","clientY","percentage","handleMouseUp","stopPropagation","onMouseUp","fontFamily","speed","borderBottom","prevProps","nextProps","uiProps","callbackProps","Component","Suspense","noop","defaultProps","playing","loop","progressInterval","onStart","onPlay","onPause","onBuffer","onBufferEnd","onEnded","onError","onDuration","onSeek","onProgress","lazy","reactLazy","omit","object","keys","isMediaStream","MediaStream","supportsWebKitPresentationMode","randomString","parseQuery","queryString","manualParse","qs","merge","source","isObject","item","IS_BROWSER","IS_GLOBAL","globalThis","IS_IOS","IS_SAFARI","SUPPORTS_HLS","Boolean","SUPPORTS_DASH","HLS_EXTENSIONS","HLS_PATHS","DASH_EXTENSIONS","VIDEO_EXTENSIONS","AUDIO_EXTENSIONS","canPlay","dash","audio","HlsPlayer","mounted","onMount","seekTo","keepPlaying","getDuration","getCurrentTime","getSecondsLoaded","buffered","getInternalPlayer","componentDidMount","componentWillUnmount","componentDidUpdate","render","displayName","FilePlayer","ready","handlePlay","handleError","onLoaded","setLoop","enablePIP","requestPictureInPicture","disablePIP","pictureInPictureElement","exitPictureInPicture","players","lazyPlayer","default","canEnablePIP","pictureInPictureEnabled","webkitSupportsPresentationMode","players_default","SEEK_ON_PLAY_EXPIRY","Player","arguments","isReady","loadOnReady","startOnPlay","seekOnPlay","onDurationCalled","handlePlayerMount","playedSeconds","loadedSeconds","played","loaded","prevPlayed","prevLoaded","progressTimeout","handleReady","handleDurationCheck","activePlayer","loopOnEnded","args","durationCheckTimeout","handleLoaded","forceLoad","amount","isFraction","UniversalSuspense","SUPPORTED_PROPS","customPlayers","createStormcloudPlayer","playerList","fallback","_a","state","showPreview","references","wrapper","getActivePlayer","getAttributes","fraction","renderActivePlayer","fallbackElement","Wrapper","attributes","wrapperRef","addCustomPlayer","removeCustomPlayers","StormcloudPlayer","StormcloudPlayer_default"],"mappings":"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","sourcesContent":["// src/ui/StormcloudVideoPlayer.tsx\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\n// src/player/StormcloudVideoPlayer.ts\nimport Hls2 from \"hls.js\";\n\n// src/utils/browserCompat.ts\nfunction getChromeVersion(ua) {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getWebKitVersion(ua) {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getPlatform() {\n if (\"userAgentData\" in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? \"iPhone\" : \"MacIntel\";\n }\n if (/Win/i.test(ua)) {\n return \"Win32\";\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? \"Linux armv8l\" : \"Linux x86_64\";\n }\n if (/CrOS/i.test(ua)) {\n return \"CrOS\";\n }\n return navigator.platform || \"Unknown\";\n}\nfunction detectBrowser() {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n let name = \"Unknown\";\n let version = \"0\";\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS2 = true;\n let recommendedAdPlayer = \"ima\";\n if (/Web0S|webOS/i.test(ua)) {\n name = \"LG WebOS\";\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = \"Samsung Tizen\";\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n }\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS2 = false;\n isLegacyTV = true;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS2 = false;\n if (isSmartTV) {\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS2 = false;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n if (typeof URLSearchParams === \"undefined\") {\n supportsModernJS2 = false;\n }\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS: supportsModernJS2,\n recommendedAdPlayer\n };\n}\nfunction supportsGoogleIMA() {\n const browser = detectBrowser();\n if (browser.isLegacyTV) {\n return false;\n }\n if (typeof document === \"undefined\" || typeof document.createElement !== \"function\") {\n return false;\n }\n try {\n const video = document.createElement(\"video\");\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n if (typeof Promise === \"undefined\") {\n return false;\n }\n return browser.supportsIMA;\n}\nfunction getRecommendedAdPlayer() {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\n}\nfunction supportsModernJS() {\n try {\n return typeof Promise !== \"undefined\" && typeof Map !== \"undefined\" && typeof Set !== \"undefined\" && typeof Array.from !== \"undefined\" && typeof Object.assign !== \"undefined\" && typeof Array.prototype.forEach !== \"undefined\" && typeof String.prototype.includes !== \"undefined\";\n } catch (e) {\n return false;\n }\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n console.log(\"[StormcloudVideoPlayer] Browser Compatibility Info:\", {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n userAgent: navigator.userAgent\n });\n}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = \"hls\";\n }\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\nfunction supportsFeature(feature) {\n switch (feature) {\n case \"ima\":\n return supportsGoogleIMA();\n case \"urlsearchparams\":\n return typeof URLSearchParams !== \"undefined\";\n case \"textencoder\":\n return typeof TextEncoder !== \"undefined\";\n case \"promises\":\n return typeof Promise !== \"undefined\";\n case \"fetch\":\n return typeof fetch !== \"undefined\";\n case \"crypto\":\n return typeof crypto !== \"undefined\" && typeof crypto.subtle !== \"undefined\";\n default:\n return false;\n }\n}\n\n// src/sdk/ima.ts\nfunction createImaController(video, options) {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume = typeof video.volume === \"number\" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;\n const listeners = /* @__PURE__ */ new Map();\n const preloadedVast = /* @__PURE__ */ new Map();\n const preloadingVast = /* @__PURE__ */ new Map();\n let adVideoElement;\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n function hideContentVideo() {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n function showContentVideo() {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n function createAdVideoElement() {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"15\";\n adVideo.playsInline = true;\n adVideo.muted = false;\n adVideo.volume = originalMutedState ? 0 : originalVolume;\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n return adVideo;\n }\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {\n }\n }\n }\n function ensureImaLoaded() {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n try {\n const frameEl = window.frameElement;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr.split(/\\s+/).map((t) => t.trim()).filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {\n }\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n );\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 1e4);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n let adsManager;\n let adsLoader;\n let adDisplayContainer;\n let adContainerEl;\n let lastAdTagUrl;\n let retryAttempts = 0;\n const maxRetries = 2;\n const backoffBaseMs = 500;\n let adsLoadedPromise;\n let adsLoadedResolve;\n let adsLoadedReject;\n function makeAdsRequest(google, vastTagUrl) {\n const adsRequest = new google.ima.AdsRequest();\n console.log(\"[IMA] \\u{1F4E1} Requesting VAST from URL (letting IMA fetch fresh)\");\n adsRequest.adTagUrl = vastTagUrl;\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 360;\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n adsRequest.vastLoadTimeout = 1e4;\n adsLoader.requestAds(adsRequest);\n }\n function ensurePlaceholderContainer() {\n if (adContainerEl) {\n return;\n }\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n async function fetchVastDocument(vastTagUrl) {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to preload VAST: ${response.status}`);\n }\n return response.text();\n }\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {\n }\n adsManager = void 0;\n }\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n return {\n initialize() {\n ensureImaLoaded().then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {\n }\n }\n }).catch(() => {\n });\n },\n async requestAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n console.warn(\"[IMA] \\u274C\", error.message);\n return Promise.reject(error);\n }\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n console.warn(\"[IMA] \\u274C\", error.message);\n return Promise.reject(error);\n }\n if (adPlaying) {\n console.warn(\n \"[IMA] \\u26A0\\uFE0F Cannot request new ads while an ad is playing. Call stop() first.\"\n );\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n destroyAdsManager();\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n let currentReject;\n adsLoadedPromise = new Promise((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n }, 1e4);\n });\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n retryAttempts = 0;\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n video.parentElement.appendChild(container);\n adContainerEl = container;\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n }\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n console.warn(\"[IMA]\", error.message);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt) => {\n try {\n const adsRenderingSettings = new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent) => {\n const error = errorEvent.getError();\n console.error(\"[DEBUG-ERROR] \\u274C AD_ERROR:\", error.getMessage?.());\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n if (lastAdTagUrl && retryAttempts < maxRetries) {\n const delay = backoffBaseMs * Math.pow(2, retryAttempts++);\n window.setTimeout(() => {\n try {\n makeAdsRequest(google, lastAdTagUrl);\n } catch {\n }\n }, delay);\n } else {\n emit(\"ad_error\");\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {\n });\n }\n }\n }\n }\n );\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n adPlaying = true;\n setAdPlayingFlag(true);\n emit(\"content_pause\");\n }\n );\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n hideContentVideo();\n if (adVideoElement) {\n adVideoElement.volume = originalMutedState ? 0 : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n emit(\"content_resume\");\n }\n );\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds && video.paused) {\n video.play().catch(() => {\n });\n }\n emit(\"all_ads_completed\");\n });\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = void 0;\n adsLoadedReject = void 0;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {\n });\n }\n }\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent) => {\n const error = adErrorEvent.getError();\n console.error(\"[DEBUG-ERROR] \\u274C ADS_LOADER ERROR:\", error.getMessage?.());\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {\n });\n }\n }\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ads loader error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n },\n false\n );\n }\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n if (preloadedVast.has(vastTagUrl)) {\n return Promise.resolve();\n }\n const inflight = preloadingVast.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {\n preloadedVast.set(vastTagUrl, xml);\n }).catch(() => {\n preloadedVast.delete(vastTagUrl);\n }).finally(() => {\n preloadingVast.delete(vastTagUrl);\n });\n preloadingVast.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl) {\n return preloadedVast.has(vastTagUrl);\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 360;\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n adPlaying = true;\n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n try {\n adsManager.setVolume(adVolume);\n } catch {\n }\n adsManager.start();\n return Promise.resolve();\n } catch (error) {\n console.error(\"[IMA] \\u274C Error starting ad:\", error);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {\n });\n }\n return Promise.reject(error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n try {\n adsManager?.stop?.();\n } catch {\n }\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n adVideoElement = void 0;\n }\n }, 300);\n }\n showContentVideo();\n try {\n adsLoader?.destroy?.();\n } catch {\n }\n adDisplayContainer = void 0;\n adsLoader = void 0;\n contentVideoHidden = false;\n preloadedVast.clear();\n preloadingVast.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {\n }\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n }\n };\n}\n\n// src/sdk/hlsAdPlayer.ts\nimport Hls from \"hls.js\";\nfunction createHlsAdPlayer(contentVideo, options) {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = /* @__PURE__ */ new Map();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n const preloadedAds = /* @__PURE__ */ new Map();\n const preloadingAds = /* @__PURE__ */ new Map();\n let destroyed = false;\n let pendingTimeouts = [];\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels(urls) {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n }\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level2 = mainHlsInstance.levels[autoLevel];\n return {\n width: level2.width || 1920,\n height: level2.height || 1080,\n bitrate: level2.bitrate || 5e6\n };\n }\n return null;\n }\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5e6\n };\n }\n function selectBestMediaFile(mediaFiles) {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n const fileBitrate = (file.bitrate || 5e3) * 1e3;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1e3;\n return { file, score, resolutionDiff, bitrateDiff };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff\n });\n return bestMatch.file;\n }\n function parseVastXml(xmlString) {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n if (!url) {\n console.warn(\n `[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0\n });\n console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not HLS)`\n );\n }\n });\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No HLS media files found in VAST XML\");\n }\n return null;\n }\n const trackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: []\n };\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n async function fetchAndParseVastAd(vastTagUrl) {\n const response = await fetch(vastTagUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml);\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n video.volume = 1;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n const progress = adVideoElement.currentTime / currentAd.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function handleAdComplete() {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n emit(\"content_resume\");\n const timeoutId = window.setTimeout(() => {\n if (destroyed) {\n console.log(\"[HlsAdPlayer] Player destroyed, skipping post-completion check\");\n return;\n }\n const stillInPod = contentVideo.dataset.stormcloudAdPlaying === \"true\";\n if (stillInPod) {\n console.log(\n \"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)\"\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n }\n const idx = pendingTimeouts.indexOf(timeoutId);\n if (idx !== -1) {\n pendingTimeouts.splice(idx, 1);\n }\n }, 50);\n pendingTimeouts.push(timeoutId);\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n contentVideo.play().catch(() => {\n });\n }\n }\n emit(\"ad_error\");\n }\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n async requestAds(vastTagUrl) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n try {\n sessionId = generateSessionId();\n let ad;\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.resolve();\n }\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n if (preloadedAds.has(vastTagUrl)) {\n return Promise.resolve();\n }\n const inflight = preloadingAds.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {\n if (ad) {\n preloadedAds.set(vastTagUrl, ad);\n console.log(\n \"[HlsAdPlayer] Cached VAST response for preloading:\",\n vastTagUrl\n );\n }\n }).catch((error) => {\n console.warn(\"[HlsAdPlayer] Failed to preload VAST response:\", error);\n preloadedAds.delete(vastTagUrl);\n }).finally(() => {\n preloadingAds.delete(vastTagUrl);\n });\n preloadingAds.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl) {\n return preloadedAds.has(vastTagUrl);\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false\n });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(\"HLS not supported\");\n }\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n currentAd = void 0;\n },\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }\n };\n}\n\n// src/utils/tracking.ts\nvar cachedBrowserId = null;\nfunction getClientInfo() {\n const ua = navigator.userAgent;\n const platform = navigator.platform;\n const vendor = navigator.vendor || \"\";\n const maxTouchPoints = navigator.maxTouchPoints || 0;\n const memory = navigator.deviceMemory || null;\n const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n const screenInfo = {\n width: screen?.width,\n height: screen?.height,\n availWidth: screen?.availWidth,\n availHeight: screen?.availHeight,\n orientation: screen?.orientation?.type || \"\",\n pixelDepth: screen?.pixelDepth\n };\n let deviceType = \"desktop\";\n let brand = \"Unknown\";\n let os = \"Unknown\";\n let model = \"\";\n let isSmartTV = false;\n let isAndroid = false;\n let isWebView = false;\n let isWebApp = false;\n if (ua.includes(\"Web0S\")) {\n brand = \"LG\";\n os = \"webOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n } else if (ua.includes(\"Tizen\")) {\n brand = \"Samsung\";\n os = \"Tizen\";\n isSmartTV = true;\n deviceType = \"tv\";\n const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n model = tizenMatch ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim() : \"Tizen TV\";\n } else if (ua.includes(\"Philips\")) {\n brand = \"Philips\";\n os = \"Saphi\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n brand = \"Sharp\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Android\") && (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))) {\n brand = \"Sony\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Android\") && (ua.includes(\"NetCast\") || ua.includes(\"LG\"))) {\n brand = \"LG\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n brand = \"Roku\";\n os = \"Roku OS\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"AppleTV\")) {\n brand = \"Apple\";\n os = \"tvOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n }\n if (ua.includes(\"Android\")) {\n isAndroid = true;\n os = \"Android\";\n deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n if (ua.includes(\"Android\") && (maxTouchPoints === 0 || ua.includes(\"Google TV\") || ua.includes(\"XiaoMi\"))) {\n deviceType = \"tv\";\n isSmartTV = true;\n brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n }\n const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n if (androidModelMatch && androidModelMatch[1]) {\n model = androidModelMatch[1];\n }\n }\n if (/iPad|iPhone|iPod/.test(ua)) {\n os = \"iOS\";\n deviceType = \"mobile\";\n brand = \"Apple\";\n if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n deviceType = \"tablet\";\n }\n }\n if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n if (ua.includes(\"Windows\")) {\n os = \"Windows\";\n deviceType = \"desktop\";\n } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n os = \"macOS\";\n deviceType = \"desktop\";\n if (maxTouchPoints > 1) deviceType = \"tablet\";\n } else if (ua.includes(\"Linux\")) {\n os = \"Linux\";\n deviceType = \"desktop\";\n }\n }\n if (brand === \"Unknown\") {\n if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n if (vendor.includes(\"Apple\")) brand = \"Apple\";\n if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n }\n isWebView = /wv|WebView|Linux; U;/.test(ua);\n if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n isWebView = true;\n }\n isWebApp = window.matchMedia(\"(display-mode: standalone)\").matches || window.navigator.standalone === true || window.screen?.orientation?.angle !== void 0;\n return {\n brand,\n os,\n model: model || ua.substring(0, 50) + \"...\",\n deviceType,\n isSmartTV,\n isAndroid,\n isWebView,\n isWebApp,\n domain: window.location.hostname,\n origin: window.location.origin,\n path: window.location.pathname,\n userAgent: ua,\n vendor,\n platform,\n screen: screenInfo,\n hardwareConcurrency,\n deviceMemory: memory,\n maxTouchPoints,\n language: navigator.language,\n languages: navigator.languages?.join(\",\") || \"\",\n cookieEnabled: navigator.cookieEnabled,\n doNotTrack: navigator.doNotTrack || \"\",\n referrer: document.referrer,\n visibilityState: document.visibilityState\n };\n}\nasync function getBrowserID(clientInfo) {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n const fingerprintString = JSON.stringify(clientInfo);\n if (typeof crypto !== \"undefined\" && crypto.subtle && crypto.subtle.digest) {\n try {\n await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n let encodedData;\n if (typeof TextEncoder !== \"undefined\") {\n encodedData = new TextEncoder().encode(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\n const buffer = new Uint8Array(utf8.length);\n for (let i = 0; i < utf8.length; i++) {\n buffer[i] = utf8.charCodeAt(i);\n }\n encodedData = buffer;\n }\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n const timestamp = Date.now().toString(16).padStart(12, \"0\");\n const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\nasync function sendInitialTracking(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = {\n browserId,\n ...clientInfo\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\nasync function sendHeartbeat(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const heartbeatData = {\n browserId,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\n\n// src/utils/polyfills.ts\nfunction polyfillURLSearchParams() {\n if (typeof URLSearchParams !== \"undefined\") {\n return;\n }\n class URLSearchParamsPolyfill {\n constructor(init) {\n this.params = /* @__PURE__ */ new Map();\n if (typeof init === \"string\") {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n parseQueryString(query) {\n const cleanQuery = query.startsWith(\"?\") ? query.slice(1) : query;\n if (!cleanQuery) return;\n cleanQuery.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : \"\";\n this.append(decodedKey, decodedValue);\n }\n });\n }\n safeDecodeURIComponent(str) {\n try {\n return decodeURIComponent(str.replace(/\\+/g, \" \"));\n } catch (e) {\n return str;\n }\n }\n append(name, value) {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n delete(name) {\n this.params.delete(name);\n }\n get(name) {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;\n }\n getAll(name) {\n return this.params.get(name) || [];\n }\n has(name) {\n return this.params.has(name);\n }\n set(name, value) {\n this.params.set(name, [String(value)]);\n }\n forEach(callback) {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n toString() {\n const parts = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join(\"&\");\n }\n }\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\nfunction polyfillTextEncoder() {\n if (typeof TextEncoder !== \"undefined\") {\n return;\n }\n class TextEncoderPolyfill {\n constructor() {\n this.encoding = \"utf-8\";\n }\n encode(str) {\n const utf8 = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 128) {\n utf8.push(charcode);\n } else if (charcode < 2048) {\n utf8.push(192 | charcode >> 6, 128 | charcode & 63);\n } else if (charcode < 55296 || charcode >= 57344) {\n utf8.push(\n 224 | charcode >> 12,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n } else {\n i++;\n charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);\n utf8.push(\n 240 | charcode >> 18,\n 128 | charcode >> 12 & 63,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n window.TextEncoder = TextEncoderPolyfill;\n}\nfunction polyfillPromiseFinally() {\n if (typeof Promise !== \"undefined\" && !Promise.prototype.finally) {\n Promise.prototype.finally = function(callback) {\n const constructor = this.constructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) => constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\nfunction polyfillObjectAssign() {\n if (typeof Object.assign !== \"function\") {\n Object.assign = function(target, ...sources) {\n if (target == null) {\n throw new TypeError(\"Cannot convert undefined or null to object\");\n }\n const to = Object(target);\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n }\n}\nfunction polyfillArrayFrom() {\n if (!Array.from) {\n Array.from = function(arrayLike, mapFn, thisArg) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError(\"Array.from requires an array-like object\");\n }\n const len = items.length >>> 0;\n const result = new Array(len);\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n return result;\n };\n }\n}\nfunction polyfillStringStartsWith() {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function(search, pos) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\nfunction polyfillStringEndsWith() {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function(search, length) {\n if (length === void 0 || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\nfunction polyfillStringIncludes() {\n if (!String.prototype.includes) {\n String.prototype.includes = function(search, start) {\n if (typeof start !== \"number\") {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\nfunction initializePolyfills() {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.adPodQueue = [];\n this.lastHeartbeatTime = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.showAds = false;\n this.isLiveStream = false;\n this.nativeHlsMode = false;\n this.videoSrcProtection = null;\n this.bufferedSegmentsCount = 0;\n this.shouldAutoplayAfterBuffering = false;\n this.hasInitialBufferCompleted = false;\n this.adPodAllUrls = [];\n this.preloadingAdUrls = /* @__PURE__ */ new Set();\n this.vastToMediaUrlMap = /* @__PURE__ */ new Map();\n this.preloadedMediaUrls = /* @__PURE__ */ new Set();\n this.preloadingMediaUrls = /* @__PURE__ */ new Set();\n this.adRequestTokenCounter = 0;\n this.activeAdRequestToken = null;\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.fetchedAdDurations = /* @__PURE__ */ new Map();\n this.targetAdBreakDurationMs = null;\n this.isAdaptiveMode = false;\n this.failedVastUrls = /* @__PURE__ */ new Set();\n this.continuousFetchingActive = false;\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n this.maxPlaceholderDurationMs = 5e3;\n this.placeholderStartTimeMs = null;\n this.isShowingPlaceholder = false;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...config, ...browserOverrides };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.ima = this.createAdPlayer(false);\n }\n createAdPlayer(continueLiveStreamDuringAds) {\n const vastMode = this.config.vastMode || \"default\";\n let adPlayerType = this.config.adPlayerType || (vastMode === \"adstorm\" ? \"hls\" : \"ima\");\n if (adPlayerType === \"ima\" && !supportsGoogleIMA()) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player\"\n );\n }\n adPlayerType = \"hls\";\n }\n if (adPlayerType === \"hls\") {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)\"\n );\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},\n ...this.hls ? { mainHlsInstance: this.hls } : {}\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)\"\n );\n }\n return createImaController(this.video, {\n continueLiveStreamDuringAds\n });\n }\n }\n async load() {\n if (!this.attached) {\n this.attach();\n }\n try {\n await this.fetchAdConfiguration();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n this.initializeTracking();\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\"\n }\n );\n }\n this.ima.destroy();\n this.ima = this.createAdPlayer(false);\n this.ima.initialize();\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n return;\n }\n this.hls = new Hls2({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,\n ...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {},\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1e3 * 1e3,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1\n });\n this.hls.on(Hls2.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n this.hls.on(Hls2.Events.MANIFEST_PARSED, async (_, data) => {\n this.isLiveStream = this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds() ? \"live (main video continues muted during ads)\" : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior\n });\n }\n this.ima.destroy();\n this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.ima.initialize();\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n }\n });\n this.hls.on(Hls2.Events.FRAG_BUFFERED, async (_evt, data) => {\n if (this.hasInitialBufferCompleted) {\n return;\n }\n this.bufferedSegmentsCount++;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n this.hls.on(Hls2.Events.FRAG_PARSING_METADATA, (_evt, data) => {\n const id3Tags = (data?.samples || []).map((s) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n this.hls.on(Hls2.Events.FRAG_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n const marker = {\n type: \"progress\",\n ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},\n ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { tag, value, attrs }\n };\n this.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n this.hls.on(Hls2.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case Hls2.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case Hls2.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n attach() {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n this.ima.initialize();\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.ima.on(\"all_ads_completed\", () => {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] IMA all_ads_completed event received - ending ad break\"\n );\n }\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n this.ima.on(\"ad_error\", (errorPayload) => {\n const remaining = this.getRemainingAdMs();\n console.error(\"[AD-ERROR] Ad playback failed\", errorPayload || \"\");\n if (this.inAdBreak) {\n if (remaining > 500 && this.adPodQueue.length > 0) {\n const nextPreloaded = this.findNextPreloadedAd();\n if (nextPreloaded) {\n this.currentAdIndex++;\n this.playSingleAd(nextPreloaded).catch(() => {\n this.handleAdFailure();\n });\n } else {\n this.handleAdFailure();\n }\n } else {\n this.handleAdFailure();\n }\n } else {\n this.handleAdFailure();\n }\n });\n this.ima.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n });\n this.ima.on(\"content_resume\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n return;\n }\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);\n }\n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n this.handleAdPodComplete();\n }\n });\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {\n });\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n shouldUseNativeHls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n parseScte35FromId3(tag) {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return void 0;\n const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) || text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...dur !== void 0 ? { durationSeconds: dur } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker = {\n type: \"progress\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n if (hasScteIn) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n }\n if (/SCTE35-OUT/i.test(text)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n }\n decodeId3ValueToText(value) {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]);\n return out;\n } catch {\n return void 0;\n }\n }\n onScte35Marker(marker) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw\n });\n }\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n return;\n }\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\"\n });\n }\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1e3;\n const nowMs = this.video.currentTime * 1e3;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1e3,\n deltaMs,\n tolerance: tol\n });\n }\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null) {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1e3\n );\n const tags = this.selectVastTagsForBreak(scheduled) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);\n if (tags && tags.length > 0) {\n const first = tags[0];\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n this.playSingleAd(first).catch(() => {\n });\n }\n }\n return;\n }\n if (marker.type === \"end\") {\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n if (this.ima.isAdPlaying()) {\n this.ima.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n return;\n }\n }\n parseCueOutDuration(value) {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match = value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) || value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? void 0 : d;\n }\n return void 0;\n }\n parseCueOutCont(value) {\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n const res = {};\n if (elapsedMatch && elapsedMatch[1] != null) {\n const e = parseFloat(elapsedMatch[1]);\n if (!Number.isNaN(e)) res.elapsed = e;\n }\n if (durationMatch && durationMatch[1] != null) {\n const d = parseFloat(durationMatch[1]);\n if (!Number.isNaN(d)) res.duration = d;\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return void 0;\n }\n parseAttributeList(value) {\n const attrs = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match;\n while ((match = regex.exec(value)) !== null) {\n const key = match[1] ?? \"\";\n let rawVal = match[3] ?? match[4] ?? \"\";\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n toNumber(val) {\n if (val == null) return void 0;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? void 0 : n;\n }\n isManifestBasedMarker(marker) {\n const raw = marker.raw;\n if (!raw) return false;\n if (raw.tag) {\n const tag = String(raw.tag);\n return tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-CUE-IN\") || tag.includes(\"EXT-X-DATERANGE\");\n }\n if (raw.id3) return false;\n if (raw.splice_command_type) return false;\n return false;\n }\n parseScte35Binary(data) {\n class BitReader {\n constructor(buf) {\n this.buf = buf;\n this.bytePos = 0;\n this.bitPos = 0;\n }\n readBits(numBits) {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos];\n const shift = remainingInByte - toRead;\n const mask = (1 << toRead) - 1 & 255;\n const bits = currentByte >> shift & mask;\n result = result << toRead | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n) {\n this.readBits(n);\n }\n }\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 252) return void 0;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return void 0;\n }\n r.readBits(32);\n const cancel = r.readBits(1) === 1;\n r.readBits(7);\n if (cancel) return void 0;\n const outOfNetwork = r.readBits(1) === 1;\n const programSpliceFlag = r.readBits(1) === 1;\n const durationFlag = r.readBits(1) === 1;\n const spliceImmediateFlag = r.readBits(1) === 1;\n r.readBits(4);\n if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n } else if (!programSpliceFlag) {\n const componentCount = r.readBits(8);\n for (let i = 0; i < componentCount; i++) {\n r.readBits(8);\n if (!spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds = void 0;\n if (durationFlag) {\n r.readBits(6);\n r.readBits(1);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const durationTicks = high * 4294967296 + low;\n durationSeconds = durationTicks / 9e4;\n }\n r.readBits(16);\n r.readBits(8);\n r.readBits(8);\n if (outOfNetwork) {\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { splice_command_type: 5 }\n };\n return marker;\n }\n return void 0;\n }\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n });\n }\n sendHeartbeatIfNeeded() {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n async fetchAdConfiguration() {\n const vastMode = this.config.vastMode || \"default\";\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n );\n }\n return;\n }\n const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n this.apiVastTagUrl = vastEndpoint;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n vastEndpoint\n );\n }\n return;\n }\n if (this.config.vastTagUrl) {\n this.apiVastTagUrl = this.config.vastTagUrl;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n return;\n }\n const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n apiUrl\n );\n }\n const headers = {};\n if (this.config.licenseKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n }\n const response = await fetch(apiUrl, { headers });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n );\n }\n return;\n }\n const data = await response.json();\n const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n if (imaPayload) {\n this.apiVastTagUrl = decodeURIComponent(imaPayload);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n );\n }\n }\n const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n if (numberAds != null && numberAds > 0) {\n this.apiNumberAds = numberAds;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n getCurrentAdIndex() {\n return this.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.totalAdsInBreak;\n }\n generateVastUrlsWithCorrelators(baseUrl, count) {\n const urls = [];\n for (let i = 0; i < count; i++) {\n try {\n const url = new URL(baseUrl);\n const timestamp = Date.now();\n const random = Math.floor(Math.random() * 1e6);\n const uniqueCorrelator = `${timestamp}${random}${i}`;\n url.searchParams.set(\"correlator\", uniqueCorrelator);\n urls.push(url.toString());\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to parse VAST URL:\",\n baseUrl,\n error\n );\n urls.push(`${baseUrl}${baseUrl.includes(\"?\") ? \"&\" : \"?\"}correlator=${Date.now()}${i}`);\n }\n }\n return urls;\n }\n isAdPlaying() {\n return this.inAdBreak && this.ima.isAdPlaying();\n }\n isShowingAds() {\n return this.showAds;\n }\n getStreamType() {\n const url = this.config.src.toLowerCase();\n if (url.includes(\".m3u8\") || url.includes(\"/hls/\") || url.includes(\"application/vnd.apple.mpegurl\")) {\n return \"hls\";\n }\n return \"other\";\n }\n shouldShowNativeControls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));\n }\n shouldContinueLiveStreamDuringAds() {\n if (this.config.allowNativeHls) {\n return false;\n }\n if (!this.isLiveStream) {\n return false;\n }\n return true;\n }\n async handleAdStart(_marker) {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1e3\n );\n const tags = this.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else {\n return;\n }\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled?.durationMs;\n if (this.isLiveStream && adBreakDurationMs != null && adBreakDurationMs > 0) {\n this.isAdaptiveMode = true;\n this.targetAdBreakDurationMs = adBreakDurationMs;\n this.fetchedAdDurations.clear();\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F4FA} LIVE MODE: Target duration=${adBreakDurationMs}ms | Will continuously fetch ads during break`\n );\n }\n } else {\n this.isAdaptiveMode = false;\n this.targetAdBreakDurationMs = null;\n this.fetchedAdDurations.clear();\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F3AC} VOD MODE: Using fixed ad strategy`\n );\n }\n }\n this.adPodAllUrls = [];\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.failedVastUrls.clear();\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n this.inAdBreak = true;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F680} Immediately requesting first ad...\");\n }\n const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const firstAdUrl = firstAdUrlArray[0];\n if (!firstAdUrl) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F Failed to generate first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n try {\n await this.ima.requestAds(firstAdUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 First ad request successful, starting playback\");\n }\n this.successfulAdRequests.push(firstAdUrl);\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n await this.ima.play();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F First ad request failed:\", error);\n }\n this.failedVastUrls.add(firstAdUrl);\n this.startContinuousFetching(baseVastUrl);\n this.tryNextAvailableAd();\n }\n }\n startContinuousFetching(baseVastUrl) {\n if (!this.continuousFetchingActive) {\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F504} Starting continuous ad fetching loop\");\n }\n this.continuousFetchLoop(baseVastUrl);\n }\n async continuousFetchLoop(baseVastUrl) {\n while (this.continuousFetchingActive && this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F Ad break time expired, stopping fetch loop\");\n }\n break;\n }\n const maxQueueSize = 3;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F8\\uFE0F Queue full (${this.adRequestQueue.length}), pausing fetching...`);\n }\n await new Promise((resolve) => setTimeout(resolve, 2e3));\n continue;\n }\n const newAdUrl = this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];\n if (!newAdUrl || this.failedVastUrls.has(newAdUrl)) {\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n continue;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F4E1} Attempting to fetch ad (${this.successfulAdRequests.length + this.adRequestQueue.length + 1} total)...`);\n }\n try {\n const response = await fetch(newAdUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status}`);\n }\n const xmlText = await response.text();\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n const mediaFiles = xmlDoc.querySelectorAll(\"MediaFile\");\n if (mediaFiles.length === 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F VAST response has no media files, skipping\");\n }\n this.failedVastUrls.add(newAdUrl);\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n continue;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u2705 Successfully fetched ad, adding to queue (queue size: ${this.adRequestQueue.length + 1})`);\n }\n this.adRequestQueue.push(newAdUrl);\n this.totalAdsInBreak++;\n await new Promise((resolve) => setTimeout(resolve, 500));\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u274C Ad fetch failed:\", error.message);\n }\n this.failedVastUrls.add(newAdUrl);\n await new Promise((resolve) => setTimeout(resolve, 2e3));\n }\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Continuous fetch loop ended\");\n }\n }\n stopContinuousFetching() {\n this.continuousFetchingActive = false;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Stopping continuous ad fetching\");\n }\n }\n async tryNextAvailableAd(retryCount = 0) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (nextAdUrl) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F3AC} Playing next queued ad (${this.currentAdIndex + 1}/${this.totalAdsInBreak}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F50A} Updated ad audio state: muted=${currentMuted}, volume=${currentVolume}`);\n }\n this.currentAdIndex++;\n this.successfulAdRequests.push(nextAdUrl);\n await this.playSingleAd(nextAdUrl).catch(() => {\n this.tryNextAvailableAd(0);\n });\n return;\n }\n }\n const maxRetries = 5;\n if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2e3) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F3 Queue empty but fetching active, waiting... (retry ${retryCount + 1}/${maxRetries})`);\n }\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n await this.tryNextAvailableAd(retryCount + 1);\n return;\n }\n if (!this.isShowingPlaceholder && remaining > 1e3) {\n this.showPlaceholderAndWaitForAds();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No more ads available, ending ad break\");\n }\n this.handleAdPodComplete();\n }\n }\n async showPlaceholderAndWaitForAds() {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n if (waitTime < 1e3) {\n this.handleAdPodComplete();\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u2B1B Showing black placeholder for ${waitTime}ms while waiting for ads`);\n }\n this.isShowingPlaceholder = true;\n this.placeholderStartTimeMs = Date.now();\n this.ima.showPlaceholder();\n const checkInterval = 500;\n const maxChecks = Math.floor(waitTime / checkInterval);\n for (let i = 0; i < maxChecks; i++) {\n await new Promise((resolve) => setTimeout(resolve, checkInterval));\n if (!this.inAdBreak) {\n return;\n }\n if (this.adRequestQueue.length > 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 New ad became available during placeholder\");\n }\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n this.ima.hidePlaceholder();\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n const nextAdUrl = this.adRequestQueue.shift();\n if (nextAdUrl) {\n this.currentAdIndex++;\n this.successfulAdRequests.push(nextAdUrl);\n await this.playSingleAd(nextAdUrl).catch(() => {\n this.tryNextAvailableAd();\n });\n }\n return;\n }\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F0 Placeholder timeout reached, no ads fetched\");\n }\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n this.ima.hidePlaceholder();\n this.handleAdPodComplete();\n }\n findCurrentOrNextBreak(nowMs) {\n const schedule = [];\n let candidate;\n for (const b of schedule) {\n const tol = this.config.driftToleranceMs ?? 1e3;\n if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {\n candidate = b;\n }\n }\n return candidate;\n }\n onTimeUpdate(currentTimeSec) {\n if (this.ima.isAdPlaying()) return;\n const nowMs = currentTimeSec * 1e3;\n const breakToPlay = this.findBreakForTime(nowMs);\n if (breakToPlay) {\n this.handleMidAdJoin(breakToPlay, nowMs);\n }\n }\n async handleMidAdJoin(adBreak, nowMs) {\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = adBreak.startTimeMs + durationMs;\n if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {\n const remainingMs = endMs - nowMs;\n const tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);\n if (tags && tags.length > 0) {\n const first = tags[0];\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n await this.playSingleAd(first);\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = remainingMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(remainingMs);\n }\n }\n }\n scheduleAdStopCountdown(remainingMs) {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.ensureAdStoppedByTimer();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.ensureAdStoppedByTimer();\n }, ms);\n }\n clearAdStopTimer() {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = void 0;\n }\n }\n ensureAdStoppedByTimer() {\n if (!this.inAdBreak) return;\n this.adStopTimerId = void 0;\n const adPlaying = this.ima.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1e3)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs = typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n if (adPlaying) {\n this.ima.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n }\n scheduleAdStartIn(delayMs) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\n updatePtsDrift(ptsSecondsSample) {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n async playSingleAd(vastTagUrl) {\n if (this.ima.isAdPlaying()) {\n return;\n }\n if (this.failedVastUrls.has(vastTagUrl)) {\n console.warn(\"[AD-ERROR] Skipping already-failed VAST URL:\", vastTagUrl.substring(0, 60));\n this.handleAdFailure();\n return;\n }\n const requestToken = ++this.adRequestTokenCounter;\n this.activeAdRequestToken = requestToken;\n this.startAdRequestWatchdog(requestToken);\n try {\n await this.ima.requestAds(vastTagUrl);\n this.clearAdRequestWatchdog();\n if (this.activeAdRequestToken !== requestToken) {\n return;\n }\n try {\n this.startAdFailsafeTimer(requestToken);\n await this.ima.play();\n } catch (playError) {\n console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n this.failedVastUrls.add(vastTagUrl);\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n this.handleAdFailure();\n return;\n }\n } catch (error) {\n console.error(\"[AD-ERROR] Ad request failed:\", error?.message);\n this.failedVastUrls.add(vastTagUrl);\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n this.handleAdFailure();\n }\n }\n handleAdPodComplete() {\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.stopContinuousFetching();\n if (this.isShowingPlaceholder) {\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n }\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.adPodAllUrls = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.ima.stop().catch(() => {\n });\n const restoredMuted = this.ima.getOriginalMutedState();\n const restoredVolume = this.ima.getOriginalVolume();\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n if (!this.shouldContinueLiveStreamDuringAds() && this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n }\n handleAdFailure() {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);\n }\n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n console.error(\"[AD-ERROR] Ad failed and no time remaining. Failed URLs:\", this.failedVastUrls.size);\n this.handleAdPodComplete();\n }\n }\n startAdRequestWatchdog(token) {\n this.clearAdRequestWatchdog();\n const timeoutMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n this.adRequestWatchdogToken = token;\n this.adRequestWatchdogId = window.setTimeout(() => {\n if (this.adRequestWatchdogToken !== token) {\n return;\n }\n this.adRequestWatchdogId = void 0;\n this.adRequestWatchdogToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n this.handleAdFailure();\n }, timeoutMs);\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n clearAdRequestWatchdog() {\n if (this.adRequestWatchdogId != null) {\n clearTimeout(this.adRequestWatchdogId);\n this.adRequestWatchdogId = void 0;\n }\n if (this.adRequestWatchdogToken != null) {\n this.logAdState(\"ad_request_watchdog_cleared\", {\n token: this.adRequestWatchdogToken\n });\n this.adRequestWatchdogToken = null;\n }\n }\n startAdFailsafeTimer(token) {\n this.clearAdFailsafeTimer();\n const failsafeMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n this.adFailsafeToken = token;\n this.adFailsafeTimerId = window.setTimeout(() => {\n if (this.adFailsafeToken !== token) {\n return;\n }\n this.adFailsafeTimerId = void 0;\n this.adFailsafeToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n this.logAdState(\"ad_failsafe_triggered\", {\n token,\n failsafeMs,\n videoPaused: this.video.paused,\n imaAdPlaying: this.ima.isAdPlaying()\n });\n this.handleAdFailure();\n }, failsafeMs);\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n clearAdFailsafeTimer() {\n if (this.adFailsafeTimerId != null) {\n clearTimeout(this.adFailsafeTimerId);\n this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n this.adFailsafeTimerId = void 0;\n }\n this.adFailsafeToken = null;\n }\n selectVastTagsForBreak(b) {\n if (!b || !b.vastTagUrl) return void 0;\n if (b.vastTagUrl.includes(\",\")) {\n return b.vastTagUrl.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n }\n return [b.vastTagUrl];\n }\n logAdState(event, extra = {}) {\n if (!this.config.debugAdTiming) {\n return;\n }\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n showAds: this.showAds,\n adPlaying: this.ima.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n async fetchAndParseVastXml(vastTagUrl) {\n try {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status}`);\n }\n const xmlText = await response.text();\n return this.extractMediaUrlsFromVast(xmlText);\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch/parse VAST XML: ${vastTagUrl}`,\n error\n );\n }\n return [];\n }\n }\n extractMediaUrlsFromVast(xmlText) {\n const mediaUrls = [];\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n for (const mediaFile of Array.from(mediaFileElements)) {\n const url = mediaFile.textContent?.trim();\n if (url) {\n const lowerUrl = url.toLowerCase();\n if (lowerUrl.endsWith(\".mp4\") || lowerUrl.endsWith(\".webm\") || lowerUrl.endsWith(\".mov\") || lowerUrl.endsWith(\".avi\") || lowerUrl.includes(\".mp4?\") || lowerUrl.includes(\".webm?\") || lowerUrl.includes(\"/mp4/\") || lowerUrl.includes(\"type=video\")) {\n mediaUrls.push(url);\n }\n }\n }\n if (this.config.debugAdTiming && mediaUrls.length > 0) {\n console.log(\n `[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs from VAST:`,\n mediaUrls\n );\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to parse VAST XML:\",\n error\n );\n }\n }\n return mediaUrls;\n }\n async fetchVastDuration(vastTagUrl) {\n try {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] Failed to fetch VAST: ${response.status}`\n );\n }\n return null;\n }\n const xmlText = await response.text();\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent;\n if (!durationText) {\n if (this.config.debugAdTiming) {\n console.warn(\"[ADAPTIVE-POD] No Duration element found in VAST\");\n }\n return null;\n }\n const durationParts = durationText.split(\":\");\n const durationSeconds = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n return durationSeconds;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] Error fetching VAST duration from ${vastTagUrl}:`,\n error\n );\n }\n return null;\n }\n }\n calculateAdditionalAdsNeeded() {\n if (!this.isAdaptiveMode || this.targetAdBreakDurationMs === null) {\n return 0;\n }\n let totalFetchedDurationMs = 0;\n for (const duration of this.fetchedAdDurations.values()) {\n totalFetchedDurationMs += duration * 1e3;\n }\n const fetchedCount = this.fetchedAdDurations.size;\n const averageDurationMs = fetchedCount > 0 ? totalFetchedDurationMs / fetchedCount : 30 * 1e3;\n const queuedButNotFetched = this.adPodAllUrls.length - fetchedCount;\n const estimatedQueuedDurationMs = queuedButNotFetched * averageDurationMs;\n const estimatedTotalDurationMs = totalFetchedDurationMs + estimatedQueuedDurationMs;\n const remainingTimeMs = this.targetAdBreakDurationMs - estimatedTotalDurationMs;\n if (remainingTimeMs <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u2705 Target duration met: Fetched=${totalFetchedDurationMs}ms + Queued(${queuedButNotFetched} ads)=${estimatedQueuedDurationMs}ms = ${estimatedTotalDurationMs}ms / Target=${this.targetAdBreakDurationMs}ms`\n );\n }\n return 0;\n }\n const additionalAds = Math.ceil(remainingTimeMs / averageDurationMs);\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F4CA} Need ${additionalAds} more ads | Fetched: ${totalFetchedDurationMs}ms (${fetchedCount} ads) | Queued: ${estimatedQueuedDurationMs}ms (${queuedButNotFetched} ads) | Target: ${this.targetAdBreakDurationMs}ms | Remaining: ${remainingTimeMs}ms | Avg duration: ${averageDurationMs}ms`\n );\n }\n return additionalAds;\n }\n async addAdaptiveAdsToQueue() {\n if (!this.isAdaptiveMode || !this.apiVastTagUrl) {\n return;\n }\n const additionalAds = this.calculateAdditionalAdsNeeded();\n if (additionalAds <= 0) {\n return;\n }\n const newUrls = this.generateVastUrlsWithCorrelators(\n this.apiVastTagUrl,\n additionalAds\n );\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F504} Adding ${newUrls.length} additional VAST URLs to queue (will be preloaded sequentially)`\n );\n }\n this.adPodAllUrls.push(...newUrls);\n this.adPodQueue.push(...newUrls);\n this.totalAdsInBreak += newUrls.length;\n }\n async preloadMediaFile(mediaUrl) {\n if (this.preloadedMediaUrls.has(mediaUrl)) {\n return;\n }\n if (this.preloadingMediaUrls.has(mediaUrl)) {\n return;\n }\n this.preloadingMediaUrls.add(mediaUrl);\n try {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Preloading video file: ${mediaUrl}`\n );\n }\n const response = await fetch(mediaUrl, {\n mode: \"cors\",\n method: \"GET\",\n headers: {\n Range: \"bytes=0-1048576\"\n }\n });\n if (response.ok || response.status === 206) {\n this.preloadedMediaUrls.add(mediaUrl);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Successfully preloaded video file: ${mediaUrl}`\n );\n }\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to preload video file: ${mediaUrl}`,\n error\n );\n }\n } finally {\n this.preloadingMediaUrls.delete(mediaUrl);\n }\n }\n async preloadAllAdsInBackground() {\n if (this.adPodAllUrls.length === 0) {\n return;\n }\n if (this.isAdaptiveMode) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F504} Starting sequential preload of remaining ads`\n );\n }\n const processedUrls = /* @__PURE__ */ new Set();\n for (const url of this.adPodAllUrls) {\n if (this.ima.hasPreloadedAd?.(url) || this.fetchedAdDurations.has(url)) {\n processedUrls.add(url);\n }\n }\n if (this.config.debugAdTiming && processedUrls.size > 0) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F4E6} Skipping ${processedUrls.size} already-preloaded ads`\n );\n }\n while (true) {\n const nextUrl = this.adPodAllUrls.find((url) => !processedUrls.has(url));\n if (!nextUrl) {\n if (this.config.debugAdTiming) {\n console.log(`[ADAPTIVE-POD] \\u2705 All queued ads processed (${processedUrls.size} total)`);\n }\n break;\n }\n processedUrls.add(nextUrl);\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F4E5} Preloading ad ${processedUrls.size}/${this.adPodAllUrls.length}...`\n );\n }\n try {\n await this.preloadSingleAd(nextUrl);\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] \\u26A0\\uFE0F Preload failed for ad ${processedUrls.size}:`,\n error\n );\n }\n }\n if (this.calculateAdditionalAdsNeeded() === 0) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u2705 Target duration reached (${processedUrls.size} ads preloaded), stopping`\n );\n }\n break;\n }\n }\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u2705 Sequential preloading completed (${processedUrls.size} ads ready)`\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Starting parallel preload of ${this.adPodAllUrls.length} ads`\n );\n }\n const preloadPromises = this.adPodAllUrls.map(\n (vastTagUrl) => this.preloadSingleAd(vastTagUrl).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Preload failed for ${vastTagUrl}:`,\n error\n );\n }\n })\n );\n await Promise.all(preloadPromises);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Background preloading completed for all ads`\n );\n }\n }\n }\n async preloadSingleAd(vastTagUrl) {\n if (!vastTagUrl) return;\n try {\n if (this.isAdaptiveMode && !this.fetchedAdDurations.has(vastTagUrl)) {\n const duration = await this.fetchVastDuration(vastTagUrl);\n if (duration !== null) {\n this.fetchedAdDurations.set(vastTagUrl, duration);\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u2713 Fetched ad duration: ${duration}s (${this.fetchedAdDurations.size} ads fetched so far)`\n );\n }\n await this.addAdaptiveAdsToQueue();\n }\n }\n if (this.ima.preloadAds && !this.ima.hasPreloadedAd(vastTagUrl)) {\n if (!this.preloadingAdUrls.has(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Preloading VAST: ${vastTagUrl}`\n );\n }\n this.preloadingAdUrls.add(vastTagUrl);\n await this.ima.preloadAds(vastTagUrl).then(() => {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA VAST preload complete: ${vastTagUrl}`\n );\n }\n }).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] IMA VAST preload failed: ${vastTagUrl}`,\n error\n );\n }\n }).finally(() => {\n this.preloadingAdUrls.delete(vastTagUrl);\n });\n }\n }\n let mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);\n if (!mediaUrls) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Fetching and parsing VAST to extract media URLs: ${vastTagUrl}`\n );\n }\n mediaUrls = await this.fetchAndParseVastXml(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs:`,\n mediaUrls\n );\n }\n if (mediaUrls.length > 0) {\n this.vastToMediaUrlMap.set(vastTagUrl, mediaUrls);\n }\n }\n if (mediaUrls && mediaUrls.length > 0) {\n const primaryMediaUrl = mediaUrls[0];\n if (primaryMediaUrl && !this.preloadedMediaUrls.has(primaryMediaUrl)) {\n await this.preloadMediaFile(primaryMediaUrl);\n }\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to preload ad: ${vastTagUrl}`,\n error\n );\n }\n }\n }\n findNextPreloadedAd() {\n for (let i = 0; i < this.adPodQueue.length; i++) {\n const vastTagUrl = this.adPodQueue[i];\n if (!vastTagUrl) continue;\n if (this.failedVastUrls.has(vastTagUrl)) {\n console.warn(\"[AD-ERROR] Skipping failed URL in queue\");\n continue;\n }\n const hasImaPreload = this.ima.hasPreloadedAd?.(vastTagUrl) ?? false;\n const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);\n const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;\n if (hasImaPreload || hasMediaPreload) {\n this.adPodQueue.splice(0, i + 1);\n return vastTagUrl;\n }\n }\n return void 0;\n }\n getRemainingAdMs() {\n if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)\n return 0;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n findBreakForTime(nowMs) {\n const schedule = [];\n for (const b of schedule) {\n const end = (b.startTimeMs || 0) + (b.durationMs || 0);\n if (nowMs >= (b.startTimeMs || 0) && (b.durationMs ? nowMs < end : true)) {\n return b;\n }\n }\n return void 0;\n }\n toggleMute() {\n if (this.ima.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n this.ima.updateOriginalMutedState(newMutedState, this.video.volume);\n this.ima.setAdVolume(newMutedState ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n toggleFullscreen() {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document.exitFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n isMuted() {\n if (this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n setMuted(muted) {\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n this.video.muted = muted;\n if (adPlaying) {\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n this.ima.setAdVolume(muted ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted\n });\n }\n return;\n }\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n setVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying) {\n this.ima.setAdVolume(clampedVolume);\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n isFullscreen() {\n return !!document.fullscreenElement;\n }\n isLive() {\n return this.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n resize() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n if (this.ima && this.ima.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 360;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n this.ima.resize(width, height);\n }\n }\n destroy() {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = void 0;\n }\n this.hls?.destroy();\n this.ima?.destroy();\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.adPodAllUrls = [];\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n }\n};\n\n// src/ui/StormcloudVideoPlayer.tsx\nimport {\n FaPlay,\n FaPause,\n FaVolumeUp,\n FaVolumeMute,\n FaVolumeDown,\n FaExpand,\n FaCompress,\n FaSpinner\n} from \"react-icons/fa\";\nimport { Fragment, jsx, jsxs } from \"react/jsx-runtime\";\nvar CRITICAL_PROPS = [\n \"src\",\n \"allowNativeHls\",\n \"licenseKey\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"vastMode\"\n];\nvar StormcloudVideoPlayerComponent = React.memo(\n (props) => {\n const {\n src,\n autoplay,\n muted,\n lowLatencyMode,\n allowNativeHls,\n driftToleranceMs,\n immediateManifestAds,\n debugAdTiming,\n showCustomControls,\n hideLoadingIndicator,\n onVolumeToggle,\n onFullscreenToggle,\n onControlClick,\n onReady,\n wrapperClassName,\n wrapperStyle,\n className,\n style,\n controls,\n playsInline,\n preload,\n poster,\n children,\n licenseKey,\n vastMode,\n vastTagUrl,\n adPlayerType,\n minSegmentsBeforePlay,\n ...restVideoAttrs\n } = props;\n const videoRef = useRef(null);\n const playerRef = useRef(null);\n const bufferingTimeoutRef = useRef(null);\n const [adStatus, setAdStatus] = React.useState({ showAds: false, currentIndex: 0, totalAds: 0 });\n const [shouldShowNativeControls, setShouldShowNativeControls] = React.useState(true);\n const [isMuted, setIsMuted] = React.useState(false);\n const [isFullscreen, setIsFullscreen] = React.useState(false);\n const [isPlaying, setIsPlaying] = React.useState(false);\n const [currentTime, setCurrentTime] = React.useState(0);\n const [duration, setDuration] = React.useState(0);\n const [volume, setVolume] = React.useState(1);\n const [playbackRate, setPlaybackRate] = React.useState(1);\n const [showVolumeSlider, setShowVolumeSlider] = React.useState(false);\n const [showSpeedMenu, setShowSpeedMenu] = React.useState(false);\n const [isLoading, setIsLoading] = React.useState(true);\n const [isBuffering, setIsBuffering] = React.useState(false);\n const [showCenterPlay, setShowCenterPlay] = React.useState(false);\n const [showLicenseWarning, setShowLicenseWarning] = React.useState(false);\n const [viewportWidth, setViewportWidth] = React.useState(\n typeof window !== \"undefined\" ? window.innerWidth : 1920\n );\n const [isPortrait, setIsPortrait] = React.useState(\n typeof window !== \"undefined\" ? window.innerHeight > window.innerWidth : false\n );\n const getResponsiveScale = () => {\n if (viewportWidth < 480) return 0.7;\n if (viewportWidth < 768) return 0.8;\n if (viewportWidth < 1024) return 0.9;\n return 1;\n };\n const responsiveScale = getResponsiveScale();\n const formatTime = (seconds) => {\n if (!isFinite(seconds)) return \"0:00:00\";\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor(seconds % 3600 / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${remainingSeconds.toString().padStart(2, \"0\")}`;\n };\n const handlePlayPause = () => {\n if (videoRef.current) {\n if (videoRef.current.paused) {\n const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== \"\" || videoRef.current.readyState >= 1;\n if (hasValidSource) {\n videoRef.current.play()?.catch((error) => {\n console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n });\n setShowCenterPlay(false);\n } else {\n console.warn(\n \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n );\n }\n } else {\n videoRef.current.pause();\n setShowCenterPlay(true);\n }\n }\n };\n const handleCenterPlayClick = () => {\n if (videoRef.current && videoRef.current.paused) {\n const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== \"\" || videoRef.current.readyState >= 1;\n if (hasValidSource) {\n videoRef.current.play()?.catch((error) => {\n console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n });\n setShowCenterPlay(false);\n } else {\n console.warn(\n \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n );\n }\n }\n };\n const handleTimelineSeek = (e) => {\n if (videoRef.current && duration > 0 && isFinite(duration)) {\n const rect = e.currentTarget.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n const progress = Math.max(0, Math.min(1, clickX / rect.width));\n const newTime = progress * duration;\n if (isFinite(newTime) && newTime >= 0 && newTime <= duration) {\n videoRef.current.currentTime = newTime;\n }\n }\n };\n const handleVolumeChange = (newVolume) => {\n if (playerRef.current && isFinite(newVolume)) {\n const clampedVolume = Math.max(0, Math.min(1, newVolume));\n playerRef.current.setVolume(clampedVolume);\n }\n };\n const handlePlaybackRateChange = (rate) => {\n if (videoRef.current && isFinite(rate) && rate > 0) {\n videoRef.current.playbackRate = rate;\n }\n setShowSpeedMenu(false);\n };\n const isHlsStream = src?.toLowerCase().includes(\".m3u8\") || src?.toLowerCase().includes(\"/hls/\");\n const shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);\n const criticalPropsKey = useMemo(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n licenseKey,\n lowLatencyMode,\n driftToleranceMs,\n vastMode\n ]);\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const el = videoRef.current;\n if (!el || !src) return;\n if (!licenseKey) {\n setShowLicenseWarning(true);\n setIsLoading(false);\n console.warn(\n \"StormcloudVideoPlayer: License key is required but not provided. Please set the licenseKey prop to use the player.\"\n );\n return;\n }\n setShowLicenseWarning(false);\n if (debugAdTiming) {\n console.log(\"[StormcloudUI] Initializing player, isLoading=true\");\n }\n if (playerRef.current) {\n try {\n playerRef.current.destroy();\n } catch {\n }\n playerRef.current = null;\n }\n const cfg = {\n src,\n videoElement: el\n };\n if (autoplay !== void 0) cfg.autoplay = autoplay;\n if (muted !== void 0) cfg.muted = muted;\n if (lowLatencyMode !== void 0) cfg.lowLatencyMode = lowLatencyMode;\n if (allowNativeHls !== void 0) cfg.allowNativeHls = allowNativeHls;\n if (driftToleranceMs !== void 0)\n cfg.driftToleranceMs = driftToleranceMs;\n if (immediateManifestAds !== void 0)\n cfg.immediateManifestAds = immediateManifestAds;\n if (debugAdTiming !== void 0) cfg.debugAdTiming = debugAdTiming;\n if (showCustomControls !== void 0)\n cfg.showCustomControls = showCustomControls;\n if (onVolumeToggle !== void 0) cfg.onVolumeToggle = onVolumeToggle;\n if (onFullscreenToggle !== void 0)\n cfg.onFullscreenToggle = onFullscreenToggle;\n if (onControlClick !== void 0) cfg.onControlClick = onControlClick;\n if (licenseKey !== void 0) cfg.licenseKey = licenseKey;\n if (vastMode !== void 0) cfg.vastMode = vastMode;\n if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;\n if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;\n if (minSegmentsBeforePlay !== void 0)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n const player = new StormcloudVideoPlayer(cfg);\n playerRef.current = player;\n player.load().then(() => {\n const showNative = player.shouldShowNativeControls();\n setShouldShowNativeControls(showNative);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Player loaded successfully, waiting for video ready\"\n );\n }\n onReady?.(player);\n }).catch((error) => {\n console.error(\n \"StormcloudVideoPlayer: Failed to load player:\",\n error\n );\n setIsLoading(false);\n onReady?.(player);\n });\n return () => {\n try {\n player.destroy();\n } catch {\n }\n playerRef.current = null;\n };\n }, [criticalPropsKey]);\n useEffect(() => {\n if (!playerRef.current) return;\n try {\n if (autoplay !== void 0 && playerRef.current.videoElement) {\n playerRef.current.videoElement.autoplay = autoplay;\n }\n if (muted !== void 0 && !playerRef.current.isShowingAds()) {\n playerRef.current.setMuted(muted);\n }\n } catch (error) {\n console.warn(\"Failed to update player properties:\", error);\n }\n }, [autoplay, muted]);\n useEffect(() => {\n if (!playerRef.current) return;\n const checkAdStatus = () => {\n if (playerRef.current) {\n const showAds = playerRef.current.isShowingAds();\n const currentIndex = playerRef.current.getCurrentAdIndex();\n const totalAds = playerRef.current.getTotalAdsInBreak();\n setAdStatus((prev) => {\n if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {\n return { showAds, currentIndex, totalAds };\n }\n return prev;\n });\n }\n };\n const interval = setInterval(checkAdStatus, 100);\n return () => clearInterval(interval);\n }, []);\n useEffect(() => {\n if (typeof window === \"undefined\" || !playerRef.current) return;\n const handleResize = () => {\n if (playerRef.current && videoRef.current) {\n if (typeof playerRef.current.resize === \"function\") {\n playerRef.current.resize();\n }\n }\n setViewportWidth(window.innerWidth);\n setIsPortrait(window.innerHeight > window.innerWidth);\n };\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n useEffect(() => {\n if (!playerRef.current || !videoRef.current) return;\n const updateStates = () => {\n if (playerRef.current && videoRef.current) {\n setIsMuted(playerRef.current.isMuted());\n setIsPlaying(!videoRef.current.paused);\n const currentTimeValue = videoRef.current.currentTime;\n setCurrentTime(isFinite(currentTimeValue) ? currentTimeValue : 0);\n const durationValue = videoRef.current.duration;\n setDuration(isFinite(durationValue) ? durationValue : 0);\n const volumeValue = videoRef.current.volume;\n setVolume(\n isFinite(volumeValue) ? Math.max(0, Math.min(1, volumeValue)) : 1\n );\n const rateValue = videoRef.current.playbackRate;\n setPlaybackRate(\n isFinite(rateValue) && rateValue > 0 ? rateValue : 1\n );\n }\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\n );\n };\n const interval = setInterval(updateStates, 200);\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\n );\n };\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n return () => {\n clearInterval(interval);\n document.removeEventListener(\n \"fullscreenchange\",\n handleFullscreenChange\n );\n };\n }, []);\n useEffect(() => {\n if (!videoRef.current) return;\n const handleLoadedMetadata = () => {\n if (videoRef.current) {\n const video2 = videoRef.current;\n void video2.offsetHeight;\n }\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadedmetadata, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n const handleLoadedData = () => {\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadeddata, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n const handleLoadStart = () => {\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadstart, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n const handleCanPlay = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: canplay, readyState:\",\n videoRef.current?.readyState,\n \"- clearing loading state, isLoading=false\"\n );\n }\n };\n const handleCanPlayThrough = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: canplaythrough, readyState:\",\n videoRef.current?.readyState,\n \"- clearing loading state, isLoading=false\"\n );\n }\n };\n const handleWaiting = () => {\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n }\n bufferingTimeoutRef.current = window.setTimeout(() => {\n setIsBuffering(true);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video buffering detected (after 300ms delay), readyState:\",\n videoRef.current?.readyState,\n \"- showing spinner, isBuffering=true\"\n );\n }\n }, 300);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: waiting, readyState:\",\n videoRef.current?.readyState,\n \"- buffering delay started (300ms)\"\n );\n }\n };\n const handlePlaying = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n setShowCenterPlay(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: playing, readyState:\",\n videoRef.current?.readyState,\n \"- playback started, isLoading=false, isBuffering=false\"\n );\n }\n };\n const handlePause = () => {\n if (playerRef.current && !playerRef.current.isShowingAds()) {\n setShowCenterPlay(true);\n } else {\n setShowCenterPlay(false);\n }\n };\n const handleEnded = () => {\n setShowCenterPlay(true);\n };\n const video = videoRef.current;\n video.addEventListener(\"loadstart\", handleLoadStart);\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.addEventListener(\"canplay\", handleCanPlay);\n video.addEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.addEventListener(\"waiting\", handleWaiting);\n video.addEventListener(\"playing\", handlePlaying);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n if (video.paused) {\n setShowCenterPlay(true);\n }\n return () => {\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n video.removeEventListener(\"loadstart\", handleLoadStart);\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n video.removeEventListener(\"canplay\", handleCanPlay);\n video.removeEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.removeEventListener(\"waiting\", handleWaiting);\n video.removeEventListener(\"playing\", handlePlaying);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n };\n }, [debugAdTiming]);\n return /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(\"style\", { children: `\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n \n .stormcloud-loading-hidden .stormcloud-loading-indicator {\n display: none !important;\n }\n \n .stormcloud-video-wrapper:fullscreen {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n \n .stormcloud-video-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n \n *:fullscreen {\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n }\n ` }),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n className: `stormcloud-video-wrapper ${wrapperClassName || \"\"}`,\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n position: isFullscreen ? \"fixed\" : \"relative\",\n top: isFullscreen ? 0 : void 0,\n left: isFullscreen ? 0 : void 0,\n overflow: \"hidden\",\n width: isFullscreen ? \"100vw\" : \"100%\",\n height: isFullscreen ? \"100vh\" : \"auto\",\n minHeight: isFullscreen ? \"100vh\" : \"auto\",\n maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : void 0,\n backgroundColor: isFullscreen ? \"#000\" : void 0,\n borderRadius: isFullscreen ? 0 : void 0,\n boxShadow: isFullscreen ? \"none\" : void 0,\n ...wrapperStyle\n },\n children: [\n /* @__PURE__ */ jsx(\n \"video\",\n {\n ref: videoRef,\n className,\n style: {\n display: \"block\",\n width: \"100%\",\n height: isFullscreen ? \"100%\" : \"auto\",\n maxWidth: \"100%\",\n maxHeight: isFullscreen ? \"100%\" : \"none\",\n objectFit: isFullscreen ? \"cover\" : \"contain\",\n backgroundColor: \"#000\",\n aspectRatio: isFullscreen ? \"unset\" : void 0,\n ...style\n },\n controls: shouldShowNativeControls && controls && !showCustomControls,\n playsInline,\n preload,\n poster,\n ...restVideoAttrs,\n children\n }\n ),\n (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ jsx(\n FaSpinner,\n {\n className: \"stormcloud-loading-indicator\",\n size: 42,\n color: \"white\",\n style: {\n position: \"absolute\",\n top: \"calc(50% - 21px)\",\n left: \"calc(50% - 21px)\",\n zIndex: 20,\n animation: \"spin 1s linear infinite\",\n filter: \"drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))\"\n }\n }\n ),\n showLicenseWarning && /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 25,\n background: \"linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)\",\n color: \"white\",\n padding: \"24px 32px\",\n borderRadius: \"16px\",\n backdropFilter: \"blur(20px)\",\n border: \"2px solid rgba(255, 255, 255, 0.2)\",\n boxShadow: \"0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\"\n },\n children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n fontSize: \"20px\",\n fontWeight: \"bold\",\n marginBottom: \"12px\",\n color: \"#ffffff\",\n textShadow: \"0 2px 4px rgba(0, 0, 0, 0.5)\"\n },\n children: \"License Key Required\"\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n fontSize: \"14px\",\n lineHeight: \"1.5\",\n color: \"rgba(255, 255, 255, 0.9)\",\n textShadow: \"0 1px 2px rgba(0, 0, 0, 0.3)\"\n },\n children: [\n \"Please provide a valid license key to use the Stormcloud Video Player.\",\n /* @__PURE__ */ jsx(\"br\", {}),\n \"Contact your administrator for licensing information.\"\n ]\n }\n )\n ]\n }\n ),\n showCenterPlay && !isLoading && !isBuffering && !showLicenseWarning && !adStatus.showAds && /* @__PURE__ */ jsx(\n \"div\",\n {\n onClick: handleCenterPlayClick,\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 15,\n cursor: \"pointer\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\",\n borderRadius: \"50%\",\n width: \"100px\",\n height: \"100px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n border: \"3px solid rgba(255, 255, 255, 0.8)\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\"\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)\";\n target.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.9)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\";\n target.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.8)\";\n },\n title: \"Play\",\n children: /* @__PURE__ */ jsx(\n FaPlay,\n {\n size: 36,\n color: \"white\",\n style: {\n marginLeft: \"6px\",\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\"\n }\n }\n )\n }\n ),\n shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background: \"linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)\",\n padding: \"20px 16px 16px\",\n zIndex: 10\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"8px\",\n background: \"linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)\",\n borderRadius: \"8px\",\n marginBottom: \"16px\",\n cursor: \"pointer\",\n position: \"relative\",\n backdropFilter: \"blur(5px)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"inset 0 2px 4px rgba(0, 0, 0, 0.2)\"\n },\n onClick: handleTimelineSeek,\n children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n height: \"100%\",\n background: \"linear-gradient(90deg, rgba(139, 92, 246, 0.9) 0%, rgba(59, 130, 246, 0.8) 50%, rgba(34, 197, 94, 0.9) 100%)\",\n borderRadius: \"8px\",\n width: `${duration > 0 ? currentTime / duration * 100 : 0}%`,\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 2px 8px rgba(139, 92, 246, 0.4)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"-6px\",\n right: `${duration > 0 ? 100 - currentTime / duration * 100 : 100}%`,\n width: \"20px\",\n height: \"20px\",\n background: \"linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)\",\n borderRadius: \"50%\",\n border: \"3px solid rgba(139, 92, 246, 0.8)\",\n boxShadow: \"0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)\",\n transform: \"translateX(50%)\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\"\n }\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n flexWrap: viewportWidth < 768 ? \"wrap\" : \"nowrap\",\n gap: `${8 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n flexWrap: viewportWidth < 480 ? \"wrap\" : \"nowrap\"\n },\n children: [\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: handlePlayPause,\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n backdropFilter: \"blur(12px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${10 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n minWidth: `${48 * responsiveScale}px`,\n minHeight: `${48 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n target.style.boxShadow = \"0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n target.style.boxShadow = \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n },\n title: isPlaying ? \"Pause\" : \"Play\",\n children: isPlaying ? /* @__PURE__ */ jsx(\n FaPause,\n {\n size: Math.max(16, 20 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n ) : /* @__PURE__ */ jsx(\n FaPlay,\n {\n size: Math.max(16, 20 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n )\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\"\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: () => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: isMuted ? \"Unmute\" : \"Mute\",\n children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(\n FaVolumeMute,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n ) : volume < 0.5 ? /* @__PURE__ */ jsx(\n FaVolumeDown,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n ) : /* @__PURE__ */ jsx(\n FaVolumeUp,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n )\n }\n ),\n showVolumeSlider && /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false)\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(15px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\",\n zIndex: 10,\n transition: \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)\";\n e.currentTarget.style.borderColor = \"rgba(59, 130, 246, 0.4)\";\n },\n onMouseLeave: (e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\";\n e.currentTarget.style.borderColor = \"rgba(255, 255, 255, 0.15)\";\n },\n children: /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n },\n onMouseLeave: (e) => {\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n const handleMouseMove = (moveEvent) => {\n if (!sliderElement) return;\n const rect2 = sliderElement.getBoundingClientRect();\n const y2 = moveEvent.clientY - rect2.top;\n const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));\n handleVolumeChange(percentage2);\n };\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n const rect = sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n onClick: (e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background: \"linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)\",\n borderRadius: \"4px\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.2)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)\",\n borderRadius: \"4px\",\n transition: \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow: \"0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 7px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"14px\",\n height: \"14px\",\n background: \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n boxShadow: \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\",\n transition: \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.boxShadow = \"0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)\";\n e.currentTarget.style.cursor = \"grab\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.boxShadow = \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\";\n },\n onMouseDown: (e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n },\n onMouseUp: (e) => {\n e.currentTarget.style.cursor = \"grab\";\n }\n }\n )\n ]\n }\n )\n }\n )\n ] })\n ]\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\"\n },\n children: [\n formatTime(currentTime),\n \" / \",\n formatTime(duration)\n ]\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: viewportWidth < 600 ? \"none\" : \"block\"\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"button\",\n {\n onClick: () => setShowSpeedMenu(!showSpeedMenu),\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n borderRadius: `${14 * responsiveScale}px`,\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n fontWeight: \"700\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${56 * responsiveScale}px`,\n minHeight: `${40 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: \"Playback Speed\",\n children: [\n playbackRate,\n \"x\"\n ]\n }\n ),\n showSpeedMenu && /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n right: 0,\n marginBottom: \"12px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)\",\n backdropFilter: \"blur(20px)\",\n borderRadius: \"12px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"90px\",\n boxShadow: \"0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)\"\n },\n children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(\n (speed) => /* @__PURE__ */ jsxs(\n \"button\",\n {\n onClick: () => handlePlaybackRateChange(speed),\n style: {\n display: \"block\",\n width: \"100%\",\n padding: \"10px 16px\",\n background: playbackRate === speed ? \"linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)\" : \"transparent\",\n border: \"none\",\n color: \"white\",\n cursor: \"pointer\",\n fontSize: \"13px\",\n fontFamily: \"monospace\",\n fontWeight: \"600\",\n textAlign: \"center\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n borderBottom: speed !== 2 ? \"1px solid rgba(255, 255, 255, 0.05)\" : \"none\"\n },\n onMouseEnter: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)\";\n }\n },\n onMouseLeave: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"transparent\";\n }\n },\n children: [\n speed,\n \"x\"\n ]\n },\n speed\n )\n )\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen ? /* @__PURE__ */ jsx(\n FaCompress,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n ) : /* @__PURE__ */ jsx(\n FaExpand,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n )\n }\n )\n ]\n }\n )\n ]\n }\n )\n ]\n }\n ) }) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n transform: \"none\",\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n gap: `${10 * responsiveScale}px`,\n zIndex: 10\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\"\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: () => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow: \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`\n },\n title: isMuted ? \"Unmute\" : \"Mute\",\n children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(\n FaVolumeMute,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : volume < 0.5 ? /* @__PURE__ */ jsx(\n FaVolumeDown,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : /* @__PURE__ */ jsx(\n FaVolumeUp,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n )\n }\n ),\n showVolumeSlider && /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false)\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(20px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.7)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\",\n zIndex: 10,\n transition: \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)\";\n e.currentTarget.style.borderColor = \"rgba(96, 165, 250, 0.8)\";\n },\n onMouseLeave: (e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\";\n e.currentTarget.style.borderColor = \"rgba(255, 255, 255, 0.7)\";\n },\n children: /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\"\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n const handleMouseMove = (moveEvent) => {\n if (!sliderElement) return;\n const rect2 = sliderElement.getBoundingClientRect();\n const y2 = moveEvent.clientY - rect2.top;\n const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));\n handleVolumeChange(percentage2);\n };\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n const rect = sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n onClick: (e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background: \"linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)\",\n borderRadius: \"4px\",\n border: \"1px solid rgba(255, 255, 255, 0.4)\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.3)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)\",\n borderRadius: \"4px\",\n transition: \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow: \"0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 8px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"16px\",\n height: \"16px\",\n background: \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n border: \"2px solid rgba(96, 165, 250, 0.9)\",\n boxShadow: \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\",\n transition: \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.boxShadow = \"0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)\";\n e.currentTarget.style.cursor = \"grab\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.boxShadow = \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\";\n },\n onMouseDown: (e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n },\n onMouseUp: (e) => {\n e.currentTarget.style.cursor = \"grab\";\n }\n }\n )\n ]\n }\n )\n }\n )\n ] })\n ]\n }\n ),\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow: \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`\n },\n title: isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen ? /* @__PURE__ */ jsx(\n FaCompress,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : /* @__PURE__ */ jsx(\n FaExpand,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n )\n }\n )\n ]\n }\n ),\n onControlClick && /* @__PURE__ */ jsx(\n \"div\",\n {\n onClick: onControlClick,\n style: {\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 1,\n cursor: \"pointer\"\n }\n }\n )\n ]\n }\n )\n ] });\n },\n (prevProps, nextProps) => {\n for (const prop of CRITICAL_PROPS) {\n if (prevProps[prop] !== nextProps[prop]) {\n return false;\n }\n }\n const uiProps = [\n \"autoplay\",\n \"muted\",\n \"controls\",\n \"showCustomControls\",\n \"className\",\n \"style\",\n \"wrapperClassName\",\n \"wrapperStyle\",\n \"playsInline\",\n \"preload\",\n \"poster\",\n \"children\"\n ];\n for (const prop of uiProps) {\n if (prevProps[prop] !== nextProps[prop]) {\n return false;\n }\n }\n const callbackProps = [\n \"onReady\",\n \"onVolumeToggle\",\n \"onFullscreenToggle\",\n \"onControlClick\"\n ];\n for (const prop of callbackProps) {\n if (prevProps[prop] !== nextProps[prop]) {\n return false;\n }\n }\n return true;\n }\n);\n\n// src/StormcloudPlayer.tsx\nimport React3, { Component as Component4, Suspense } from \"react\";\n\n// src/props.ts\nvar noop = () => {\n};\nvar defaultProps = {\n playing: false,\n loop: false,\n controls: true,\n volume: 1,\n muted: false,\n playbackRate: 1,\n width: \"100%\",\n height: \"auto\",\n style: {},\n progressInterval: 1e3,\n playsInline: false,\n autoplay: false,\n preload: \"metadata\",\n poster: \"\",\n className: \"\",\n wrapperClassName: \"\",\n wrapperStyle: {},\n allowNativeHls: false,\n lowLatencyMode: false,\n driftToleranceMs: 1e3,\n immediateManifestAds: true,\n debugAdTiming: false,\n showCustomControls: false,\n hideLoadingIndicator: false,\n licenseKey: \"\",\n adFailsafeTimeoutMs: 1e4,\n minSegmentsBeforePlay: 2,\n onStart: noop,\n onPlay: noop,\n onPause: noop,\n onBuffer: noop,\n onBufferEnd: noop,\n onEnded: noop,\n onError: noop,\n onDuration: noop,\n onSeek: noop,\n onProgress: noop,\n onVolumeToggle: noop,\n onFullscreenToggle: noop,\n onControlClick: noop\n};\n\n// src/utils.ts\nimport { lazy as reactLazy } from \"react\";\nvar lazy = reactLazy;\nvar omit = (object, keys) => {\n const result = { ...object };\n keys.forEach((key) => {\n delete result[key];\n });\n return result;\n};\nvar isMediaStream = (url) => {\n return typeof window !== \"undefined\" && window.MediaStream && url instanceof window.MediaStream;\n};\nvar supportsWebKitPresentationMode = () => {\n if (typeof window === \"undefined\") return false;\n const video = document.createElement(\"video\");\n return \"webkitSupportsPresentationMode\" in video;\n};\nvar randomString = () => {\n return Math.random().toString(36).substr(2, 9);\n};\nvar parseQuery = (url) => {\n const query = {};\n const queryString = url.split(\"?\")[1] || \"\";\n if (!queryString) return query;\n const manualParse = (qs) => {\n qs.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n try {\n query[decodeURIComponent(key)] = value ? decodeURIComponent(value.replace(/\\+/g, \" \")) : \"\";\n } catch (e) {\n query[key] = value || \"\";\n }\n }\n });\n };\n if (typeof URLSearchParams !== \"undefined\") {\n try {\n const params = new URLSearchParams(queryString);\n params.forEach((value, key) => {\n query[key] = value;\n });\n return query;\n } catch (e) {\n manualParse(queryString);\n }\n } else {\n manualParse(queryString);\n }\n return query;\n};\nvar merge = (target, ...sources) => {\n if (!sources.length) return target;\n const source = sources.shift();\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n merge(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n return merge(target, ...sources);\n};\nvar isObject = (item) => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\nvar IS_BROWSER = typeof window !== \"undefined\" && window.document;\nvar IS_GLOBAL = typeof globalThis !== \"undefined\" && globalThis.window && globalThis.window.document;\nvar IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(navigator.userAgent);\nvar IS_SAFARI = IS_BROWSER && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\nvar SUPPORTS_HLS = () => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/vnd.apple.mpegurl\"));\n};\nvar SUPPORTS_DASH = () => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/dash+xml\"));\n};\n\n// src/patterns.ts\nvar HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nvar HLS_PATHS = /\\/hls\\//i;\nvar DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nvar VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nvar AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\nvar canPlay = {\n hls: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n dash: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n video: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n audio: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n file: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n }\n};\n\n// src/players/HlsPlayer.tsx\nimport { Component } from \"react\";\nvar HlsPlayer = class extends Component {\n constructor() {\n super(...arguments);\n this.player = null;\n this.mounted = false;\n this.load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n const config = {\n src: this.props.src,\n videoElement: this.props.videoElement\n };\n if (this.props.autoplay !== void 0)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== void 0)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== void 0)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== void 0)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== void 0)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== void 0)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== void 0)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== void 0)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== void 0)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== void 0)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== void 0)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== void 0)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== void 0)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n this.player = new StormcloudVideoPlayer(config);\n this.props.onMount?.(this);\n await this.player.load();\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return this.player.hls;\n return null;\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nHlsPlayer.displayName = \"HlsPlayer\";\nHlsPlayer.canPlay = canPlay.hls;\n\n// src/players/FilePlayer.tsx\nimport { Component as Component2 } from \"react\";\nvar FilePlayer = class extends Component2 {\n constructor() {\n super(...arguments);\n this.mounted = false;\n this.ready = false;\n this.load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n const video = this.props.videoElement;\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n const handleError = (error) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\n };\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.src = this.props.src;\n if (this.props.autoplay !== void 0) video.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) video.muted = this.props.muted;\n if (this.props.loop !== void 0) video.loop = this.props.loop;\n if (this.props.controls !== void 0) video.controls = this.props.controls;\n if (this.props.playsInline !== void 0)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== void 0)\n video.preload = this.props.preload;\n if (this.props.poster !== void 0) video.poster = this.props.poster;\n this.props.onMount?.(this);\n return () => {\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n };\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[FilePlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n } else {\n console.warn(\"[FilePlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.setLoop = (loop) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n this.enablePIP = async () => {\n if (this.props.videoElement && \"requestPictureInPicture\" in this.props.videoElement) {\n try {\n await this.props.videoElement.requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n this.disablePIP = async () => {\n if (document.pictureInPictureElement) {\n try {\n await document.exitPictureInPicture();\n } catch (error) {\n console.warn(\"Exit Picture-in-Picture failed:\", error);\n }\n }\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nFilePlayer.displayName = \"FilePlayer\";\nFilePlayer.canPlay = canPlay.file;\n\n// src/players/index.ts\nvar players = [\n {\n key: \"hls\",\n name: \"HLS Player\",\n canPlay: canPlay.hls,\n lazyPlayer: lazy(() => Promise.resolve({ default: HlsPlayer }))\n },\n {\n key: \"file\",\n name: \"File Player\",\n canPlay: canPlay.file,\n canEnablePIP: (url) => {\n return canPlay.file(url) && (document.pictureInPictureEnabled || typeof document.webkitSupportsPresentationMode === \"function\");\n },\n lazyPlayer: lazy(() => Promise.resolve({ default: FilePlayer }))\n }\n];\nvar players_default = players;\n\n// src/Player.tsx\nimport React2, { Component as Component3 } from \"react\";\nvar SEEK_ON_PLAY_EXPIRY = 5e3;\nvar Player = class extends Component3 {\n constructor() {\n super(...arguments);\n this.mounted = false;\n this.isReady = false;\n this.isPlaying = false;\n this.isLoading = true;\n this.loadOnReady = null;\n this.startOnPlay = true;\n this.seekOnPlay = null;\n this.onDurationCalled = false;\n this.handlePlayerMount = (player) => {\n if (this.player) {\n this.progress();\n return;\n }\n this.player = player;\n this.player.load(this.props.src);\n this.progress();\n };\n this.getInternalPlayer = (key) => {\n if (!this.player) return null;\n return this.player.getInternalPlayer(key);\n };\n this.progress = () => {\n if (this.props.src && this.player && this.isReady) {\n const playedSeconds = this.getCurrentTime() || 0;\n const loadedSeconds = this.getSecondsLoaded();\n const duration = this.getDuration();\n if (duration) {\n const progress = {\n playedSeconds,\n played: playedSeconds / duration,\n loaded: 0,\n loadedSeconds: 0\n };\n if (loadedSeconds !== null) {\n progress.loadedSeconds = loadedSeconds;\n progress.loaded = loadedSeconds / duration;\n }\n if (progress.playedSeconds !== this.prevPlayed || progress.loadedSeconds !== this.prevLoaded) {\n this.props.onProgress?.(progress);\n }\n this.prevPlayed = progress.playedSeconds;\n this.prevLoaded = progress.loadedSeconds;\n }\n }\n this.progressTimeout = window.setTimeout(\n this.progress,\n this.props.progressInterval || 1e3\n );\n };\n this.handleReady = () => {\n if (!this.mounted) return;\n this.isReady = true;\n this.isLoading = false;\n const { onReady, playing, volume, muted } = this.props;\n onReady();\n if (!muted && volume !== null) {\n this.player.setVolume(volume);\n }\n if (this.loadOnReady) {\n this.player.load(this.loadOnReady, true);\n this.loadOnReady = null;\n } else if (playing) {\n this.player.play();\n }\n this.handleDurationCheck();\n };\n this.handlePlay = () => {\n this.isPlaying = true;\n this.isLoading = false;\n const { onStart, onPlay, playbackRate } = this.props;\n if (this.startOnPlay) {\n if (this.player.setPlaybackRate && playbackRate !== 1) {\n this.player.setPlaybackRate(playbackRate);\n }\n onStart?.();\n this.startOnPlay = false;\n }\n onPlay?.();\n if (this.seekOnPlay) {\n this.seekTo(this.seekOnPlay);\n this.seekOnPlay = null;\n }\n this.handleDurationCheck();\n };\n this.handlePause = (e) => {\n this.isPlaying = false;\n if (!this.isLoading) {\n this.props.onPause?.(e);\n }\n };\n this.handleEnded = () => {\n const { activePlayer, loop, onEnded } = this.props;\n if (activePlayer.loopOnEnded && loop) {\n this.seekTo(0);\n }\n if (!loop) {\n this.isPlaying = false;\n onEnded?.();\n }\n };\n this.handleError = (...args) => {\n this.isLoading = false;\n this.props.onError?.(args[0], args[1], args[2], args[3]);\n };\n this.handleDurationCheck = () => {\n clearTimeout(this.durationCheckTimeout);\n const duration = this.getDuration();\n if (duration) {\n if (!this.onDurationCalled) {\n this.props.onDuration?.(duration);\n this.onDurationCalled = true;\n }\n } else {\n this.durationCheckTimeout = window.setTimeout(\n this.handleDurationCheck,\n 100\n );\n }\n };\n this.handleLoaded = () => {\n this.isLoading = false;\n };\n }\n componentDidMount() {\n this.mounted = true;\n }\n componentWillUnmount() {\n clearTimeout(this.progressTimeout);\n clearTimeout(this.durationCheckTimeout);\n this.mounted = false;\n }\n componentDidUpdate(prevProps) {\n if (!this.player) return;\n const { src, playing, volume, muted, playbackRate, loop, activePlayer } = this.props;\n if (prevProps.src !== src) {\n if (this.isLoading && !activePlayer.forceLoad && !isMediaStream(src)) {\n console.warn(\n `StormcloudPlayer: the attempt to load ${src} is being deferred until the player has loaded`\n );\n this.loadOnReady = src || null;\n return;\n }\n this.isLoading = true;\n this.startOnPlay = true;\n this.onDurationCalled = false;\n this.player.load(src, this.isReady);\n }\n if (!prevProps.playing && playing && !this.isPlaying) {\n this.player.play();\n }\n if (prevProps.playing && !playing && this.isPlaying) {\n this.player.pause();\n }\n if (prevProps.volume !== volume && volume !== null) {\n this.player.setVolume(volume);\n }\n if (prevProps.muted !== muted) {\n if (muted) {\n this.player.mute();\n } else {\n this.player.unmute();\n if (volume !== null) {\n setTimeout(() => this.player.setVolume(volume));\n }\n }\n }\n if (prevProps.playbackRate !== playbackRate && this.player.setPlaybackRate) {\n this.player.setPlaybackRate(playbackRate);\n }\n if (prevProps.loop !== loop && this.player.setLoop) {\n this.player.setLoop(loop);\n }\n }\n getDuration() {\n if (!this.isReady) return null;\n return this.player.getDuration();\n }\n getCurrentTime() {\n if (!this.isReady) return null;\n return this.player.getCurrentTime();\n }\n getSecondsLoaded() {\n if (!this.isReady) return null;\n return this.player.getSecondsLoaded();\n }\n seekTo(amount, type, keepPlaying) {\n if (!this.isReady) {\n if (amount !== 0) {\n this.seekOnPlay = amount;\n setTimeout(() => {\n this.seekOnPlay = null;\n }, SEEK_ON_PLAY_EXPIRY);\n }\n return;\n }\n const isFraction = !type ? amount > 0 && amount < 1 : type === \"fraction\";\n if (isFraction) {\n const duration = this.player.getDuration();\n if (!duration) {\n console.warn(\n \"StormcloudPlayer: could not seek using fraction \\u2013 duration not yet available\"\n );\n return;\n }\n this.player.seekTo(duration * amount, keepPlaying);\n return;\n }\n this.player.seekTo(amount, keepPlaying);\n }\n render() {\n const Player2 = this.props.activePlayer;\n if (!Player2) {\n return null;\n }\n return React2.createElement(Player2, {\n ...this.props,\n onMount: this.handlePlayerMount,\n onReady: this.handleReady,\n onPlay: this.handlePlay,\n onPause: this.handlePause,\n onEnded: this.handleEnded,\n onLoaded: this.handleLoaded,\n onError: this.handleError\n });\n }\n};\nPlayer.displayName = \"Player\";\nPlayer.defaultProps = defaultProps;\n\n// src/StormcloudPlayer.tsx\nvar IS_BROWSER2 = typeof window !== \"undefined\" && window.document;\nvar IS_GLOBAL2 = typeof globalThis !== \"undefined\" && globalThis.window && globalThis.window.document;\nvar UniversalSuspense = IS_BROWSER2 || IS_GLOBAL2 ? Suspense : () => null;\nvar SUPPORTED_PROPS = [\n \"src\",\n \"playing\",\n \"loop\",\n \"controls\",\n \"volume\",\n \"muted\",\n \"playbackRate\",\n \"width\",\n \"height\",\n \"style\",\n \"progressInterval\",\n \"playsInline\",\n \"autoplay\",\n \"preload\",\n \"poster\",\n \"className\",\n \"wrapperClassName\",\n \"wrapperStyle\",\n \"allowNativeHls\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"immediateManifestAds\",\n \"debugAdTiming\",\n \"showCustomControls\",\n \"licenseKey\",\n \"adFailsafeTimeoutMs\",\n \"minSegmentsBeforePlay\",\n \"onReady\",\n \"onStart\",\n \"onPlay\",\n \"onPause\",\n \"onBuffer\",\n \"onBufferEnd\",\n \"onEnded\",\n \"onError\",\n \"onDuration\",\n \"onSeek\",\n \"onProgress\",\n \"onVolumeToggle\",\n \"onFullscreenToggle\",\n \"onControlClick\"\n];\nvar customPlayers = [];\nvar createStormcloudPlayer = (playerList, fallback) => {\n var _a;\n return _a = class extends Component4 {\n constructor() {\n super(...arguments);\n this.state = {\n showPreview: false\n };\n this.references = {\n wrapper: (wrapper) => {\n this.wrapper = wrapper;\n },\n player: (player) => {\n this.player = player;\n }\n };\n this.getActivePlayer = (src) => {\n if (!src) return null;\n for (const player of [...customPlayers, ...playerList]) {\n if (player.canPlay(src)) {\n return player;\n }\n }\n if (fallback) {\n return fallback;\n }\n return null;\n };\n this.getAttributes = (src) => {\n return omit(this.props, SUPPORTED_PROPS);\n };\n this.handleReady = () => {\n this.props.onReady?.(this);\n };\n this.seekTo = (fraction, type, keepPlaying) => {\n if (!this.player) return null;\n this.player.seekTo(fraction, type, keepPlaying);\n };\n this.getCurrentTime = () => {\n if (!this.player) return null;\n return this.player.getCurrentTime();\n };\n this.getSecondsLoaded = () => {\n if (!this.player) return null;\n return this.player.getSecondsLoaded();\n };\n this.getDuration = () => {\n if (!this.player) return null;\n return this.player.getDuration();\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (!this.player) return null;\n return this.player.getInternalPlayer(key);\n };\n this.renderActivePlayer = (src) => {\n if (!src) return null;\n const activePlayer = this.getActivePlayer(src);\n if (!activePlayer) return null;\n return React3.createElement(Player, {\n ...this.props,\n key: activePlayer.key,\n ref: this.references.player,\n activePlayer: activePlayer.lazyPlayer || activePlayer,\n onReady: this.handleReady\n });\n };\n }\n render() {\n const {\n src,\n style,\n width,\n height,\n fallback: fallbackElement,\n wrapper: Wrapper\n } = this.props;\n const attributes = this.getAttributes(src);\n const wrapperRef = typeof Wrapper === \"string\" ? this.references.wrapper : void 0;\n return React3.createElement(\n Wrapper,\n {\n ref: wrapperRef,\n style: { ...style, width, height },\n ...attributes\n },\n React3.createElement(\n UniversalSuspense,\n { fallback: fallbackElement },\n this.renderActivePlayer(src)\n )\n );\n }\n }, _a.displayName = \"StormcloudPlayer\", _a.defaultProps = {\n ...defaultProps,\n fallback: null,\n wrapper: \"div\"\n }, _a.addCustomPlayer = (player) => {\n customPlayers.push(player);\n }, _a.removeCustomPlayers = () => {\n customPlayers.length = 0;\n }, _a.canPlay = (src) => {\n for (const Player2 of [...customPlayers, ...playerList]) {\n if (Player2.canPlay(src)) {\n return true;\n }\n }\n return false;\n }, _a.canEnablePIP = (src) => {\n for (const Player2 of [...customPlayers, ...playerList]) {\n if (Player2.canEnablePIP && Player2.canEnablePIP(src)) {\n return true;\n }\n }\n return false;\n }, _a;\n};\nvar StormcloudPlayer = createStormcloudPlayer(\n players_default,\n players_default[players_default.length - 1]\n);\nvar StormcloudPlayer_default = StormcloudPlayer;\nexport {\n IS_BROWSER,\n IS_GLOBAL,\n IS_IOS,\n IS_SAFARI,\n SUPPORTS_DASH,\n SUPPORTS_HLS,\n StormcloudPlayer_default as StormcloudPlayer,\n StormcloudVideoPlayer,\n StormcloudVideoPlayerComponent,\n canPlay,\n createHlsAdPlayer,\n createImaController,\n createStormcloudPlayer,\n StormcloudVideoPlayerComponent as default,\n detectBrowser,\n getBrowserConfigOverrides,\n getBrowserID,\n getClientInfo,\n getRecommendedAdPlayer,\n initializePolyfills,\n isMediaStream,\n lazy,\n logBrowserInfo,\n merge,\n omit,\n parseQuery,\n players_default as players,\n randomString,\n sendHeartbeat,\n sendInitialTracking,\n supportsFeature,\n supportsGoogleIMA,\n supportsModernJS,\n supportsWebKitPresentationMode\n};\n","import React, { useEffect, useRef, useMemo } from \"react\";\nimport { StormcloudVideoPlayer } from \"../player/StormcloudVideoPlayer\";\nimport type { StormcloudVideoPlayerConfig } from \"../types\";\nimport {\n FaPlay,\n FaPause,\n FaVolumeUp,\n FaVolumeMute,\n FaVolumeDown,\n FaExpand,\n FaCompress,\n FaSpinner,\n} from \"react-icons/fa\";\n\nexport type StormcloudVideoPlayerProps = Omit<\n StormcloudVideoPlayerConfig,\n \"videoElement\"\n> &\n React.VideoHTMLAttributes<HTMLVideoElement> & {\n onReady?: (player: StormcloudVideoPlayer) => void;\n wrapperClassName?: string;\n wrapperStyle?: React.CSSProperties;\n licenseKey?: string;\n };\n\nconst CRITICAL_PROPS = [\n \"src\",\n \"allowNativeHls\",\n \"licenseKey\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"vastMode\",\n] as const;\n\nexport const StormcloudVideoPlayerComponent: React.FC<StormcloudVideoPlayerProps> =\n React.memo(\n (props) => {\n const {\n src,\n autoplay,\n muted,\n lowLatencyMode,\n allowNativeHls,\n driftToleranceMs,\n immediateManifestAds,\n debugAdTiming,\n showCustomControls,\n hideLoadingIndicator,\n onVolumeToggle,\n onFullscreenToggle,\n onControlClick,\n onReady,\n wrapperClassName,\n wrapperStyle,\n className,\n style,\n controls,\n playsInline,\n preload,\n poster,\n children,\n licenseKey,\n vastMode,\n vastTagUrl,\n adPlayerType,\n minSegmentsBeforePlay,\n ...restVideoAttrs\n } = props;\n\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const playerRef = useRef<StormcloudVideoPlayer | null>(null);\n const bufferingTimeoutRef = useRef<number | null>(null);\n const [adStatus, setAdStatus] = React.useState<{\n showAds: boolean;\n currentIndex: number;\n totalAds: number;\n }>({ showAds: false, currentIndex: 0, totalAds: 0 });\n\n const [shouldShowNativeControls, setShouldShowNativeControls] =\n React.useState(true);\n\n const [isMuted, setIsMuted] = React.useState(false);\n const [isFullscreen, setIsFullscreen] = React.useState(false);\n const [isPlaying, setIsPlaying] = React.useState(false);\n const [currentTime, setCurrentTime] = React.useState(0);\n const [duration, setDuration] = React.useState(0);\n const [volume, setVolume] = React.useState(1);\n const [playbackRate, setPlaybackRate] = React.useState(1);\n const [showVolumeSlider, setShowVolumeSlider] = React.useState(false);\n const [showSpeedMenu, setShowSpeedMenu] = React.useState(false);\n const [isLoading, setIsLoading] = React.useState(true);\n const [isBuffering, setIsBuffering] = React.useState(false);\n const [showCenterPlay, setShowCenterPlay] = React.useState(false);\n const [showLicenseWarning, setShowLicenseWarning] = React.useState(false);\n const [viewportWidth, setViewportWidth] = React.useState(\n typeof window !== \"undefined\" ? window.innerWidth : 1920\n );\n const [isPortrait, setIsPortrait] = React.useState(\n typeof window !== \"undefined\"\n ? window.innerHeight > window.innerWidth\n : false\n );\n\n const getResponsiveScale = () => {\n if (viewportWidth < 480) return 0.7;\n if (viewportWidth < 768) return 0.8;\n if (viewportWidth < 1024) return 0.9;\n return 1;\n };\n\n const responsiveScale = getResponsiveScale();\n\n const formatTime = (seconds: number): string => {\n if (!isFinite(seconds)) return \"0:00:00\";\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n return `${hours}:${minutes\n .toString()\n .padStart(2, \"0\")}:${remainingSeconds.toString().padStart(2, \"0\")}`;\n };\n\n const handlePlayPause = () => {\n if (videoRef.current) {\n if (videoRef.current.paused) {\n const hasValidSource =\n videoRef.current.src ||\n (videoRef.current.currentSrc &&\n videoRef.current.currentSrc !== \"\") ||\n videoRef.current.readyState >= 1;\n\n if (hasValidSource) {\n videoRef.current.play()?.catch((error) => {\n console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n });\n setShowCenterPlay(false);\n } else {\n console.warn(\n \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n );\n }\n } else {\n videoRef.current.pause();\n setShowCenterPlay(true);\n }\n }\n };\n\n const handleCenterPlayClick = () => {\n if (videoRef.current && videoRef.current.paused) {\n const hasValidSource =\n videoRef.current.src ||\n (videoRef.current.currentSrc &&\n videoRef.current.currentSrc !== \"\") ||\n videoRef.current.readyState >= 1;\n\n if (hasValidSource) {\n videoRef.current.play()?.catch((error) => {\n console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n });\n setShowCenterPlay(false);\n } else {\n console.warn(\n \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n );\n }\n }\n };\n\n const handleTimelineSeek = (e: React.MouseEvent<HTMLDivElement>) => {\n if (videoRef.current && duration > 0 && isFinite(duration)) {\n const rect = e.currentTarget.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n const progress = Math.max(0, Math.min(1, clickX / rect.width));\n const newTime = progress * duration;\n\n if (isFinite(newTime) && newTime >= 0 && newTime <= duration) {\n videoRef.current.currentTime = newTime;\n }\n }\n };\n\n const handleVolumeChange = (newVolume: number) => {\n if (playerRef.current && isFinite(newVolume)) {\n const clampedVolume = Math.max(0, Math.min(1, newVolume));\n playerRef.current.setVolume(clampedVolume);\n }\n };\n\n const handlePlaybackRateChange = (rate: number) => {\n if (videoRef.current && isFinite(rate) && rate > 0) {\n videoRef.current.playbackRate = rate;\n }\n setShowSpeedMenu(false);\n };\n\n const isHlsStream =\n src?.toLowerCase().includes(\".m3u8\") ||\n src?.toLowerCase().includes(\"/hls/\");\n const shouldShowEnhancedControls =\n showCustomControls && (isHlsStream ? allowNativeHls : true);\n\n const criticalPropsKey = useMemo(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n licenseKey,\n lowLatencyMode,\n driftToleranceMs,\n vastMode,\n ]);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const el = videoRef.current;\n if (!el || !src) return;\n\n if (!licenseKey) {\n setShowLicenseWarning(true);\n setIsLoading(false);\n console.warn(\n \"StormcloudVideoPlayer: License key is required but not provided. Please set the licenseKey prop to use the player.\"\n );\n return;\n }\n\n setShowLicenseWarning(false);\n\n if (debugAdTiming) {\n console.log(\"[StormcloudUI] Initializing player, isLoading=true\");\n }\n\n if (playerRef.current) {\n try {\n playerRef.current.destroy();\n } catch {}\n playerRef.current = null;\n }\n\n const cfg: StormcloudVideoPlayerConfig = {\n src,\n videoElement: el,\n } as StormcloudVideoPlayerConfig;\n if (autoplay !== undefined) cfg.autoplay = autoplay;\n if (muted !== undefined) cfg.muted = muted;\n if (lowLatencyMode !== undefined) cfg.lowLatencyMode = lowLatencyMode;\n if (allowNativeHls !== undefined) cfg.allowNativeHls = allowNativeHls;\n if (driftToleranceMs !== undefined)\n cfg.driftToleranceMs = driftToleranceMs;\n if (immediateManifestAds !== undefined)\n cfg.immediateManifestAds = immediateManifestAds;\n if (debugAdTiming !== undefined) cfg.debugAdTiming = debugAdTiming;\n if (showCustomControls !== undefined)\n cfg.showCustomControls = showCustomControls;\n if (onVolumeToggle !== undefined) cfg.onVolumeToggle = onVolumeToggle;\n if (onFullscreenToggle !== undefined)\n cfg.onFullscreenToggle = onFullscreenToggle;\n if (onControlClick !== undefined) cfg.onControlClick = onControlClick;\n if (licenseKey !== undefined) cfg.licenseKey = licenseKey;\n if (vastMode !== undefined) cfg.vastMode = vastMode;\n if (vastTagUrl !== undefined) cfg.vastTagUrl = vastTagUrl;\n if (adPlayerType !== undefined) cfg.adPlayerType = adPlayerType;\n if (minSegmentsBeforePlay !== undefined)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n\n const player = new StormcloudVideoPlayer(cfg);\n playerRef.current = player;\n player\n .load()\n .then(() => {\n const showNative = player.shouldShowNativeControls();\n setShouldShowNativeControls(showNative);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Player loaded successfully, waiting for video ready\"\n );\n }\n onReady?.(player);\n })\n .catch((error) => {\n console.error(\n \"StormcloudVideoPlayer: Failed to load player:\",\n error\n );\n setIsLoading(false);\n onReady?.(player);\n });\n\n return () => {\n try {\n player.destroy();\n } catch {}\n playerRef.current = null;\n };\n }, [criticalPropsKey]);\n\n useEffect(() => {\n if (!playerRef.current) return;\n\n try {\n if (autoplay !== undefined && playerRef.current.videoElement) {\n playerRef.current.videoElement.autoplay = autoplay;\n }\n // Only apply muted prop when NOT showing ads to prevent interference with ad audio\n if (muted !== undefined && !playerRef.current.isShowingAds()) {\n playerRef.current.setMuted(muted);\n }\n } catch (error) {\n console.warn(\"Failed to update player properties:\", error);\n }\n }, [autoplay, muted]);\n\n useEffect(() => {\n if (!playerRef.current) return;\n\n const checkAdStatus = () => {\n if (playerRef.current) {\n const showAds = playerRef.current.isShowingAds();\n const currentIndex = playerRef.current.getCurrentAdIndex();\n const totalAds = playerRef.current.getTotalAdsInBreak();\n\n setAdStatus((prev) => {\n if (\n prev.showAds !== showAds ||\n prev.currentIndex !== currentIndex ||\n prev.totalAds !== totalAds\n ) {\n return { showAds, currentIndex, totalAds };\n }\n return prev;\n });\n }\n };\n\n const interval = setInterval(checkAdStatus, 100);\n return () => clearInterval(interval);\n }, []);\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !playerRef.current) return;\n\n const handleResize = () => {\n if (playerRef.current && videoRef.current) {\n if (typeof playerRef.current.resize === \"function\") {\n playerRef.current.resize();\n }\n }\n setViewportWidth(window.innerWidth);\n setIsPortrait(window.innerHeight > window.innerWidth);\n };\n\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n useEffect(() => {\n if (!playerRef.current || !videoRef.current) return;\n\n const updateStates = () => {\n if (playerRef.current && videoRef.current) {\n setIsMuted(playerRef.current.isMuted());\n setIsPlaying(!videoRef.current.paused);\n\n const currentTimeValue = videoRef.current.currentTime;\n setCurrentTime(isFinite(currentTimeValue) ? currentTimeValue : 0);\n\n const durationValue = videoRef.current.duration;\n setDuration(isFinite(durationValue) ? durationValue : 0);\n\n const volumeValue = videoRef.current.volume;\n setVolume(\n isFinite(volumeValue) ? Math.max(0, Math.min(1, volumeValue)) : 1\n );\n\n const rateValue = videoRef.current.playbackRate;\n setPlaybackRate(\n isFinite(rateValue) && rateValue > 0 ? rateValue : 1\n );\n }\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\n );\n };\n\n const interval = setInterval(updateStates, 200);\n\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\n );\n };\n\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n\n return () => {\n clearInterval(interval);\n document.removeEventListener(\n \"fullscreenchange\",\n handleFullscreenChange\n );\n };\n }, []);\n\n useEffect(() => {\n if (!videoRef.current) return;\n\n const handleLoadedMetadata = () => {\n if (videoRef.current) {\n const video = videoRef.current;\n void video.offsetHeight;\n }\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadedmetadata, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n\n const handleLoadedData = () => {\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadeddata, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n\n const handleLoadStart = () => {\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadstart, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n\n const handleCanPlay = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: canplay, readyState:\",\n videoRef.current?.readyState,\n \"- clearing loading state, isLoading=false\"\n );\n }\n };\n\n const handleCanPlayThrough = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: canplaythrough, readyState:\",\n videoRef.current?.readyState,\n \"- clearing loading state, isLoading=false\"\n );\n }\n };\n\n const handleWaiting = () => {\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n }\n\n bufferingTimeoutRef.current = window.setTimeout(() => {\n setIsBuffering(true);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video buffering detected (after 300ms delay), readyState:\",\n videoRef.current?.readyState,\n \"- showing spinner, isBuffering=true\"\n );\n }\n }, 300);\n\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: waiting, readyState:\",\n videoRef.current?.readyState,\n \"- buffering delay started (300ms)\"\n );\n }\n };\n\n const handlePlaying = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n setShowCenterPlay(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: playing, readyState:\",\n videoRef.current?.readyState,\n \"- playback started, isLoading=false, isBuffering=false\"\n );\n }\n };\n\n const handlePause = () => {\n if (playerRef.current && !playerRef.current.isShowingAds()) {\n setShowCenterPlay(true);\n } else {\n setShowCenterPlay(false);\n }\n };\n\n const handleEnded = () => {\n setShowCenterPlay(true);\n };\n\n const video = videoRef.current;\n video.addEventListener(\"loadstart\", handleLoadStart);\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.addEventListener(\"canplay\", handleCanPlay);\n video.addEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.addEventListener(\"waiting\", handleWaiting);\n video.addEventListener(\"playing\", handlePlaying);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n\n if (video.paused) {\n setShowCenterPlay(true);\n }\n\n return () => {\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n\n video.removeEventListener(\"loadstart\", handleLoadStart);\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n video.removeEventListener(\"canplay\", handleCanPlay);\n video.removeEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.removeEventListener(\"waiting\", handleWaiting);\n video.removeEventListener(\"playing\", handlePlaying);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n };\n }, [debugAdTiming]);\n\n return (\n <>\n <style>\n {`\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n \n .stormcloud-loading-hidden .stormcloud-loading-indicator {\n display: none !important;\n }\n \n .stormcloud-video-wrapper:fullscreen {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n \n .stormcloud-video-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n \n *:fullscreen {\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n }\n `}\n </style>\n <div\n className={`stormcloud-video-wrapper ${wrapperClassName || \"\"}`}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n position: isFullscreen ? \"fixed\" : \"relative\",\n top: isFullscreen ? 0 : undefined,\n left: isFullscreen ? 0 : undefined,\n overflow: \"hidden\",\n width: isFullscreen ? \"100vw\" : \"100%\",\n height: isFullscreen ? \"100vh\" : \"auto\",\n minHeight: isFullscreen ? \"100vh\" : \"auto\",\n maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : undefined,\n backgroundColor: isFullscreen ? \"#000\" : undefined,\n borderRadius: isFullscreen ? 0 : undefined,\n boxShadow: isFullscreen ? \"none\" : undefined,\n ...wrapperStyle,\n }}\n >\n <video\n ref={videoRef}\n className={className}\n style={{\n display: \"block\",\n width: \"100%\",\n height: isFullscreen ? \"100%\" : \"auto\",\n maxWidth: \"100%\",\n maxHeight: isFullscreen ? \"100%\" : \"none\",\n objectFit: isFullscreen ? \"cover\" : \"contain\",\n backgroundColor: \"#000\",\n aspectRatio: isFullscreen ? \"unset\" : undefined,\n ...style,\n }}\n controls={\n shouldShowNativeControls && controls && !showCustomControls\n }\n playsInline={playsInline}\n preload={preload}\n poster={poster}\n {...restVideoAttrs}\n >\n {children}\n </video>\n\n {(isLoading || isBuffering) && !hideLoadingIndicator && (\n <FaSpinner\n className=\"stormcloud-loading-indicator\"\n size={42}\n color=\"white\"\n style={{\n position: \"absolute\",\n top: \"calc(50% - 21px)\",\n left: \"calc(50% - 21px)\",\n zIndex: 20,\n animation: \"spin 1s linear infinite\",\n filter: \"drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))\",\n }}\n />\n )}\n\n {showLicenseWarning && (\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 25,\n background:\n \"linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)\",\n color: \"white\",\n padding: \"24px 32px\",\n borderRadius: \"16px\",\n backdropFilter: \"blur(20px)\",\n border: \"2px solid rgba(255, 255, 255, 0.2)\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\",\n }}\n >\n <div\n style={{\n fontSize: \"20px\",\n fontWeight: \"bold\",\n marginBottom: \"12px\",\n color: \"#ffffff\",\n textShadow: \"0 2px 4px rgba(0, 0, 0, 0.5)\",\n }}\n >\n License Key Required\n </div>\n <div\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.5\",\n color: \"rgba(255, 255, 255, 0.9)\",\n textShadow: \"0 1px 2px rgba(0, 0, 0, 0.3)\",\n }}\n >\n Please provide a valid license key to use the Stormcloud Video\n Player.\n <br />\n Contact your administrator for licensing information.\n </div>\n </div>\n )}\n\n {showCenterPlay &&\n !isLoading &&\n !isBuffering &&\n !showLicenseWarning &&\n !adStatus.showAds && (\n <div\n onClick={handleCenterPlayClick}\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 15,\n cursor: \"pointer\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\",\n borderRadius: \"50%\",\n width: \"100px\",\n height: \"100px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n border: \"3px solid rgba(255, 255, 255, 0.8)\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLElement;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)\";\n target.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.9)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLElement;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\";\n target.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.8)\";\n }}\n title=\"Play\"\n >\n <FaPlay\n size={36}\n color=\"white\"\n style={{\n marginLeft: \"6px\",\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n }}\n />\n </div>\n )}\n\n {shouldShowEnhancedControls && !showLicenseWarning ? (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background:\n \"linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)\",\n padding: \"20px 16px 16px\",\n zIndex: 10,\n }}\n >\n <div\n style={{\n width: \"100%\",\n height: \"8px\",\n background:\n \"linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)\",\n borderRadius: \"8px\",\n marginBottom: \"16px\",\n cursor: \"pointer\",\n position: \"relative\",\n backdropFilter: \"blur(5px)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"inset 0 2px 4px rgba(0, 0, 0, 0.2)\",\n }}\n onClick={handleTimelineSeek}\n >\n <div\n style={{\n height: \"100%\",\n background:\n \"linear-gradient(90deg, rgba(139, 92, 246, 0.9) 0%, rgba(59, 130, 246, 0.8) 50%, rgba(34, 197, 94, 0.9) 100%)\",\n borderRadius: \"8px\",\n width: `${\n duration > 0 ? (currentTime / duration) * 100 : 0\n }%`,\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 2px 8px rgba(139, 92, 246, 0.4)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n top: \"-6px\",\n right: `${\n duration > 0\n ? 100 - (currentTime / duration) * 100\n : 100\n }%`,\n width: \"20px\",\n height: \"20px\",\n background:\n \"linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)\",\n borderRadius: \"50%\",\n border: \"3px solid rgba(139, 92, 246, 0.8)\",\n boxShadow:\n \"0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)\",\n transform: \"translateX(50%)\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n />\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n flexWrap: viewportWidth < 768 ? \"wrap\" : \"nowrap\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n flexWrap: viewportWidth < 480 ? \"wrap\" : \"nowrap\",\n }}\n >\n <button\n onClick={handlePlayPause}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n backdropFilter: \"blur(12px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${10 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n minWidth: `${48 * responsiveScale}px`,\n minHeight: `${48 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n target.style.boxShadow =\n \"0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n target.style.boxShadow =\n \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n }}\n title={isPlaying ? \"Pause\" : \"Play\"}\n >\n {isPlaying ? (\n <FaPause\n size={Math.max(16, 20 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n ) : (\n <FaPlay\n size={Math.max(16, 20 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n )}\n </button>\n\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\",\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n onClick={() => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n {isMuted || volume === 0 ? (\n <FaVolumeMute\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n ) : volume < 0.5 ? (\n <FaVolumeDown\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n ) : (\n <FaVolumeUp\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n )}\n </button>\n\n {showVolumeSlider && (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(15px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\",\n zIndex: 10,\n transition:\n \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)\";\n e.currentTarget.style.borderColor =\n \"rgba(59, 130, 246, 0.4)\";\n }}\n onMouseLeave={(e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\";\n e.currentTarget.style.borderColor =\n \"rgba(255, 255, 255, 0.15)\";\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n // Hover effect removed\n }}\n onMouseLeave={(e) => {\n // Hover effect removed\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n\n const handleMouseMove = (\n moveEvent: MouseEvent\n ) => {\n if (!sliderElement) return;\n const rect =\n sliderElement.getBoundingClientRect();\n const y = moveEvent.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n };\n\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n\n const rect =\n sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n onClick={(e) => {\n e.stopPropagation();\n const rect =\n e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background:\n \"linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)\",\n borderRadius: \"4px\",\n boxShadow:\n \"inset 0 1px 3px rgba(0, 0, 0, 0.2)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background:\n \"linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)\",\n borderRadius: \"4px\",\n transition:\n \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow:\n \"0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: `calc(${\n (isMuted ? 0 : volume) * 100\n }% - 7px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"14px\",\n height: \"14px\",\n background:\n \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n boxShadow:\n \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\",\n transition:\n \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)\";\n e.currentTarget.style.cursor = \"grab\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n }}\n onMouseUp={(e) => {\n e.currentTarget.style.cursor = \"grab\";\n }}\n />\n </div>\n </div>\n </>\n )}\n </div>\n\n <div\n style={{\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\",\n }}\n >\n {formatTime(currentTime)} / {formatTime(duration)}\n </div>\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n }}\n >\n <div\n style={{\n position: \"relative\",\n display: viewportWidth < 600 ? \"none\" : \"block\",\n }}\n >\n <button\n onClick={() => setShowSpeedMenu(!showSpeedMenu)}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px ${\n 14 * responsiveScale\n }px`,\n borderRadius: `${14 * responsiveScale}px`,\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n fontWeight: \"700\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${56 * responsiveScale}px`,\n minHeight: `${40 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title=\"Playback Speed\"\n >\n {playbackRate}x\n </button>\n\n {showSpeedMenu && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n right: 0,\n marginBottom: \"12px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)\",\n backdropFilter: \"blur(20px)\",\n borderRadius: \"12px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"90px\",\n boxShadow:\n \"0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)\",\n }}\n >\n {[0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(\n (speed) => (\n <button\n key={speed}\n onClick={() =>\n handlePlaybackRateChange(speed)\n }\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"10px 16px\",\n background:\n playbackRate === speed\n ? \"linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)\"\n : \"transparent\",\n border: \"none\",\n color: \"white\",\n cursor: \"pointer\",\n fontSize: \"13px\",\n fontFamily: \"monospace\",\n fontWeight: \"600\",\n textAlign: \"center\",\n transition:\n \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n borderBottom:\n speed !== 2\n ? \"1px solid rgba(255, 255, 255, 0.05)\"\n : \"none\",\n }}\n onMouseEnter={(e) => {\n if (playbackRate !== speed) {\n (\n e.target as HTMLElement\n ).style.background =\n \"linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)\";\n }\n }}\n onMouseLeave={(e) => {\n if (playbackRate !== speed) {\n (\n e.target as HTMLElement\n ).style.background = \"transparent\";\n }\n }}\n >\n {speed}x\n </button>\n )\n )}\n </div>\n )}\n </div>\n\n <button\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current\n .toggleFullscreen()\n .catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title={\n isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"\n }\n >\n {isFullscreen ? (\n <FaCompress\n size={Math.max(14, 16 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n ) : (\n <FaExpand\n size={Math.max(14, 16 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n )}\n </button>\n </div>\n </div>\n </div>\n </>\n ) : (\n showCustomControls &&\n !showLicenseWarning && (\n <div\n style={{\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n transform: \"none\",\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n gap: `${10 * responsiveScale}px`,\n zIndex: 10,\n }}\n >\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\",\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n onClick={() => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow:\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`,\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n {isMuted || volume === 0 ? (\n <FaVolumeMute\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : volume < 0.5 ? (\n <FaVolumeDown\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : (\n <FaVolumeUp\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n )}\n </button>\n\n {showVolumeSlider && (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(20px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.7)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\",\n zIndex: 10,\n transition:\n \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)\";\n e.currentTarget.style.borderColor =\n \"rgba(96, 165, 250, 0.8)\";\n }}\n onMouseLeave={(e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\";\n e.currentTarget.style.borderColor =\n \"rgba(255, 255, 255, 0.7)\";\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\",\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n\n const handleMouseMove = (\n moveEvent: MouseEvent\n ) => {\n if (!sliderElement) return;\n const rect =\n sliderElement.getBoundingClientRect();\n const y = moveEvent.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n };\n\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n\n const rect =\n sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n onClick={(e) => {\n e.stopPropagation();\n const rect =\n e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background:\n \"linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)\",\n borderRadius: \"4px\",\n border: \"1px solid rgba(255, 255, 255, 0.4)\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.3)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background:\n \"linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)\",\n borderRadius: \"4px\",\n transition:\n \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow:\n \"0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: `calc(${\n (isMuted ? 0 : volume) * 100\n }% - 8px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"16px\",\n height: \"16px\",\n background:\n \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n border: \"2px solid rgba(96, 165, 250, 0.9)\",\n boxShadow:\n \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\",\n transition:\n \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)\";\n e.currentTarget.style.cursor = \"grab\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n }}\n onMouseUp={(e) => {\n e.currentTarget.style.cursor = \"grab\";\n }}\n />\n </div>\n </div>\n </>\n )}\n </div>\n\n <button\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow:\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`,\n }}\n title={\n isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"\n }\n >\n {isFullscreen ? (\n <FaCompress\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : (\n <FaExpand\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n )}\n </button>\n </div>\n )\n )}\n\n {onControlClick && (\n <div\n onClick={onControlClick}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 1,\n cursor: \"pointer\",\n }}\n />\n )}\n </div>\n </>\n );\n },\n (prevProps, nextProps) => {\n for (const prop of CRITICAL_PROPS) {\n if ((prevProps as any)[prop] !== (nextProps as any)[prop]) {\n return false;\n }\n }\n\n const uiProps = [\n \"autoplay\",\n \"muted\",\n \"controls\",\n \"showCustomControls\",\n \"className\",\n \"style\",\n \"wrapperClassName\",\n \"wrapperStyle\",\n \"playsInline\",\n \"preload\",\n \"poster\",\n \"children\",\n ] as const;\n\n for (const prop of uiProps) {\n if ((prevProps as any)[prop] !== (nextProps as any)[prop]) {\n return false;\n }\n }\n\n const callbackProps = [\n \"onReady\",\n \"onVolumeToggle\",\n \"onFullscreenToggle\",\n \"onControlClick\",\n ] as const;\n for (const prop of callbackProps) {\n if ((prevProps as any)[prop] !== (nextProps as any)[prop]) {\n return false;\n }\n }\n\n return true;\n }\n );\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n ImaController,\n AdBreak,\n StormcloudApiResponse,\n} from \"../types\";\nimport { createImaController } from \"../sdk/ima\";\nimport { createHlsAdPlayer } from \"../sdk/hlsAdPlayer\";\nimport { sendInitialTracking, sendHeartbeat } from \"../utils/tracking\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport {\n supportsGoogleIMA,\n logBrowserInfo,\n getBrowserConfigOverrides,\n} from \"../utils/browserCompat\";\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private ima: ImaController;\n private attached = false;\n private inAdBreak = false;\n private currentAdBreakStartWallClockMs: number | undefined;\n private expectedAdBreakDurationMs: number | undefined;\n private adStopTimerId: number | undefined;\n private adStartTimerId: number | undefined;\n private adFailsafeTimerId: number | undefined;\n private ptsDriftEmaMs = 0;\n private adPodQueue: string[] = [];\n private apiVastTagUrl: string | undefined;\n private apiNumberAds: number | undefined;\n private lastHeartbeatTime: number = 0;\n private heartbeatInterval: number | undefined;\n private currentAdIndex: number = 0;\n private totalAdsInBreak: number = 0;\n private showAds: boolean = false;\n private isLiveStream: boolean = false;\n private nativeHlsMode: boolean = false;\n private videoSrcProtection: string | null = null;\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n private adPodAllUrls: string[] = [];\n private preloadingAdUrls: Set<string> = new Set();\n private vastToMediaUrlMap: Map<string, string[]> = new Map();\n private preloadedMediaUrls: Set<string> = new Set();\n private preloadingMediaUrls: Set<string> = new Set();\n private adRequestTokenCounter = 0;\n private activeAdRequestToken: number | null = null;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n private fetchedAdDurations: Map<string, number> = new Map();\n private targetAdBreakDurationMs: number | null = null;\n private isAdaptiveMode: boolean = false;\n private failedVastUrls: Set<string> = new Set();\n private continuousFetchingActive: boolean = false;\n private adRequestQueue: string[] = [];\n private successfulAdRequests: string[] = [];\n private maxPlaceholderDurationMs: number = 5000;\n private placeholderStartTimeMs: number | null = null;\n private isShowingPlaceholder: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n\n constructor(config: StormcloudVideoPlayerConfig) {\n initializePolyfills();\n\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...config, ...browserOverrides };\n this.video = config.videoElement;\n\n logBrowserInfo(config.debugAdTiming);\n\n this.ima = this.createAdPlayer(false);\n }\n\n private createAdPlayer(continueLiveStreamDuringAds: boolean): ImaController {\n const vastMode = this.config.vastMode || \"default\";\n let adPlayerType =\n this.config.adPlayerType || (vastMode === \"adstorm\" ? \"hls\" : \"ima\");\n\n if (adPlayerType === \"ima\" && !supportsGoogleIMA()) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player\"\n );\n }\n adPlayerType = \"hls\";\n }\n\n if (adPlayerType === \"hls\") {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)\"\n );\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...(this.config.licenseKey\n ? { licenseKey: this.config.licenseKey }\n : {}),\n ...(this.hls ? { mainHlsInstance: this.hls } : {}),\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)\"\n );\n }\n return createImaController(this.video, {\n continueLiveStreamDuringAds,\n });\n }\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\n }\n\n try {\n await this.fetchAdConfiguration();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n\n this.initializeTracking();\n\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\",\n }\n );\n }\n\n this.ima.destroy();\n this.ima = this.createAdPlayer(false);\n this.ima.initialize();\n\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n return;\n }\n\n this.hls = new Hls({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1.0,\n ...(this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}),\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1000 * 1000,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1,\n });\n\n this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n\n this.hls.on(Hls.Events.MANIFEST_PARSED, async (_, data: any) => {\n this.isLiveStream =\n this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds()\n ? \"live (main video continues muted during ads)\"\n : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior,\n });\n }\n\n this.ima.destroy();\n this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.ima.initialize();\n\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_BUFFERED, async (_evt, data: any) => {\n if (this.hasInitialBufferCompleted) {\n return;\n }\n\n this.bufferedSegmentsCount++;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_PARSING_METADATA, (_evt, data: any) => {\n const id3Tags: Id3TagInfo[] = (data?.samples || []).map((s: any) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts,\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n\n this.hls.on(Hls.Events.FRAG_CHANGED, (_evt, data: any) => {\n const frag = data?.frag;\n const tagList: any[] | undefined = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(prog?.duration !== undefined\n ? { durationSeconds: prog.duration }\n : {}),\n ...(prog?.elapsed !== undefined\n ? { ptsSeconds: prog.elapsed }\n : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { tag, value, attrs },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n\n this.hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case Hls.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case Hls.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private attach(): void {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n\n this.ima.initialize();\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.ima.on(\"all_ads_completed\", () => {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] IMA all_ads_completed event received - ending ad break\"\n );\n }\n\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n this.ima.on(\"ad_error\", (errorPayload?: any) => {\n const remaining = this.getRemainingAdMs();\n console.error(\"[AD-ERROR] Ad playback failed\", errorPayload || \"\");\n \n if (this.inAdBreak) {\n if (remaining > 500 && this.adPodQueue.length > 0) {\n const nextPreloaded = this.findNextPreloadedAd();\n if (nextPreloaded) {\n this.currentAdIndex++;\n this.playSingleAd(nextPreloaded).catch(() => {\n this.handleAdFailure();\n });\n } else {\n this.handleAdFailure();\n }\n } else {\n this.handleAdFailure();\n }\n } else {\n this.handleAdFailure();\n }\n });\n this.ima.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n });\n this.ima.on(\"content_resume\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n return;\n }\n\n const remaining = this.getRemainingAdMs();\n \n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);\n }\n\n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n this.handleAdPodComplete();\n }\n });\n\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n\n this.emptiedHandler = () => {\n if (\n this.nativeHlsMode &&\n this.videoSrcProtection &&\n !this.ima.isAdPlaying()\n ) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n\n if (streamType === \"other\") {\n return true;\n }\n\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return undefined;\n\n const cueOutMatch =\n text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) ||\n text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(dur !== undefined ? { durationSeconds: dur } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(cont?.duration !== undefined\n ? { durationSeconds: cont.duration }\n : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n if (hasScteIn) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n }\n\n if (/SCTE35-OUT/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n }\n\n private decodeId3ValueToText(value: string | Uint8Array): string | undefined {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]!);\n return out;\n } catch {\n return undefined;\n }\n }\n\n private onScte35Marker(marker: Scte35Marker): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n });\n }\n\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n return;\n }\n\n this.inAdBreak = true;\n const durationMs =\n marker.durationSeconds != null\n ? marker.durationSeconds * 1000\n : undefined;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n });\n }\n\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1000;\n const nowMs = this.video.currentTime * 1000;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1000 - estCurrentPtsMs);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1000,\n deltaMs,\n tolerance: tol,\n });\n }\n\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n if (\n this.expectedAdBreakDurationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n \n if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null) {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1000\n );\n const tags =\n this.selectVastTagsForBreak(scheduled) ||\n (this.apiVastTagUrl ? [this.apiVastTagUrl] : undefined);\n if (tags && tags.length > 0) {\n const first = tags[0] as string;\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n \n this.playSingleAd(first).catch(() => {});\n }\n }\n return;\n }\n if (marker.type === \"end\") {\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n \n if (this.ima.isAdPlaying()) {\n this.ima.stop().catch(() => {});\n }\n \n this.handleAdPodComplete();\n return;\n }\n }\n\n private parseCueOutDuration(value: string): number | undefined {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match =\n value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) ||\n value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? undefined : d;\n }\n return undefined;\n }\n\n private parseCueOutCont(\n value: string\n ): { elapsed?: number; duration?: number } | undefined {\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n const res: { elapsed?: number; duration?: number } = {};\n if (elapsedMatch && elapsedMatch[1] != null) {\n const e = parseFloat(elapsedMatch[1]);\n if (!Number.isNaN(e)) res.elapsed = e;\n }\n if (durationMatch && durationMatch[1] != null) {\n const d = parseFloat(durationMatch[1]);\n if (!Number.isNaN(d)) res.duration = d;\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return undefined;\n }\n\n private parseAttributeList(value: string): Record<string, string> {\n const attrs: Record<string, string> = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(value)) !== null) {\n const key: string = (match[1] ?? \"\") as string;\n let rawVal: string = (match[3] ?? match[4] ?? \"\") as string;\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n\n private toNumber(val: unknown): number | undefined {\n if (val == null) return undefined;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? undefined : n;\n }\n\n private isManifestBasedMarker(marker: Scte35Marker): boolean {\n const raw = marker.raw as any;\n if (!raw) return false;\n\n if (raw.tag) {\n const tag = String(raw.tag);\n return (\n tag.includes(\"EXT-X-CUE-OUT\") ||\n tag.includes(\"EXT-X-CUE-IN\") ||\n tag.includes(\"EXT-X-DATERANGE\")\n );\n }\n\n if (raw.id3) return false;\n\n if (raw.splice_command_type) return false;\n\n return false;\n }\n\n private parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\n class BitReader {\n private bytePos = 0;\n private bitPos = 0;\n constructor(private readonly buf: Uint8Array) {}\n readBits(numBits: number): number {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos]!;\n const shift = remainingInByte - toRead;\n const mask = ((1 << toRead) - 1) & 0xff;\n const bits = (currentByte >> shift) & mask;\n result = (result << toRead) | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n: number): void {\n this.readBits(n);\n }\n }\n\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 0xfc) return undefined;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return undefined;\n }\n r.readBits(32);\n const cancel = r.readBits(1) === 1;\n r.readBits(7);\n if (cancel) return undefined;\n const outOfNetwork = r.readBits(1) === 1;\n const programSpliceFlag = r.readBits(1) === 1;\n const durationFlag = r.readBits(1) === 1;\n const spliceImmediateFlag = r.readBits(1) === 1;\n r.readBits(4);\n if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n } else if (!programSpliceFlag) {\n const componentCount = r.readBits(8);\n for (let i = 0; i < componentCount; i++) {\n r.readBits(8);\n if (!spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds: number | undefined = undefined;\n if (durationFlag) {\n r.readBits(6);\n r.readBits(1);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const durationTicks = high * 0x100000000 + low;\n durationSeconds = durationTicks / 90000;\n }\n r.readBits(16);\n r.readBits(8);\n r.readBits(8);\n\n if (outOfNetwork) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { splice_command_type: 5 },\n } as Scte35Marker;\n return marker;\n }\n return undefined;\n }\n\n private initializeTracking(): void {\n sendInitialTracking(this.config.licenseKey)\n .then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n })\n .catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n });\n }\n\n private sendHeartbeatIfNeeded(): void {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 30000) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n private async fetchAdConfiguration(): Promise<void> {\n const vastMode = this.config.vastMode || \"default\";\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n );\n }\n return;\n }\n\n const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n this.apiVastTagUrl = vastEndpoint;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n vastEndpoint\n );\n }\n return;\n }\n\n if (this.config.vastTagUrl) {\n this.apiVastTagUrl = this.config.vastTagUrl;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n return;\n }\n\n const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n apiUrl\n );\n }\n\n const headers: Record<string, string> = {};\n if (this.config.licenseKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n }\n\n const response = await fetch(apiUrl, { headers });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n );\n }\n return;\n }\n\n const data: StormcloudApiResponse = await response.json();\n\n const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n if (imaPayload) {\n this.apiVastTagUrl = decodeURIComponent(imaPayload);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n );\n }\n }\n\n const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n if (numberAds != null && numberAds > 0) {\n this.apiNumberAds = numberAds;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n\n getCurrentAdIndex(): number {\n return this.currentAdIndex;\n }\n\n getTotalAdsInBreak(): number {\n return this.totalAdsInBreak;\n }\n\n private generateVastUrlsWithCorrelators(\n baseUrl: string,\n count: number\n ): string[] {\n const urls: string[] = [];\n \n for (let i = 0; i < count; i++) {\n try {\n const url = new URL(baseUrl);\n const timestamp = Date.now();\n const random = Math.floor(Math.random() * 1000000);\n const uniqueCorrelator = `${timestamp}${random}${i}`;\n \n url.searchParams.set(\"correlator\", uniqueCorrelator);\n \n urls.push(url.toString());\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to parse VAST URL:\",\n baseUrl,\n error\n );\n urls.push(`${baseUrl}${baseUrl.includes(\"?\") ? \"&\" : \"?\"}correlator=${Date.now()}${i}`);\n }\n }\n \n return urls;\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.ima.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.showAds;\n }\n\n getStreamType(): \"hls\" | \"other\" {\n const url = this.config.src.toLowerCase();\n if (\n url.includes(\".m3u8\") ||\n url.includes(\"/hls/\") ||\n url.includes(\"application/vnd.apple.mpegurl\")\n ) {\n return \"hls\";\n }\n return \"other\";\n }\n\n shouldShowNativeControls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(\n this.config.allowNativeHls && !(this.config.showCustomControls ?? false)\n );\n }\n\n private shouldContinueLiveStreamDuringAds(): boolean {\n if (this.config.allowNativeHls) {\n return false;\n }\n\n if (!this.isLiveStream) {\n return false;\n }\n\n return true;\n }\n\n private async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1000\n );\n const tags = this.selectVastTagsForBreak(scheduled);\n\n let baseVastUrl: string;\n\n if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else {\n return;\n }\n\n const adBreakDurationMs = \n _marker.durationSeconds != null \n ? _marker.durationSeconds * 1000 \n : scheduled?.durationMs;\n\n if (this.isLiveStream && adBreakDurationMs != null && adBreakDurationMs > 0) {\n this.isAdaptiveMode = true;\n this.targetAdBreakDurationMs = adBreakDurationMs;\n this.fetchedAdDurations.clear();\n\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] 📺 LIVE MODE: Target duration=${adBreakDurationMs}ms | ` +\n `Will continuously fetch ads during break`\n );\n }\n } else {\n this.isAdaptiveMode = false;\n this.targetAdBreakDurationMs = null;\n this.fetchedAdDurations.clear();\n\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] 🎬 VOD MODE: Using fixed ad strategy`\n );\n }\n }\n\n this.adPodAllUrls = [];\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.failedVastUrls.clear();\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n\n this.inAdBreak = true;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n\n if (\n this.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🚀 Immediately requesting first ad...\");\n }\n\n const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const firstAdUrl = firstAdUrlArray[0];\n \n if (!firstAdUrl) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ Failed to generate first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n try {\n await this.ima.requestAds(firstAdUrl);\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ First ad request successful, starting playback\");\n }\n\n this.successfulAdRequests.push(firstAdUrl);\n this.currentAdIndex++;\n \n this.startContinuousFetching(baseVastUrl);\n \n await this.ima.play();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ First ad request failed:\", error);\n }\n this.failedVastUrls.add(firstAdUrl);\n \n this.startContinuousFetching(baseVastUrl);\n this.tryNextAvailableAd();\n }\n }\n\n private startContinuousFetching(baseVastUrl: string): void {\n if (!this.continuousFetchingActive) {\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🔄 Starting continuous ad fetching loop\");\n }\n\n this.continuousFetchLoop(baseVastUrl);\n }\n\n private async continuousFetchLoop(baseVastUrl: string): Promise<void> {\n while (this.continuousFetchingActive && this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n \n if (remaining <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ Ad break time expired, stopping fetch loop\");\n }\n break;\n }\n\n const maxQueueSize = 3;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏸️ Queue full (${this.adRequestQueue.length}), pausing fetching...`);\n }\n await new Promise(resolve => setTimeout(resolve, 2000));\n continue;\n }\n\n const newAdUrl = this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];\n \n if (!newAdUrl || this.failedVastUrls.has(newAdUrl)) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 📡 Attempting to fetch ad (${this.successfulAdRequests.length + this.adRequestQueue.length + 1} total)...`);\n }\n\n try {\n const response = await fetch(newAdUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status}`);\n }\n \n const xmlText = await response.text();\n \n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n const mediaFiles = xmlDoc.querySelectorAll(\"MediaFile\");\n \n if (mediaFiles.length === 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⚠️ VAST response has no media files, skipping\");\n }\n this.failedVastUrls.add(newAdUrl);\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ✅ Successfully fetched ad, adding to queue (queue size: ${this.adRequestQueue.length + 1})`);\n }\n \n this.adRequestQueue.push(newAdUrl);\n this.totalAdsInBreak++;\n \n await new Promise(resolve => setTimeout(resolve, 500));\n \n } catch (error) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ❌ Ad fetch failed:\", (error as Error).message);\n }\n this.failedVastUrls.add(newAdUrl);\n \n await new Promise(resolve => setTimeout(resolve, 2000));\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Continuous fetch loop ended\");\n }\n }\n\n private stopContinuousFetching(): void {\n this.continuousFetchingActive = false;\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Stopping continuous ad fetching\");\n }\n }\n\n private async tryNextAvailableAd(retryCount: number = 0): Promise<void> {\n const remaining = this.getRemainingAdMs();\n \n if (remaining <= 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (nextAdUrl) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🎬 Playing next queued ad (${this.currentAdIndex + 1}/${this.totalAdsInBreak}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n \n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🔊 Updated ad audio state: muted=${currentMuted}, volume=${currentVolume}`);\n }\n \n this.currentAdIndex++;\n this.successfulAdRequests.push(nextAdUrl);\n await this.playSingleAd(nextAdUrl).catch(() => {\n this.tryNextAvailableAd(0);\n });\n return;\n }\n }\n\n const maxRetries = 5;\n if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2000) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏳ Queue empty but fetching active, waiting... (retry ${retryCount + 1}/${maxRetries})`);\n }\n \n await new Promise(resolve => setTimeout(resolve, 1000));\n \n await this.tryNextAvailableAd(retryCount + 1);\n return;\n }\n\n if (!this.isShowingPlaceholder && remaining > 1000) {\n this.showPlaceholderAndWaitForAds();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No more ads available, ending ad break\");\n }\n this.handleAdPodComplete();\n }\n }\n\n private async showPlaceholderAndWaitForAds(): Promise<void> {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n \n if (waitTime < 1000) {\n this.handleAdPodComplete();\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⬛ Showing black placeholder for ${waitTime}ms while waiting for ads`);\n }\n\n this.isShowingPlaceholder = true;\n this.placeholderStartTimeMs = Date.now();\n \n this.ima.showPlaceholder();\n\n const checkInterval = 500;\n const maxChecks = Math.floor(waitTime / checkInterval);\n \n for (let i = 0; i < maxChecks; i++) {\n await new Promise(resolve => setTimeout(resolve, checkInterval));\n \n if (!this.inAdBreak) {\n return;\n }\n\n if (this.adRequestQueue.length > 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ New ad became available during placeholder\");\n }\n \n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n this.ima.hidePlaceholder();\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n \n const nextAdUrl = this.adRequestQueue.shift();\n if (nextAdUrl) {\n this.currentAdIndex++;\n this.successfulAdRequests.push(nextAdUrl);\n await this.playSingleAd(nextAdUrl).catch(() => {\n this.tryNextAvailableAd();\n });\n }\n return;\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏰ Placeholder timeout reached, no ads fetched\");\n }\n \n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n this.ima.hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n private findCurrentOrNextBreak(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = [];\n let candidate: AdBreak | undefined;\n for (const b of schedule) {\n const tol = this.config.driftToleranceMs ?? 1000;\n if (\n b.startTimeMs <= nowMs + tol &&\n (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))\n ) {\n candidate = b;\n }\n }\n return candidate;\n }\n\n private onTimeUpdate(currentTimeSec: number): void {\n if (this.ima.isAdPlaying()) return;\n const nowMs = currentTimeSec * 1000;\n const breakToPlay = this.findBreakForTime(nowMs);\n if (breakToPlay) {\n this.handleMidAdJoin(breakToPlay, nowMs);\n }\n }\n\n private async handleMidAdJoin(\n adBreak: AdBreak,\n nowMs: number\n ): Promise<void> {\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = adBreak.startTimeMs + durationMs;\n if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {\n const remainingMs = endMs - nowMs;\n const tags =\n this.selectVastTagsForBreak(adBreak) ||\n (this.apiVastTagUrl ? [this.apiVastTagUrl] : undefined);\n if (tags && tags.length > 0) {\n const first = tags[0] as string;\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n \n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n \n await this.playSingleAd(first);\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = remainingMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(remainingMs);\n }\n }\n }\n\n private scheduleAdStopCountdown(remainingMs: number): void {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.ensureAdStoppedByTimer();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.ensureAdStoppedByTimer();\n }, ms) as unknown as number;\n }\n\n private clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private ensureAdStoppedByTimer(): void {\n if (!this.inAdBreak) return;\n\n this.adStopTimerId = undefined;\n\n const adPlaying = this.ima.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1000)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs =\n typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0\n ? maxExtensionMsConfig\n : 60000;\n\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n\n const shouldExtendAdBreak =\n (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n\n if (adPlaying) {\n this.ima.stop().catch(() => {});\n }\n\n this.handleAdPodComplete();\n }\n\n private scheduleAdStartIn(delayMs: number): void {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n }, ms) as unknown as number;\n }\n\n private clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n private updatePtsDrift(ptsSecondsSample: number): void {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1000;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 60000) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n\n private async playSingleAd(vastTagUrl: string): Promise<void> {\n if (this.ima.isAdPlaying()) {\n return;\n }\n\n if (this.failedVastUrls.has(vastTagUrl)) {\n console.warn(\"[AD-ERROR] Skipping already-failed VAST URL:\", vastTagUrl.substring(0, 60));\n this.handleAdFailure();\n return;\n }\n\n const requestToken = ++this.adRequestTokenCounter;\n this.activeAdRequestToken = requestToken;\n \n this.startAdRequestWatchdog(requestToken);\n\n try {\n await this.ima.requestAds(vastTagUrl);\n\n this.clearAdRequestWatchdog();\n\n if (this.activeAdRequestToken !== requestToken) {\n return;\n }\n\n try {\n this.startAdFailsafeTimer(requestToken);\n await this.ima.play();\n } catch (playError) {\n console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n this.failedVastUrls.add(vastTagUrl);\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n this.handleAdFailure();\n return;\n }\n } catch (error) {\n console.error(\"[AD-ERROR] Ad request failed:\", (error as Error)?.message);\n this.failedVastUrls.add(vastTagUrl);\n\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n\n this.handleAdFailure();\n }\n }\n\n private handleAdPodComplete(): void {\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n\n this.stopContinuousFetching();\n \n if (this.isShowingPlaceholder) {\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n }\n\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.adPodAllUrls = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n\n this.ima.stop().catch(() => {});\n\n const restoredMuted = this.ima.getOriginalMutedState();\n const restoredVolume = this.ima.getOriginalVolume();\n\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n\n if (!this.shouldContinueLiveStreamDuringAds() && this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n }\n\n private handleAdFailure(): void {\n const remaining = this.getRemainingAdMs();\n \n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);\n }\n \n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n console.error(\"[AD-ERROR] Ad failed and no time remaining. Failed URLs:\", this.failedVastUrls.size);\n this.handleAdPodComplete();\n }\n }\n\n\n private startAdRequestWatchdog(token: number): void {\n this.clearAdRequestWatchdog();\n\n const timeoutMs = this.config.adFailsafeTimeoutMs ?? 10000;\n this.adRequestWatchdogToken = token;\n this.adRequestWatchdogId = window.setTimeout(() => {\n if (this.adRequestWatchdogToken !== token) {\n return;\n }\n\n this.adRequestWatchdogId = undefined;\n this.adRequestWatchdogToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n\n this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n this.handleAdFailure();\n }, timeoutMs) as unknown as number;\n\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n\n private clearAdRequestWatchdog(): void {\n if (this.adRequestWatchdogId != null) {\n clearTimeout(this.adRequestWatchdogId);\n this.adRequestWatchdogId = undefined;\n }\n\n if (this.adRequestWatchdogToken != null) {\n this.logAdState(\"ad_request_watchdog_cleared\", {\n token: this.adRequestWatchdogToken,\n });\n this.adRequestWatchdogToken = null;\n }\n }\n\n private startAdFailsafeTimer(token: number): void {\n this.clearAdFailsafeTimer();\n\n const failsafeMs = this.config.adFailsafeTimeoutMs ?? 10000;\n this.adFailsafeToken = token;\n\n this.adFailsafeTimerId = window.setTimeout(() => {\n if (this.adFailsafeToken !== token) {\n return;\n }\n\n this.adFailsafeTimerId = undefined;\n this.adFailsafeToken = null;\n\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n\n this.logAdState(\"ad_failsafe_triggered\", {\n token,\n failsafeMs,\n videoPaused: this.video.paused,\n imaAdPlaying: this.ima.isAdPlaying(),\n });\n\n this.handleAdFailure();\n }, failsafeMs) as unknown as number;\n\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n\n private clearAdFailsafeTimer(): void {\n if (this.adFailsafeTimerId != null) {\n clearTimeout(this.adFailsafeTimerId);\n this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n this.adFailsafeTimerId = undefined;\n }\n\n this.adFailsafeToken = null;\n }\n\n private selectVastTagsForBreak(b?: AdBreak): string[] | undefined {\n if (!b || !b.vastTagUrl) return undefined;\n if (b.vastTagUrl.includes(\",\")) {\n return b.vastTagUrl\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n }\n return [b.vastTagUrl];\n }\n\n private logAdState(event: string, extra: Record<string, unknown> = {}): void {\n if (!this.config.debugAdTiming) {\n return;\n }\n\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: new Date().toISOString(),\n showAds: this.showAds,\n adPlaying: this.ima.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n private async fetchAndParseVastXml(vastTagUrl: string): Promise<string[]> {\n try {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status}`);\n }\n const xmlText = await response.text();\n return this.extractMediaUrlsFromVast(xmlText);\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch/parse VAST XML: ${vastTagUrl}`,\n error\n );\n }\n return [];\n }\n }\n\n private extractMediaUrlsFromVast(xmlText: string): string[] {\n const mediaUrls: string[] = [];\n \n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n \n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n \n for (const mediaFile of Array.from(mediaFileElements)) {\n const url = mediaFile.textContent?.trim();\n if (url) {\n const lowerUrl = url.toLowerCase();\n if (\n lowerUrl.endsWith(\".mp4\") ||\n lowerUrl.endsWith(\".webm\") ||\n lowerUrl.endsWith(\".mov\") ||\n lowerUrl.endsWith(\".avi\") ||\n lowerUrl.includes(\".mp4?\") ||\n lowerUrl.includes(\".webm?\") ||\n lowerUrl.includes(\"/mp4/\") ||\n lowerUrl.includes(\"type=video\")\n ) {\n mediaUrls.push(url);\n }\n }\n }\n \n if (this.config.debugAdTiming && mediaUrls.length > 0) {\n console.log(\n `[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs from VAST:`,\n mediaUrls\n );\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to parse VAST XML:\",\n error\n );\n }\n }\n \n return mediaUrls;\n }\n\n private async fetchVastDuration(vastTagUrl: string): Promise<number | null> {\n try {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] Failed to fetch VAST: ${response.status}`\n );\n }\n return null;\n }\n \n const xmlText = await response.text();\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n \n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent;\n if (!durationText) {\n if (this.config.debugAdTiming) {\n console.warn(\"[ADAPTIVE-POD] No Duration element found in VAST\");\n }\n return null;\n }\n \n const durationParts = durationText.split(\":\");\n const durationSeconds =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n \n return durationSeconds;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] Error fetching VAST duration from ${vastTagUrl}:`,\n error\n );\n }\n return null;\n }\n }\n\n private calculateAdditionalAdsNeeded(): number {\n if (!this.isAdaptiveMode || this.targetAdBreakDurationMs === null) {\n return 0;\n }\n\n let totalFetchedDurationMs = 0;\n for (const duration of this.fetchedAdDurations.values()) {\n totalFetchedDurationMs += duration * 1000;\n }\n\n const fetchedCount = this.fetchedAdDurations.size;\n const averageDurationMs = fetchedCount > 0 \n ? totalFetchedDurationMs / fetchedCount \n : 30 * 1000;\n\n const queuedButNotFetched = this.adPodAllUrls.length - fetchedCount;\n \n const estimatedQueuedDurationMs = queuedButNotFetched * averageDurationMs;\n const estimatedTotalDurationMs = totalFetchedDurationMs + estimatedQueuedDurationMs;\n\n const remainingTimeMs = this.targetAdBreakDurationMs - estimatedTotalDurationMs;\n\n if (remainingTimeMs <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] ✅ Target duration met: Fetched=${totalFetchedDurationMs}ms + Queued(${queuedButNotFetched} ads)=${estimatedQueuedDurationMs}ms = ${estimatedTotalDurationMs}ms / Target=${this.targetAdBreakDurationMs}ms`\n );\n }\n return 0;\n }\n\n const additionalAds = Math.ceil(remainingTimeMs / averageDurationMs);\n\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] 📊 Need ${additionalAds} more ads | ` +\n `Fetched: ${totalFetchedDurationMs}ms (${fetchedCount} ads) | ` +\n `Queued: ${estimatedQueuedDurationMs}ms (${queuedButNotFetched} ads) | ` +\n `Target: ${this.targetAdBreakDurationMs}ms | ` +\n `Remaining: ${remainingTimeMs}ms | ` +\n `Avg duration: ${averageDurationMs}ms`\n );\n }\n\n return additionalAds;\n }\n\n private async addAdaptiveAdsToQueue(): Promise<void> {\n if (!this.isAdaptiveMode || !this.apiVastTagUrl) {\n return;\n }\n\n const additionalAds = this.calculateAdditionalAdsNeeded();\n if (additionalAds <= 0) {\n return;\n }\n\n const newUrls = this.generateVastUrlsWithCorrelators(\n this.apiVastTagUrl,\n additionalAds\n );\n\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] 🔄 Adding ${newUrls.length} additional VAST URLs to queue (will be preloaded sequentially)`\n );\n }\n\n this.adPodAllUrls.push(...newUrls);\n this.adPodQueue.push(...newUrls);\n this.totalAdsInBreak += newUrls.length;\n }\n\n private async preloadMediaFile(mediaUrl: string): Promise<void> {\n if (this.preloadedMediaUrls.has(mediaUrl)) {\n return;\n }\n\n if (this.preloadingMediaUrls.has(mediaUrl)) {\n return;\n }\n\n this.preloadingMediaUrls.add(mediaUrl);\n\n try {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Preloading video file: ${mediaUrl}`\n );\n }\n\n const response = await fetch(mediaUrl, {\n mode: \"cors\",\n method: \"GET\",\n headers: {\n Range: \"bytes=0-1048576\",\n },\n });\n\n if (response.ok || response.status === 206) {\n this.preloadedMediaUrls.add(mediaUrl);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Successfully preloaded video file: ${mediaUrl}`\n );\n }\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to preload video file: ${mediaUrl}`,\n error\n );\n }\n } finally {\n this.preloadingMediaUrls.delete(mediaUrl);\n }\n }\n\n private async preloadAllAdsInBackground(): Promise<void> {\n if (this.adPodAllUrls.length === 0) {\n return;\n }\n\n if (this.isAdaptiveMode) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] 🔄 Starting sequential preload of remaining ads`\n );\n }\n\n const processedUrls = new Set<string>();\n \n for (const url of this.adPodAllUrls) {\n if (this.ima.hasPreloadedAd?.(url) || this.fetchedAdDurations.has(url)) {\n processedUrls.add(url);\n }\n }\n\n if (this.config.debugAdTiming && processedUrls.size > 0) {\n console.log(\n `[ADAPTIVE-POD] 📦 Skipping ${processedUrls.size} already-preloaded ads`\n );\n }\n\n while (true) {\n const nextUrl = this.adPodAllUrls.find(url => !processedUrls.has(url));\n \n if (!nextUrl) {\n if (this.config.debugAdTiming) {\n console.log(`[ADAPTIVE-POD] ✅ All queued ads processed (${processedUrls.size} total)`);\n }\n break;\n }\n\n processedUrls.add(nextUrl);\n\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] 📥 Preloading ad ${processedUrls.size}/${this.adPodAllUrls.length}...`\n );\n }\n\n try {\n await this.preloadSingleAd(nextUrl);\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] ⚠️ Preload failed for ad ${processedUrls.size}:`,\n error\n );\n }\n }\n\n if (this.calculateAdditionalAdsNeeded() === 0) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] ✅ Target duration reached (${processedUrls.size} ads preloaded), stopping`\n );\n }\n break;\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] ✅ Sequential preloading completed (${processedUrls.size} ads ready)`\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Starting parallel preload of ${this.adPodAllUrls.length} ads`\n );\n }\n\n const preloadPromises = this.adPodAllUrls.map((vastTagUrl) =>\n this.preloadSingleAd(vastTagUrl).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Preload failed for ${vastTagUrl}:`,\n error\n );\n }\n })\n );\n\n await Promise.all(preloadPromises);\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Background preloading completed for all ads`\n );\n }\n }\n }\n\n private async preloadSingleAd(vastTagUrl: string): Promise<void> {\n if (!vastTagUrl) return;\n\n try {\n if (this.isAdaptiveMode && !this.fetchedAdDurations.has(vastTagUrl)) {\n const duration = await this.fetchVastDuration(vastTagUrl);\n if (duration !== null) {\n this.fetchedAdDurations.set(vastTagUrl, duration);\n \n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] ✓ Fetched ad duration: ${duration}s (${this.fetchedAdDurations.size} ads fetched so far)`\n );\n }\n\n await this.addAdaptiveAdsToQueue();\n }\n }\n\n if (this.ima.preloadAds && !this.ima.hasPreloadedAd(vastTagUrl)) {\n if (!this.preloadingAdUrls.has(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Preloading VAST: ${vastTagUrl}`\n );\n }\n\n this.preloadingAdUrls.add(vastTagUrl);\n\n await this.ima\n .preloadAds(vastTagUrl)\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA VAST preload complete: ${vastTagUrl}`\n );\n }\n })\n .catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] IMA VAST preload failed: ${vastTagUrl}`,\n error\n );\n }\n })\n .finally(() => {\n this.preloadingAdUrls.delete(vastTagUrl);\n });\n }\n }\n\n let mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);\n\n if (!mediaUrls) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Fetching and parsing VAST to extract media URLs: ${vastTagUrl}`\n );\n }\n\n mediaUrls = await this.fetchAndParseVastXml(vastTagUrl);\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs:`,\n mediaUrls\n );\n }\n\n if (mediaUrls.length > 0) {\n this.vastToMediaUrlMap.set(vastTagUrl, mediaUrls);\n }\n }\n\n if (mediaUrls && mediaUrls.length > 0) {\n const primaryMediaUrl = mediaUrls[0];\n if (primaryMediaUrl && !this.preloadedMediaUrls.has(primaryMediaUrl)) {\n await this.preloadMediaFile(primaryMediaUrl);\n }\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to preload ad: ${vastTagUrl}`,\n error\n );\n }\n }\n }\n\n private findNextPreloadedAd(): string | undefined {\n for (let i = 0; i < this.adPodQueue.length; i++) {\n const vastTagUrl = this.adPodQueue[i];\n if (!vastTagUrl) continue;\n\n if (this.failedVastUrls.has(vastTagUrl)) {\n console.warn(\"[AD-ERROR] Skipping failed URL in queue\");\n continue;\n }\n\n const hasImaPreload = this.ima.hasPreloadedAd?.(vastTagUrl) ?? false;\n const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);\n const hasMediaPreload =\n mediaUrls && mediaUrls.length > 0\n ? this.preloadedMediaUrls.has(mediaUrls[0]!)\n : false;\n\n if (hasImaPreload || hasMediaPreload) {\n this.adPodQueue.splice(0, i + 1);\n return vastTagUrl;\n }\n }\n\n return undefined;\n }\n\n private getRemainingAdMs(): number {\n if (\n this.expectedAdBreakDurationMs == null ||\n this.currentAdBreakStartWallClockMs == null\n )\n return 0;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n\n private findBreakForTime(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = [];\n for (const b of schedule) {\n const end = (b.startTimeMs || 0) + (b.durationMs || 0);\n if (\n nowMs >= (b.startTimeMs || 0) &&\n (b.durationMs ? nowMs < end : true)\n ) {\n return b;\n }\n }\n return undefined;\n }\n\n toggleMute(): void {\n if (this.ima.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n\n this.ima.updateOriginalMutedState(newMutedState, this.video.volume);\n this.ima.setAdVolume(newMutedState ? 0 : 1);\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n\n toggleFullscreen(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container\n .requestFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document\n .exitFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n\n isMuted(): boolean {\n if (this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n const adPlaying = this.ima.isAdPlaying();\n\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n\n this.video.muted = muted;\n\n if (adPlaying) {\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n this.ima.setAdVolume(muted ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted,\n });\n }\n return;\n }\n\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n\n setVolume(volume: number): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.ima.isAdPlaying();\n\n if (adPlaying) {\n this.ima.setAdVolume(clampedVolume);\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume,\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n\n isFullscreen(): boolean {\n return !!document.fullscreenElement;\n }\n\n isLive(): boolean {\n return this.isLiveStream;\n }\n\n get videoElement(): HTMLVideoElement {\n return this.video;\n }\n\n resize(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n\n if (this.ima && this.ima.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 360;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n\n this.ima.resize(width, height);\n }\n }\n\n destroy(): void {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n \n // Remove event listeners to prevent race conditions\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n \n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n this.hls?.destroy();\n this.ima?.destroy();\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.adPodAllUrls = [];\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n }\n}\n","interface NavigatorUAData {\n platform?: string;\n brands?: Array<{ brand: string; version: string }>;\n mobile?: boolean;\n}\n\ndeclare global {\n interface Navigator {\n userAgentData?: NavigatorUAData;\n }\n}\n\nexport interface BrowserInfo {\n name: string;\n version: string;\n majorVersion: number;\n isSmartTV: boolean;\n isLegacyTV: boolean;\n platform: string;\n supportsIMA: boolean;\n supportsModernJS: boolean;\n recommendedAdPlayer: 'ima' | 'hls';\n}\n\nfunction getChromeVersion(ua: string): number {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getWebKitVersion(ua: string): number {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getPlatform(): string {\n if ('userAgentData' in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? 'iPhone' : 'MacIntel';\n }\n if (/Win/i.test(ua)) {\n return 'Win32';\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? 'Linux armv8l' : 'Linux x86_64';\n }\n if (/CrOS/i.test(ua)) {\n return 'CrOS';\n }\n\n // eslint-disable-next-line deprecation/deprecation\n return (navigator as any).platform || 'Unknown';\n}\n\nexport function detectBrowser(): BrowserInfo {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n\n let name = 'Unknown';\n let version = '0';\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer: 'ima' | 'hls' = 'ima';\n\n if (/Web0S|webOS/i.test(ua)) {\n name = 'LG WebOS';\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = 'Samsung Tizen';\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n }\n\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n isLegacyTV = true;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n\n if (typeof URLSearchParams === 'undefined') {\n supportsModernJS = false;\n }\n\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n };\n}\n\nexport function supportsGoogleIMA(): boolean {\n const browser = detectBrowser();\n\n if (browser.isLegacyTV) {\n return false;\n }\n\n if (typeof document === 'undefined' ||\n typeof document.createElement !== 'function') {\n return false;\n }\n\n try {\n const video = document.createElement('video');\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n\n if (typeof Promise === 'undefined') {\n return false;\n }\n\n return browser.supportsIMA;\n}\n\nexport function getRecommendedAdPlayer(): 'ima' | 'hls' {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\n}\n\nexport function supportsModernJS(): boolean {\n try {\n return (\n typeof Promise !== 'undefined' &&\n typeof Map !== 'undefined' &&\n typeof Set !== 'undefined' &&\n typeof Array.from !== 'undefined' &&\n typeof Object.assign !== 'undefined' &&\n typeof Array.prototype.forEach !== 'undefined' &&\n typeof String.prototype.includes !== 'undefined'\n );\n } catch (e) {\n return false;\n }\n}\n\nexport function logBrowserInfo(debug: boolean = false): void {\n if (!debug) return;\n\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n\n console.log('[StormcloudVideoPlayer] Browser Compatibility Info:', {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n userAgent: navigator.userAgent,\n });\n}\n\nexport function getBrowserConfigOverrides(): {\n adPlayerType?: 'ima' | 'hls';\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: any = {};\n\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = 'hls';\n }\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'ima':\n return supportsGoogleIMA();\n case 'urlsearchparams':\n return typeof URLSearchParams !== 'undefined';\n case 'textencoder':\n return typeof TextEncoder !== 'undefined';\n case 'promises':\n return typeof Promise !== 'undefined';\n case 'fetch':\n return typeof fetch !== 'undefined';\n case 'crypto':\n return typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined';\n default:\n return false;\n }\n}\n\n","import type { ImaController } from \"../types\";\nimport { supportsGoogleIMA } from \"../utils/browserCompat\";\n\ndeclare global {\n interface Window {\n google?: any;\n }\n}\n\nexport function createImaController(\n video: HTMLVideoElement,\n options?: { continueLiveStreamDuringAds?: boolean }\n): ImaController {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume =\n typeof video.volume === \"number\" && !Number.isNaN(video.volume)\n ? Math.max(0, Math.min(1, video.volume))\n : 1;\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const preloadedVast = new Map<string, string>();\n const preloadingVast = new Map<string, Promise<void>>();\n let adVideoElement: HTMLVideoElement | undefined;\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n\n function hideContentVideo(): void {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n\n function showContentVideo(): void {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"15\";\n adVideo.playsInline = true;\n adVideo.muted = false;\n adVideo.volume = originalMutedState ? 0 : originalVolume;\n\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n\n return adVideo;\n }\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {}\n }\n }\n\n function ensureImaLoaded(): Promise<void> {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n\n try {\n const frameEl = window.frameElement as HTMLIFrameElement | null;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n // eslint-disable-next-line no-console\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {}\n\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n ) as HTMLScriptElement | null;\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 10000);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n\n let adsManager: any | undefined;\n let adsLoader: any | undefined;\n let adDisplayContainer: any | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let lastAdTagUrl: string | undefined;\n let retryAttempts = 0;\n const maxRetries = 2;\n const backoffBaseMs = 500;\n let adsLoadedPromise: Promise<void> | undefined;\n let adsLoadedResolve: (() => void) | undefined;\n let adsLoadedReject: ((error: Error) => void) | undefined;\n\n function makeAdsRequest(google: any, vastTagUrl: string) {\n const adsRequest = new google.ima.AdsRequest();\n \n console.log(\"[IMA] 📡 Requesting VAST from URL (letting IMA fetch fresh)\");\n adsRequest.adTagUrl = vastTagUrl;\n\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 360;\n\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n\n adsRequest.vastLoadTimeout = 10000;\n\n adsLoader.requestAds(adsRequest);\n }\n\n function ensurePlaceholderContainer(): void {\n if (adContainerEl) {\n return;\n }\n\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition =\n \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n async function fetchVastDocument(vastTagUrl: string): Promise<string> {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to preload VAST: ${response.status}`);\n }\n return response.text();\n }\n\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {}\n adsManager = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n\n return {\n initialize() {\n ensureImaLoaded()\n .then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {}\n }\n })\n .catch(() => {});\n },\n async requestAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n console.warn(\"[IMA] ❌\", error.message);\n return Promise.reject(error);\n }\n\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n console.warn(\"[IMA] ❌\", error.message);\n return Promise.reject(error);\n }\n\n if (adPlaying) {\n console.warn(\n \"[IMA] ⚠️ Cannot request new ads while an ad is playing. Call stop() first.\"\n );\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n\n destroyAdsManager();\n\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n\n let currentReject: ((error: Error) => void) | undefined;\n adsLoadedPromise = new Promise<void>((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n }, 10000);\n });\n\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n retryAttempts = 0;\n\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition =\n \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n\n video.parentElement.appendChild(container);\n adContainerEl = container;\n\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n\n }\n\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n\n if (\n !videoWidth ||\n !videoHeight ||\n videoWidth === 0 ||\n videoHeight === 0\n ) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n console.warn(\"[IMA]\", error.message);\n currentReject?.(error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt: any) => {\n try {\n const adsRenderingSettings =\n new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent: any) => {\n const error = errorEvent.getError();\n console.error(\"[DEBUG-ERROR] ❌ AD_ERROR:\", error.getMessage?.());\n\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n\n if (lastAdTagUrl && retryAttempts < maxRetries) {\n const delay =\n backoffBaseMs * Math.pow(2, retryAttempts++);\n window.setTimeout(() => {\n try {\n makeAdsRequest(google, lastAdTagUrl!);\n } catch {}\n }, delay);\n } else {\n emit(\"ad_error\");\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {});\n }\n }\n }\n }\n );\n\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n\n adPlaying = true;\n setAdPlayingFlag(true);\n \n emit(\"content_pause\");\n }\n );\n\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n\n hideContentVideo();\n\n if (adVideoElement) {\n adVideoElement.volume = originalMutedState\n ? 0\n : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n \n emit(\"content_resume\");\n }\n );\n\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (!options?.continueLiveStreamDuringAds && video.paused) {\n video.play().catch(() => {});\n }\n\n emit(\"all_ads_completed\");\n });\n\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = undefined;\n adsLoadedReject = undefined;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {});\n }\n }\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent: any) => {\n const error = adErrorEvent.getError();\n console.error(\"[DEBUG-ERROR] ❌ ADS_LOADER ERROR:\", error.getMessage?.());\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {});\n }\n }\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ads loader error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\");\n },\n false\n );\n }\n\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n\n currentReject?.(error as Error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n\n if (preloadedVast.has(vastTagUrl)) {\n return Promise.resolve();\n }\n\n const inflight = preloadingVast.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n\n const preloadPromise = fetchVastDocument(vastTagUrl)\n .then((xml) => {\n preloadedVast.set(vastTagUrl, xml);\n })\n .catch(() => {\n preloadedVast.delete(vastTagUrl);\n })\n .finally(() => {\n preloadingVast.delete(vastTagUrl);\n });\n\n preloadingVast.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl: string) {\n return preloadedVast.has(vastTagUrl);\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 360;\n\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n\n adPlaying = true;\n\n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n\n try {\n adsManager.setVolume(adVolume);\n } catch {}\n\n adsManager.start();\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[IMA] ❌ Error starting ad:\", error);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {});\n }\n return Promise.reject(error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n try {\n adsManager?.stop?.();\n } catch {}\n\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n adVideoElement = undefined;\n }\n }, 300);\n }\n\n showContentVideo();\n\n try {\n adsLoader?.destroy?.();\n } catch {}\n\n adDisplayContainer = undefined;\n adsLoader = undefined;\n contentVideoHidden = false;\n preloadedVast.clear();\n preloadingVast.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width: number, height: number) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume: number) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {}\n }\n },\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n },\n };\n}\n","import type { ImaController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): ImaController {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n const preloadedAds = new Map<string, VastAd>();\n const preloadingAds = new Map<string, Promise<void>>();\n let destroyed = false;\n let pendingTimeouts: number[] = [];\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n if (sessionId) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function getMainStreamQuality(): {\n width: number;\n height: number;\n bitrate: number;\n } | null {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level = mainHlsInstance.levels[autoLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n return null;\n }\n\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n\n const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n return { file, score, resolutionDiff, bitrateDiff };\n });\n\n scoredFiles.sort((a, b) => a.score - b.score);\n\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff,\n });\n\n return bestMatch.file;\n }\n\n function parseVastXml(xmlString: string): VastAd | null {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const isNoAdAvailable =\n adId === \"empty\" ||\n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\n\n const durationText =\n xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n\n if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n if (!url) {\n console.warn(\n `[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`\n );\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate:\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n\n console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not HLS)`\n );\n }\n });\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No HLS media files found in VAST XML\");\n }\n return null;\n }\n\n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string\n ): Promise<VastAd | null> {\n const response = await fetch(vastTagUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml);\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n\n video.volume = 1.0;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n emit(\"content_resume\");\n\n const timeoutId = window.setTimeout(() => {\n if (destroyed) {\n console.log(\"[HlsAdPlayer] Player destroyed, skipping post-completion check\");\n return;\n }\n \n const stillInPod = contentVideo.dataset.stormcloudAdPlaying === \"true\";\n if (stillInPod) {\n console.log(\n \"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)\"\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n }\n \n const idx = pendingTimeouts.indexOf(timeoutId);\n if (idx !== -1) {\n pendingTimeouts.splice(idx, 1);\n }\n }, 50);\n \n pendingTimeouts.push(timeoutId);\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`\n );\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (!options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n contentVideo.play().catch(() => {});\n }\n }\n\n emit(\"ad_error\");\n }\n\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(vastTagUrl: string) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n\n try {\n sessionId = generateSessionId();\n let ad: VastAd | null | undefined;\n\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.resolve();\n }\n\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n\n if (preloadedAds.has(vastTagUrl)) {\n return Promise.resolve();\n }\n\n const inflight = preloadingAds.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n\n const preloadPromise = fetchAndParseVastAd(vastTagUrl)\n .then((ad) => {\n if (ad) {\n preloadedAds.set(vastTagUrl, ad);\n console.log(\n \"[HlsAdPlayer] Cached VAST response for preloading:\",\n vastTagUrl\n );\n }\n })\n .catch((error) => {\n console.warn(\"[HlsAdPlayer] Failed to preload VAST response:\", error);\n preloadedAds.delete(vastTagUrl);\n })\n .finally(() => {\n preloadingAds.delete(vastTagUrl);\n });\n\n preloadingAds.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl: string) {\n return preloadedAds.has(vastTagUrl);\n },\n\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n // Capture content volume BEFORE muting\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);\n\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false,\n });\n\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement!.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (\n adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")\n ) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(\"HLS not supported\");\n }\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n\n currentAd = undefined;\n },\n\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n \n // Clear all pending timeouts\n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n \n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n },\n };\n}\n","import type { ClientInfo, TrackingData, HeartbeatData } from \"../types\";\n\nlet cachedBrowserId: string | null = null;\n\nexport function getClientInfo(): ClientInfo {\n const ua = navigator.userAgent;\n const platform = navigator.platform;\n const vendor = navigator.vendor || \"\";\n const maxTouchPoints = navigator.maxTouchPoints || 0;\n const memory = (navigator as any).deviceMemory || null;\n const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n\n const screenInfo = {\n width: screen?.width,\n height: screen?.height,\n availWidth: screen?.availWidth,\n availHeight: screen?.availHeight,\n orientation: (screen?.orientation as any)?.type || \"\",\n pixelDepth: screen?.pixelDepth,\n };\n\n let deviceType: \"tv\" | \"mobile\" | \"tablet\" | \"desktop\" = \"desktop\";\n let brand = \"Unknown\";\n let os = \"Unknown\";\n let model = \"\";\n let isSmartTV = false;\n let isAndroid = false;\n let isWebView = false;\n let isWebApp = false;\n\n if (ua.includes(\"Web0S\")) {\n brand = \"LG\";\n os = \"webOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n } else if (ua.includes(\"Tizen\")) {\n brand = \"Samsung\";\n os = \"Tizen\";\n isSmartTV = true;\n deviceType = \"tv\";\n const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n model = tizenMatch\n ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim()\n : \"Tizen TV\";\n } else if (ua.includes(\"Philips\")) {\n brand = \"Philips\";\n os = \"Saphi\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n brand = \"Sharp\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (\n ua.includes(\"Android\") &&\n (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))\n ) {\n brand = \"Sony\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (\n ua.includes(\"Android\") &&\n (ua.includes(\"NetCast\") || ua.includes(\"LG\"))\n ) {\n brand = \"LG\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n brand = \"Roku\";\n os = \"Roku OS\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"AppleTV\")) {\n brand = \"Apple\";\n os = \"tvOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n }\n\n if (ua.includes(\"Android\")) {\n isAndroid = true;\n os = \"Android\";\n deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n\n if (\n ua.includes(\"Android\") &&\n (maxTouchPoints === 0 ||\n ua.includes(\"Google TV\") ||\n ua.includes(\"XiaoMi\"))\n ) {\n deviceType = \"tv\";\n isSmartTV = true;\n brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n }\n\n const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n if (androidModelMatch && androidModelMatch[1]) {\n model = androidModelMatch[1];\n }\n }\n\n if (/iPad|iPhone|iPod/.test(ua)) {\n os = \"iOS\";\n deviceType = \"mobile\";\n brand = \"Apple\";\n if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n deviceType = \"tablet\";\n }\n }\n\n if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n if (ua.includes(\"Windows\")) {\n os = \"Windows\";\n deviceType = \"desktop\";\n } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n os = \"macOS\";\n deviceType = \"desktop\";\n if (maxTouchPoints > 1) deviceType = \"tablet\";\n } else if (ua.includes(\"Linux\")) {\n os = \"Linux\";\n deviceType = \"desktop\";\n }\n }\n\n if (brand === \"Unknown\") {\n if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n if (vendor.includes(\"Apple\")) brand = \"Apple\";\n if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n }\n\n isWebView = /wv|WebView|Linux; U;/.test(ua);\n\n if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n isWebView = true;\n }\n\n isWebApp =\n window.matchMedia(\"(display-mode: standalone)\").matches ||\n (window.navigator as any).standalone === true ||\n window.screen?.orientation?.angle !== undefined;\n\n return {\n brand,\n os,\n model: model || ua.substring(0, 50) + \"...\",\n deviceType,\n isSmartTV,\n isAndroid,\n isWebView,\n isWebApp,\n domain: window.location.hostname,\n origin: window.location.origin,\n path: window.location.pathname,\n userAgent: ua,\n vendor,\n platform,\n screen: screenInfo,\n hardwareConcurrency,\n deviceMemory: memory,\n maxTouchPoints,\n language: navigator.language,\n languages: navigator.languages?.join(\",\") || \"\",\n cookieEnabled: navigator.cookieEnabled,\n doNotTrack: navigator.doNotTrack || \"\",\n referrer: document.referrer,\n visibilityState: document.visibilityState,\n };\n}\n\nexport async function getBrowserID(clientInfo: ClientInfo): Promise<string> {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n\n const fingerprintString = JSON.stringify(clientInfo);\n\n if (typeof crypto !== \"undefined\" && crypto.subtle && crypto.subtle.digest) {\n try {\n await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n\n let encodedData: BufferSource;\n if (typeof TextEncoder !== \"undefined\") {\n encodedData = new TextEncoder().encode(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\n const buffer = new Uint8Array(utf8.length);\n for (let i = 0; i < utf8.length; i++) {\n buffer[i] = utf8.charCodeAt(i);\n }\n encodedData = buffer;\n }\n\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n\n const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n const timestamp = Date.now().toString(16).padStart(12, \"0\");\n const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n\n cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\n\nexport async function sendInitialTracking(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const trackingData: TrackingData = {\n browserId,\n ...clientInfo,\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\n\nexport async function sendHeartbeat(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const heartbeatData: HeartbeatData = {\n browserId,\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\n","export function polyfillURLSearchParams(): void {\n if (typeof URLSearchParams !== 'undefined') {\n return;\n }\n\n class URLSearchParamsPolyfill {\n private params: Map<string, string[]>;\n\n constructor(init?: string | URLSearchParamsPolyfill) {\n this.params = new Map();\n\n if (typeof init === 'string') {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n\n private parseQueryString(query: string): void {\n const cleanQuery = query.startsWith('?') ? query.slice(1) : query;\n if (!cleanQuery) return;\n\n cleanQuery.split('&').forEach((param) => {\n const [key, value] = param.split('=');\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : '';\n this.append(decodedKey, decodedValue);\n }\n });\n }\n\n private safeDecodeURIComponent(str: string): string {\n try {\n return decodeURIComponent(str.replace(/\\+/g, ' '));\n } catch (e) {\n return str;\n }\n }\n\n append(name: string, value: string): void {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n\n delete(name: string): void {\n this.params.delete(name);\n }\n\n get(name: string): string | null {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== undefined ? values[0] : null;\n }\n\n getAll(name: string): string[] {\n return this.params.get(name) || [];\n }\n\n has(name: string): boolean {\n return this.params.has(name);\n }\n\n set(name: string, value: string): void {\n this.params.set(name, [String(value)]);\n }\n\n forEach(callback: (value: string, key: string, parent: URLSearchParamsPolyfill) => void): void {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n\n toString(): string {\n const parts: string[] = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join('&');\n }\n }\n\n // @ts-ignore\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\n\nexport function polyfillTextEncoder(): void {\n if (typeof TextEncoder !== 'undefined') {\n return;\n }\n\n class TextEncoderPolyfill {\n encoding = 'utf-8';\n\n encode(str: string): Uint8Array {\n const utf8: number[] = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 0x80) {\n utf8.push(charcode);\n } else if (charcode < 0x800) {\n utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));\n } else if (charcode < 0xd800 || charcode >= 0xe000) {\n utf8.push(\n 0xe0 | (charcode >> 12),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n } else {\n i++;\n charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));\n utf8.push(\n 0xf0 | (charcode >> 18),\n 0x80 | ((charcode >> 12) & 0x3f),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n\n // @ts-ignore\n window.TextEncoder = TextEncoderPolyfill;\n}\n\nexport function polyfillPromiseFinally(): void {\n if (typeof Promise !== 'undefined' && !Promise.prototype.finally) {\n Promise.prototype.finally = function (callback: () => void) {\n const constructor = this.constructor as PromiseConstructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) =>\n constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\n\nexport function polyfillObjectAssign(): void {\n if (typeof Object.assign !== 'function') {\n Object.assign = function (target: any, ...sources: any[]) {\n if (target == null) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n const to = Object(target);\n\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n\n return to;\n };\n }\n}\n\nexport function polyfillArrayFrom(): void {\n if (!Array.from) {\n Array.from = function (arrayLike: any, mapFn?: any, thisArg?: any) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object');\n }\n\n const len = items.length >>> 0;\n const result = new Array(len);\n\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n\n return result;\n };\n }\n}\n\nexport function polyfillStringStartsWith(): void {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function (search: string, pos?: number) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\n\nexport function polyfillStringEndsWith(): void {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function (search: string, length?: number) {\n if (length === undefined || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\n\nexport function polyfillStringIncludes(): void {\n if (!String.prototype.includes) {\n String.prototype.includes = function (search: string, start?: number) {\n if (typeof start !== 'number') {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\n\nexport function initializePolyfills(): void {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n","import React, { Component, Suspense } from \"react\";\nimport type { BaseStormcloudPlayerProps } from \"./props\";\nimport { defaultProps } from \"./props\";\nimport { omit } from \"./utils\";\nimport players from \"./players\";\nimport type { PlayerConfig } from \"./players\";\nimport Player from \"./Player.js\";\n\nconst IS_BROWSER = typeof window !== \"undefined\" && window.document;\nconst IS_GLOBAL =\n typeof globalThis !== \"undefined\" &&\n globalThis.window &&\n globalThis.window.document;\nconst UniversalSuspense = IS_BROWSER || IS_GLOBAL ? Suspense : () => null;\n\nconst SUPPORTED_PROPS = [\n \"src\",\n \"playing\",\n \"loop\",\n \"controls\",\n \"volume\",\n \"muted\",\n \"playbackRate\",\n \"width\",\n \"height\",\n \"style\",\n \"progressInterval\",\n \"playsInline\",\n \"autoplay\",\n \"preload\",\n \"poster\",\n \"className\",\n \"wrapperClassName\",\n \"wrapperStyle\",\n \"allowNativeHls\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"immediateManifestAds\",\n \"debugAdTiming\",\n \"showCustomControls\",\n \"licenseKey\",\n \"adFailsafeTimeoutMs\",\n \"minSegmentsBeforePlay\",\n \"onReady\",\n \"onStart\",\n \"onPlay\",\n \"onPause\",\n \"onBuffer\",\n \"onBufferEnd\",\n \"onEnded\",\n \"onError\",\n \"onDuration\",\n \"onSeek\",\n \"onProgress\",\n \"onVolumeToggle\",\n \"onFullscreenToggle\",\n \"onControlClick\",\n];\n\nexport interface StormcloudPlayerProps extends BaseStormcloudPlayerProps {\n fallback?: React.ReactElement;\n wrapper?: React.ComponentType<{ children: React.ReactNode }> | string;\n}\n\ninterface StormcloudPlayerState {\n showPreview: boolean;\n}\n\nconst customPlayers: PlayerConfig[] = [];\n\nexport const createStormcloudPlayer = (\n playerList: PlayerConfig[],\n fallback?: PlayerConfig\n) => {\n return class StormcloudPlayerClass extends Component<\n StormcloudPlayerProps,\n StormcloudPlayerState\n > {\n static displayName = \"StormcloudPlayer\";\n\n static defaultProps = {\n ...defaultProps,\n fallback: null,\n wrapper: \"div\",\n };\n\n static addCustomPlayer = (player: PlayerConfig) => {\n customPlayers.push(player);\n };\n\n static removeCustomPlayers = () => {\n customPlayers.length = 0;\n };\n\n static canPlay = (src: string): boolean => {\n for (const Player of [...customPlayers, ...playerList]) {\n if (Player.canPlay(src)) {\n return true;\n }\n }\n return false;\n };\n\n static canEnablePIP = (src: string): boolean => {\n for (const Player of [...customPlayers, ...playerList]) {\n if (Player.canEnablePIP && Player.canEnablePIP(src)) {\n return true;\n }\n }\n return false;\n };\n\n state: StormcloudPlayerState = {\n showPreview: false,\n };\n\n public wrapper?: HTMLElement;\n public player?: any;\n\n references = {\n wrapper: (wrapper: HTMLElement) => {\n this.wrapper = wrapper;\n },\n player: (player: any) => {\n this.player = player;\n },\n };\n\n getActivePlayer = (src?: string): PlayerConfig | null => {\n if (!src) return null;\n\n for (const player of [...customPlayers, ...playerList]) {\n if (player.canPlay(src)) {\n return player;\n }\n }\n\n if (fallback) {\n return fallback;\n }\n\n return null;\n };\n\n getAttributes = (src?: string) => {\n return omit(this.props, SUPPORTED_PROPS as any);\n };\n\n handleReady = () => {\n this.props.onReady?.(this as any);\n };\n\n seekTo = (\n fraction: number,\n type?: \"seconds\" | \"fraction\",\n keepPlaying?: boolean\n ) => {\n if (!this.player) return null;\n this.player.seekTo(fraction, type, keepPlaying);\n };\n\n getCurrentTime = (): number | null => {\n if (!this.player) return null;\n return this.player.getCurrentTime();\n };\n\n getSecondsLoaded = (): number | null => {\n if (!this.player) return null;\n return this.player.getSecondsLoaded();\n };\n\n getDuration = (): number | null => {\n if (!this.player) return null;\n return this.player.getDuration();\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (!this.player) return null;\n return this.player.getInternalPlayer(key);\n };\n\n renderActivePlayer = (src?: string) => {\n if (!src) return null;\n\n const activePlayer = this.getActivePlayer(src);\n if (!activePlayer) return null;\n\n return React.createElement(Player, {\n ...this.props,\n key: activePlayer.key,\n ref: this.references.player,\n activePlayer: activePlayer.lazyPlayer || activePlayer,\n onReady: this.handleReady,\n });\n };\n\n render() {\n const {\n src,\n style,\n width,\n height,\n fallback: fallbackElement,\n wrapper: Wrapper,\n } = this.props;\n const attributes = this.getAttributes(src);\n const wrapperRef =\n typeof Wrapper === \"string\" ? this.references.wrapper : undefined;\n\n return React.createElement(\n Wrapper as any,\n {\n ref: wrapperRef,\n style: { ...style, width, height },\n ...attributes,\n },\n React.createElement(\n UniversalSuspense,\n { fallback: fallbackElement },\n this.renderActivePlayer(src)\n )\n );\n }\n };\n};\n\nconst StormcloudPlayer = createStormcloudPlayer(\n players,\n players[players.length - 1]\n);\n\nexport default StormcloudPlayer;\n","import type { CSSProperties } from \"react\";\nimport { StormcloudVideoPlayer } from \"./player/StormcloudVideoPlayer\";\n\nexport interface OnProgressProps {\n played: number;\n playedSeconds: number;\n loaded: number;\n loadedSeconds: number;\n}\n\nexport interface BaseStormcloudPlayerProps {\n src?: string;\n playing?: boolean;\n loop?: boolean;\n controls?: boolean;\n volume?: number;\n muted?: boolean;\n playbackRate?: number;\n width?: string | number;\n height?: string | number;\n style?: CSSProperties;\n progressInterval?: number;\n playsInline?: boolean;\n autoplay?: boolean;\n preload?: string;\n poster?: string;\n className?: string;\n wrapperClassName?: string;\n wrapperStyle?: CSSProperties;\n\n allowNativeHls?: boolean;\n lowLatencyMode?: boolean;\n driftToleranceMs?: number;\n immediateManifestAds?: boolean;\n debugAdTiming?: boolean;\n showCustomControls?: boolean;\n hideLoadingIndicator?: boolean;\n licenseKey?: string;\n adFailsafeTimeoutMs?: number;\n minSegmentsBeforePlay?: number;\n\n onReady?: (player: StormcloudVideoPlayer) => void;\n onStart?: () => void;\n onPlay?: () => void;\n onPause?: (e?: any) => void;\n onBuffer?: () => void;\n onBufferEnd?: () => void;\n onEnded?: () => void;\n onError?: (\n error: any,\n data?: any,\n hlsInstance?: any,\n hlsGlobal?: any\n ) => void;\n onDuration?: (duration: number) => void;\n onSeek?: (seconds: number) => void;\n onProgress?: (state: OnProgressProps) => void;\n onVolumeToggle?: () => void;\n onFullscreenToggle?: () => void;\n onControlClick?: () => void;\n\n [otherProps: string]: any;\n}\n\nconst noop = () => {};\n\nexport const defaultProps: Required<\n Omit<\n BaseStormcloudPlayerProps,\n | \"src\"\n | \"onReady\"\n | \"children\"\n | keyof React.VideoHTMLAttributes<HTMLVideoElement>\n >\n> = {\n playing: false,\n loop: false,\n controls: true,\n volume: 1,\n muted: false,\n playbackRate: 1,\n width: \"100%\",\n height: \"auto\",\n style: {},\n progressInterval: 1000,\n playsInline: false,\n autoplay: false,\n preload: \"metadata\",\n poster: \"\",\n className: \"\",\n wrapperClassName: \"\",\n wrapperStyle: {},\n\n allowNativeHls: false,\n lowLatencyMode: false,\n driftToleranceMs: 1000,\n immediateManifestAds: true,\n debugAdTiming: false,\n showCustomControls: false,\n hideLoadingIndicator: false,\n licenseKey: \"\",\n adFailsafeTimeoutMs: 10000,\n minSegmentsBeforePlay: 2,\n\n onStart: noop,\n onPlay: noop,\n onPause: noop,\n onBuffer: noop,\n onBufferEnd: noop,\n onEnded: noop,\n onError: noop,\n onDuration: noop,\n onSeek: noop,\n onProgress: noop,\n onVolumeToggle: noop,\n onFullscreenToggle: noop,\n onControlClick: noop,\n};\n","import { lazy as reactLazy } from \"react\";\n\nexport const lazy = reactLazy;\n\nexport const omit = <T extends Record<string, any>, K extends keyof T>(\n object: T,\n keys: K[]\n): Omit<T, K> => {\n const result = { ...object };\n keys.forEach((key) => {\n delete result[key];\n });\n return result;\n};\n\nexport const isMediaStream = (url: any): url is MediaStream => {\n return (\n typeof window !== \"undefined\" &&\n window.MediaStream &&\n url instanceof window.MediaStream\n );\n};\n\nexport const supportsWebKitPresentationMode = (): boolean => {\n if (typeof window === \"undefined\") return false;\n const video = document.createElement(\"video\");\n return \"webkitSupportsPresentationMode\" in video;\n};\n\nexport const randomString = (): string => {\n return Math.random().toString(36).substr(2, 9);\n};\n\nexport const parseQuery = (url: string): Record<string, string> => {\n const query: Record<string, string> = {};\n const queryString = url.split(\"?\")[1] || \"\";\n\n if (!queryString) return query;\n\n const manualParse = (qs: string) => {\n qs.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n try {\n query[decodeURIComponent(key)] = value\n ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n : \"\";\n } catch (e) {\n query[key] = value || \"\";\n }\n }\n });\n };\n\n if (typeof URLSearchParams !== \"undefined\") {\n try {\n const params = new URLSearchParams(queryString);\n params.forEach((value, key) => {\n query[key] = value;\n });\n return query;\n } catch (e) {\n manualParse(queryString);\n }\n } else {\n manualParse(queryString);\n }\n\n return query;\n};\n\nexport const merge = <T extends Record<string, any>>(\n target: T,\n ...sources: Partial<T>[]\n): T => {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n merge(target[key] as any, source[key] as any);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return merge(target, ...sources);\n};\n\nconst isObject = (item: any): item is Record<string, any> => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\n\nexport const IS_BROWSER = typeof window !== \"undefined\" && window.document;\nexport const IS_GLOBAL =\n typeof globalThis !== \"undefined\" &&\n globalThis.window &&\n globalThis.window.document;\nexport const IS_IOS =\n IS_BROWSER && /iPad|iPhone|iPod/.test(navigator.userAgent);\nexport const IS_SAFARI =\n IS_BROWSER && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n\nexport const SUPPORTS_HLS = (): boolean => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/vnd.apple.mpegurl\"));\n};\n\nexport const SUPPORTS_DASH = (): boolean => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/dash+xml\"));\n};\n","export const HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nexport const HLS_PATHS = /\\/hls\\//i;\nexport const DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nexport const VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nexport const AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\n\nexport const canPlay = {\n hls: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n\n dash: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n\n video: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n\n audio: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n\n file: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n },\n};\n","import { Component } from \"react\";\nimport { StormcloudVideoPlayer } from \"../player/StormcloudVideoPlayer\";\nimport type { StormcloudVideoPlayerConfig } from \"../types\";\nimport { canPlay } from \"../patterns\";\n\nexport interface HlsPlayerProps extends StormcloudVideoPlayerConfig {\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n}\n\nexport default class HlsPlayer extends Component<HlsPlayerProps> {\n static displayName = \"HlsPlayer\";\n\n static canPlay = canPlay.hls;\n\n private player: StormcloudVideoPlayer | null = null;\n private mounted = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n\n componentDidUpdate(prevProps: HlsPlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n\n const config: StormcloudVideoPlayerConfig = {\n src: this.props.src,\n videoElement: this.props.videoElement,\n };\n\n if (this.props.autoplay !== undefined)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== undefined)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== undefined)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== undefined)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== undefined)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== undefined)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== undefined)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== undefined)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== undefined)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== undefined)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== undefined)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== undefined)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== undefined)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n\n this.player = new StormcloudVideoPlayer(config);\n\n this.props.onMount?.(this);\n\n await this.player.load();\n\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n\n play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource =\n video.src ||\n (video.currentSrc && video.currentSrc !== \"\") ||\n video.readyState >= 1;\n\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return (this.player as any).hls;\n return null;\n };\n\n render() {\n return null;\n }\n}\n","import { Component } from \"react\";\nimport { canPlay } from \"../patterns\";\n\nexport interface FilePlayerProps {\n src: string;\n videoElement?: HTMLVideoElement;\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n autoplay?: boolean;\n muted?: boolean;\n loop?: boolean;\n controls?: boolean;\n playsInline?: boolean;\n preload?: string;\n poster?: string;\n}\n\nexport default class FilePlayer extends Component<FilePlayerProps> {\n static displayName = \"FilePlayer\";\n\n static canPlay = canPlay.file;\n\n private mounted = false;\n private ready = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n }\n\n componentDidUpdate(prevProps: FilePlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n const video = this.props.videoElement;\n\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n\n const handleError = (error: any) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\n };\n\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n\n video.src = this.props.src;\n if (this.props.autoplay !== undefined) video.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) video.muted = this.props.muted;\n if (this.props.loop !== undefined) video.loop = this.props.loop;\n if (this.props.controls !== undefined) video.controls = this.props.controls;\n if (this.props.playsInline !== undefined)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== undefined)\n video.preload = this.props.preload as \"\" | \"metadata\" | \"none\" | \"auto\";\n if (this.props.poster !== undefined) video.poster = this.props.poster;\n\n this.props.onMount?.(this);\n\n return () => {\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n };\n };\n\n play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource =\n video.src ||\n (video.currentSrc && video.currentSrc !== \"\") ||\n video.readyState >= 1;\n\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[FilePlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n } else {\n console.warn(\"[FilePlayer] Cannot play: video has no valid source\");\n }\n }\n };\n\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n setLoop = (loop: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n\n enablePIP = async () => {\n if (\n this.props.videoElement &&\n \"requestPictureInPicture\" in this.props.videoElement\n ) {\n try {\n await (this.props.videoElement as any).requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n\n disablePIP = async () => {\n if (document.pictureInPictureElement) {\n try {\n await document.exitPictureInPicture();\n } catch (error) {\n console.warn(\"Exit Picture-in-Picture failed:\", error);\n }\n }\n };\n\n render() {\n return null;\n }\n}\n","import { lazy } from \"../utils\";\nimport { canPlay } from \"../patterns\";\nimport HlsPlayer from \"./HlsPlayer\";\nimport FilePlayer from \"./FilePlayer\";\n\nexport interface PlayerConfig {\n key: string;\n name: string;\n canPlay: (url: string) => boolean;\n canEnablePIP?: (url: string) => boolean;\n lazyPlayer?: any;\n}\n\nconst players: PlayerConfig[] = [\n {\n key: \"hls\",\n name: \"HLS Player\",\n canPlay: canPlay.hls,\n lazyPlayer: lazy(() => Promise.resolve({ default: HlsPlayer })),\n },\n {\n key: \"file\",\n name: \"File Player\",\n canPlay: canPlay.file,\n canEnablePIP: (url: string) => {\n return (\n canPlay.file(url) &&\n (document.pictureInPictureEnabled ||\n typeof (document as any).webkitSupportsPresentationMode ===\n \"function\")\n );\n },\n lazyPlayer: lazy(() => Promise.resolve({ default: FilePlayer })),\n },\n];\n\nexport default players;\n","import React, { Component } from \"react\";\nimport type { BaseStormcloudPlayerProps, OnProgressProps } from \"./props\";\nimport { defaultProps } from \"./props\";\nimport { isMediaStream } from \"./utils\";\n\nconst SEEK_ON_PLAY_EXPIRY = 5000;\n\nexport interface PlayerProps extends BaseStormcloudPlayerProps {\n activePlayer: any;\n onReady: () => void;\n}\n\nexport default class Player extends Component<PlayerProps> {\n static displayName = \"Player\";\n static defaultProps = defaultProps;\n\n private mounted = false;\n private isReady = false;\n private isPlaying = false;\n private isLoading = true;\n private loadOnReady: string | null = null;\n private startOnPlay = true;\n private seekOnPlay: number | null = null;\n private onDurationCalled = false;\n private progressTimeout?: number;\n private durationCheckTimeout?: number;\n private prevPlayed?: number;\n private prevLoaded?: number;\n private player?: any;\n\n componentDidMount() {\n this.mounted = true;\n }\n\n componentWillUnmount() {\n clearTimeout(this.progressTimeout);\n clearTimeout(this.durationCheckTimeout);\n this.mounted = false;\n }\n\n componentDidUpdate(prevProps: PlayerProps) {\n if (!this.player) return;\n\n const { src, playing, volume, muted, playbackRate, loop, activePlayer } =\n this.props;\n\n if (prevProps.src !== src) {\n if (this.isLoading && !activePlayer.forceLoad && !isMediaStream(src)) {\n console.warn(\n `StormcloudPlayer: the attempt to load ${src} is being deferred until the player has loaded`\n );\n this.loadOnReady = src || null;\n return;\n }\n this.isLoading = true;\n this.startOnPlay = true;\n this.onDurationCalled = false;\n this.player.load(src, this.isReady);\n }\n\n if (!prevProps.playing && playing && !this.isPlaying) {\n this.player.play();\n }\n\n if (prevProps.playing && !playing && this.isPlaying) {\n this.player.pause();\n }\n\n if (prevProps.volume !== volume && volume !== null) {\n this.player.setVolume(volume);\n }\n\n if (prevProps.muted !== muted) {\n if (muted) {\n this.player.mute();\n } else {\n this.player.unmute();\n if (volume !== null) {\n setTimeout(() => this.player.setVolume(volume));\n }\n }\n }\n\n if (\n prevProps.playbackRate !== playbackRate &&\n this.player.setPlaybackRate\n ) {\n this.player.setPlaybackRate(playbackRate);\n }\n\n if (prevProps.loop !== loop && this.player.setLoop) {\n this.player.setLoop(loop);\n }\n }\n\n handlePlayerMount = (player: any) => {\n if (this.player) {\n this.progress();\n return;\n }\n\n this.player = player;\n this.player.load(this.props.src);\n this.progress();\n };\n\n getInternalPlayer = (key?: string) => {\n if (!this.player) return null;\n return this.player.getInternalPlayer(key);\n };\n\n progress = () => {\n if (this.props.src && this.player && this.isReady) {\n const playedSeconds = this.getCurrentTime() || 0;\n const loadedSeconds = this.getSecondsLoaded();\n const duration = this.getDuration();\n\n if (duration) {\n const progress: OnProgressProps = {\n playedSeconds,\n played: playedSeconds / duration,\n loaded: 0,\n loadedSeconds: 0,\n };\n\n if (loadedSeconds !== null) {\n progress.loadedSeconds = loadedSeconds;\n progress.loaded = loadedSeconds / duration;\n }\n\n if (\n progress.playedSeconds !== this.prevPlayed ||\n progress.loadedSeconds !== this.prevLoaded\n ) {\n this.props.onProgress?.(progress);\n }\n\n this.prevPlayed = progress.playedSeconds;\n this.prevLoaded = progress.loadedSeconds;\n }\n }\n\n this.progressTimeout = window.setTimeout(\n this.progress,\n this.props.progressInterval || 1000\n );\n };\n\n handleReady = () => {\n if (!this.mounted) return;\n\n this.isReady = true;\n this.isLoading = false;\n\n const { onReady, playing, volume, muted } = this.props;\n onReady();\n\n if (!muted && volume !== null) {\n this.player.setVolume(volume);\n }\n\n if (this.loadOnReady) {\n this.player.load(this.loadOnReady, true);\n this.loadOnReady = null;\n } else if (playing) {\n this.player.play();\n }\n\n this.handleDurationCheck();\n };\n\n handlePlay = () => {\n this.isPlaying = true;\n this.isLoading = false;\n\n const { onStart, onPlay, playbackRate } = this.props;\n\n if (this.startOnPlay) {\n if (this.player.setPlaybackRate && playbackRate !== 1) {\n this.player.setPlaybackRate(playbackRate);\n }\n onStart?.();\n this.startOnPlay = false;\n }\n\n onPlay?.();\n\n if (this.seekOnPlay) {\n this.seekTo(this.seekOnPlay);\n this.seekOnPlay = null;\n }\n\n this.handleDurationCheck();\n };\n\n handlePause = (e?: any) => {\n this.isPlaying = false;\n if (!this.isLoading) {\n this.props.onPause?.(e);\n }\n };\n\n handleEnded = () => {\n const { activePlayer, loop, onEnded } = this.props;\n if (activePlayer.loopOnEnded && loop) {\n this.seekTo(0);\n }\n if (!loop) {\n this.isPlaying = false;\n onEnded?.();\n }\n };\n\n handleError = (...args: any[]) => {\n this.isLoading = false;\n this.props.onError?.(args[0], args[1], args[2], args[3]);\n };\n\n handleDurationCheck = () => {\n clearTimeout(this.durationCheckTimeout);\n const duration = this.getDuration();\n if (duration) {\n if (!this.onDurationCalled) {\n this.props.onDuration?.(duration);\n this.onDurationCalled = true;\n }\n } else {\n this.durationCheckTimeout = window.setTimeout(\n this.handleDurationCheck,\n 100\n );\n }\n };\n\n handleLoaded = () => {\n this.isLoading = false;\n };\n\n getDuration(): number | null {\n if (!this.isReady) return null;\n return this.player.getDuration();\n }\n\n getCurrentTime(): number | null {\n if (!this.isReady) return null;\n return this.player.getCurrentTime();\n }\n\n getSecondsLoaded(): number | null {\n if (!this.isReady) return null;\n return this.player.getSecondsLoaded();\n }\n\n seekTo(amount: number, type?: \"seconds\" | \"fraction\", keepPlaying?: boolean) {\n if (!this.isReady) {\n if (amount !== 0) {\n this.seekOnPlay = amount;\n setTimeout(() => {\n this.seekOnPlay = null;\n }, SEEK_ON_PLAY_EXPIRY);\n }\n return;\n }\n\n const isFraction = !type ? amount > 0 && amount < 1 : type === \"fraction\";\n if (isFraction) {\n const duration = this.player.getDuration();\n if (!duration) {\n console.warn(\n \"StormcloudPlayer: could not seek using fraction – duration not yet available\"\n );\n return;\n }\n this.player.seekTo(duration * amount, keepPlaying);\n return;\n }\n this.player.seekTo(amount, keepPlaying);\n }\n\n render() {\n const Player = this.props.activePlayer;\n if (!Player) {\n return null;\n }\n\n return React.createElement(Player, {\n ...this.props,\n onMount: this.handlePlayerMount,\n onReady: this.handleReady,\n onPlay: this.handlePlay,\n onPause: this.handlePause,\n onEnded: this.handleEnded,\n onLoaded: this.handleLoaded,\n onError: this.handleError,\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24/Dev/stormcloud-vp/lib/index.js","../src/ui/StormcloudVideoPlayer.tsx","../src/player/StormcloudVideoPlayer.ts","../src/utils/browserCompat.ts","../src/sdk/ima.ts","../src/sdk/hlsAdPlayer.ts","../src/utils/tracking.ts","../src/utils/polyfills.ts","../src/StormcloudPlayer.tsx","../src/props.ts","../src/utils.ts","../src/patterns.ts","../src/players/HlsPlayer.tsx","../src/players/FilePlayer.tsx","../src/players/index.ts","../src/Player.tsx"],"names":["React","useEffect","useRef","useMemo","Hls","getChromeVersion","ua","match","parseInt","getWebKitVersion","getPlatform","navigator","userAgentData","platform","userAgent","test","detectBrowser","name","version","majorVersion","isSmartTV","isLegacyTV","supportsIMA","supportsModernJS","recommendedAdPlayer","parts","split","chromeVersion","webkitVersion","toString","Promise","Map","Set","URLSearchParams","supportsGoogleIMA","browser","document","createElement","video","e","getRecommendedAdPlayer","Array","from","Object","assign","prototype","forEach","String","includes","logBrowserInfo","debug","imaSupport","console","log","getBrowserConfigOverrides","overrides","adPlayerType","allowNativeHls","supportsFeature","feature","TextEncoder","fetch","crypto","subtle","createImaController","options","adPlaying","contentVideoHidden","originalMutedState","originalVolume","volume","Number","isNaN","Math","max","min","listeners","preloadedVast","preloadingVast","adVideoElement","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","hideContentVideo","style","transition","opacity","setTimeout","visibility","muted","showContentVideo","offsetHeight","createAdVideoElement","adVideo","position","top","left","width","height","objectFit","backgroundColor","zIndex","playsInline","addEventListener","once","emit","event","payload","set","get","fn","ensureImaLoaded","window","warn","reject","Error","frameEl","frameElement","sandboxAttr","getAttribute","tokens","map","t","trim","filter","length","allowsScripts","has","error","google","ima","resolve","existing","querySelector","timeout","clearTimeout","script","src","async","defer","setAttribute","onload","onerror","head","appendChild","adsManager","adsLoader","adDisplayContainer","adContainerEl","lastAdTagUrl","retryAttempts","maxRetries","backoffBaseMs","adsLoadedPromise","adsLoadedResolve","adsLoadedReject","makeAdsRequest","vastTagUrl","adsRequest","AdsRequest","adTagUrl","videoWidth","offsetWidth","clientWidth","videoHeight","clientHeight","linearAdSlotWidth","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","setAdWillAutoPlay","willAutoPlay","paused","autoplay","setAdWillPlayMuted","willPlayMuted","vastLoadTimeout","requestAds","ensurePlaceholderContainer","container","right","bottom","display","alignItems","justifyContent","pointerEvents","parentElement","fetchVastDocument","response","mode","ok","status","text","destroyAdsManager","destroy","initialize","then","AdDisplayContainer","catch","currentReject","adsLoaderCls","message","URL","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","evt","adsRenderingSettings","AdsRenderingSettings","enablePreloading","getAdsManager","AdEvent","AdErrorEvent","AD_ERROR","errorEvent","getError","getMessage","delay","pow","continueLiveStreamDuringAds","play","CONTENT_PAUSE_REQUESTED","pause","STARTED","CONTENT_RESUME_REQUESTED","ALL_ADS_COMPLETED","adErrorEvent","preloadAds","inflight","preloadPromise","xml","delete","finally","hasPreloadedAd","adVolume","init","ViewMode","NORMAL","setVolume","start","stop","removeChild","clear","isAdPlaying","resize","on","listener","add","off","updateOriginalMutedState","nextVolume","getOriginalMutedState","getOriginalVolume","setAdVolume","clampedVolume","getAdVolume","getVolume","showPlaceholder","hidePlaceholder","createHlsAdPlayer","contentVideo","licenseKey","mainHlsInstance","adHls","currentAd","sessionId","preloadedAds","preloadingAds","destroyed","pendingTimeouts","trackingFired","impression","firstQuartile","midpoint","thirdQuartile","complete","generateSessionId","Date","now","random","substr","fireTrackingPixels","urls","url","trackingUrl","img","Image","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","bitrate","selectBestMediaFile","mediaFiles","firstFile","mainQuality","scoredFiles","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","sort","a","b","bestMatch","resolution","parseVastXml","xmlString","xmlDoc","parser","DOMParser","parseFromString","parserError","textContent","adElement","adId","title","isNoAdAvailable","toLowerCase","durationText","durationParts","duration","mediaFileElements","querySelectorAll","mf","index","type","bitrateAttr","bitrateValue","push","trackingUrls","mute","unmute","resume","fullscreen","exitFullscreen","skip","el","eventKey","clickThrough","id","fetchAndParseVastAd","vastXml","statusText","substring","setupAdEventListeners","progress","currentTime","handleAdComplete","handleAdError","ended","timeoutId","stillInPod","idx","indexOf","splice","previousMutedState","ad","contentVolume","mediaFile","isSupported","enableWorker","lowLatencyMode","loadSource","attachMedia","Events","MANIFEST_PARSED","ERROR","data","fatal","canPlayType","remove","cachedBrowserId","getClientInfo","screen","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isAndroid","isWebView","isWebApp","webosMatch","tizenMatch","tvMatch","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","location","hostname","origin","path","pathname","language","languages","join","cookieEnabled","doNotTrack","referrer","visibilityState","getBrowserID","clientInfo","fingerprintString","encodedData","utf8","buffer","i","hashBuffer","hashArray","hashHex","hash","char","fallbackHash","timestamp","JSON","stringify","digest","Uint8Array","encode","unescape","encodeURIComponent","charCodeAt","padStart","padEnd","sendInitialTracking","browserId","trackingData","headers","method","body","json","sendHeartbeat","heartbeatData","toISOString","polyfillURLSearchParams","URLSearchParamsPolyfill","params","parseQueryString","value","key","append","query","cleanQuery","startsWith","slice","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","replace","values","getAll","callback","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","constructor","reason","polyfillObjectAssign","target","sources","TypeError","to","nextSource","nextKey","hasOwnProperty","call","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","len","result","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","endsWith","polyfillStringIncludes","initializePolyfills","StormcloudVideoPlayer","config","attached","inAdBreak","ptsDriftEmaMs","adPodQueue","lastHeartbeatTime","currentAdIndex","totalAdsInBreak","showAds","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","adPodAllUrls","preloadingAdUrls","vastToMediaUrlMap","preloadedMediaUrls","preloadingMediaUrls","adRequestTokenCounter","activeAdRequestToken","adRequestWatchdogToken","adFailsafeToken","fetchedAdDurations","targetAdBreakDurationMs","isAdaptiveMode","failedVastUrls","continuousFetchingActive","adRequestQueue","successfulAdRequests","maxPlaceholderDurationMs","placeholderStartTimeMs","isShowingPlaceholder","consecutiveEmptyResponses","totalAdRequestsInBreak","lastEmptyResponseTimeMs","maxTotalAdRequestsPerBreak","maxConsecutiveEmptyResponses","baseEmptyResponseDelayMs","maxEmptyResponseDelayMs","browserOverrides","videoElement","debugAdTiming","createAdPlayer","vastMode","hls","load","attach","fetchAdConfiguration","initializeTracking","shouldUseNativeHls","isLive","adBehavior","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","_","minSegments","some","details","live","shouldContinueLiveStreamDuringAds","minSegmentsBeforePlay","LEVEL_LOADED","_evt","fragments","fragmentsToScan","frag","tagList","isArray","entry","tag","attrs","parseAttributeList","hasScteOut","durationSeconds","parseCueOutDuration","marker","raw","earlyDetection","expectedAdBreakDurationMs","currentAdBreakStartWallClockMs","clearAdStartTimer","handleAdStart","scheduleAdStopCountdown","FRAG_BUFFERED","err","FRAG_PARSING_METADATA","id3Tags","samples","s","ptsSeconds","pts","onId3Tag","FRAG_CHANGED","onScte35Marker","prog","parseCueOutCont","elapsed","hasScteIn","klass","toNumber","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","remaining","getRemainingAdMs","tryNextAvailableAd","handleAdPodComplete","errorPayload","nextPreloaded","findNextPreloadedAd","playSingleAd","handleAdFailure","clearAdFailsafeTimer","clearAdRequestWatchdog","timeUpdateHandler","onTimeUpdate","emptiedHandler","wasPaused","streamType","getStreamType","canNative","updatePtsDrift","parseScte35FromId3","decodeId3ValueToText","cueOutMatch","arg","dur","id3","cueOutContMatch","cont","cueInMatch","daterangeMatch","bin","parseScte35Binary","decoder","TextDecoder","decode","out","fromCharCode","durationMs","isManifestMarker","isManifestBasedMarker","forceImmediate","immediateManifestAds","hasPts","tol","driftToleranceMs","nowMs","estCurrentPtsMs","deltaMs","floor","markerPtsMs","tolerance","scheduleAdStartIn","elapsedMs","remainingMs","scheduled","findCurrentOrNextBreak","tags","selectVastTagsForBreak","apiVastTagUrl","first","rest","clearAdStopTimer","num","parseFloat","dStr","d","elapsedMatch","durationMatch","res","regex","exec","rawVal","val","n","splice_command_type","BitReader","buf","bytePos","bitPos","readBits","numBits","remainingInByte","toRead","currentByte","shift","mask","bits","skipBits","r","tableId","sectionLength","ptsAdjHigh","ptsAdjLow","spliceCommandLength","spliceCommandType","cancel","outOfNetwork","programSpliceFlag","durationFlag","spliceImmediateFlag","timeSpecifiedFlag","componentCount","high","low","durationTicks","heartbeatInterval","setInterval","sendHeartbeatIfNeeded","vastEndpoint","apiUrl","imaPayload","numberAds","vast","cue_tones","number_ads","apiNumberAds","getCurrentAdIndex","getTotalAdsInBreak","generateVastUrlsWithCorrelators","baseUrl","count","uniqueCorrelator","searchParams","isShowingAds","shouldShowNativeControls","showCustomControls","_marker","baseVastUrl","adBreakDurationMs","currentMuted","currentVolume","firstAdUrlArray","firstAdUrl","startContinuousFetching","continuousFetchLoop","maxQueueSize","newAdUrl","backoffDelay","stopContinuousFetching","retryCount","nextAdUrl","showPlaceholderAndWaitForAds","waitTime","checkInterval","maxChecks","schedule","candidate","startTimeMs","currentTimeSec","breakToPlay","findBreakForTime","handleMidAdJoin","adBreak","endMs","ms","ensureAdStoppedByTimer","adStopTimerId","pendingAds","checkIntervalMs","adBreakCheckIntervalMs","maxExtensionMsConfig","maxAdBreakExtensionMs","maxExtensionMs","elapsedSinceStartMs","expectedDurationMs","overrunMs","shouldExtendAdBreak","delayMs","adStartTimerId","ptsSecondsSample","sampleMs","isFinite","alpha","requestToken","playError","startAdRequestWatchdog","startAdFailsafeTimer","restoredMuted","restoredVolume","size","token","timeoutMs","adFailsafeTimeoutMs","adRequestWatchdogId","logAdState","failsafeMs","adFailsafeTimerId","videoPaused","imaAdPlaying","extra","fetchAndParseVastXml","xmlText","extractMediaUrlsFromVast","mediaUrls","lowerUrl","fetchVastDuration","calculateAdditionalAdsNeeded","totalFetchedDurationMs","fetchedCount","averageDurationMs","queuedButNotFetched","estimatedQueuedDurationMs","estimatedTotalDurationMs","remainingTimeMs","additionalAds","ceil","addAdaptiveAdsToQueue","newUrls","preloadMediaFile","mediaUrl","Range","preloadAllAdsInBackground","processedUrls","nextUrl","preloadPromises","find","preloadSingleAd","all","primaryMediaUrl","hasImaPreload","hasMediaPreload","end","toggleMute","currentPerceptualState","isMuted","newMutedState","toggleFullscreen","fullscreenElement","requestFullscreen","setMuted","isFullscreen","removeEventListener","clearInterval","FaPlay","FaPause","FaVolumeUp","FaVolumeMute","FaVolumeDown","FaExpand","FaCompress","FaSpinner","Fragment","jsx","jsxs","CRITICAL_PROPS","StormcloudVideoPlayerComponent","memo","props","hideLoadingIndicator","onVolumeToggle","onFullscreenToggle","onControlClick","onReady","wrapperClassName","wrapperStyle","className","controls","preload","poster","children","restVideoAttrs","videoRef","playerRef","bufferingTimeoutRef","useState","currentIndex","totalAds","adStatus","setAdStatus","setShouldShowNativeControls","setIsMuted","setIsFullscreen","setIsPlaying","setCurrentTime","setDuration","playbackRate","setPlaybackRate","showVolumeSlider","setShowVolumeSlider","showSpeedMenu","setShowSpeedMenu","isLoading","setIsLoading","isBuffering","setIsBuffering","showCenterPlay","setShowCenterPlay","showLicenseWarning","setShowLicenseWarning","innerWidth","viewportWidth","setViewportWidth","innerHeight","isPortrait","setIsPortrait","getResponsiveScale","responsiveScale","formatTime","seconds","hours","minutes","remainingSeconds","handlePlayPause","current","hasValidSource","currentSrc","readyState","handleCenterPlayClick","handleTimelineSeek","rect","currentTarget","getBoundingClientRect","clickX","clientX","newTime","handleVolumeChange","newVolume","handlePlaybackRateChange","rate","isHlsStream","shouldShowEnhancedControls","criticalPropsKey","prop","cfg","player","showNative","checkAdStatus","showAdsFromMethod","showAdsFromAttribute","prev","interval","handleResize","updateStates","currentTimeValue","durationValue","volumeValue","rateValue","handleFullscreenChange","handleLoadedMetadata","handleLoadedData","handleLoadStart","handleCanPlay","handleCanPlayThrough","handleWaiting","handlePlaying","handlePause","isAdActive","handleEnded","overflow","minHeight","maxWidth","maxHeight","borderRadius","boxShadow","ref","aspectRatio","color","animation","transform","background","padding","backdropFilter","border","textAlign","margin","fontSize","fontWeight","marginBottom","textShadow","lineHeight","onClick","cursor","onMouseEnter","borderColor","onMouseLeave","marginLeft","flexWrap","gap","minWidth","flexDirection","onMouseDown","preventDefault","sliderElement","handleMouseMove","moveEvent","y","clientY","percentage","handleMouseUp","stopPropagation","onMouseUp","fontFamily","speed","borderBottom","prevProps","nextProps","uiProps","callbackProps","Component","Suspense","noop","defaultProps","playing","loop","progressInterval","onStart","onPlay","onPause","onBuffer","onBufferEnd","onEnded","onError","onDuration","onSeek","onProgress","lazy","reactLazy","omit","object","keys","isMediaStream","MediaStream","supportsWebKitPresentationMode","randomString","parseQuery","queryString","manualParse","qs","merge","source","isObject","item","IS_BROWSER","IS_GLOBAL","globalThis","IS_IOS","IS_SAFARI","SUPPORTS_HLS","Boolean","SUPPORTS_DASH","HLS_EXTENSIONS","HLS_PATHS","DASH_EXTENSIONS","VIDEO_EXTENSIONS","AUDIO_EXTENSIONS","canPlay","dash","audio","HlsPlayer","mounted","onMount","seekTo","keepPlaying","getDuration","getCurrentTime","getSecondsLoaded","buffered","getInternalPlayer","componentDidMount","componentWillUnmount","componentDidUpdate","render","displayName","FilePlayer","ready","handlePlay","handleError","onLoaded","setLoop","enablePIP","requestPictureInPicture","disablePIP","pictureInPictureElement","exitPictureInPicture","players","lazyPlayer","default","canEnablePIP","pictureInPictureEnabled","webkitSupportsPresentationMode","players_default","SEEK_ON_PLAY_EXPIRY","Player","arguments","isReady","loadOnReady","startOnPlay","seekOnPlay","onDurationCalled","handlePlayerMount","playedSeconds","loadedSeconds","played","loaded","prevPlayed","prevLoaded","progressTimeout","handleReady","handleDurationCheck","activePlayer","loopOnEnded","args","durationCheckTimeout","handleLoaded","forceLoad","amount","isFraction","UniversalSuspense","SUPPORTED_PROPS","customPlayers","createStormcloudPlayer","playerList","fallback","_a","state","showPreview","references","wrapper","getActivePlayer","getAttributes","fraction","renderActivePlayer","fallbackElement","Wrapper","attributes","wrapperRef","addCustomPlayer","removeCustomPlayers","StormcloudPlayer","StormcloudPlayer_default"],"mappings":"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","sourcesContent":["// src/ui/StormcloudVideoPlayer.tsx\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\n// src/player/StormcloudVideoPlayer.ts\nimport Hls2 from \"hls.js\";\n\n// src/utils/browserCompat.ts\nfunction getChromeVersion(ua) {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getWebKitVersion(ua) {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getPlatform() {\n if (\"userAgentData\" in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? \"iPhone\" : \"MacIntel\";\n }\n if (/Win/i.test(ua)) {\n return \"Win32\";\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? \"Linux armv8l\" : \"Linux x86_64\";\n }\n if (/CrOS/i.test(ua)) {\n return \"CrOS\";\n }\n return navigator.platform || \"Unknown\";\n}\nfunction detectBrowser() {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n let name = \"Unknown\";\n let version = \"0\";\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS2 = true;\n let recommendedAdPlayer = \"ima\";\n if (/Web0S|webOS/i.test(ua)) {\n name = \"LG WebOS\";\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = \"Samsung Tizen\";\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n }\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS2 = false;\n isLegacyTV = true;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS2 = false;\n if (isSmartTV) {\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS2 = false;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n if (typeof URLSearchParams === \"undefined\") {\n supportsModernJS2 = false;\n }\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS: supportsModernJS2,\n recommendedAdPlayer\n };\n}\nfunction supportsGoogleIMA() {\n const browser = detectBrowser();\n if (browser.isLegacyTV) {\n return false;\n }\n if (typeof document === \"undefined\" || typeof document.createElement !== \"function\") {\n return false;\n }\n try {\n const video = document.createElement(\"video\");\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n if (typeof Promise === \"undefined\") {\n return false;\n }\n return browser.supportsIMA;\n}\nfunction getRecommendedAdPlayer() {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\n}\nfunction supportsModernJS() {\n try {\n return typeof Promise !== \"undefined\" && typeof Map !== \"undefined\" && typeof Set !== \"undefined\" && typeof Array.from !== \"undefined\" && typeof Object.assign !== \"undefined\" && typeof Array.prototype.forEach !== \"undefined\" && typeof String.prototype.includes !== \"undefined\";\n } catch (e) {\n return false;\n }\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n console.log(\"[StormcloudVideoPlayer] Browser Compatibility Info:\", {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n userAgent: navigator.userAgent\n });\n}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = \"hls\";\n }\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\nfunction supportsFeature(feature) {\n switch (feature) {\n case \"ima\":\n return supportsGoogleIMA();\n case \"urlsearchparams\":\n return typeof URLSearchParams !== \"undefined\";\n case \"textencoder\":\n return typeof TextEncoder !== \"undefined\";\n case \"promises\":\n return typeof Promise !== \"undefined\";\n case \"fetch\":\n return typeof fetch !== \"undefined\";\n case \"crypto\":\n return typeof crypto !== \"undefined\" && typeof crypto.subtle !== \"undefined\";\n default:\n return false;\n }\n}\n\n// src/sdk/ima.ts\nfunction createImaController(video, options) {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume = typeof video.volume === \"number\" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;\n const listeners = /* @__PURE__ */ new Map();\n const preloadedVast = /* @__PURE__ */ new Map();\n const preloadingVast = /* @__PURE__ */ new Map();\n let adVideoElement;\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n function hideContentVideo() {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n function showContentVideo() {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n function createAdVideoElement() {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"15\";\n adVideo.playsInline = true;\n adVideo.muted = false;\n adVideo.volume = originalMutedState ? 0 : originalVolume;\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n return adVideo;\n }\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {\n }\n }\n }\n function ensureImaLoaded() {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n try {\n const frameEl = window.frameElement;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr.split(/\\s+/).map((t) => t.trim()).filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {\n }\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n );\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 1e4);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n let adsManager;\n let adsLoader;\n let adDisplayContainer;\n let adContainerEl;\n let lastAdTagUrl;\n let retryAttempts = 0;\n const maxRetries = 2;\n const backoffBaseMs = 500;\n let adsLoadedPromise;\n let adsLoadedResolve;\n let adsLoadedReject;\n function makeAdsRequest(google, vastTagUrl) {\n const adsRequest = new google.ima.AdsRequest();\n console.log(\"[IMA] \\u{1F4E1} Requesting VAST from URL (letting IMA fetch fresh)\");\n adsRequest.adTagUrl = vastTagUrl;\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 360;\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n adsRequest.vastLoadTimeout = 1e4;\n adsLoader.requestAds(adsRequest);\n }\n function ensurePlaceholderContainer() {\n if (adContainerEl) {\n return;\n }\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n async function fetchVastDocument(vastTagUrl) {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to preload VAST: ${response.status}`);\n }\n return response.text();\n }\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {\n }\n adsManager = void 0;\n }\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n return {\n initialize() {\n ensureImaLoaded().then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {\n }\n }\n }).catch(() => {\n });\n },\n async requestAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n console.warn(\"[IMA] \\u274C\", error.message);\n return Promise.reject(error);\n }\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n console.warn(\"[IMA] \\u274C\", error.message);\n return Promise.reject(error);\n }\n if (adPlaying) {\n console.warn(\n \"[IMA] \\u26A0\\uFE0F Cannot request new ads while an ad is playing. Call stop() first.\"\n );\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n destroyAdsManager();\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n let currentReject;\n adsLoadedPromise = new Promise((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n }, 1e4);\n });\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n retryAttempts = 0;\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n video.parentElement.appendChild(container);\n adContainerEl = container;\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n }\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n console.warn(\"[IMA]\", error.message);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt) => {\n try {\n const adsRenderingSettings = new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent) => {\n const error = errorEvent.getError();\n console.error(\"[DEBUG-ERROR] \\u274C AD_ERROR:\", error.getMessage?.());\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n if (lastAdTagUrl && retryAttempts < maxRetries) {\n const delay = backoffBaseMs * Math.pow(2, retryAttempts++);\n window.setTimeout(() => {\n try {\n makeAdsRequest(google, lastAdTagUrl);\n } catch {\n }\n }, delay);\n } else {\n emit(\"ad_error\");\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {\n });\n }\n }\n }\n }\n );\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n adPlaying = true;\n setAdPlayingFlag(true);\n emit(\"content_pause\");\n }\n );\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n hideContentVideo();\n if (adVideoElement) {\n adVideoElement.volume = originalMutedState ? 0 : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n emit(\"content_resume\");\n }\n );\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds && video.paused) {\n video.play().catch(() => {\n });\n }\n emit(\"all_ads_completed\");\n });\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = void 0;\n adsLoadedReject = void 0;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {\n });\n }\n }\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent) => {\n const error = adErrorEvent.getError();\n console.error(\"[DEBUG-ERROR] \\u274C ADS_LOADER ERROR:\", error.getMessage?.());\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {\n });\n }\n }\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ads loader error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n },\n false\n );\n }\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n if (preloadedVast.has(vastTagUrl)) {\n return Promise.resolve();\n }\n const inflight = preloadingVast.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {\n preloadedVast.set(vastTagUrl, xml);\n }).catch(() => {\n preloadedVast.delete(vastTagUrl);\n }).finally(() => {\n preloadingVast.delete(vastTagUrl);\n });\n preloadingVast.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl) {\n return preloadedVast.has(vastTagUrl);\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 360;\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n adPlaying = true;\n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n try {\n adsManager.setVolume(adVolume);\n } catch {\n }\n adsManager.start();\n return Promise.resolve();\n } catch (error) {\n console.error(\"[IMA] \\u274C Error starting ad:\", error);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {\n });\n }\n return Promise.reject(error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n try {\n adsManager?.stop?.();\n } catch {\n }\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n adVideoElement = void 0;\n }\n }, 300);\n }\n showContentVideo();\n try {\n adsLoader?.destroy?.();\n } catch {\n }\n adDisplayContainer = void 0;\n adsLoader = void 0;\n contentVideoHidden = false;\n preloadedVast.clear();\n preloadingVast.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {\n }\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n hideContentVideo();\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n if (!adPlaying) {\n showContentVideo();\n }\n }\n };\n}\n\n// src/sdk/hlsAdPlayer.ts\nimport Hls from \"hls.js\";\nfunction createHlsAdPlayer(contentVideo, options) {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = /* @__PURE__ */ new Map();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n const preloadedAds = /* @__PURE__ */ new Map();\n const preloadingAds = /* @__PURE__ */ new Map();\n let destroyed = false;\n let pendingTimeouts = [];\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels(urls) {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n }\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level2 = mainHlsInstance.levels[autoLevel];\n return {\n width: level2.width || 1920,\n height: level2.height || 1080,\n bitrate: level2.bitrate || 5e6\n };\n }\n return null;\n }\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5e6\n };\n }\n function selectBestMediaFile(mediaFiles) {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n const fileBitrate = (file.bitrate || 5e3) * 1e3;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1e3;\n return { file, score, resolutionDiff, bitrateDiff };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff\n });\n return bestMatch.file;\n }\n function parseVastXml(xmlString) {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n if (!url) {\n console.warn(\n `[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0\n });\n console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not HLS)`\n );\n }\n });\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No HLS media files found in VAST XML\");\n }\n return null;\n }\n const trackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: []\n };\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n async function fetchAndParseVastAd(vastTagUrl) {\n const response = await fetch(vastTagUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml);\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n video.volume = 1;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n const progress = adVideoElement.currentTime / currentAd.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function handleAdComplete() {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n emit(\"content_resume\");\n const timeoutId = window.setTimeout(() => {\n if (destroyed) {\n console.log(\"[HlsAdPlayer] Player destroyed, skipping post-completion check\");\n return;\n }\n const stillInPod = contentVideo.dataset.stormcloudAdPlaying === \"true\";\n if (stillInPod) {\n console.log(\n \"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)\"\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n }\n const idx = pendingTimeouts.indexOf(timeoutId);\n if (idx !== -1) {\n pendingTimeouts.splice(idx, 1);\n }\n }, 50);\n pendingTimeouts.push(timeoutId);\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n contentVideo.play().catch(() => {\n });\n }\n }\n emit(\"ad_error\");\n }\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n async requestAds(vastTagUrl) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n try {\n sessionId = generateSessionId();\n let ad;\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.resolve();\n }\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n if (preloadedAds.has(vastTagUrl)) {\n return Promise.resolve();\n }\n const inflight = preloadingAds.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {\n if (ad) {\n preloadedAds.set(vastTagUrl, ad);\n console.log(\n \"[HlsAdPlayer] Cached VAST response for preloading:\",\n vastTagUrl\n );\n }\n }).catch((error) => {\n console.warn(\"[HlsAdPlayer] Failed to preload VAST response:\", error);\n preloadedAds.delete(vastTagUrl);\n }).finally(() => {\n preloadingAds.delete(vastTagUrl);\n });\n preloadingAds.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl) {\n return preloadedAds.has(vastTagUrl);\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false\n });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(\"HLS not supported\");\n }\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n currentAd = void 0;\n },\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n }\n };\n}\n\n// src/utils/tracking.ts\nvar cachedBrowserId = null;\nfunction getClientInfo() {\n const ua = navigator.userAgent;\n const platform = navigator.platform;\n const vendor = navigator.vendor || \"\";\n const maxTouchPoints = navigator.maxTouchPoints || 0;\n const memory = navigator.deviceMemory || null;\n const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n const screenInfo = {\n width: screen?.width,\n height: screen?.height,\n availWidth: screen?.availWidth,\n availHeight: screen?.availHeight,\n orientation: screen?.orientation?.type || \"\",\n pixelDepth: screen?.pixelDepth\n };\n let deviceType = \"desktop\";\n let brand = \"Unknown\";\n let os = \"Unknown\";\n let model = \"\";\n let isSmartTV = false;\n let isAndroid = false;\n let isWebView = false;\n let isWebApp = false;\n if (ua.includes(\"Web0S\")) {\n brand = \"LG\";\n os = \"webOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n } else if (ua.includes(\"Tizen\")) {\n brand = \"Samsung\";\n os = \"Tizen\";\n isSmartTV = true;\n deviceType = \"tv\";\n const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n model = tizenMatch ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim() : \"Tizen TV\";\n } else if (ua.includes(\"Philips\")) {\n brand = \"Philips\";\n os = \"Saphi\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n brand = \"Sharp\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Android\") && (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))) {\n brand = \"Sony\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Android\") && (ua.includes(\"NetCast\") || ua.includes(\"LG\"))) {\n brand = \"LG\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n brand = \"Roku\";\n os = \"Roku OS\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"AppleTV\")) {\n brand = \"Apple\";\n os = \"tvOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n }\n if (ua.includes(\"Android\")) {\n isAndroid = true;\n os = \"Android\";\n deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n if (ua.includes(\"Android\") && (maxTouchPoints === 0 || ua.includes(\"Google TV\") || ua.includes(\"XiaoMi\"))) {\n deviceType = \"tv\";\n isSmartTV = true;\n brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n }\n const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n if (androidModelMatch && androidModelMatch[1]) {\n model = androidModelMatch[1];\n }\n }\n if (/iPad|iPhone|iPod/.test(ua)) {\n os = \"iOS\";\n deviceType = \"mobile\";\n brand = \"Apple\";\n if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n deviceType = \"tablet\";\n }\n }\n if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n if (ua.includes(\"Windows\")) {\n os = \"Windows\";\n deviceType = \"desktop\";\n } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n os = \"macOS\";\n deviceType = \"desktop\";\n if (maxTouchPoints > 1) deviceType = \"tablet\";\n } else if (ua.includes(\"Linux\")) {\n os = \"Linux\";\n deviceType = \"desktop\";\n }\n }\n if (brand === \"Unknown\") {\n if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n if (vendor.includes(\"Apple\")) brand = \"Apple\";\n if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n }\n isWebView = /wv|WebView|Linux; U;/.test(ua);\n if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n isWebView = true;\n }\n isWebApp = window.matchMedia(\"(display-mode: standalone)\").matches || window.navigator.standalone === true || window.screen?.orientation?.angle !== void 0;\n return {\n brand,\n os,\n model: model || ua.substring(0, 50) + \"...\",\n deviceType,\n isSmartTV,\n isAndroid,\n isWebView,\n isWebApp,\n domain: window.location.hostname,\n origin: window.location.origin,\n path: window.location.pathname,\n userAgent: ua,\n vendor,\n platform,\n screen: screenInfo,\n hardwareConcurrency,\n deviceMemory: memory,\n maxTouchPoints,\n language: navigator.language,\n languages: navigator.languages?.join(\",\") || \"\",\n cookieEnabled: navigator.cookieEnabled,\n doNotTrack: navigator.doNotTrack || \"\",\n referrer: document.referrer,\n visibilityState: document.visibilityState\n };\n}\nasync function getBrowserID(clientInfo) {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n const fingerprintString = JSON.stringify(clientInfo);\n if (typeof crypto !== \"undefined\" && crypto.subtle && crypto.subtle.digest) {\n try {\n await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n let encodedData;\n if (typeof TextEncoder !== \"undefined\") {\n encodedData = new TextEncoder().encode(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\n const buffer = new Uint8Array(utf8.length);\n for (let i = 0; i < utf8.length; i++) {\n buffer[i] = utf8.charCodeAt(i);\n }\n encodedData = buffer;\n }\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n const timestamp = Date.now().toString(16).padStart(12, \"0\");\n const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\nasync function sendInitialTracking(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = {\n browserId,\n ...clientInfo\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\nasync function sendHeartbeat(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const heartbeatData = {\n browserId,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\n\n// src/utils/polyfills.ts\nfunction polyfillURLSearchParams() {\n if (typeof URLSearchParams !== \"undefined\") {\n return;\n }\n class URLSearchParamsPolyfill {\n constructor(init) {\n this.params = /* @__PURE__ */ new Map();\n if (typeof init === \"string\") {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n parseQueryString(query) {\n const cleanQuery = query.startsWith(\"?\") ? query.slice(1) : query;\n if (!cleanQuery) return;\n cleanQuery.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : \"\";\n this.append(decodedKey, decodedValue);\n }\n });\n }\n safeDecodeURIComponent(str) {\n try {\n return decodeURIComponent(str.replace(/\\+/g, \" \"));\n } catch (e) {\n return str;\n }\n }\n append(name, value) {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n delete(name) {\n this.params.delete(name);\n }\n get(name) {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;\n }\n getAll(name) {\n return this.params.get(name) || [];\n }\n has(name) {\n return this.params.has(name);\n }\n set(name, value) {\n this.params.set(name, [String(value)]);\n }\n forEach(callback) {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n toString() {\n const parts = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join(\"&\");\n }\n }\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\nfunction polyfillTextEncoder() {\n if (typeof TextEncoder !== \"undefined\") {\n return;\n }\n class TextEncoderPolyfill {\n constructor() {\n this.encoding = \"utf-8\";\n }\n encode(str) {\n const utf8 = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 128) {\n utf8.push(charcode);\n } else if (charcode < 2048) {\n utf8.push(192 | charcode >> 6, 128 | charcode & 63);\n } else if (charcode < 55296 || charcode >= 57344) {\n utf8.push(\n 224 | charcode >> 12,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n } else {\n i++;\n charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);\n utf8.push(\n 240 | charcode >> 18,\n 128 | charcode >> 12 & 63,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n window.TextEncoder = TextEncoderPolyfill;\n}\nfunction polyfillPromiseFinally() {\n if (typeof Promise !== \"undefined\" && !Promise.prototype.finally) {\n Promise.prototype.finally = function(callback) {\n const constructor = this.constructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) => constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\nfunction polyfillObjectAssign() {\n if (typeof Object.assign !== \"function\") {\n Object.assign = function(target, ...sources) {\n if (target == null) {\n throw new TypeError(\"Cannot convert undefined or null to object\");\n }\n const to = Object(target);\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n }\n}\nfunction polyfillArrayFrom() {\n if (!Array.from) {\n Array.from = function(arrayLike, mapFn, thisArg) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError(\"Array.from requires an array-like object\");\n }\n const len = items.length >>> 0;\n const result = new Array(len);\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n return result;\n };\n }\n}\nfunction polyfillStringStartsWith() {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function(search, pos) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\nfunction polyfillStringEndsWith() {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function(search, length) {\n if (length === void 0 || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\nfunction polyfillStringIncludes() {\n if (!String.prototype.includes) {\n String.prototype.includes = function(search, start) {\n if (typeof start !== \"number\") {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\nfunction initializePolyfills() {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.adPodQueue = [];\n this.lastHeartbeatTime = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.showAds = false;\n this.isLiveStream = false;\n this.nativeHlsMode = false;\n this.videoSrcProtection = null;\n this.bufferedSegmentsCount = 0;\n this.shouldAutoplayAfterBuffering = false;\n this.hasInitialBufferCompleted = false;\n this.adPodAllUrls = [];\n this.preloadingAdUrls = /* @__PURE__ */ new Set();\n this.vastToMediaUrlMap = /* @__PURE__ */ new Map();\n this.preloadedMediaUrls = /* @__PURE__ */ new Set();\n this.preloadingMediaUrls = /* @__PURE__ */ new Set();\n this.adRequestTokenCounter = 0;\n this.activeAdRequestToken = null;\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.fetchedAdDurations = /* @__PURE__ */ new Map();\n this.targetAdBreakDurationMs = null;\n this.isAdaptiveMode = false;\n this.failedVastUrls = /* @__PURE__ */ new Set();\n this.continuousFetchingActive = false;\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n this.maxPlaceholderDurationMs = 5e3;\n this.placeholderStartTimeMs = null;\n this.isShowingPlaceholder = false;\n this.consecutiveEmptyResponses = 0;\n this.totalAdRequestsInBreak = 0;\n this.lastEmptyResponseTimeMs = 0;\n this.maxTotalAdRequestsPerBreak = 20;\n this.maxConsecutiveEmptyResponses = 5;\n this.baseEmptyResponseDelayMs = 2e3;\n this.maxEmptyResponseDelayMs = 3e4;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...config, ...browserOverrides };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.ima = this.createAdPlayer(false);\n }\n createAdPlayer(continueLiveStreamDuringAds) {\n const vastMode = this.config.vastMode || \"default\";\n let adPlayerType = this.config.adPlayerType || (vastMode === \"adstorm\" ? \"hls\" : \"ima\");\n if (adPlayerType === \"ima\" && !supportsGoogleIMA()) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player\"\n );\n }\n adPlayerType = \"hls\";\n }\n if (adPlayerType === \"hls\") {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)\"\n );\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},\n ...this.hls ? { mainHlsInstance: this.hls } : {}\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)\"\n );\n }\n return createImaController(this.video, {\n continueLiveStreamDuringAds\n });\n }\n }\n async load() {\n if (!this.attached) {\n this.attach();\n }\n try {\n await this.fetchAdConfiguration();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n this.initializeTracking();\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\"\n }\n );\n }\n this.ima.destroy();\n this.ima = this.createAdPlayer(false);\n this.ima.initialize();\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n return;\n }\n this.hls = new Hls2({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,\n ...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {},\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1e3 * 1e3,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1\n });\n this.hls.on(Hls2.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n this.hls.on(Hls2.Events.MANIFEST_PARSED, async (_, data) => {\n this.isLiveStream = this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds() ? \"live (main video continues muted during ads)\" : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior\n });\n }\n this.ima.destroy();\n this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.ima.initialize();\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n }\n });\n this.hls.on(Hls2.Events.LEVEL_LOADED, (_evt, data) => {\n if (this.inAdBreak) {\n return;\n }\n const details = data?.details;\n if (!details || !details.fragments || details.fragments.length === 0) {\n return;\n }\n const fragmentsToScan = Math.min(5, details.fragments.length);\n for (let i = 0; i < fragmentsToScan; i++) {\n const frag = details.fragments[i];\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) continue;\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n }\n }\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = tag.includes(\"EXT-X-DATERANGE\") ? this.parseAttributeList(value) : {};\n const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") || \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n if (hasScteOut) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] \\u{1F3AF} EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- triggering ad handling immediately\");\n }\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value, earlyDetection: true }\n };\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = durationSeconds ? durationSeconds * 1e3 : void 0;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n }\n }\n }\n });\n this.hls.on(Hls2.Events.FRAG_BUFFERED, async (_evt, data) => {\n if (this.hasInitialBufferCompleted) {\n return;\n }\n this.bufferedSegmentsCount++;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n this.hls.on(Hls2.Events.FRAG_PARSING_METADATA, (_evt, data) => {\n const id3Tags = (data?.samples || []).map((s) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n this.hls.on(Hls2.Events.FRAG_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n const marker = {\n type: \"progress\",\n ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},\n ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { tag, value, attrs }\n };\n this.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n this.hls.on(Hls2.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case Hls2.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case Hls2.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n attach() {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n this.ima.initialize();\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.ima.on(\"all_ads_completed\", () => {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`\n );\n }\n if (this.inAdBreak) {\n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n this.ima.on(\"ad_error\", (errorPayload) => {\n const remaining = this.getRemainingAdMs();\n console.error(\"[AD-ERROR] Ad playback failed\", errorPayload || \"\");\n if (this.inAdBreak) {\n if (remaining > 500 && this.adPodQueue.length > 0) {\n const nextPreloaded = this.findNextPreloadedAd();\n if (nextPreloaded) {\n this.currentAdIndex++;\n this.playSingleAd(nextPreloaded).catch(() => {\n this.handleAdFailure();\n });\n } else {\n this.handleAdFailure();\n }\n } else {\n this.handleAdFailure();\n }\n } else {\n this.handleAdFailure();\n }\n });\n this.ima.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n });\n this.ima.on(\"content_resume\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n return;\n }\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);\n }\n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n this.handleAdPodComplete();\n }\n });\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {\n });\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n shouldUseNativeHls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n parseScte35FromId3(tag) {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return void 0;\n const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) || text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...dur !== void 0 ? { durationSeconds: dur } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker = {\n type: \"progress\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n if (hasScteIn) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n }\n if (/SCTE35-OUT/i.test(text)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n }\n decodeId3ValueToText(value) {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]);\n return out;\n } catch {\n return void 0;\n }\n }\n onScte35Marker(marker) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw\n });\n }\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n return;\n }\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\"\n });\n }\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1e3;\n const nowMs = this.video.currentTime * 1e3;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1e3,\n deltaMs,\n tolerance: tol\n });\n }\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null) {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1e3\n );\n const tags = this.selectVastTagsForBreak(scheduled) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);\n if (tags && tags.length > 0) {\n const first = tags[0];\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n this.playSingleAd(first).catch(() => {\n });\n }\n }\n return;\n }\n if (marker.type === \"end\") {\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n if (this.ima.isAdPlaying()) {\n this.ima.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n return;\n }\n }\n parseCueOutDuration(value) {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match = value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) || value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? void 0 : d;\n }\n return void 0;\n }\n parseCueOutCont(value) {\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n const res = {};\n if (elapsedMatch && elapsedMatch[1] != null) {\n const e = parseFloat(elapsedMatch[1]);\n if (!Number.isNaN(e)) res.elapsed = e;\n }\n if (durationMatch && durationMatch[1] != null) {\n const d = parseFloat(durationMatch[1]);\n if (!Number.isNaN(d)) res.duration = d;\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return void 0;\n }\n parseAttributeList(value) {\n const attrs = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match;\n while ((match = regex.exec(value)) !== null) {\n const key = match[1] ?? \"\";\n let rawVal = match[3] ?? match[4] ?? \"\";\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n toNumber(val) {\n if (val == null) return void 0;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? void 0 : n;\n }\n isManifestBasedMarker(marker) {\n const raw = marker.raw;\n if (!raw) return false;\n if (raw.tag) {\n const tag = String(raw.tag);\n return tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-CUE-IN\") || tag.includes(\"EXT-X-DATERANGE\");\n }\n if (raw.id3) return false;\n if (raw.splice_command_type) return false;\n return false;\n }\n parseScte35Binary(data) {\n class BitReader {\n constructor(buf) {\n this.buf = buf;\n this.bytePos = 0;\n this.bitPos = 0;\n }\n readBits(numBits) {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos];\n const shift = remainingInByte - toRead;\n const mask = (1 << toRead) - 1 & 255;\n const bits = currentByte >> shift & mask;\n result = result << toRead | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n) {\n this.readBits(n);\n }\n }\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 252) return void 0;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return void 0;\n }\n r.readBits(32);\n const cancel = r.readBits(1) === 1;\n r.readBits(7);\n if (cancel) return void 0;\n const outOfNetwork = r.readBits(1) === 1;\n const programSpliceFlag = r.readBits(1) === 1;\n const durationFlag = r.readBits(1) === 1;\n const spliceImmediateFlag = r.readBits(1) === 1;\n r.readBits(4);\n if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n } else if (!programSpliceFlag) {\n const componentCount = r.readBits(8);\n for (let i = 0; i < componentCount; i++) {\n r.readBits(8);\n if (!spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds = void 0;\n if (durationFlag) {\n r.readBits(6);\n r.readBits(1);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const durationTicks = high * 4294967296 + low;\n durationSeconds = durationTicks / 9e4;\n }\n r.readBits(16);\n r.readBits(8);\n r.readBits(8);\n if (outOfNetwork) {\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { splice_command_type: 5 }\n };\n return marker;\n }\n return void 0;\n }\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n });\n }\n sendHeartbeatIfNeeded() {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n async fetchAdConfiguration() {\n const vastMode = this.config.vastMode || \"default\";\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n );\n }\n return;\n }\n const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n this.apiVastTagUrl = vastEndpoint;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n vastEndpoint\n );\n }\n return;\n }\n if (this.config.vastTagUrl) {\n this.apiVastTagUrl = this.config.vastTagUrl;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n return;\n }\n const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n apiUrl\n );\n }\n const headers = {};\n if (this.config.licenseKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n }\n const response = await fetch(apiUrl, { headers });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n );\n }\n return;\n }\n const data = await response.json();\n const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n if (imaPayload) {\n this.apiVastTagUrl = decodeURIComponent(imaPayload);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n );\n }\n }\n const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n if (numberAds != null && numberAds > 0) {\n this.apiNumberAds = numberAds;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n getCurrentAdIndex() {\n return this.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.totalAdsInBreak;\n }\n generateVastUrlsWithCorrelators(baseUrl, count) {\n const urls = [];\n for (let i = 0; i < count; i++) {\n try {\n const url = new URL(baseUrl);\n const timestamp = Date.now();\n const random = Math.floor(Math.random() * 1e6);\n const uniqueCorrelator = `${timestamp}${random}${i}`;\n url.searchParams.set(\"correlator\", uniqueCorrelator);\n urls.push(url.toString());\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to parse VAST URL:\",\n baseUrl,\n error\n );\n urls.push(`${baseUrl}${baseUrl.includes(\"?\") ? \"&\" : \"?\"}correlator=${Date.now()}${i}`);\n }\n }\n return urls;\n }\n isAdPlaying() {\n return this.inAdBreak && this.ima.isAdPlaying();\n }\n isShowingAds() {\n return this.showAds;\n }\n getStreamType() {\n const url = this.config.src.toLowerCase();\n if (url.includes(\".m3u8\") || url.includes(\"/hls/\") || url.includes(\"application/vnd.apple.mpegurl\")) {\n return \"hls\";\n }\n return \"other\";\n }\n shouldShowNativeControls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));\n }\n shouldContinueLiveStreamDuringAds() {\n if (this.config.allowNativeHls) {\n return false;\n }\n if (!this.isLiveStream) {\n return false;\n }\n return true;\n }\n async handleAdStart(_marker) {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1e3\n );\n const tags = this.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else {\n return;\n }\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled?.durationMs;\n if (this.isLiveStream && adBreakDurationMs != null && adBreakDurationMs > 0) {\n this.isAdaptiveMode = true;\n this.targetAdBreakDurationMs = adBreakDurationMs;\n this.fetchedAdDurations.clear();\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F4FA} LIVE MODE: Target duration=${adBreakDurationMs}ms | Will continuously fetch ads during break`\n );\n }\n } else {\n this.isAdaptiveMode = false;\n this.targetAdBreakDurationMs = null;\n this.fetchedAdDurations.clear();\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F3AC} VOD MODE: Using fixed ad strategy`\n );\n }\n }\n this.adPodAllUrls = [];\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.failedVastUrls.clear();\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n this.consecutiveEmptyResponses = 0;\n this.totalAdRequestsInBreak = 0;\n this.lastEmptyResponseTimeMs = 0;\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n this.inAdBreak = true;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n this.showAds = true;\n this.ima.showPlaceholder();\n if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F680} Immediately requesting first ad...\");\n }\n const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const firstAdUrl = firstAdUrlArray[0];\n if (!firstAdUrl) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F Failed to generate first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n try {\n await this.ima.requestAds(firstAdUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 First ad request successful, starting playback\");\n }\n this.successfulAdRequests.push(firstAdUrl);\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n await this.ima.play();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F First ad request failed:\", error);\n }\n this.failedVastUrls.add(firstAdUrl);\n this.startContinuousFetching(baseVastUrl);\n this.tryNextAvailableAd();\n }\n }\n startContinuousFetching(baseVastUrl) {\n if (!this.continuousFetchingActive) {\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F504} Starting continuous ad fetching loop\");\n }\n this.continuousFetchLoop(baseVastUrl);\n }\n async continuousFetchLoop(baseVastUrl) {\n while (this.continuousFetchingActive && this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F Ad break time expired, stopping fetch loop\");\n }\n break;\n }\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Maximum ad requests reached (${this.maxTotalAdRequestsPerBreak}), stopping fetch loop to prevent server blocks`);\n }\n break;\n }\n if (this.consecutiveEmptyResponses >= this.maxConsecutiveEmptyResponses) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive empty responses (${this.maxConsecutiveEmptyResponses}), stopping fetch loop`);\n }\n break;\n }\n const maxQueueSize = 3;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F8\\uFE0F Queue full (${this.adRequestQueue.length}), pausing fetching...`);\n }\n await new Promise((resolve) => setTimeout(resolve, 2e3));\n continue;\n }\n const newAdUrl = this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];\n if (!newAdUrl || this.failedVastUrls.has(newAdUrl)) {\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n continue;\n }\n this.totalAdRequestsInBreak++;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F4E1} Attempting to fetch ad (request ${this.totalAdRequestsInBreak}/${this.maxTotalAdRequestsPerBreak}, queue: ${this.adRequestQueue.length})...`);\n }\n try {\n if (this.ima.preloadAds) {\n await this.ima.preloadAds(newAdUrl);\n }\n const hasPreloadedAd = this.ima.hasPreloadedAd?.(newAdUrl) ?? false;\n if (!hasPreloadedAd) {\n this.consecutiveEmptyResponses++;\n this.lastEmptyResponseTimeMs = Date.now();\n const backoffDelay = Math.min(\n this.baseEmptyResponseDelayMs * Math.pow(2, this.consecutiveEmptyResponses - 1),\n this.maxEmptyResponseDelayMs\n );\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u26A0\\uFE0F Empty/invalid VAST response (${this.consecutiveEmptyResponses}/${this.maxConsecutiveEmptyResponses} consecutive), backing off for ${backoffDelay}ms`);\n }\n this.failedVastUrls.add(newAdUrl);\n await new Promise((resolve) => setTimeout(resolve, backoffDelay));\n continue;\n }\n this.consecutiveEmptyResponses = 0;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u2705 Successfully preloaded ad, adding to queue (queue size: ${this.adRequestQueue.length + 1})`);\n }\n this.adRequestQueue.push(newAdUrl);\n this.totalAdsInBreak++;\n await new Promise((resolve) => setTimeout(resolve, 500));\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u274C Ad preload failed:\", error.message);\n }\n this.failedVastUrls.add(newAdUrl);\n this.consecutiveEmptyResponses++;\n const backoffDelay = Math.min(\n this.baseEmptyResponseDelayMs * Math.pow(2, this.consecutiveEmptyResponses - 1),\n this.maxEmptyResponseDelayMs\n );\n await new Promise((resolve) => setTimeout(resolve, backoffDelay));\n }\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Continuous fetch loop ended (total requests: ${this.totalAdRequestsInBreak}, empty responses: ${this.consecutiveEmptyResponses})`);\n }\n }\n stopContinuousFetching() {\n this.continuousFetchingActive = false;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Stopping continuous ad fetching\");\n }\n }\n async tryNextAvailableAd(retryCount = 0) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (nextAdUrl) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F3AC} Playing next queued ad (${this.currentAdIndex + 1}/${this.totalAdsInBreak}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F50A} Updated ad audio state: muted=${currentMuted}, volume=${currentVolume}`);\n }\n this.currentAdIndex++;\n this.successfulAdRequests.push(nextAdUrl);\n await this.playSingleAd(nextAdUrl).catch(() => {\n this.tryNextAvailableAd(0);\n });\n return;\n }\n }\n const maxRetries = 5;\n if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2e3) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F3 Queue empty but fetching active, waiting... (retry ${retryCount + 1}/${maxRetries})`);\n }\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n await this.tryNextAvailableAd(retryCount + 1);\n return;\n }\n if (!this.isShowingPlaceholder && remaining > 1e3) {\n this.showPlaceholderAndWaitForAds();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No more ads available, ending ad break\");\n }\n this.handleAdPodComplete();\n }\n }\n async showPlaceholderAndWaitForAds() {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n if (waitTime < 1e3) {\n this.handleAdPodComplete();\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u2B1B Showing black placeholder for ${waitTime}ms while waiting for ads`);\n }\n this.isShowingPlaceholder = true;\n this.placeholderStartTimeMs = Date.now();\n this.ima.showPlaceholder();\n const checkInterval = 500;\n const maxChecks = Math.floor(waitTime / checkInterval);\n for (let i = 0; i < maxChecks; i++) {\n await new Promise((resolve) => setTimeout(resolve, checkInterval));\n if (!this.inAdBreak) {\n return;\n }\n if (this.adRequestQueue.length > 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 New ad became available during placeholder\");\n }\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n this.ima.hidePlaceholder();\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n const nextAdUrl = this.adRequestQueue.shift();\n if (nextAdUrl) {\n this.currentAdIndex++;\n this.successfulAdRequests.push(nextAdUrl);\n await this.playSingleAd(nextAdUrl).catch(() => {\n this.tryNextAvailableAd();\n });\n }\n return;\n }\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F0 Placeholder timeout reached, no ads fetched\");\n }\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n this.ima.hidePlaceholder();\n this.handleAdPodComplete();\n }\n findCurrentOrNextBreak(nowMs) {\n const schedule = [];\n let candidate;\n for (const b of schedule) {\n const tol = this.config.driftToleranceMs ?? 1e3;\n if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {\n candidate = b;\n }\n }\n return candidate;\n }\n onTimeUpdate(currentTimeSec) {\n if (this.ima.isAdPlaying()) return;\n const nowMs = currentTimeSec * 1e3;\n const breakToPlay = this.findBreakForTime(nowMs);\n if (breakToPlay) {\n this.handleMidAdJoin(breakToPlay, nowMs);\n }\n }\n async handleMidAdJoin(adBreak, nowMs) {\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = adBreak.startTimeMs + durationMs;\n if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {\n const remainingMs = endMs - nowMs;\n const tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);\n if (tags && tags.length > 0) {\n const first = tags[0];\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n await this.playSingleAd(first);\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = remainingMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(remainingMs);\n }\n }\n }\n scheduleAdStopCountdown(remainingMs) {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.ensureAdStoppedByTimer();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.ensureAdStoppedByTimer();\n }, ms);\n }\n clearAdStopTimer() {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = void 0;\n }\n }\n ensureAdStoppedByTimer() {\n if (!this.inAdBreak) return;\n this.adStopTimerId = void 0;\n const adPlaying = this.ima.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1e3)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs = typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n if (adPlaying) {\n this.ima.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n }\n scheduleAdStartIn(delayMs) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\n updatePtsDrift(ptsSecondsSample) {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n async playSingleAd(vastTagUrl) {\n if (this.ima.isAdPlaying()) {\n return;\n }\n if (this.failedVastUrls.has(vastTagUrl)) {\n console.warn(\"[AD-ERROR] Skipping already-failed VAST URL:\", vastTagUrl.substring(0, 60));\n this.handleAdFailure();\n return;\n }\n const requestToken = ++this.adRequestTokenCounter;\n this.activeAdRequestToken = requestToken;\n this.startAdRequestWatchdog(requestToken);\n try {\n await this.ima.requestAds(vastTagUrl);\n this.clearAdRequestWatchdog();\n if (this.activeAdRequestToken !== requestToken) {\n return;\n }\n try {\n this.startAdFailsafeTimer(requestToken);\n await this.ima.play();\n } catch (playError) {\n console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n this.failedVastUrls.add(vastTagUrl);\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n this.handleAdFailure();\n return;\n }\n } catch (error) {\n console.error(\"[AD-ERROR] Ad request failed:\", error?.message);\n this.failedVastUrls.add(vastTagUrl);\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n this.handleAdFailure();\n }\n }\n handleAdPodComplete() {\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.stopContinuousFetching();\n if (this.isShowingPlaceholder) {\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n }\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.adPodAllUrls = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.ima.stop().catch(() => {\n });\n const restoredMuted = this.ima.getOriginalMutedState();\n const restoredVolume = this.ima.getOriginalVolume();\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n if (!this.shouldContinueLiveStreamDuringAds() && this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n }\n handleAdFailure() {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);\n }\n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n console.error(\"[AD-ERROR] Ad failed and no time remaining. Failed URLs:\", this.failedVastUrls.size);\n this.handleAdPodComplete();\n }\n }\n startAdRequestWatchdog(token) {\n this.clearAdRequestWatchdog();\n const timeoutMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n this.adRequestWatchdogToken = token;\n this.adRequestWatchdogId = window.setTimeout(() => {\n if (this.adRequestWatchdogToken !== token) {\n return;\n }\n this.adRequestWatchdogId = void 0;\n this.adRequestWatchdogToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n this.handleAdFailure();\n }, timeoutMs);\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n clearAdRequestWatchdog() {\n if (this.adRequestWatchdogId != null) {\n clearTimeout(this.adRequestWatchdogId);\n this.adRequestWatchdogId = void 0;\n }\n if (this.adRequestWatchdogToken != null) {\n this.logAdState(\"ad_request_watchdog_cleared\", {\n token: this.adRequestWatchdogToken\n });\n this.adRequestWatchdogToken = null;\n }\n }\n startAdFailsafeTimer(token) {\n this.clearAdFailsafeTimer();\n const failsafeMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n this.adFailsafeToken = token;\n this.adFailsafeTimerId = window.setTimeout(() => {\n if (this.adFailsafeToken !== token) {\n return;\n }\n this.adFailsafeTimerId = void 0;\n this.adFailsafeToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n this.logAdState(\"ad_failsafe_triggered\", {\n token,\n failsafeMs,\n videoPaused: this.video.paused,\n imaAdPlaying: this.ima.isAdPlaying()\n });\n this.handleAdFailure();\n }, failsafeMs);\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n clearAdFailsafeTimer() {\n if (this.adFailsafeTimerId != null) {\n clearTimeout(this.adFailsafeTimerId);\n this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n this.adFailsafeTimerId = void 0;\n }\n this.adFailsafeToken = null;\n }\n selectVastTagsForBreak(b) {\n if (!b || !b.vastTagUrl) return void 0;\n if (b.vastTagUrl.includes(\",\")) {\n return b.vastTagUrl.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n }\n return [b.vastTagUrl];\n }\n logAdState(event, extra = {}) {\n if (!this.config.debugAdTiming) {\n return;\n }\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n showAds: this.showAds,\n adPlaying: this.ima.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n async fetchAndParseVastXml(vastTagUrl) {\n try {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status}`);\n }\n const xmlText = await response.text();\n return this.extractMediaUrlsFromVast(xmlText);\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch/parse VAST XML: ${vastTagUrl}`,\n error\n );\n }\n return [];\n }\n }\n extractMediaUrlsFromVast(xmlText) {\n const mediaUrls = [];\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n for (const mediaFile of Array.from(mediaFileElements)) {\n const url = mediaFile.textContent?.trim();\n if (url) {\n const lowerUrl = url.toLowerCase();\n if (lowerUrl.endsWith(\".mp4\") || lowerUrl.endsWith(\".webm\") || lowerUrl.endsWith(\".mov\") || lowerUrl.endsWith(\".avi\") || lowerUrl.includes(\".mp4?\") || lowerUrl.includes(\".webm?\") || lowerUrl.includes(\"/mp4/\") || lowerUrl.includes(\"type=video\")) {\n mediaUrls.push(url);\n }\n }\n }\n if (this.config.debugAdTiming && mediaUrls.length > 0) {\n console.log(\n `[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs from VAST:`,\n mediaUrls\n );\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to parse VAST XML:\",\n error\n );\n }\n }\n return mediaUrls;\n }\n async fetchVastDuration(vastTagUrl) {\n try {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] Failed to fetch VAST: ${response.status}`\n );\n }\n return null;\n }\n const xmlText = await response.text();\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent;\n if (!durationText) {\n if (this.config.debugAdTiming) {\n console.warn(\"[ADAPTIVE-POD] No Duration element found in VAST\");\n }\n return null;\n }\n const durationParts = durationText.split(\":\");\n const durationSeconds = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n return durationSeconds;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] Error fetching VAST duration from ${vastTagUrl}:`,\n error\n );\n }\n return null;\n }\n }\n calculateAdditionalAdsNeeded() {\n if (!this.isAdaptiveMode || this.targetAdBreakDurationMs === null) {\n return 0;\n }\n let totalFetchedDurationMs = 0;\n for (const duration of this.fetchedAdDurations.values()) {\n totalFetchedDurationMs += duration * 1e3;\n }\n const fetchedCount = this.fetchedAdDurations.size;\n const averageDurationMs = fetchedCount > 0 ? totalFetchedDurationMs / fetchedCount : 30 * 1e3;\n const queuedButNotFetched = this.adPodAllUrls.length - fetchedCount;\n const estimatedQueuedDurationMs = queuedButNotFetched * averageDurationMs;\n const estimatedTotalDurationMs = totalFetchedDurationMs + estimatedQueuedDurationMs;\n const remainingTimeMs = this.targetAdBreakDurationMs - estimatedTotalDurationMs;\n if (remainingTimeMs <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u2705 Target duration met: Fetched=${totalFetchedDurationMs}ms + Queued(${queuedButNotFetched} ads)=${estimatedQueuedDurationMs}ms = ${estimatedTotalDurationMs}ms / Target=${this.targetAdBreakDurationMs}ms`\n );\n }\n return 0;\n }\n const additionalAds = Math.ceil(remainingTimeMs / averageDurationMs);\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F4CA} Need ${additionalAds} more ads | Fetched: ${totalFetchedDurationMs}ms (${fetchedCount} ads) | Queued: ${estimatedQueuedDurationMs}ms (${queuedButNotFetched} ads) | Target: ${this.targetAdBreakDurationMs}ms | Remaining: ${remainingTimeMs}ms | Avg duration: ${averageDurationMs}ms`\n );\n }\n return additionalAds;\n }\n async addAdaptiveAdsToQueue() {\n if (!this.isAdaptiveMode || !this.apiVastTagUrl) {\n return;\n }\n const additionalAds = this.calculateAdditionalAdsNeeded();\n if (additionalAds <= 0) {\n return;\n }\n const newUrls = this.generateVastUrlsWithCorrelators(\n this.apiVastTagUrl,\n additionalAds\n );\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F504} Adding ${newUrls.length} additional VAST URLs to queue (will be preloaded sequentially)`\n );\n }\n this.adPodAllUrls.push(...newUrls);\n this.adPodQueue.push(...newUrls);\n this.totalAdsInBreak += newUrls.length;\n }\n async preloadMediaFile(mediaUrl) {\n if (this.preloadedMediaUrls.has(mediaUrl)) {\n return;\n }\n if (this.preloadingMediaUrls.has(mediaUrl)) {\n return;\n }\n this.preloadingMediaUrls.add(mediaUrl);\n try {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Preloading video file: ${mediaUrl}`\n );\n }\n const response = await fetch(mediaUrl, {\n mode: \"cors\",\n method: \"GET\",\n headers: {\n Range: \"bytes=0-1048576\"\n }\n });\n if (response.ok || response.status === 206) {\n this.preloadedMediaUrls.add(mediaUrl);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Successfully preloaded video file: ${mediaUrl}`\n );\n }\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to preload video file: ${mediaUrl}`,\n error\n );\n }\n } finally {\n this.preloadingMediaUrls.delete(mediaUrl);\n }\n }\n async preloadAllAdsInBackground() {\n if (this.adPodAllUrls.length === 0) {\n return;\n }\n if (this.isAdaptiveMode) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F504} Starting sequential preload of remaining ads`\n );\n }\n const processedUrls = /* @__PURE__ */ new Set();\n for (const url of this.adPodAllUrls) {\n if (this.ima.hasPreloadedAd?.(url) || this.fetchedAdDurations.has(url)) {\n processedUrls.add(url);\n }\n }\n if (this.config.debugAdTiming && processedUrls.size > 0) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F4E6} Skipping ${processedUrls.size} already-preloaded ads`\n );\n }\n while (true) {\n const nextUrl = this.adPodAllUrls.find((url) => !processedUrls.has(url));\n if (!nextUrl) {\n if (this.config.debugAdTiming) {\n console.log(`[ADAPTIVE-POD] \\u2705 All queued ads processed (${processedUrls.size} total)`);\n }\n break;\n }\n processedUrls.add(nextUrl);\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u{1F4E5} Preloading ad ${processedUrls.size}/${this.adPodAllUrls.length}...`\n );\n }\n try {\n await this.preloadSingleAd(nextUrl);\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] \\u26A0\\uFE0F Preload failed for ad ${processedUrls.size}:`,\n error\n );\n }\n }\n if (this.calculateAdditionalAdsNeeded() === 0) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u2705 Target duration reached (${processedUrls.size} ads preloaded), stopping`\n );\n }\n break;\n }\n }\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u2705 Sequential preloading completed (${processedUrls.size} ads ready)`\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Starting parallel preload of ${this.adPodAllUrls.length} ads`\n );\n }\n const preloadPromises = this.adPodAllUrls.map(\n (vastTagUrl) => this.preloadSingleAd(vastTagUrl).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Preload failed for ${vastTagUrl}:`,\n error\n );\n }\n })\n );\n await Promise.all(preloadPromises);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Background preloading completed for all ads`\n );\n }\n }\n }\n async preloadSingleAd(vastTagUrl) {\n if (!vastTagUrl) return;\n try {\n if (this.isAdaptiveMode && !this.fetchedAdDurations.has(vastTagUrl)) {\n const duration = await this.fetchVastDuration(vastTagUrl);\n if (duration !== null) {\n this.fetchedAdDurations.set(vastTagUrl, duration);\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] \\u2713 Fetched ad duration: ${duration}s (${this.fetchedAdDurations.size} ads fetched so far)`\n );\n }\n await this.addAdaptiveAdsToQueue();\n }\n }\n if (this.ima.preloadAds && !this.ima.hasPreloadedAd(vastTagUrl)) {\n if (!this.preloadingAdUrls.has(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Preloading VAST: ${vastTagUrl}`\n );\n }\n this.preloadingAdUrls.add(vastTagUrl);\n await this.ima.preloadAds(vastTagUrl).then(() => {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA VAST preload complete: ${vastTagUrl}`\n );\n }\n }).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] IMA VAST preload failed: ${vastTagUrl}`,\n error\n );\n }\n }).finally(() => {\n this.preloadingAdUrls.delete(vastTagUrl);\n });\n }\n }\n let mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);\n if (!mediaUrls) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Fetching and parsing VAST to extract media URLs: ${vastTagUrl}`\n );\n }\n mediaUrls = await this.fetchAndParseVastXml(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs:`,\n mediaUrls\n );\n }\n if (mediaUrls.length > 0) {\n this.vastToMediaUrlMap.set(vastTagUrl, mediaUrls);\n }\n }\n if (mediaUrls && mediaUrls.length > 0) {\n const primaryMediaUrl = mediaUrls[0];\n if (primaryMediaUrl && !this.preloadedMediaUrls.has(primaryMediaUrl)) {\n await this.preloadMediaFile(primaryMediaUrl);\n }\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to preload ad: ${vastTagUrl}`,\n error\n );\n }\n }\n }\n findNextPreloadedAd() {\n for (let i = 0; i < this.adPodQueue.length; i++) {\n const vastTagUrl = this.adPodQueue[i];\n if (!vastTagUrl) continue;\n if (this.failedVastUrls.has(vastTagUrl)) {\n console.warn(\"[AD-ERROR] Skipping failed URL in queue\");\n continue;\n }\n const hasImaPreload = this.ima.hasPreloadedAd?.(vastTagUrl) ?? false;\n const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);\n const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;\n if (hasImaPreload || hasMediaPreload) {\n this.adPodQueue.splice(0, i + 1);\n return vastTagUrl;\n }\n }\n return void 0;\n }\n getRemainingAdMs() {\n if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)\n return 0;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n findBreakForTime(nowMs) {\n const schedule = [];\n for (const b of schedule) {\n const end = (b.startTimeMs || 0) + (b.durationMs || 0);\n if (nowMs >= (b.startTimeMs || 0) && (b.durationMs ? nowMs < end : true)) {\n return b;\n }\n }\n return void 0;\n }\n toggleMute() {\n if (this.ima.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n this.ima.updateOriginalMutedState(newMutedState, this.video.volume);\n this.ima.setAdVolume(newMutedState ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n toggleFullscreen() {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document.exitFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n isMuted() {\n if (this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n setMuted(muted) {\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n this.video.muted = muted;\n if (adPlaying) {\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n this.ima.setAdVolume(muted ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted\n });\n }\n return;\n }\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n setVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying) {\n this.ima.setAdVolume(clampedVolume);\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n isFullscreen() {\n return !!document.fullscreenElement;\n }\n isLive() {\n return this.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n resize() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n if (this.ima && this.ima.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 360;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n this.ima.resize(width, height);\n }\n }\n destroy() {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = void 0;\n }\n this.hls?.destroy();\n this.ima?.destroy();\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.adPodAllUrls = [];\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n }\n};\n\n// src/ui/StormcloudVideoPlayer.tsx\nimport {\n FaPlay,\n FaPause,\n FaVolumeUp,\n FaVolumeMute,\n FaVolumeDown,\n FaExpand,\n FaCompress,\n FaSpinner\n} from \"react-icons/fa\";\nimport { Fragment, jsx, jsxs } from \"react/jsx-runtime\";\nvar CRITICAL_PROPS = [\n \"src\",\n \"allowNativeHls\",\n \"licenseKey\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"vastMode\"\n];\nvar StormcloudVideoPlayerComponent = React.memo(\n (props) => {\n const {\n src,\n autoplay,\n muted,\n lowLatencyMode,\n allowNativeHls,\n driftToleranceMs,\n immediateManifestAds,\n debugAdTiming,\n showCustomControls,\n hideLoadingIndicator,\n onVolumeToggle,\n onFullscreenToggle,\n onControlClick,\n onReady,\n wrapperClassName,\n wrapperStyle,\n className,\n style,\n controls,\n playsInline,\n preload,\n poster,\n children,\n licenseKey,\n vastMode,\n vastTagUrl,\n adPlayerType,\n minSegmentsBeforePlay,\n ...restVideoAttrs\n } = props;\n const videoRef = useRef(null);\n const playerRef = useRef(null);\n const bufferingTimeoutRef = useRef(null);\n const [adStatus, setAdStatus] = React.useState({ showAds: false, currentIndex: 0, totalAds: 0 });\n const [shouldShowNativeControls, setShouldShowNativeControls] = React.useState(true);\n const [isMuted, setIsMuted] = React.useState(false);\n const [isFullscreen, setIsFullscreen] = React.useState(false);\n const [isPlaying, setIsPlaying] = React.useState(false);\n const [currentTime, setCurrentTime] = React.useState(0);\n const [duration, setDuration] = React.useState(0);\n const [volume, setVolume] = React.useState(1);\n const [playbackRate, setPlaybackRate] = React.useState(1);\n const [showVolumeSlider, setShowVolumeSlider] = React.useState(false);\n const [showSpeedMenu, setShowSpeedMenu] = React.useState(false);\n const [isLoading, setIsLoading] = React.useState(true);\n const [isBuffering, setIsBuffering] = React.useState(false);\n const [showCenterPlay, setShowCenterPlay] = React.useState(false);\n const [showLicenseWarning, setShowLicenseWarning] = React.useState(false);\n const [viewportWidth, setViewportWidth] = React.useState(\n typeof window !== \"undefined\" ? window.innerWidth : 1920\n );\n const [isPortrait, setIsPortrait] = React.useState(\n typeof window !== \"undefined\" ? window.innerHeight > window.innerWidth : false\n );\n const getResponsiveScale = () => {\n if (viewportWidth < 480) return 0.7;\n if (viewportWidth < 768) return 0.8;\n if (viewportWidth < 1024) return 0.9;\n return 1;\n };\n const responsiveScale = getResponsiveScale();\n const formatTime = (seconds) => {\n if (!isFinite(seconds)) return \"0:00:00\";\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor(seconds % 3600 / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${remainingSeconds.toString().padStart(2, \"0\")}`;\n };\n const handlePlayPause = () => {\n if (videoRef.current) {\n if (videoRef.current.paused) {\n const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== \"\" || videoRef.current.readyState >= 1;\n if (hasValidSource) {\n videoRef.current.play()?.catch((error) => {\n console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n });\n setShowCenterPlay(false);\n } else {\n console.warn(\n \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n );\n }\n } else {\n videoRef.current.pause();\n setShowCenterPlay(true);\n }\n }\n };\n const handleCenterPlayClick = () => {\n if (videoRef.current && videoRef.current.paused) {\n const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== \"\" || videoRef.current.readyState >= 1;\n if (hasValidSource) {\n videoRef.current.play()?.catch((error) => {\n console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n });\n setShowCenterPlay(false);\n } else {\n console.warn(\n \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n );\n }\n }\n };\n const handleTimelineSeek = (e) => {\n if (videoRef.current && duration > 0 && isFinite(duration)) {\n const rect = e.currentTarget.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n const progress = Math.max(0, Math.min(1, clickX / rect.width));\n const newTime = progress * duration;\n if (isFinite(newTime) && newTime >= 0 && newTime <= duration) {\n videoRef.current.currentTime = newTime;\n }\n }\n };\n const handleVolumeChange = (newVolume) => {\n if (playerRef.current && isFinite(newVolume)) {\n const clampedVolume = Math.max(0, Math.min(1, newVolume));\n playerRef.current.setVolume(clampedVolume);\n }\n };\n const handlePlaybackRateChange = (rate) => {\n if (videoRef.current && isFinite(rate) && rate > 0) {\n videoRef.current.playbackRate = rate;\n }\n setShowSpeedMenu(false);\n };\n const isHlsStream = src?.toLowerCase().includes(\".m3u8\") || src?.toLowerCase().includes(\"/hls/\");\n const shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);\n const criticalPropsKey = useMemo(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n licenseKey,\n lowLatencyMode,\n driftToleranceMs,\n vastMode\n ]);\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const el = videoRef.current;\n if (!el || !src) return;\n if (!licenseKey) {\n setShowLicenseWarning(true);\n setIsLoading(false);\n console.warn(\n \"StormcloudVideoPlayer: License key is required but not provided. Please set the licenseKey prop to use the player.\"\n );\n return;\n }\n setShowLicenseWarning(false);\n if (debugAdTiming) {\n console.log(\"[StormcloudUI] Initializing player, isLoading=true\");\n }\n if (playerRef.current) {\n try {\n playerRef.current.destroy();\n } catch {\n }\n playerRef.current = null;\n }\n const cfg = {\n src,\n videoElement: el\n };\n if (autoplay !== void 0) cfg.autoplay = autoplay;\n if (muted !== void 0) cfg.muted = muted;\n if (lowLatencyMode !== void 0) cfg.lowLatencyMode = lowLatencyMode;\n if (allowNativeHls !== void 0) cfg.allowNativeHls = allowNativeHls;\n if (driftToleranceMs !== void 0)\n cfg.driftToleranceMs = driftToleranceMs;\n if (immediateManifestAds !== void 0)\n cfg.immediateManifestAds = immediateManifestAds;\n if (debugAdTiming !== void 0) cfg.debugAdTiming = debugAdTiming;\n if (showCustomControls !== void 0)\n cfg.showCustomControls = showCustomControls;\n if (onVolumeToggle !== void 0) cfg.onVolumeToggle = onVolumeToggle;\n if (onFullscreenToggle !== void 0)\n cfg.onFullscreenToggle = onFullscreenToggle;\n if (onControlClick !== void 0) cfg.onControlClick = onControlClick;\n if (licenseKey !== void 0) cfg.licenseKey = licenseKey;\n if (vastMode !== void 0) cfg.vastMode = vastMode;\n if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;\n if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;\n if (minSegmentsBeforePlay !== void 0)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n const player = new StormcloudVideoPlayer(cfg);\n playerRef.current = player;\n player.load().then(() => {\n const showNative = player.shouldShowNativeControls();\n setShouldShowNativeControls(showNative);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Player loaded successfully, waiting for video ready\"\n );\n }\n onReady?.(player);\n }).catch((error) => {\n console.error(\n \"StormcloudVideoPlayer: Failed to load player:\",\n error\n );\n setIsLoading(false);\n onReady?.(player);\n });\n return () => {\n try {\n player.destroy();\n } catch {\n }\n playerRef.current = null;\n };\n }, [criticalPropsKey]);\n useEffect(() => {\n if (!playerRef.current) return;\n try {\n if (autoplay !== void 0 && playerRef.current.videoElement) {\n playerRef.current.videoElement.autoplay = autoplay;\n }\n if (muted !== void 0 && !playerRef.current.isShowingAds()) {\n playerRef.current.setMuted(muted);\n }\n } catch (error) {\n console.warn(\"Failed to update player properties:\", error);\n }\n }, [autoplay, muted]);\n useEffect(() => {\n if (!playerRef.current) return;\n const checkAdStatus = () => {\n if (playerRef.current) {\n const showAdsFromMethod = playerRef.current.isShowingAds();\n const showAdsFromAttribute = videoRef.current?.dataset?.stormcloudAdPlaying === \"true\";\n const showAds = showAdsFromMethod || showAdsFromAttribute;\n const currentIndex = playerRef.current.getCurrentAdIndex();\n const totalAds = playerRef.current.getTotalAdsInBreak();\n setAdStatus((prev) => {\n if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds };\n }\n return prev;\n });\n }\n };\n const interval = setInterval(checkAdStatus, 50);\n return () => clearInterval(interval);\n }, []);\n useEffect(() => {\n if (typeof window === \"undefined\" || !playerRef.current) return;\n const handleResize = () => {\n if (playerRef.current && videoRef.current) {\n if (typeof playerRef.current.resize === \"function\") {\n playerRef.current.resize();\n }\n }\n setViewportWidth(window.innerWidth);\n setIsPortrait(window.innerHeight > window.innerWidth);\n };\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n useEffect(() => {\n if (!playerRef.current || !videoRef.current) return;\n const updateStates = () => {\n if (playerRef.current && videoRef.current) {\n setIsMuted(playerRef.current.isMuted());\n setIsPlaying(!videoRef.current.paused);\n const currentTimeValue = videoRef.current.currentTime;\n setCurrentTime(isFinite(currentTimeValue) ? currentTimeValue : 0);\n const durationValue = videoRef.current.duration;\n setDuration(isFinite(durationValue) ? durationValue : 0);\n const volumeValue = videoRef.current.volume;\n setVolume(\n isFinite(volumeValue) ? Math.max(0, Math.min(1, volumeValue)) : 1\n );\n const rateValue = videoRef.current.playbackRate;\n setPlaybackRate(\n isFinite(rateValue) && rateValue > 0 ? rateValue : 1\n );\n }\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\n );\n };\n const interval = setInterval(updateStates, 200);\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\n );\n };\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n return () => {\n clearInterval(interval);\n document.removeEventListener(\n \"fullscreenchange\",\n handleFullscreenChange\n );\n };\n }, []);\n useEffect(() => {\n if (!videoRef.current) return;\n const handleLoadedMetadata = () => {\n if (videoRef.current) {\n const video2 = videoRef.current;\n void video2.offsetHeight;\n }\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadedmetadata, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n const handleLoadedData = () => {\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadeddata, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n const handleLoadStart = () => {\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadstart, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n const handleCanPlay = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: canplay, readyState:\",\n videoRef.current?.readyState,\n \"- clearing loading state, isLoading=false\"\n );\n }\n };\n const handleCanPlayThrough = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: canplaythrough, readyState:\",\n videoRef.current?.readyState,\n \"- clearing loading state, isLoading=false\"\n );\n }\n };\n const handleWaiting = () => {\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n }\n bufferingTimeoutRef.current = window.setTimeout(() => {\n setIsBuffering(true);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video buffering detected (after 300ms delay), readyState:\",\n videoRef.current?.readyState,\n \"- showing spinner, isBuffering=true\"\n );\n }\n }, 300);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: waiting, readyState:\",\n videoRef.current?.readyState,\n \"- buffering delay started (300ms)\"\n );\n }\n };\n const handlePlaying = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n setShowCenterPlay(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: playing, readyState:\",\n videoRef.current?.readyState,\n \"- playback started, isLoading=false, isBuffering=false\"\n );\n }\n };\n const handlePause = () => {\n const isAdActive = playerRef.current?.isShowingAds() || videoRef.current?.dataset?.stormcloudAdPlaying === \"true\";\n if (playerRef.current && !isAdActive) {\n setShowCenterPlay(true);\n } else {\n setShowCenterPlay(false);\n }\n };\n const handleEnded = () => {\n setShowCenterPlay(true);\n };\n const video = videoRef.current;\n video.addEventListener(\"loadstart\", handleLoadStart);\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.addEventListener(\"canplay\", handleCanPlay);\n video.addEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.addEventListener(\"waiting\", handleWaiting);\n video.addEventListener(\"playing\", handlePlaying);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n if (video.paused) {\n setShowCenterPlay(true);\n }\n return () => {\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n video.removeEventListener(\"loadstart\", handleLoadStart);\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n video.removeEventListener(\"canplay\", handleCanPlay);\n video.removeEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.removeEventListener(\"waiting\", handleWaiting);\n video.removeEventListener(\"playing\", handlePlaying);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n };\n }, [debugAdTiming]);\n return /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(\"style\", { children: `\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n \n .stormcloud-loading-hidden .stormcloud-loading-indicator {\n display: none !important;\n }\n \n .stormcloud-video-wrapper:fullscreen {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n \n .stormcloud-video-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n \n *:fullscreen {\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n }\n ` }),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n className: `stormcloud-video-wrapper ${wrapperClassName || \"\"}`,\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n position: isFullscreen ? \"fixed\" : \"relative\",\n top: isFullscreen ? 0 : void 0,\n left: isFullscreen ? 0 : void 0,\n overflow: \"hidden\",\n width: isFullscreen ? \"100vw\" : \"100%\",\n height: isFullscreen ? \"100vh\" : \"auto\",\n minHeight: isFullscreen ? \"100vh\" : \"auto\",\n maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : void 0,\n backgroundColor: isFullscreen ? \"#000\" : void 0,\n borderRadius: isFullscreen ? 0 : void 0,\n boxShadow: isFullscreen ? \"none\" : void 0,\n ...wrapperStyle\n },\n children: [\n /* @__PURE__ */ jsx(\n \"video\",\n {\n ref: videoRef,\n className,\n style: {\n display: \"block\",\n width: \"100%\",\n height: isFullscreen ? \"100%\" : \"auto\",\n maxWidth: \"100%\",\n maxHeight: isFullscreen ? \"100%\" : \"none\",\n objectFit: isFullscreen ? \"cover\" : \"contain\",\n backgroundColor: \"#000\",\n aspectRatio: isFullscreen ? \"unset\" : void 0,\n ...style\n },\n controls: shouldShowNativeControls && controls && !showCustomControls,\n playsInline,\n preload,\n poster,\n ...restVideoAttrs,\n children\n }\n ),\n (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ jsx(\n FaSpinner,\n {\n className: \"stormcloud-loading-indicator\",\n size: 42,\n color: \"white\",\n style: {\n position: \"absolute\",\n top: \"calc(50% - 21px)\",\n left: \"calc(50% - 21px)\",\n zIndex: 20,\n animation: \"spin 1s linear infinite\",\n filter: \"drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))\"\n }\n }\n ),\n showLicenseWarning && /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 25,\n background: \"linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)\",\n color: \"white\",\n padding: \"24px 32px\",\n borderRadius: \"16px\",\n backdropFilter: \"blur(20px)\",\n border: \"2px solid rgba(255, 255, 255, 0.2)\",\n boxShadow: \"0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\"\n },\n children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n fontSize: \"20px\",\n fontWeight: \"bold\",\n marginBottom: \"12px\",\n color: \"#ffffff\",\n textShadow: \"0 2px 4px rgba(0, 0, 0, 0.5)\"\n },\n children: \"License Key Required\"\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n fontSize: \"14px\",\n lineHeight: \"1.5\",\n color: \"rgba(255, 255, 255, 0.9)\",\n textShadow: \"0 1px 2px rgba(0, 0, 0, 0.3)\"\n },\n children: [\n \"Please provide a valid license key to use the Stormcloud Video Player.\",\n /* @__PURE__ */ jsx(\"br\", {}),\n \"Contact your administrator for licensing information.\"\n ]\n }\n )\n ]\n }\n ),\n showCenterPlay && !isLoading && !isBuffering && !showLicenseWarning && !adStatus.showAds && /* @__PURE__ */ jsx(\n \"div\",\n {\n onClick: handleCenterPlayClick,\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 15,\n cursor: \"pointer\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\",\n borderRadius: \"50%\",\n width: \"100px\",\n height: \"100px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n border: \"3px solid rgba(255, 255, 255, 0.8)\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\"\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)\";\n target.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.9)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\";\n target.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.8)\";\n },\n title: \"Play\",\n children: /* @__PURE__ */ jsx(\n FaPlay,\n {\n size: 36,\n color: \"white\",\n style: {\n marginLeft: \"6px\",\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\"\n }\n }\n )\n }\n ),\n shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background: \"linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)\",\n padding: \"20px 16px 16px\",\n zIndex: 10\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"8px\",\n background: \"linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)\",\n borderRadius: \"8px\",\n marginBottom: \"16px\",\n cursor: \"pointer\",\n position: \"relative\",\n backdropFilter: \"blur(5px)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"inset 0 2px 4px rgba(0, 0, 0, 0.2)\"\n },\n onClick: handleTimelineSeek,\n children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n height: \"100%\",\n background: \"linear-gradient(90deg, rgba(139, 92, 246, 0.9) 0%, rgba(59, 130, 246, 0.8) 50%, rgba(34, 197, 94, 0.9) 100%)\",\n borderRadius: \"8px\",\n width: `${duration > 0 ? currentTime / duration * 100 : 0}%`,\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 2px 8px rgba(139, 92, 246, 0.4)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"-6px\",\n right: `${duration > 0 ? 100 - currentTime / duration * 100 : 100}%`,\n width: \"20px\",\n height: \"20px\",\n background: \"linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)\",\n borderRadius: \"50%\",\n border: \"3px solid rgba(139, 92, 246, 0.8)\",\n boxShadow: \"0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)\",\n transform: \"translateX(50%)\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\"\n }\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n flexWrap: viewportWidth < 768 ? \"wrap\" : \"nowrap\",\n gap: `${8 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n flexWrap: viewportWidth < 480 ? \"wrap\" : \"nowrap\"\n },\n children: [\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: handlePlayPause,\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n backdropFilter: \"blur(12px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${10 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n minWidth: `${48 * responsiveScale}px`,\n minHeight: `${48 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n target.style.boxShadow = \"0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n target.style.boxShadow = \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n },\n title: isPlaying ? \"Pause\" : \"Play\",\n children: isPlaying ? /* @__PURE__ */ jsx(\n FaPause,\n {\n size: Math.max(16, 20 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n ) : /* @__PURE__ */ jsx(\n FaPlay,\n {\n size: Math.max(16, 20 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n )\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\"\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: () => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: isMuted ? \"Unmute\" : \"Mute\",\n children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(\n FaVolumeMute,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n ) : volume < 0.5 ? /* @__PURE__ */ jsx(\n FaVolumeDown,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n ) : /* @__PURE__ */ jsx(\n FaVolumeUp,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n )\n }\n ),\n showVolumeSlider && /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false)\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(15px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\",\n zIndex: 10,\n transition: \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)\";\n e.currentTarget.style.borderColor = \"rgba(59, 130, 246, 0.4)\";\n },\n onMouseLeave: (e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\";\n e.currentTarget.style.borderColor = \"rgba(255, 255, 255, 0.15)\";\n },\n children: /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n },\n onMouseLeave: (e) => {\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n const handleMouseMove = (moveEvent) => {\n if (!sliderElement) return;\n const rect2 = sliderElement.getBoundingClientRect();\n const y2 = moveEvent.clientY - rect2.top;\n const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));\n handleVolumeChange(percentage2);\n };\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n const rect = sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n onClick: (e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background: \"linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)\",\n borderRadius: \"4px\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.2)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)\",\n borderRadius: \"4px\",\n transition: \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow: \"0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 7px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"14px\",\n height: \"14px\",\n background: \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n boxShadow: \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\",\n transition: \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.boxShadow = \"0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)\";\n e.currentTarget.style.cursor = \"grab\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.boxShadow = \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\";\n },\n onMouseDown: (e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n },\n onMouseUp: (e) => {\n e.currentTarget.style.cursor = \"grab\";\n }\n }\n )\n ]\n }\n )\n }\n )\n ] })\n ]\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\"\n },\n children: [\n formatTime(currentTime),\n \" / \",\n formatTime(duration)\n ]\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: viewportWidth < 600 ? \"none\" : \"block\"\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"button\",\n {\n onClick: () => setShowSpeedMenu(!showSpeedMenu),\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n borderRadius: `${14 * responsiveScale}px`,\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n fontWeight: \"700\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${56 * responsiveScale}px`,\n minHeight: `${40 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: \"Playback Speed\",\n children: [\n playbackRate,\n \"x\"\n ]\n }\n ),\n showSpeedMenu && /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n right: 0,\n marginBottom: \"12px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)\",\n backdropFilter: \"blur(20px)\",\n borderRadius: \"12px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"90px\",\n boxShadow: \"0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)\"\n },\n children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(\n (speed) => /* @__PURE__ */ jsxs(\n \"button\",\n {\n onClick: () => handlePlaybackRateChange(speed),\n style: {\n display: \"block\",\n width: \"100%\",\n padding: \"10px 16px\",\n background: playbackRate === speed ? \"linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)\" : \"transparent\",\n border: \"none\",\n color: \"white\",\n cursor: \"pointer\",\n fontSize: \"13px\",\n fontFamily: \"monospace\",\n fontWeight: \"600\",\n textAlign: \"center\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n borderBottom: speed !== 2 ? \"1px solid rgba(255, 255, 255, 0.05)\" : \"none\"\n },\n onMouseEnter: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)\";\n }\n },\n onMouseLeave: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"transparent\";\n }\n },\n children: [\n speed,\n \"x\"\n ]\n },\n speed\n )\n )\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen ? /* @__PURE__ */ jsx(\n FaCompress,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n ) : /* @__PURE__ */ jsx(\n FaExpand,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n )\n }\n )\n ]\n }\n )\n ]\n }\n )\n ]\n }\n ) }) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n transform: \"none\",\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n gap: `${10 * responsiveScale}px`,\n zIndex: 10\n },\n children: [\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\"\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: () => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow: \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`\n },\n title: isMuted ? \"Unmute\" : \"Mute\",\n children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(\n FaVolumeMute,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : volume < 0.5 ? /* @__PURE__ */ jsx(\n FaVolumeDown,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : /* @__PURE__ */ jsx(\n FaVolumeUp,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n )\n }\n ),\n showVolumeSlider && /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false)\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(20px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.7)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\",\n zIndex: 10,\n transition: \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)\";\n e.currentTarget.style.borderColor = \"rgba(96, 165, 250, 0.8)\";\n },\n onMouseLeave: (e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\";\n e.currentTarget.style.borderColor = \"rgba(255, 255, 255, 0.7)\";\n },\n children: /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\"\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n const handleMouseMove = (moveEvent) => {\n if (!sliderElement) return;\n const rect2 = sliderElement.getBoundingClientRect();\n const y2 = moveEvent.clientY - rect2.top;\n const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));\n handleVolumeChange(percentage2);\n };\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n const rect = sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n onClick: (e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n children: [\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background: \"linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)\",\n borderRadius: \"4px\",\n border: \"1px solid rgba(255, 255, 255, 0.4)\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.3)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)\",\n borderRadius: \"4px\",\n transition: \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow: \"0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)\"\n }\n }\n ),\n /* @__PURE__ */ jsx(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 8px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"16px\",\n height: \"16px\",\n background: \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n border: \"2px solid rgba(96, 165, 250, 0.9)\",\n boxShadow: \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\",\n transition: \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.boxShadow = \"0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)\";\n e.currentTarget.style.cursor = \"grab\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.boxShadow = \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\";\n },\n onMouseDown: (e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n },\n onMouseUp: (e) => {\n e.currentTarget.style.cursor = \"grab\";\n }\n }\n )\n ]\n }\n )\n }\n )\n ] })\n ]\n }\n ),\n /* @__PURE__ */ jsx(\n \"button\",\n {\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow: \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`\n },\n title: isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen ? /* @__PURE__ */ jsx(\n FaCompress,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : /* @__PURE__ */ jsx(\n FaExpand,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n )\n }\n )\n ]\n }\n ),\n onControlClick && /* @__PURE__ */ jsx(\n \"div\",\n {\n onClick: onControlClick,\n style: {\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 1,\n cursor: \"pointer\"\n }\n }\n )\n ]\n }\n )\n ] });\n },\n (prevProps, nextProps) => {\n for (const prop of CRITICAL_PROPS) {\n if (prevProps[prop] !== nextProps[prop]) {\n return false;\n }\n }\n const uiProps = [\n \"autoplay\",\n \"muted\",\n \"controls\",\n \"showCustomControls\",\n \"className\",\n \"style\",\n \"wrapperClassName\",\n \"wrapperStyle\",\n \"playsInline\",\n \"preload\",\n \"poster\",\n \"children\"\n ];\n for (const prop of uiProps) {\n if (prevProps[prop] !== nextProps[prop]) {\n return false;\n }\n }\n const callbackProps = [\n \"onReady\",\n \"onVolumeToggle\",\n \"onFullscreenToggle\",\n \"onControlClick\"\n ];\n for (const prop of callbackProps) {\n if (prevProps[prop] !== nextProps[prop]) {\n return false;\n }\n }\n return true;\n }\n);\n\n// src/StormcloudPlayer.tsx\nimport React3, { Component as Component4, Suspense } from \"react\";\n\n// src/props.ts\nvar noop = () => {\n};\nvar defaultProps = {\n playing: false,\n loop: false,\n controls: true,\n volume: 1,\n muted: false,\n playbackRate: 1,\n width: \"100%\",\n height: \"auto\",\n style: {},\n progressInterval: 1e3,\n playsInline: false,\n autoplay: false,\n preload: \"metadata\",\n poster: \"\",\n className: \"\",\n wrapperClassName: \"\",\n wrapperStyle: {},\n allowNativeHls: false,\n lowLatencyMode: false,\n driftToleranceMs: 1e3,\n immediateManifestAds: true,\n debugAdTiming: false,\n showCustomControls: false,\n hideLoadingIndicator: false,\n licenseKey: \"\",\n adFailsafeTimeoutMs: 1e4,\n minSegmentsBeforePlay: 2,\n onStart: noop,\n onPlay: noop,\n onPause: noop,\n onBuffer: noop,\n onBufferEnd: noop,\n onEnded: noop,\n onError: noop,\n onDuration: noop,\n onSeek: noop,\n onProgress: noop,\n onVolumeToggle: noop,\n onFullscreenToggle: noop,\n onControlClick: noop\n};\n\n// src/utils.ts\nimport { lazy as reactLazy } from \"react\";\nvar lazy = reactLazy;\nvar omit = (object, keys) => {\n const result = { ...object };\n keys.forEach((key) => {\n delete result[key];\n });\n return result;\n};\nvar isMediaStream = (url) => {\n return typeof window !== \"undefined\" && window.MediaStream && url instanceof window.MediaStream;\n};\nvar supportsWebKitPresentationMode = () => {\n if (typeof window === \"undefined\") return false;\n const video = document.createElement(\"video\");\n return \"webkitSupportsPresentationMode\" in video;\n};\nvar randomString = () => {\n return Math.random().toString(36).substr(2, 9);\n};\nvar parseQuery = (url) => {\n const query = {};\n const queryString = url.split(\"?\")[1] || \"\";\n if (!queryString) return query;\n const manualParse = (qs) => {\n qs.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n try {\n query[decodeURIComponent(key)] = value ? decodeURIComponent(value.replace(/\\+/g, \" \")) : \"\";\n } catch (e) {\n query[key] = value || \"\";\n }\n }\n });\n };\n if (typeof URLSearchParams !== \"undefined\") {\n try {\n const params = new URLSearchParams(queryString);\n params.forEach((value, key) => {\n query[key] = value;\n });\n return query;\n } catch (e) {\n manualParse(queryString);\n }\n } else {\n manualParse(queryString);\n }\n return query;\n};\nvar merge = (target, ...sources) => {\n if (!sources.length) return target;\n const source = sources.shift();\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n merge(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n return merge(target, ...sources);\n};\nvar isObject = (item) => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\nvar IS_BROWSER = typeof window !== \"undefined\" && window.document;\nvar IS_GLOBAL = typeof globalThis !== \"undefined\" && globalThis.window && globalThis.window.document;\nvar IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(navigator.userAgent);\nvar IS_SAFARI = IS_BROWSER && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\nvar SUPPORTS_HLS = () => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/vnd.apple.mpegurl\"));\n};\nvar SUPPORTS_DASH = () => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/dash+xml\"));\n};\n\n// src/patterns.ts\nvar HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nvar HLS_PATHS = /\\/hls\\//i;\nvar DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nvar VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nvar AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\nvar canPlay = {\n hls: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n dash: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n video: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n audio: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n file: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n }\n};\n\n// src/players/HlsPlayer.tsx\nimport { Component } from \"react\";\nvar HlsPlayer = class extends Component {\n constructor() {\n super(...arguments);\n this.player = null;\n this.mounted = false;\n this.load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n const config = {\n src: this.props.src,\n videoElement: this.props.videoElement\n };\n if (this.props.autoplay !== void 0)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== void 0)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== void 0)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== void 0)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== void 0)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== void 0)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== void 0)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== void 0)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== void 0)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== void 0)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== void 0)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== void 0)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== void 0)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n this.player = new StormcloudVideoPlayer(config);\n this.props.onMount?.(this);\n await this.player.load();\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return this.player.hls;\n return null;\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nHlsPlayer.displayName = \"HlsPlayer\";\nHlsPlayer.canPlay = canPlay.hls;\n\n// src/players/FilePlayer.tsx\nimport { Component as Component2 } from \"react\";\nvar FilePlayer = class extends Component2 {\n constructor() {\n super(...arguments);\n this.mounted = false;\n this.ready = false;\n this.load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n const video = this.props.videoElement;\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n const handleError = (error) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\n };\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.src = this.props.src;\n if (this.props.autoplay !== void 0) video.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) video.muted = this.props.muted;\n if (this.props.loop !== void 0) video.loop = this.props.loop;\n if (this.props.controls !== void 0) video.controls = this.props.controls;\n if (this.props.playsInline !== void 0)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== void 0)\n video.preload = this.props.preload;\n if (this.props.poster !== void 0) video.poster = this.props.poster;\n this.props.onMount?.(this);\n return () => {\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n };\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[FilePlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n } else {\n console.warn(\"[FilePlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.setLoop = (loop) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n this.enablePIP = async () => {\n if (this.props.videoElement && \"requestPictureInPicture\" in this.props.videoElement) {\n try {\n await this.props.videoElement.requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n this.disablePIP = async () => {\n if (document.pictureInPictureElement) {\n try {\n await document.exitPictureInPicture();\n } catch (error) {\n console.warn(\"Exit Picture-in-Picture failed:\", error);\n }\n }\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nFilePlayer.displayName = \"FilePlayer\";\nFilePlayer.canPlay = canPlay.file;\n\n// src/players/index.ts\nvar players = [\n {\n key: \"hls\",\n name: \"HLS Player\",\n canPlay: canPlay.hls,\n lazyPlayer: lazy(() => Promise.resolve({ default: HlsPlayer }))\n },\n {\n key: \"file\",\n name: \"File Player\",\n canPlay: canPlay.file,\n canEnablePIP: (url) => {\n return canPlay.file(url) && (document.pictureInPictureEnabled || typeof document.webkitSupportsPresentationMode === \"function\");\n },\n lazyPlayer: lazy(() => Promise.resolve({ default: FilePlayer }))\n }\n];\nvar players_default = players;\n\n// src/Player.tsx\nimport React2, { Component as Component3 } from \"react\";\nvar SEEK_ON_PLAY_EXPIRY = 5e3;\nvar Player = class extends Component3 {\n constructor() {\n super(...arguments);\n this.mounted = false;\n this.isReady = false;\n this.isPlaying = false;\n this.isLoading = true;\n this.loadOnReady = null;\n this.startOnPlay = true;\n this.seekOnPlay = null;\n this.onDurationCalled = false;\n this.handlePlayerMount = (player) => {\n if (this.player) {\n this.progress();\n return;\n }\n this.player = player;\n this.player.load(this.props.src);\n this.progress();\n };\n this.getInternalPlayer = (key) => {\n if (!this.player) return null;\n return this.player.getInternalPlayer(key);\n };\n this.progress = () => {\n if (this.props.src && this.player && this.isReady) {\n const playedSeconds = this.getCurrentTime() || 0;\n const loadedSeconds = this.getSecondsLoaded();\n const duration = this.getDuration();\n if (duration) {\n const progress = {\n playedSeconds,\n played: playedSeconds / duration,\n loaded: 0,\n loadedSeconds: 0\n };\n if (loadedSeconds !== null) {\n progress.loadedSeconds = loadedSeconds;\n progress.loaded = loadedSeconds / duration;\n }\n if (progress.playedSeconds !== this.prevPlayed || progress.loadedSeconds !== this.prevLoaded) {\n this.props.onProgress?.(progress);\n }\n this.prevPlayed = progress.playedSeconds;\n this.prevLoaded = progress.loadedSeconds;\n }\n }\n this.progressTimeout = window.setTimeout(\n this.progress,\n this.props.progressInterval || 1e3\n );\n };\n this.handleReady = () => {\n if (!this.mounted) return;\n this.isReady = true;\n this.isLoading = false;\n const { onReady, playing, volume, muted } = this.props;\n onReady();\n if (!muted && volume !== null) {\n this.player.setVolume(volume);\n }\n if (this.loadOnReady) {\n this.player.load(this.loadOnReady, true);\n this.loadOnReady = null;\n } else if (playing) {\n this.player.play();\n }\n this.handleDurationCheck();\n };\n this.handlePlay = () => {\n this.isPlaying = true;\n this.isLoading = false;\n const { onStart, onPlay, playbackRate } = this.props;\n if (this.startOnPlay) {\n if (this.player.setPlaybackRate && playbackRate !== 1) {\n this.player.setPlaybackRate(playbackRate);\n }\n onStart?.();\n this.startOnPlay = false;\n }\n onPlay?.();\n if (this.seekOnPlay) {\n this.seekTo(this.seekOnPlay);\n this.seekOnPlay = null;\n }\n this.handleDurationCheck();\n };\n this.handlePause = (e) => {\n this.isPlaying = false;\n if (!this.isLoading) {\n this.props.onPause?.(e);\n }\n };\n this.handleEnded = () => {\n const { activePlayer, loop, onEnded } = this.props;\n if (activePlayer.loopOnEnded && loop) {\n this.seekTo(0);\n }\n if (!loop) {\n this.isPlaying = false;\n onEnded?.();\n }\n };\n this.handleError = (...args) => {\n this.isLoading = false;\n this.props.onError?.(args[0], args[1], args[2], args[3]);\n };\n this.handleDurationCheck = () => {\n clearTimeout(this.durationCheckTimeout);\n const duration = this.getDuration();\n if (duration) {\n if (!this.onDurationCalled) {\n this.props.onDuration?.(duration);\n this.onDurationCalled = true;\n }\n } else {\n this.durationCheckTimeout = window.setTimeout(\n this.handleDurationCheck,\n 100\n );\n }\n };\n this.handleLoaded = () => {\n this.isLoading = false;\n };\n }\n componentDidMount() {\n this.mounted = true;\n }\n componentWillUnmount() {\n clearTimeout(this.progressTimeout);\n clearTimeout(this.durationCheckTimeout);\n this.mounted = false;\n }\n componentDidUpdate(prevProps) {\n if (!this.player) return;\n const { src, playing, volume, muted, playbackRate, loop, activePlayer } = this.props;\n if (prevProps.src !== src) {\n if (this.isLoading && !activePlayer.forceLoad && !isMediaStream(src)) {\n console.warn(\n `StormcloudPlayer: the attempt to load ${src} is being deferred until the player has loaded`\n );\n this.loadOnReady = src || null;\n return;\n }\n this.isLoading = true;\n this.startOnPlay = true;\n this.onDurationCalled = false;\n this.player.load(src, this.isReady);\n }\n if (!prevProps.playing && playing && !this.isPlaying) {\n this.player.play();\n }\n if (prevProps.playing && !playing && this.isPlaying) {\n this.player.pause();\n }\n if (prevProps.volume !== volume && volume !== null) {\n this.player.setVolume(volume);\n }\n if (prevProps.muted !== muted) {\n if (muted) {\n this.player.mute();\n } else {\n this.player.unmute();\n if (volume !== null) {\n setTimeout(() => this.player.setVolume(volume));\n }\n }\n }\n if (prevProps.playbackRate !== playbackRate && this.player.setPlaybackRate) {\n this.player.setPlaybackRate(playbackRate);\n }\n if (prevProps.loop !== loop && this.player.setLoop) {\n this.player.setLoop(loop);\n }\n }\n getDuration() {\n if (!this.isReady) return null;\n return this.player.getDuration();\n }\n getCurrentTime() {\n if (!this.isReady) return null;\n return this.player.getCurrentTime();\n }\n getSecondsLoaded() {\n if (!this.isReady) return null;\n return this.player.getSecondsLoaded();\n }\n seekTo(amount, type, keepPlaying) {\n if (!this.isReady) {\n if (amount !== 0) {\n this.seekOnPlay = amount;\n setTimeout(() => {\n this.seekOnPlay = null;\n }, SEEK_ON_PLAY_EXPIRY);\n }\n return;\n }\n const isFraction = !type ? amount > 0 && amount < 1 : type === \"fraction\";\n if (isFraction) {\n const duration = this.player.getDuration();\n if (!duration) {\n console.warn(\n \"StormcloudPlayer: could not seek using fraction \\u2013 duration not yet available\"\n );\n return;\n }\n this.player.seekTo(duration * amount, keepPlaying);\n return;\n }\n this.player.seekTo(amount, keepPlaying);\n }\n render() {\n const Player2 = this.props.activePlayer;\n if (!Player2) {\n return null;\n }\n return React2.createElement(Player2, {\n ...this.props,\n onMount: this.handlePlayerMount,\n onReady: this.handleReady,\n onPlay: this.handlePlay,\n onPause: this.handlePause,\n onEnded: this.handleEnded,\n onLoaded: this.handleLoaded,\n onError: this.handleError\n });\n }\n};\nPlayer.displayName = \"Player\";\nPlayer.defaultProps = defaultProps;\n\n// src/StormcloudPlayer.tsx\nvar IS_BROWSER2 = typeof window !== \"undefined\" && window.document;\nvar IS_GLOBAL2 = typeof globalThis !== \"undefined\" && globalThis.window && globalThis.window.document;\nvar UniversalSuspense = IS_BROWSER2 || IS_GLOBAL2 ? Suspense : () => null;\nvar SUPPORTED_PROPS = [\n \"src\",\n \"playing\",\n \"loop\",\n \"controls\",\n \"volume\",\n \"muted\",\n \"playbackRate\",\n \"width\",\n \"height\",\n \"style\",\n \"progressInterval\",\n \"playsInline\",\n \"autoplay\",\n \"preload\",\n \"poster\",\n \"className\",\n \"wrapperClassName\",\n \"wrapperStyle\",\n \"allowNativeHls\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"immediateManifestAds\",\n \"debugAdTiming\",\n \"showCustomControls\",\n \"licenseKey\",\n \"adFailsafeTimeoutMs\",\n \"minSegmentsBeforePlay\",\n \"onReady\",\n \"onStart\",\n \"onPlay\",\n \"onPause\",\n \"onBuffer\",\n \"onBufferEnd\",\n \"onEnded\",\n \"onError\",\n \"onDuration\",\n \"onSeek\",\n \"onProgress\",\n \"onVolumeToggle\",\n \"onFullscreenToggle\",\n \"onControlClick\"\n];\nvar customPlayers = [];\nvar createStormcloudPlayer = (playerList, fallback) => {\n var _a;\n return _a = class extends Component4 {\n constructor() {\n super(...arguments);\n this.state = {\n showPreview: false\n };\n this.references = {\n wrapper: (wrapper) => {\n this.wrapper = wrapper;\n },\n player: (player) => {\n this.player = player;\n }\n };\n this.getActivePlayer = (src) => {\n if (!src) return null;\n for (const player of [...customPlayers, ...playerList]) {\n if (player.canPlay(src)) {\n return player;\n }\n }\n if (fallback) {\n return fallback;\n }\n return null;\n };\n this.getAttributes = (src) => {\n return omit(this.props, SUPPORTED_PROPS);\n };\n this.handleReady = () => {\n this.props.onReady?.(this);\n };\n this.seekTo = (fraction, type, keepPlaying) => {\n if (!this.player) return null;\n this.player.seekTo(fraction, type, keepPlaying);\n };\n this.getCurrentTime = () => {\n if (!this.player) return null;\n return this.player.getCurrentTime();\n };\n this.getSecondsLoaded = () => {\n if (!this.player) return null;\n return this.player.getSecondsLoaded();\n };\n this.getDuration = () => {\n if (!this.player) return null;\n return this.player.getDuration();\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (!this.player) return null;\n return this.player.getInternalPlayer(key);\n };\n this.renderActivePlayer = (src) => {\n if (!src) return null;\n const activePlayer = this.getActivePlayer(src);\n if (!activePlayer) return null;\n return React3.createElement(Player, {\n ...this.props,\n key: activePlayer.key,\n ref: this.references.player,\n activePlayer: activePlayer.lazyPlayer || activePlayer,\n onReady: this.handleReady\n });\n };\n }\n render() {\n const {\n src,\n style,\n width,\n height,\n fallback: fallbackElement,\n wrapper: Wrapper\n } = this.props;\n const attributes = this.getAttributes(src);\n const wrapperRef = typeof Wrapper === \"string\" ? this.references.wrapper : void 0;\n return React3.createElement(\n Wrapper,\n {\n ref: wrapperRef,\n style: { ...style, width, height },\n ...attributes\n },\n React3.createElement(\n UniversalSuspense,\n { fallback: fallbackElement },\n this.renderActivePlayer(src)\n )\n );\n }\n }, _a.displayName = \"StormcloudPlayer\", _a.defaultProps = {\n ...defaultProps,\n fallback: null,\n wrapper: \"div\"\n }, _a.addCustomPlayer = (player) => {\n customPlayers.push(player);\n }, _a.removeCustomPlayers = () => {\n customPlayers.length = 0;\n }, _a.canPlay = (src) => {\n for (const Player2 of [...customPlayers, ...playerList]) {\n if (Player2.canPlay(src)) {\n return true;\n }\n }\n return false;\n }, _a.canEnablePIP = (src) => {\n for (const Player2 of [...customPlayers, ...playerList]) {\n if (Player2.canEnablePIP && Player2.canEnablePIP(src)) {\n return true;\n }\n }\n return false;\n }, _a;\n};\nvar StormcloudPlayer = createStormcloudPlayer(\n players_default,\n players_default[players_default.length - 1]\n);\nvar StormcloudPlayer_default = StormcloudPlayer;\nexport {\n IS_BROWSER,\n IS_GLOBAL,\n IS_IOS,\n IS_SAFARI,\n SUPPORTS_DASH,\n SUPPORTS_HLS,\n StormcloudPlayer_default as StormcloudPlayer,\n StormcloudVideoPlayer,\n StormcloudVideoPlayerComponent,\n canPlay,\n createHlsAdPlayer,\n createImaController,\n createStormcloudPlayer,\n StormcloudVideoPlayerComponent as default,\n detectBrowser,\n getBrowserConfigOverrides,\n getBrowserID,\n getClientInfo,\n getRecommendedAdPlayer,\n initializePolyfills,\n isMediaStream,\n lazy,\n logBrowserInfo,\n merge,\n omit,\n parseQuery,\n players_default as players,\n randomString,\n sendHeartbeat,\n sendInitialTracking,\n supportsFeature,\n supportsGoogleIMA,\n supportsModernJS,\n supportsWebKitPresentationMode\n};\n","import React, { useEffect, useRef, useMemo } from \"react\";\nimport { StormcloudVideoPlayer } from \"../player/StormcloudVideoPlayer\";\nimport type { StormcloudVideoPlayerConfig } from \"../types\";\nimport {\n FaPlay,\n FaPause,\n FaVolumeUp,\n FaVolumeMute,\n FaVolumeDown,\n FaExpand,\n FaCompress,\n FaSpinner,\n} from \"react-icons/fa\";\n\nexport type StormcloudVideoPlayerProps = Omit<\n StormcloudVideoPlayerConfig,\n \"videoElement\"\n> &\n React.VideoHTMLAttributes<HTMLVideoElement> & {\n onReady?: (player: StormcloudVideoPlayer) => void;\n wrapperClassName?: string;\n wrapperStyle?: React.CSSProperties;\n licenseKey?: string;\n };\n\nconst CRITICAL_PROPS = [\n \"src\",\n \"allowNativeHls\",\n \"licenseKey\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"vastMode\",\n] as const;\n\nexport const StormcloudVideoPlayerComponent: React.FC<StormcloudVideoPlayerProps> =\n React.memo(\n (props) => {\n const {\n src,\n autoplay,\n muted,\n lowLatencyMode,\n allowNativeHls,\n driftToleranceMs,\n immediateManifestAds,\n debugAdTiming,\n showCustomControls,\n hideLoadingIndicator,\n onVolumeToggle,\n onFullscreenToggle,\n onControlClick,\n onReady,\n wrapperClassName,\n wrapperStyle,\n className,\n style,\n controls,\n playsInline,\n preload,\n poster,\n children,\n licenseKey,\n vastMode,\n vastTagUrl,\n adPlayerType,\n minSegmentsBeforePlay,\n ...restVideoAttrs\n } = props;\n\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const playerRef = useRef<StormcloudVideoPlayer | null>(null);\n const bufferingTimeoutRef = useRef<number | null>(null);\n const [adStatus, setAdStatus] = React.useState<{\n showAds: boolean;\n currentIndex: number;\n totalAds: number;\n }>({ showAds: false, currentIndex: 0, totalAds: 0 });\n\n const [shouldShowNativeControls, setShouldShowNativeControls] =\n React.useState(true);\n\n const [isMuted, setIsMuted] = React.useState(false);\n const [isFullscreen, setIsFullscreen] = React.useState(false);\n const [isPlaying, setIsPlaying] = React.useState(false);\n const [currentTime, setCurrentTime] = React.useState(0);\n const [duration, setDuration] = React.useState(0);\n const [volume, setVolume] = React.useState(1);\n const [playbackRate, setPlaybackRate] = React.useState(1);\n const [showVolumeSlider, setShowVolumeSlider] = React.useState(false);\n const [showSpeedMenu, setShowSpeedMenu] = React.useState(false);\n const [isLoading, setIsLoading] = React.useState(true);\n const [isBuffering, setIsBuffering] = React.useState(false);\n const [showCenterPlay, setShowCenterPlay] = React.useState(false);\n const [showLicenseWarning, setShowLicenseWarning] = React.useState(false);\n const [viewportWidth, setViewportWidth] = React.useState(\n typeof window !== \"undefined\" ? window.innerWidth : 1920\n );\n const [isPortrait, setIsPortrait] = React.useState(\n typeof window !== \"undefined\"\n ? window.innerHeight > window.innerWidth\n : false\n );\n\n const getResponsiveScale = () => {\n if (viewportWidth < 480) return 0.7;\n if (viewportWidth < 768) return 0.8;\n if (viewportWidth < 1024) return 0.9;\n return 1;\n };\n\n const responsiveScale = getResponsiveScale();\n\n const formatTime = (seconds: number): string => {\n if (!isFinite(seconds)) return \"0:00:00\";\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n return `${hours}:${minutes\n .toString()\n .padStart(2, \"0\")}:${remainingSeconds.toString().padStart(2, \"0\")}`;\n };\n\n const handlePlayPause = () => {\n if (videoRef.current) {\n if (videoRef.current.paused) {\n const hasValidSource =\n videoRef.current.src ||\n (videoRef.current.currentSrc &&\n videoRef.current.currentSrc !== \"\") ||\n videoRef.current.readyState >= 1;\n\n if (hasValidSource) {\n videoRef.current.play()?.catch((error) => {\n console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n });\n setShowCenterPlay(false);\n } else {\n console.warn(\n \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n );\n }\n } else {\n videoRef.current.pause();\n setShowCenterPlay(true);\n }\n }\n };\n\n const handleCenterPlayClick = () => {\n if (videoRef.current && videoRef.current.paused) {\n const hasValidSource =\n videoRef.current.src ||\n (videoRef.current.currentSrc &&\n videoRef.current.currentSrc !== \"\") ||\n videoRef.current.readyState >= 1;\n\n if (hasValidSource) {\n videoRef.current.play()?.catch((error) => {\n console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n });\n setShowCenterPlay(false);\n } else {\n console.warn(\n \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n );\n }\n }\n };\n\n const handleTimelineSeek = (e: React.MouseEvent<HTMLDivElement>) => {\n if (videoRef.current && duration > 0 && isFinite(duration)) {\n const rect = e.currentTarget.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n const progress = Math.max(0, Math.min(1, clickX / rect.width));\n const newTime = progress * duration;\n\n if (isFinite(newTime) && newTime >= 0 && newTime <= duration) {\n videoRef.current.currentTime = newTime;\n }\n }\n };\n\n const handleVolumeChange = (newVolume: number) => {\n if (playerRef.current && isFinite(newVolume)) {\n const clampedVolume = Math.max(0, Math.min(1, newVolume));\n playerRef.current.setVolume(clampedVolume);\n }\n };\n\n const handlePlaybackRateChange = (rate: number) => {\n if (videoRef.current && isFinite(rate) && rate > 0) {\n videoRef.current.playbackRate = rate;\n }\n setShowSpeedMenu(false);\n };\n\n const isHlsStream =\n src?.toLowerCase().includes(\".m3u8\") ||\n src?.toLowerCase().includes(\"/hls/\");\n const shouldShowEnhancedControls =\n showCustomControls && (isHlsStream ? allowNativeHls : true);\n\n const criticalPropsKey = useMemo(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n licenseKey,\n lowLatencyMode,\n driftToleranceMs,\n vastMode,\n ]);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const el = videoRef.current;\n if (!el || !src) return;\n\n if (!licenseKey) {\n setShowLicenseWarning(true);\n setIsLoading(false);\n console.warn(\n \"StormcloudVideoPlayer: License key is required but not provided. Please set the licenseKey prop to use the player.\"\n );\n return;\n }\n\n setShowLicenseWarning(false);\n\n if (debugAdTiming) {\n console.log(\"[StormcloudUI] Initializing player, isLoading=true\");\n }\n\n if (playerRef.current) {\n try {\n playerRef.current.destroy();\n } catch {}\n playerRef.current = null;\n }\n\n const cfg: StormcloudVideoPlayerConfig = {\n src,\n videoElement: el,\n } as StormcloudVideoPlayerConfig;\n if (autoplay !== undefined) cfg.autoplay = autoplay;\n if (muted !== undefined) cfg.muted = muted;\n if (lowLatencyMode !== undefined) cfg.lowLatencyMode = lowLatencyMode;\n if (allowNativeHls !== undefined) cfg.allowNativeHls = allowNativeHls;\n if (driftToleranceMs !== undefined)\n cfg.driftToleranceMs = driftToleranceMs;\n if (immediateManifestAds !== undefined)\n cfg.immediateManifestAds = immediateManifestAds;\n if (debugAdTiming !== undefined) cfg.debugAdTiming = debugAdTiming;\n if (showCustomControls !== undefined)\n cfg.showCustomControls = showCustomControls;\n if (onVolumeToggle !== undefined) cfg.onVolumeToggle = onVolumeToggle;\n if (onFullscreenToggle !== undefined)\n cfg.onFullscreenToggle = onFullscreenToggle;\n if (onControlClick !== undefined) cfg.onControlClick = onControlClick;\n if (licenseKey !== undefined) cfg.licenseKey = licenseKey;\n if (vastMode !== undefined) cfg.vastMode = vastMode;\n if (vastTagUrl !== undefined) cfg.vastTagUrl = vastTagUrl;\n if (adPlayerType !== undefined) cfg.adPlayerType = adPlayerType;\n if (minSegmentsBeforePlay !== undefined)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n\n const player = new StormcloudVideoPlayer(cfg);\n playerRef.current = player;\n player\n .load()\n .then(() => {\n const showNative = player.shouldShowNativeControls();\n setShouldShowNativeControls(showNative);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Player loaded successfully, waiting for video ready\"\n );\n }\n onReady?.(player);\n })\n .catch((error) => {\n console.error(\n \"StormcloudVideoPlayer: Failed to load player:\",\n error\n );\n setIsLoading(false);\n onReady?.(player);\n });\n\n return () => {\n try {\n player.destroy();\n } catch {}\n playerRef.current = null;\n };\n }, [criticalPropsKey]);\n\n useEffect(() => {\n if (!playerRef.current) return;\n\n try {\n if (autoplay !== undefined && playerRef.current.videoElement) {\n playerRef.current.videoElement.autoplay = autoplay;\n }\n if (muted !== undefined && !playerRef.current.isShowingAds()) {\n playerRef.current.setMuted(muted);\n }\n } catch (error) {\n console.warn(\"Failed to update player properties:\", error);\n }\n }, [autoplay, muted]);\n\n useEffect(() => {\n if (!playerRef.current) return;\n\n const checkAdStatus = () => {\n if (playerRef.current) {\n const showAdsFromMethod = playerRef.current.isShowingAds();\n const showAdsFromAttribute = videoRef.current?.dataset?.stormcloudAdPlaying === \"true\";\n const showAds = showAdsFromMethod || showAdsFromAttribute;\n const currentIndex = playerRef.current.getCurrentAdIndex();\n const totalAds = playerRef.current.getTotalAdsInBreak();\n\n setAdStatus((prev) => {\n if (\n prev.showAds !== showAds ||\n prev.currentIndex !== currentIndex ||\n prev.totalAds !== totalAds\n ) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds };\n }\n return prev;\n });\n }\n };\n\n const interval = setInterval(checkAdStatus, 50);\n return () => clearInterval(interval);\n }, []);\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !playerRef.current) return;\n\n const handleResize = () => {\n if (playerRef.current && videoRef.current) {\n if (typeof playerRef.current.resize === \"function\") {\n playerRef.current.resize();\n }\n }\n setViewportWidth(window.innerWidth);\n setIsPortrait(window.innerHeight > window.innerWidth);\n };\n\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n useEffect(() => {\n if (!playerRef.current || !videoRef.current) return;\n\n const updateStates = () => {\n if (playerRef.current && videoRef.current) {\n setIsMuted(playerRef.current.isMuted());\n setIsPlaying(!videoRef.current.paused);\n\n const currentTimeValue = videoRef.current.currentTime;\n setCurrentTime(isFinite(currentTimeValue) ? currentTimeValue : 0);\n\n const durationValue = videoRef.current.duration;\n setDuration(isFinite(durationValue) ? durationValue : 0);\n\n const volumeValue = videoRef.current.volume;\n setVolume(\n isFinite(volumeValue) ? Math.max(0, Math.min(1, volumeValue)) : 1\n );\n\n const rateValue = videoRef.current.playbackRate;\n setPlaybackRate(\n isFinite(rateValue) && rateValue > 0 ? rateValue : 1\n );\n }\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\n );\n };\n\n const interval = setInterval(updateStates, 200);\n\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\n );\n };\n\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n\n return () => {\n clearInterval(interval);\n document.removeEventListener(\n \"fullscreenchange\",\n handleFullscreenChange\n );\n };\n }, []);\n\n useEffect(() => {\n if (!videoRef.current) return;\n\n const handleLoadedMetadata = () => {\n if (videoRef.current) {\n const video = videoRef.current;\n void video.offsetHeight;\n }\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadedmetadata, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n\n const handleLoadedData = () => {\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadeddata, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n\n const handleLoadStart = () => {\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: loadstart, readyState:\",\n videoRef.current?.readyState\n );\n }\n };\n\n const handleCanPlay = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: canplay, readyState:\",\n videoRef.current?.readyState,\n \"- clearing loading state, isLoading=false\"\n );\n }\n };\n\n const handleCanPlayThrough = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: canplaythrough, readyState:\",\n videoRef.current?.readyState,\n \"- clearing loading state, isLoading=false\"\n );\n }\n };\n\n const handleWaiting = () => {\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n }\n\n bufferingTimeoutRef.current = window.setTimeout(() => {\n setIsBuffering(true);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video buffering detected (after 300ms delay), readyState:\",\n videoRef.current?.readyState,\n \"- showing spinner, isBuffering=true\"\n );\n }\n }, 300);\n\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: waiting, readyState:\",\n videoRef.current?.readyState,\n \"- buffering delay started (300ms)\"\n );\n }\n };\n\n const handlePlaying = () => {\n setIsLoading(false);\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n setIsBuffering(false);\n setShowCenterPlay(false);\n if (debugAdTiming) {\n console.log(\n \"[StormcloudUI] Video event: playing, readyState:\",\n videoRef.current?.readyState,\n \"- playback started, isLoading=false, isBuffering=false\"\n );\n }\n };\n\n const handlePause = () => {\n const isAdActive = playerRef.current?.isShowingAds() || \n videoRef.current?.dataset?.stormcloudAdPlaying === \"true\";\n \n if (playerRef.current && !isAdActive) {\n setShowCenterPlay(true);\n } else {\n setShowCenterPlay(false);\n }\n };\n\n const handleEnded = () => {\n setShowCenterPlay(true);\n };\n\n const video = videoRef.current;\n video.addEventListener(\"loadstart\", handleLoadStart);\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.addEventListener(\"canplay\", handleCanPlay);\n video.addEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.addEventListener(\"waiting\", handleWaiting);\n video.addEventListener(\"playing\", handlePlaying);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n\n if (video.paused) {\n setShowCenterPlay(true);\n }\n\n return () => {\n if (bufferingTimeoutRef.current) {\n clearTimeout(bufferingTimeoutRef.current);\n bufferingTimeoutRef.current = null;\n }\n\n video.removeEventListener(\"loadstart\", handleLoadStart);\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n video.removeEventListener(\"canplay\", handleCanPlay);\n video.removeEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.removeEventListener(\"waiting\", handleWaiting);\n video.removeEventListener(\"playing\", handlePlaying);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n };\n }, [debugAdTiming]);\n\n return (\n <>\n <style>\n {`\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n \n .stormcloud-loading-hidden .stormcloud-loading-indicator {\n display: none !important;\n }\n \n .stormcloud-video-wrapper:fullscreen {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n \n .stormcloud-video-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n \n *:fullscreen {\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n }\n `}\n </style>\n <div\n className={`stormcloud-video-wrapper ${wrapperClassName || \"\"}`}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n position: isFullscreen ? \"fixed\" : \"relative\",\n top: isFullscreen ? 0 : undefined,\n left: isFullscreen ? 0 : undefined,\n overflow: \"hidden\",\n width: isFullscreen ? \"100vw\" : \"100%\",\n height: isFullscreen ? \"100vh\" : \"auto\",\n minHeight: isFullscreen ? \"100vh\" : \"auto\",\n maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : undefined,\n backgroundColor: isFullscreen ? \"#000\" : undefined,\n borderRadius: isFullscreen ? 0 : undefined,\n boxShadow: isFullscreen ? \"none\" : undefined,\n ...wrapperStyle,\n }}\n >\n <video\n ref={videoRef}\n className={className}\n style={{\n display: \"block\",\n width: \"100%\",\n height: isFullscreen ? \"100%\" : \"auto\",\n maxWidth: \"100%\",\n maxHeight: isFullscreen ? \"100%\" : \"none\",\n objectFit: isFullscreen ? \"cover\" : \"contain\",\n backgroundColor: \"#000\",\n aspectRatio: isFullscreen ? \"unset\" : undefined,\n ...style,\n }}\n controls={\n shouldShowNativeControls && controls && !showCustomControls\n }\n playsInline={playsInline}\n preload={preload}\n poster={poster}\n {...restVideoAttrs}\n >\n {children}\n </video>\n\n {(isLoading || isBuffering) && !hideLoadingIndicator && (\n <FaSpinner\n className=\"stormcloud-loading-indicator\"\n size={42}\n color=\"white\"\n style={{\n position: \"absolute\",\n top: \"calc(50% - 21px)\",\n left: \"calc(50% - 21px)\",\n zIndex: 20,\n animation: \"spin 1s linear infinite\",\n filter: \"drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))\",\n }}\n />\n )}\n\n {showLicenseWarning && (\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 25,\n background:\n \"linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)\",\n color: \"white\",\n padding: \"24px 32px\",\n borderRadius: \"16px\",\n backdropFilter: \"blur(20px)\",\n border: \"2px solid rgba(255, 255, 255, 0.2)\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\",\n }}\n >\n <div\n style={{\n fontSize: \"20px\",\n fontWeight: \"bold\",\n marginBottom: \"12px\",\n color: \"#ffffff\",\n textShadow: \"0 2px 4px rgba(0, 0, 0, 0.5)\",\n }}\n >\n License Key Required\n </div>\n <div\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.5\",\n color: \"rgba(255, 255, 255, 0.9)\",\n textShadow: \"0 1px 2px rgba(0, 0, 0, 0.3)\",\n }}\n >\n Please provide a valid license key to use the Stormcloud Video\n Player.\n <br />\n Contact your administrator for licensing information.\n </div>\n </div>\n )}\n\n {showCenterPlay &&\n !isLoading &&\n !isBuffering &&\n !showLicenseWarning &&\n !adStatus.showAds && (\n <div\n onClick={handleCenterPlayClick}\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 15,\n cursor: \"pointer\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\",\n borderRadius: \"50%\",\n width: \"100px\",\n height: \"100px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n border: \"3px solid rgba(255, 255, 255, 0.8)\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLElement;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)\";\n target.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.9)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLElement;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\";\n target.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.8)\";\n }}\n title=\"Play\"\n >\n <FaPlay\n size={36}\n color=\"white\"\n style={{\n marginLeft: \"6px\",\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n }}\n />\n </div>\n )}\n\n {shouldShowEnhancedControls && !showLicenseWarning ? (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background:\n \"linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)\",\n padding: \"20px 16px 16px\",\n zIndex: 10,\n }}\n >\n <div\n style={{\n width: \"100%\",\n height: \"8px\",\n background:\n \"linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)\",\n borderRadius: \"8px\",\n marginBottom: \"16px\",\n cursor: \"pointer\",\n position: \"relative\",\n backdropFilter: \"blur(5px)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"inset 0 2px 4px rgba(0, 0, 0, 0.2)\",\n }}\n onClick={handleTimelineSeek}\n >\n <div\n style={{\n height: \"100%\",\n background:\n \"linear-gradient(90deg, rgba(139, 92, 246, 0.9) 0%, rgba(59, 130, 246, 0.8) 50%, rgba(34, 197, 94, 0.9) 100%)\",\n borderRadius: \"8px\",\n width: `${\n duration > 0 ? (currentTime / duration) * 100 : 0\n }%`,\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 2px 8px rgba(139, 92, 246, 0.4)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n top: \"-6px\",\n right: `${\n duration > 0\n ? 100 - (currentTime / duration) * 100\n : 100\n }%`,\n width: \"20px\",\n height: \"20px\",\n background:\n \"linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)\",\n borderRadius: \"50%\",\n border: \"3px solid rgba(139, 92, 246, 0.8)\",\n boxShadow:\n \"0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)\",\n transform: \"translateX(50%)\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n />\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n flexWrap: viewportWidth < 768 ? \"wrap\" : \"nowrap\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n flexWrap: viewportWidth < 480 ? \"wrap\" : \"nowrap\",\n }}\n >\n <button\n onClick={handlePlayPause}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n backdropFilter: \"blur(12px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${10 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n minWidth: `${48 * responsiveScale}px`,\n minHeight: `${48 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n target.style.boxShadow =\n \"0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n target.style.boxShadow =\n \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n }}\n title={isPlaying ? \"Pause\" : \"Play\"}\n >\n {isPlaying ? (\n <FaPause\n size={Math.max(16, 20 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n ) : (\n <FaPlay\n size={Math.max(16, 20 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n )}\n </button>\n\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\",\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n onClick={() => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n {isMuted || volume === 0 ? (\n <FaVolumeMute\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n ) : volume < 0.5 ? (\n <FaVolumeDown\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n ) : (\n <FaVolumeUp\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n )}\n </button>\n\n {showVolumeSlider && (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(15px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\",\n zIndex: 10,\n transition:\n \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)\";\n e.currentTarget.style.borderColor =\n \"rgba(59, 130, 246, 0.4)\";\n }}\n onMouseLeave={(e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\";\n e.currentTarget.style.borderColor =\n \"rgba(255, 255, 255, 0.15)\";\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n // Hover effect removed\n }}\n onMouseLeave={(e) => {\n // Hover effect removed\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n\n const handleMouseMove = (\n moveEvent: MouseEvent\n ) => {\n if (!sliderElement) return;\n const rect =\n sliderElement.getBoundingClientRect();\n const y = moveEvent.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n };\n\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n\n const rect =\n sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n onClick={(e) => {\n e.stopPropagation();\n const rect =\n e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background:\n \"linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)\",\n borderRadius: \"4px\",\n boxShadow:\n \"inset 0 1px 3px rgba(0, 0, 0, 0.2)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background:\n \"linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)\",\n borderRadius: \"4px\",\n transition:\n \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow:\n \"0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: `calc(${\n (isMuted ? 0 : volume) * 100\n }% - 7px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"14px\",\n height: \"14px\",\n background:\n \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n boxShadow:\n \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\",\n transition:\n \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)\";\n e.currentTarget.style.cursor = \"grab\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n }}\n onMouseUp={(e) => {\n e.currentTarget.style.cursor = \"grab\";\n }}\n />\n </div>\n </div>\n </>\n )}\n </div>\n\n <div\n style={{\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\",\n }}\n >\n {formatTime(currentTime)} / {formatTime(duration)}\n </div>\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n }}\n >\n <div\n style={{\n position: \"relative\",\n display: viewportWidth < 600 ? \"none\" : \"block\",\n }}\n >\n <button\n onClick={() => setShowSpeedMenu(!showSpeedMenu)}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px ${\n 14 * responsiveScale\n }px`,\n borderRadius: `${14 * responsiveScale}px`,\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n fontWeight: \"700\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${56 * responsiveScale}px`,\n minHeight: `${40 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title=\"Playback Speed\"\n >\n {playbackRate}x\n </button>\n\n {showSpeedMenu && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n right: 0,\n marginBottom: \"12px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)\",\n backdropFilter: \"blur(20px)\",\n borderRadius: \"12px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"90px\",\n boxShadow:\n \"0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)\",\n }}\n >\n {[0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(\n (speed) => (\n <button\n key={speed}\n onClick={() =>\n handlePlaybackRateChange(speed)\n }\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"10px 16px\",\n background:\n playbackRate === speed\n ? \"linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)\"\n : \"transparent\",\n border: \"none\",\n color: \"white\",\n cursor: \"pointer\",\n fontSize: \"13px\",\n fontFamily: \"monospace\",\n fontWeight: \"600\",\n textAlign: \"center\",\n transition:\n \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n borderBottom:\n speed !== 2\n ? \"1px solid rgba(255, 255, 255, 0.05)\"\n : \"none\",\n }}\n onMouseEnter={(e) => {\n if (playbackRate !== speed) {\n (\n e.target as HTMLElement\n ).style.background =\n \"linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)\";\n }\n }}\n onMouseLeave={(e) => {\n if (playbackRate !== speed) {\n (\n e.target as HTMLElement\n ).style.background = \"transparent\";\n }\n }}\n >\n {speed}x\n </button>\n )\n )}\n </div>\n )}\n </div>\n\n <button\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current\n .toggleFullscreen()\n .catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title={\n isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"\n }\n >\n {isFullscreen ? (\n <FaCompress\n size={Math.max(14, 16 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n ) : (\n <FaExpand\n size={Math.max(14, 16 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n )}\n </button>\n </div>\n </div>\n </div>\n </>\n ) : (\n showCustomControls &&\n !showLicenseWarning && (\n <div\n style={{\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n transform: \"none\",\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n gap: `${10 * responsiveScale}px`,\n zIndex: 10,\n }}\n >\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\",\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n onClick={() => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow:\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`,\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n {isMuted || volume === 0 ? (\n <FaVolumeMute\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : volume < 0.5 ? (\n <FaVolumeDown\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : (\n <FaVolumeUp\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n )}\n </button>\n\n {showVolumeSlider && (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(20px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.7)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\",\n zIndex: 10,\n transition:\n \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)\";\n e.currentTarget.style.borderColor =\n \"rgba(96, 165, 250, 0.8)\";\n }}\n onMouseLeave={(e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\";\n e.currentTarget.style.borderColor =\n \"rgba(255, 255, 255, 0.7)\";\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\",\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n\n const handleMouseMove = (\n moveEvent: MouseEvent\n ) => {\n if (!sliderElement) return;\n const rect =\n sliderElement.getBoundingClientRect();\n const y = moveEvent.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n };\n\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n\n const rect =\n sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n onClick={(e) => {\n e.stopPropagation();\n const rect =\n e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background:\n \"linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)\",\n borderRadius: \"4px\",\n border: \"1px solid rgba(255, 255, 255, 0.4)\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.3)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background:\n \"linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)\",\n borderRadius: \"4px\",\n transition:\n \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow:\n \"0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: `calc(${\n (isMuted ? 0 : volume) * 100\n }% - 8px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"16px\",\n height: \"16px\",\n background:\n \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n border: \"2px solid rgba(96, 165, 250, 0.9)\",\n boxShadow:\n \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\",\n transition:\n \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)\";\n e.currentTarget.style.cursor = \"grab\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n }}\n onMouseUp={(e) => {\n e.currentTarget.style.cursor = \"grab\";\n }}\n />\n </div>\n </div>\n </>\n )}\n </div>\n\n <button\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow:\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`,\n }}\n title={\n isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"\n }\n >\n {isFullscreen ? (\n <FaCompress\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : (\n <FaExpand\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n )}\n </button>\n </div>\n )\n )}\n\n {onControlClick && (\n <div\n onClick={onControlClick}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 1,\n cursor: \"pointer\",\n }}\n />\n )}\n </div>\n </>\n );\n },\n (prevProps, nextProps) => {\n for (const prop of CRITICAL_PROPS) {\n if ((prevProps as any)[prop] !== (nextProps as any)[prop]) {\n return false;\n }\n }\n\n const uiProps = [\n \"autoplay\",\n \"muted\",\n \"controls\",\n \"showCustomControls\",\n \"className\",\n \"style\",\n \"wrapperClassName\",\n \"wrapperStyle\",\n \"playsInline\",\n \"preload\",\n \"poster\",\n \"children\",\n ] as const;\n\n for (const prop of uiProps) {\n if ((prevProps as any)[prop] !== (nextProps as any)[prop]) {\n return false;\n }\n }\n\n const callbackProps = [\n \"onReady\",\n \"onVolumeToggle\",\n \"onFullscreenToggle\",\n \"onControlClick\",\n ] as const;\n for (const prop of callbackProps) {\n if ((prevProps as any)[prop] !== (nextProps as any)[prop]) {\n return false;\n }\n }\n\n return true;\n }\n );\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n ImaController,\n AdBreak,\n StormcloudApiResponse,\n} from \"../types\";\nimport { createImaController } from \"../sdk/ima\";\nimport { createHlsAdPlayer } from \"../sdk/hlsAdPlayer\";\nimport { sendInitialTracking, sendHeartbeat } from \"../utils/tracking\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport {\n supportsGoogleIMA,\n logBrowserInfo,\n getBrowserConfigOverrides,\n} from \"../utils/browserCompat\";\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private ima: ImaController;\n private attached = false;\n private inAdBreak = false;\n private currentAdBreakStartWallClockMs: number | undefined;\n private expectedAdBreakDurationMs: number | undefined;\n private adStopTimerId: number | undefined;\n private adStartTimerId: number | undefined;\n private adFailsafeTimerId: number | undefined;\n private ptsDriftEmaMs = 0;\n private adPodQueue: string[] = [];\n private apiVastTagUrl: string | undefined;\n private apiNumberAds: number | undefined;\n private lastHeartbeatTime: number = 0;\n private heartbeatInterval: number | undefined;\n private currentAdIndex: number = 0;\n private totalAdsInBreak: number = 0;\n private showAds: boolean = false;\n private isLiveStream: boolean = false;\n private nativeHlsMode: boolean = false;\n private videoSrcProtection: string | null = null;\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n private adPodAllUrls: string[] = [];\n private preloadingAdUrls: Set<string> = new Set();\n private vastToMediaUrlMap: Map<string, string[]> = new Map();\n private preloadedMediaUrls: Set<string> = new Set();\n private preloadingMediaUrls: Set<string> = new Set();\n private adRequestTokenCounter = 0;\n private activeAdRequestToken: number | null = null;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n private fetchedAdDurations: Map<string, number> = new Map();\n private targetAdBreakDurationMs: number | null = null;\n private isAdaptiveMode: boolean = false;\n private failedVastUrls: Set<string> = new Set();\n private continuousFetchingActive: boolean = false;\n private adRequestQueue: string[] = [];\n private successfulAdRequests: string[] = [];\n private maxPlaceholderDurationMs: number = 5000;\n private placeholderStartTimeMs: number | null = null;\n private isShowingPlaceholder: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n \n private consecutiveEmptyResponses: number = 0;\n private totalAdRequestsInBreak: number = 0;\n private lastEmptyResponseTimeMs: number = 0;\n private readonly maxTotalAdRequestsPerBreak: number = 20;\n private readonly maxConsecutiveEmptyResponses: number = 5;\n private readonly baseEmptyResponseDelayMs: number = 2000;\n private readonly maxEmptyResponseDelayMs: number = 30000;\n\n constructor(config: StormcloudVideoPlayerConfig) {\n initializePolyfills();\n\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...config, ...browserOverrides };\n this.video = config.videoElement;\n\n logBrowserInfo(config.debugAdTiming);\n\n this.ima = this.createAdPlayer(false);\n }\n\n private createAdPlayer(continueLiveStreamDuringAds: boolean): ImaController {\n const vastMode = this.config.vastMode || \"default\";\n let adPlayerType =\n this.config.adPlayerType || (vastMode === \"adstorm\" ? \"hls\" : \"ima\");\n\n if (adPlayerType === \"ima\" && !supportsGoogleIMA()) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player\"\n );\n }\n adPlayerType = \"hls\";\n }\n\n if (adPlayerType === \"hls\") {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)\"\n );\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...(this.config.licenseKey\n ? { licenseKey: this.config.licenseKey }\n : {}),\n ...(this.hls ? { mainHlsInstance: this.hls } : {}),\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)\"\n );\n }\n return createImaController(this.video, {\n continueLiveStreamDuringAds,\n });\n }\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\n }\n\n try {\n await this.fetchAdConfiguration();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n\n this.initializeTracking();\n\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\",\n }\n );\n }\n\n this.ima.destroy();\n this.ima = this.createAdPlayer(false);\n this.ima.initialize();\n\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n return;\n }\n\n this.hls = new Hls({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1.0,\n ...(this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}),\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1000 * 1000,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1,\n });\n\n this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n\n this.hls.on(Hls.Events.MANIFEST_PARSED, async (_, data: any) => {\n this.isLiveStream =\n this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds()\n ? \"live (main video continues muted during ads)\"\n : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior,\n });\n }\n\n this.ima.destroy();\n this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.ima.initialize();\n\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n }\n });\n\n this.hls.on(Hls.Events.LEVEL_LOADED, (_evt, data: any) => {\n if (this.inAdBreak) {\n return;\n }\n\n const details = data?.details;\n if (!details || !details.fragments || details.fragments.length === 0) {\n return;\n }\n\n const fragmentsToScan = Math.min(5, details.fragments.length);\n \n for (let i = 0; i < fragmentsToScan; i++) {\n const frag = details.fragments[i];\n const tagList: any[] | undefined = frag?.tagList;\n \n if (!Array.isArray(tagList)) continue;\n\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n \n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n }\n }\n\n if (!tag) continue;\n\n if (tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = tag.includes(\"EXT-X-DATERANGE\") \n ? this.parseAttributeList(value)\n : {};\n const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") || \n \"SCTE35-OUT\" in attrs || \n attrs[\"SCTE35-OUT\"] !== undefined;\n\n if (hasScteOut) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] 🎯 EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- triggering ad handling immediately\");\n }\n\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value, earlyDetection: true },\n } as Scte35Marker;\n\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = durationSeconds ? durationSeconds * 1000 : undefined;\n this.currentAdBreakStartWallClockMs = Date.now();\n\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n }\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_BUFFERED, async (_evt, data: any) => {\n if (this.hasInitialBufferCompleted) {\n return;\n }\n\n this.bufferedSegmentsCount++;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_PARSING_METADATA, (_evt, data: any) => {\n const id3Tags: Id3TagInfo[] = (data?.samples || []).map((s: any) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts,\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n\n this.hls.on(Hls.Events.FRAG_CHANGED, (_evt, data: any) => {\n const frag = data?.frag;\n const tagList: any[] | undefined = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(prog?.duration !== undefined\n ? { durationSeconds: prog.duration }\n : {}),\n ...(prog?.elapsed !== undefined\n ? { ptsSeconds: prog.elapsed }\n : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { tag, value, attrs },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n\n this.hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case Hls.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case Hls.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private attach(): void {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n\n this.ima.initialize();\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.ima.on(\"all_ads_completed\", () => {\n const remaining = this.getRemainingAdMs();\n \n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`\n );\n }\n\n if (this.inAdBreak) {\n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n this.ima.on(\"ad_error\", (errorPayload?: any) => {\n const remaining = this.getRemainingAdMs();\n console.error(\"[AD-ERROR] Ad playback failed\", errorPayload || \"\");\n \n if (this.inAdBreak) {\n if (remaining > 500 && this.adPodQueue.length > 0) {\n const nextPreloaded = this.findNextPreloadedAd();\n if (nextPreloaded) {\n this.currentAdIndex++;\n this.playSingleAd(nextPreloaded).catch(() => {\n this.handleAdFailure();\n });\n } else {\n this.handleAdFailure();\n }\n } else {\n this.handleAdFailure();\n }\n } else {\n this.handleAdFailure();\n }\n });\n this.ima.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n });\n this.ima.on(\"content_resume\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n return;\n }\n\n const remaining = this.getRemainingAdMs();\n \n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);\n }\n\n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n this.handleAdPodComplete();\n }\n });\n\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n\n this.emptiedHandler = () => {\n if (\n this.nativeHlsMode &&\n this.videoSrcProtection &&\n !this.ima.isAdPlaying()\n ) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n\n if (streamType === \"other\") {\n return true;\n }\n\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return undefined;\n\n const cueOutMatch =\n text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) ||\n text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(dur !== undefined ? { durationSeconds: dur } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(cont?.duration !== undefined\n ? { durationSeconds: cont.duration }\n : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n if (hasScteIn) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n }\n\n if (/SCTE35-OUT/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n }\n\n private decodeId3ValueToText(value: string | Uint8Array): string | undefined {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]!);\n return out;\n } catch {\n return undefined;\n }\n }\n\n private onScte35Marker(marker: Scte35Marker): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n });\n }\n\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n return;\n }\n\n this.inAdBreak = true;\n const durationMs =\n marker.durationSeconds != null\n ? marker.durationSeconds * 1000\n : undefined;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n });\n }\n\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1000;\n const nowMs = this.video.currentTime * 1000;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1000 - estCurrentPtsMs);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1000,\n deltaMs,\n tolerance: tol,\n });\n }\n\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n if (\n this.expectedAdBreakDurationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n \n if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null) {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1000\n );\n const tags =\n this.selectVastTagsForBreak(scheduled) ||\n (this.apiVastTagUrl ? [this.apiVastTagUrl] : undefined);\n if (tags && tags.length > 0) {\n const first = tags[0] as string;\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n \n this.playSingleAd(first).catch(() => {});\n }\n }\n return;\n }\n if (marker.type === \"end\") {\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n \n if (this.ima.isAdPlaying()) {\n this.ima.stop().catch(() => {});\n }\n \n this.handleAdPodComplete();\n return;\n }\n }\n\n private parseCueOutDuration(value: string): number | undefined {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match =\n value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) ||\n value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? undefined : d;\n }\n return undefined;\n }\n\n private parseCueOutCont(\n value: string\n ): { elapsed?: number; duration?: number } | undefined {\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n const res: { elapsed?: number; duration?: number } = {};\n if (elapsedMatch && elapsedMatch[1] != null) {\n const e = parseFloat(elapsedMatch[1]);\n if (!Number.isNaN(e)) res.elapsed = e;\n }\n if (durationMatch && durationMatch[1] != null) {\n const d = parseFloat(durationMatch[1]);\n if (!Number.isNaN(d)) res.duration = d;\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return undefined;\n }\n\n private parseAttributeList(value: string): Record<string, string> {\n const attrs: Record<string, string> = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(value)) !== null) {\n const key: string = (match[1] ?? \"\") as string;\n let rawVal: string = (match[3] ?? match[4] ?? \"\") as string;\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n\n private toNumber(val: unknown): number | undefined {\n if (val == null) return undefined;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? undefined : n;\n }\n\n private isManifestBasedMarker(marker: Scte35Marker): boolean {\n const raw = marker.raw as any;\n if (!raw) return false;\n\n if (raw.tag) {\n const tag = String(raw.tag);\n return (\n tag.includes(\"EXT-X-CUE-OUT\") ||\n tag.includes(\"EXT-X-CUE-IN\") ||\n tag.includes(\"EXT-X-DATERANGE\")\n );\n }\n\n if (raw.id3) return false;\n\n if (raw.splice_command_type) return false;\n\n return false;\n }\n\n private parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\n class BitReader {\n private bytePos = 0;\n private bitPos = 0;\n constructor(private readonly buf: Uint8Array) {}\n readBits(numBits: number): number {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos]!;\n const shift = remainingInByte - toRead;\n const mask = ((1 << toRead) - 1) & 0xff;\n const bits = (currentByte >> shift) & mask;\n result = (result << toRead) | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n: number): void {\n this.readBits(n);\n }\n }\n\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 0xfc) return undefined;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return undefined;\n }\n r.readBits(32);\n const cancel = r.readBits(1) === 1;\n r.readBits(7);\n if (cancel) return undefined;\n const outOfNetwork = r.readBits(1) === 1;\n const programSpliceFlag = r.readBits(1) === 1;\n const durationFlag = r.readBits(1) === 1;\n const spliceImmediateFlag = r.readBits(1) === 1;\n r.readBits(4);\n if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n } else if (!programSpliceFlag) {\n const componentCount = r.readBits(8);\n for (let i = 0; i < componentCount; i++) {\n r.readBits(8);\n if (!spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds: number | undefined = undefined;\n if (durationFlag) {\n r.readBits(6);\n r.readBits(1);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const durationTicks = high * 0x100000000 + low;\n durationSeconds = durationTicks / 90000;\n }\n r.readBits(16);\n r.readBits(8);\n r.readBits(8);\n\n if (outOfNetwork) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { splice_command_type: 5 },\n } as Scte35Marker;\n return marker;\n }\n return undefined;\n }\n\n private initializeTracking(): void {\n sendInitialTracking(this.config.licenseKey)\n .then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n })\n .catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n });\n }\n\n private sendHeartbeatIfNeeded(): void {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 30000) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n private async fetchAdConfiguration(): Promise<void> {\n const vastMode = this.config.vastMode || \"default\";\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n );\n }\n return;\n }\n\n const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n this.apiVastTagUrl = vastEndpoint;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n vastEndpoint\n );\n }\n return;\n }\n\n if (this.config.vastTagUrl) {\n this.apiVastTagUrl = this.config.vastTagUrl;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n return;\n }\n\n const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n apiUrl\n );\n }\n\n const headers: Record<string, string> = {};\n if (this.config.licenseKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n }\n\n const response = await fetch(apiUrl, { headers });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n );\n }\n return;\n }\n\n const data: StormcloudApiResponse = await response.json();\n\n const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n if (imaPayload) {\n this.apiVastTagUrl = decodeURIComponent(imaPayload);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n );\n }\n }\n\n const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n if (numberAds != null && numberAds > 0) {\n this.apiNumberAds = numberAds;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n\n getCurrentAdIndex(): number {\n return this.currentAdIndex;\n }\n\n getTotalAdsInBreak(): number {\n return this.totalAdsInBreak;\n }\n\n private generateVastUrlsWithCorrelators(\n baseUrl: string,\n count: number\n ): string[] {\n const urls: string[] = [];\n \n for (let i = 0; i < count; i++) {\n try {\n const url = new URL(baseUrl);\n const timestamp = Date.now();\n const random = Math.floor(Math.random() * 1000000);\n const uniqueCorrelator = `${timestamp}${random}${i}`;\n \n url.searchParams.set(\"correlator\", uniqueCorrelator);\n \n urls.push(url.toString());\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to parse VAST URL:\",\n baseUrl,\n error\n );\n urls.push(`${baseUrl}${baseUrl.includes(\"?\") ? \"&\" : \"?\"}correlator=${Date.now()}${i}`);\n }\n }\n \n return urls;\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.ima.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.showAds;\n }\n\n getStreamType(): \"hls\" | \"other\" {\n const url = this.config.src.toLowerCase();\n if (\n url.includes(\".m3u8\") ||\n url.includes(\"/hls/\") ||\n url.includes(\"application/vnd.apple.mpegurl\")\n ) {\n return \"hls\";\n }\n return \"other\";\n }\n\n shouldShowNativeControls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(\n this.config.allowNativeHls && !(this.config.showCustomControls ?? false)\n );\n }\n\n private shouldContinueLiveStreamDuringAds(): boolean {\n if (this.config.allowNativeHls) {\n return false;\n }\n\n if (!this.isLiveStream) {\n return false;\n }\n\n return true;\n }\n\n private async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1000\n );\n const tags = this.selectVastTagsForBreak(scheduled);\n\n let baseVastUrl: string;\n\n if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else {\n return;\n }\n\n const adBreakDurationMs = \n _marker.durationSeconds != null \n ? _marker.durationSeconds * 1000 \n : scheduled?.durationMs;\n\n if (this.isLiveStream && adBreakDurationMs != null && adBreakDurationMs > 0) {\n this.isAdaptiveMode = true;\n this.targetAdBreakDurationMs = adBreakDurationMs;\n this.fetchedAdDurations.clear();\n\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] 📺 LIVE MODE: Target duration=${adBreakDurationMs}ms | ` +\n `Will continuously fetch ads during break`\n );\n }\n } else {\n this.isAdaptiveMode = false;\n this.targetAdBreakDurationMs = null;\n this.fetchedAdDurations.clear();\n\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] 🎬 VOD MODE: Using fixed ad strategy`\n );\n }\n }\n\n this.adPodAllUrls = [];\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.failedVastUrls.clear();\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n \n this.consecutiveEmptyResponses = 0;\n this.totalAdRequestsInBreak = 0;\n this.lastEmptyResponseTimeMs = 0;\n\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n\n this.inAdBreak = true;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n \n this.showAds = true;\n \n this.ima.showPlaceholder();\n\n if (\n this.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🚀 Immediately requesting first ad...\");\n }\n\n const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const firstAdUrl = firstAdUrlArray[0];\n \n if (!firstAdUrl) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ Failed to generate first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n try {\n await this.ima.requestAds(firstAdUrl);\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ First ad request successful, starting playback\");\n }\n\n this.successfulAdRequests.push(firstAdUrl);\n this.currentAdIndex++;\n \n this.startContinuousFetching(baseVastUrl);\n \n await this.ima.play();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ First ad request failed:\", error);\n }\n this.failedVastUrls.add(firstAdUrl);\n \n this.startContinuousFetching(baseVastUrl);\n this.tryNextAvailableAd();\n }\n }\n\n private startContinuousFetching(baseVastUrl: string): void {\n if (!this.continuousFetchingActive) {\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🔄 Starting continuous ad fetching loop\");\n }\n\n this.continuousFetchLoop(baseVastUrl);\n }\n\n private async continuousFetchLoop(baseVastUrl: string): Promise<void> {\n while (this.continuousFetchingActive && this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n \n if (remaining <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ Ad break time expired, stopping fetch loop\");\n }\n break;\n }\n\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Maximum ad requests reached (${this.maxTotalAdRequestsPerBreak}), stopping fetch loop to prevent server blocks`);\n }\n break;\n }\n\n if (this.consecutiveEmptyResponses >= this.maxConsecutiveEmptyResponses) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive empty responses (${this.maxConsecutiveEmptyResponses}), stopping fetch loop`);\n }\n break;\n }\n\n const maxQueueSize = 3;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏸️ Queue full (${this.adRequestQueue.length}), pausing fetching...`);\n }\n await new Promise(resolve => setTimeout(resolve, 2000));\n continue;\n }\n\n const newAdUrl = this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];\n \n if (!newAdUrl || this.failedVastUrls.has(newAdUrl)) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n this.totalAdRequestsInBreak++;\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 📡 Attempting to fetch ad (request ${this.totalAdRequestsInBreak}/${this.maxTotalAdRequestsPerBreak}, queue: ${this.adRequestQueue.length})...`);\n }\n\n try {\n if (this.ima.preloadAds) {\n await this.ima.preloadAds(newAdUrl);\n }\n \n const hasPreloadedAd = this.ima.hasPreloadedAd?.(newAdUrl) ?? false;\n \n if (!hasPreloadedAd) {\n this.consecutiveEmptyResponses++;\n this.lastEmptyResponseTimeMs = Date.now();\n \n const backoffDelay = Math.min(\n this.baseEmptyResponseDelayMs * Math.pow(2, this.consecutiveEmptyResponses - 1),\n this.maxEmptyResponseDelayMs\n );\n \n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⚠️ Empty/invalid VAST response (${this.consecutiveEmptyResponses}/${this.maxConsecutiveEmptyResponses} consecutive), backing off for ${backoffDelay}ms`);\n }\n \n this.failedVastUrls.add(newAdUrl);\n await new Promise(resolve => setTimeout(resolve, backoffDelay));\n continue;\n }\n\n this.consecutiveEmptyResponses = 0;\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ✅ Successfully preloaded ad, adding to queue (queue size: ${this.adRequestQueue.length + 1})`);\n }\n \n this.adRequestQueue.push(newAdUrl);\n this.totalAdsInBreak++;\n \n await new Promise(resolve => setTimeout(resolve, 500));\n \n } catch (error) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ❌ Ad preload failed:\", (error as Error).message);\n }\n this.failedVastUrls.add(newAdUrl);\n \n this.consecutiveEmptyResponses++;\n const backoffDelay = Math.min(\n this.baseEmptyResponseDelayMs * Math.pow(2, this.consecutiveEmptyResponses - 1),\n this.maxEmptyResponseDelayMs\n );\n \n await new Promise(resolve => setTimeout(resolve, backoffDelay));\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Continuous fetch loop ended (total requests: ${this.totalAdRequestsInBreak}, empty responses: ${this.consecutiveEmptyResponses})`);\n }\n }\n\n private stopContinuousFetching(): void {\n this.continuousFetchingActive = false;\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Stopping continuous ad fetching\");\n }\n }\n\n private async tryNextAvailableAd(retryCount: number = 0): Promise<void> {\n const remaining = this.getRemainingAdMs();\n \n if (remaining <= 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (nextAdUrl) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🎬 Playing next queued ad (${this.currentAdIndex + 1}/${this.totalAdsInBreak}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n \n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🔊 Updated ad audio state: muted=${currentMuted}, volume=${currentVolume}`);\n }\n \n this.currentAdIndex++;\n this.successfulAdRequests.push(nextAdUrl);\n await this.playSingleAd(nextAdUrl).catch(() => {\n this.tryNextAvailableAd(0);\n });\n return;\n }\n }\n\n const maxRetries = 5;\n if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2000) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏳ Queue empty but fetching active, waiting... (retry ${retryCount + 1}/${maxRetries})`);\n }\n \n await new Promise(resolve => setTimeout(resolve, 1000));\n \n await this.tryNextAvailableAd(retryCount + 1);\n return;\n }\n\n if (!this.isShowingPlaceholder && remaining > 1000) {\n this.showPlaceholderAndWaitForAds();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No more ads available, ending ad break\");\n }\n this.handleAdPodComplete();\n }\n }\n\n private async showPlaceholderAndWaitForAds(): Promise<void> {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n \n if (waitTime < 1000) {\n this.handleAdPodComplete();\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⬛ Showing black placeholder for ${waitTime}ms while waiting for ads`);\n }\n\n this.isShowingPlaceholder = true;\n this.placeholderStartTimeMs = Date.now();\n \n this.ima.showPlaceholder();\n\n const checkInterval = 500;\n const maxChecks = Math.floor(waitTime / checkInterval);\n \n for (let i = 0; i < maxChecks; i++) {\n await new Promise(resolve => setTimeout(resolve, checkInterval));\n \n if (!this.inAdBreak) {\n return;\n }\n\n if (this.adRequestQueue.length > 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ New ad became available during placeholder\");\n }\n \n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n this.ima.hidePlaceholder();\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n \n const nextAdUrl = this.adRequestQueue.shift();\n if (nextAdUrl) {\n this.currentAdIndex++;\n this.successfulAdRequests.push(nextAdUrl);\n await this.playSingleAd(nextAdUrl).catch(() => {\n this.tryNextAvailableAd();\n });\n }\n return;\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏰ Placeholder timeout reached, no ads fetched\");\n }\n \n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n this.ima.hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n private findCurrentOrNextBreak(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = [];\n let candidate: AdBreak | undefined;\n for (const b of schedule) {\n const tol = this.config.driftToleranceMs ?? 1000;\n if (\n b.startTimeMs <= nowMs + tol &&\n (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))\n ) {\n candidate = b;\n }\n }\n return candidate;\n }\n\n private onTimeUpdate(currentTimeSec: number): void {\n if (this.ima.isAdPlaying()) return;\n const nowMs = currentTimeSec * 1000;\n const breakToPlay = this.findBreakForTime(nowMs);\n if (breakToPlay) {\n this.handleMidAdJoin(breakToPlay, nowMs);\n }\n }\n\n private async handleMidAdJoin(\n adBreak: AdBreak,\n nowMs: number\n ): Promise<void> {\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = adBreak.startTimeMs + durationMs;\n if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {\n const remainingMs = endMs - nowMs;\n const tags =\n this.selectVastTagsForBreak(adBreak) ||\n (this.apiVastTagUrl ? [this.apiVastTagUrl] : undefined);\n if (tags && tags.length > 0) {\n const first = tags[0] as string;\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n \n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n \n await this.playSingleAd(first);\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = remainingMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(remainingMs);\n }\n }\n }\n\n private scheduleAdStopCountdown(remainingMs: number): void {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.ensureAdStoppedByTimer();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.ensureAdStoppedByTimer();\n }, ms) as unknown as number;\n }\n\n private clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private ensureAdStoppedByTimer(): void {\n if (!this.inAdBreak) return;\n\n this.adStopTimerId = undefined;\n\n const adPlaying = this.ima.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1000)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs =\n typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0\n ? maxExtensionMsConfig\n : 60000;\n\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n\n const shouldExtendAdBreak =\n (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n\n if (adPlaying) {\n this.ima.stop().catch(() => {});\n }\n\n this.handleAdPodComplete();\n }\n\n private scheduleAdStartIn(delayMs: number): void {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n }, ms) as unknown as number;\n }\n\n private clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n private updatePtsDrift(ptsSecondsSample: number): void {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1000;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 60000) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n\n private async playSingleAd(vastTagUrl: string): Promise<void> {\n if (this.ima.isAdPlaying()) {\n return;\n }\n\n if (this.failedVastUrls.has(vastTagUrl)) {\n console.warn(\"[AD-ERROR] Skipping already-failed VAST URL:\", vastTagUrl.substring(0, 60));\n this.handleAdFailure();\n return;\n }\n\n const requestToken = ++this.adRequestTokenCounter;\n this.activeAdRequestToken = requestToken;\n \n this.startAdRequestWatchdog(requestToken);\n\n try {\n await this.ima.requestAds(vastTagUrl);\n\n this.clearAdRequestWatchdog();\n\n if (this.activeAdRequestToken !== requestToken) {\n return;\n }\n\n try {\n this.startAdFailsafeTimer(requestToken);\n await this.ima.play();\n } catch (playError) {\n console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n this.failedVastUrls.add(vastTagUrl);\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n this.handleAdFailure();\n return;\n }\n } catch (error) {\n console.error(\"[AD-ERROR] Ad request failed:\", (error as Error)?.message);\n this.failedVastUrls.add(vastTagUrl);\n\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n\n this.handleAdFailure();\n }\n }\n\n private handleAdPodComplete(): void {\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n\n this.stopContinuousFetching();\n \n if (this.isShowingPlaceholder) {\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n this.placeholderStartTimeMs = null;\n }\n\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.adPodAllUrls = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n\n this.ima.stop().catch(() => {});\n\n const restoredMuted = this.ima.getOriginalMutedState();\n const restoredVolume = this.ima.getOriginalVolume();\n\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n\n if (!this.shouldContinueLiveStreamDuringAds() && this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n }\n\n private handleAdFailure(): void {\n const remaining = this.getRemainingAdMs();\n \n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);\n }\n \n if (remaining > 500) {\n this.tryNextAvailableAd();\n } else {\n console.error(\"[AD-ERROR] Ad failed and no time remaining. Failed URLs:\", this.failedVastUrls.size);\n this.handleAdPodComplete();\n }\n }\n\n\n private startAdRequestWatchdog(token: number): void {\n this.clearAdRequestWatchdog();\n\n const timeoutMs = this.config.adFailsafeTimeoutMs ?? 10000;\n this.adRequestWatchdogToken = token;\n this.adRequestWatchdogId = window.setTimeout(() => {\n if (this.adRequestWatchdogToken !== token) {\n return;\n }\n\n this.adRequestWatchdogId = undefined;\n this.adRequestWatchdogToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n\n this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n this.handleAdFailure();\n }, timeoutMs) as unknown as number;\n\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n\n private clearAdRequestWatchdog(): void {\n if (this.adRequestWatchdogId != null) {\n clearTimeout(this.adRequestWatchdogId);\n this.adRequestWatchdogId = undefined;\n }\n\n if (this.adRequestWatchdogToken != null) {\n this.logAdState(\"ad_request_watchdog_cleared\", {\n token: this.adRequestWatchdogToken,\n });\n this.adRequestWatchdogToken = null;\n }\n }\n\n private startAdFailsafeTimer(token: number): void {\n this.clearAdFailsafeTimer();\n\n const failsafeMs = this.config.adFailsafeTimeoutMs ?? 10000;\n this.adFailsafeToken = token;\n\n this.adFailsafeTimerId = window.setTimeout(() => {\n if (this.adFailsafeToken !== token) {\n return;\n }\n\n this.adFailsafeTimerId = undefined;\n this.adFailsafeToken = null;\n\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n\n this.logAdState(\"ad_failsafe_triggered\", {\n token,\n failsafeMs,\n videoPaused: this.video.paused,\n imaAdPlaying: this.ima.isAdPlaying(),\n });\n\n this.handleAdFailure();\n }, failsafeMs) as unknown as number;\n\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n\n private clearAdFailsafeTimer(): void {\n if (this.adFailsafeTimerId != null) {\n clearTimeout(this.adFailsafeTimerId);\n this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n this.adFailsafeTimerId = undefined;\n }\n\n this.adFailsafeToken = null;\n }\n\n private selectVastTagsForBreak(b?: AdBreak): string[] | undefined {\n if (!b || !b.vastTagUrl) return undefined;\n if (b.vastTagUrl.includes(\",\")) {\n return b.vastTagUrl\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n }\n return [b.vastTagUrl];\n }\n\n private logAdState(event: string, extra: Record<string, unknown> = {}): void {\n if (!this.config.debugAdTiming) {\n return;\n }\n\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: new Date().toISOString(),\n showAds: this.showAds,\n adPlaying: this.ima.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n private async fetchAndParseVastXml(vastTagUrl: string): Promise<string[]> {\n try {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status}`);\n }\n const xmlText = await response.text();\n return this.extractMediaUrlsFromVast(xmlText);\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch/parse VAST XML: ${vastTagUrl}`,\n error\n );\n }\n return [];\n }\n }\n\n private extractMediaUrlsFromVast(xmlText: string): string[] {\n const mediaUrls: string[] = [];\n \n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n \n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n \n for (const mediaFile of Array.from(mediaFileElements)) {\n const url = mediaFile.textContent?.trim();\n if (url) {\n const lowerUrl = url.toLowerCase();\n if (\n lowerUrl.endsWith(\".mp4\") ||\n lowerUrl.endsWith(\".webm\") ||\n lowerUrl.endsWith(\".mov\") ||\n lowerUrl.endsWith(\".avi\") ||\n lowerUrl.includes(\".mp4?\") ||\n lowerUrl.includes(\".webm?\") ||\n lowerUrl.includes(\"/mp4/\") ||\n lowerUrl.includes(\"type=video\")\n ) {\n mediaUrls.push(url);\n }\n }\n }\n \n if (this.config.debugAdTiming && mediaUrls.length > 0) {\n console.log(\n `[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs from VAST:`,\n mediaUrls\n );\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to parse VAST XML:\",\n error\n );\n }\n }\n \n return mediaUrls;\n }\n\n private async fetchVastDuration(vastTagUrl: string): Promise<number | null> {\n try {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] Failed to fetch VAST: ${response.status}`\n );\n }\n return null;\n }\n \n const xmlText = await response.text();\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlText, \"text/xml\");\n \n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent;\n if (!durationText) {\n if (this.config.debugAdTiming) {\n console.warn(\"[ADAPTIVE-POD] No Duration element found in VAST\");\n }\n return null;\n }\n \n const durationParts = durationText.split(\":\");\n const durationSeconds =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n \n return durationSeconds;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] Error fetching VAST duration from ${vastTagUrl}:`,\n error\n );\n }\n return null;\n }\n }\n\n private calculateAdditionalAdsNeeded(): number {\n if (!this.isAdaptiveMode || this.targetAdBreakDurationMs === null) {\n return 0;\n }\n\n let totalFetchedDurationMs = 0;\n for (const duration of this.fetchedAdDurations.values()) {\n totalFetchedDurationMs += duration * 1000;\n }\n\n const fetchedCount = this.fetchedAdDurations.size;\n const averageDurationMs = fetchedCount > 0 \n ? totalFetchedDurationMs / fetchedCount \n : 30 * 1000;\n\n const queuedButNotFetched = this.adPodAllUrls.length - fetchedCount;\n \n const estimatedQueuedDurationMs = queuedButNotFetched * averageDurationMs;\n const estimatedTotalDurationMs = totalFetchedDurationMs + estimatedQueuedDurationMs;\n\n const remainingTimeMs = this.targetAdBreakDurationMs - estimatedTotalDurationMs;\n\n if (remainingTimeMs <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] ✅ Target duration met: Fetched=${totalFetchedDurationMs}ms + Queued(${queuedButNotFetched} ads)=${estimatedQueuedDurationMs}ms = ${estimatedTotalDurationMs}ms / Target=${this.targetAdBreakDurationMs}ms`\n );\n }\n return 0;\n }\n\n const additionalAds = Math.ceil(remainingTimeMs / averageDurationMs);\n\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] 📊 Need ${additionalAds} more ads | ` +\n `Fetched: ${totalFetchedDurationMs}ms (${fetchedCount} ads) | ` +\n `Queued: ${estimatedQueuedDurationMs}ms (${queuedButNotFetched} ads) | ` +\n `Target: ${this.targetAdBreakDurationMs}ms | ` +\n `Remaining: ${remainingTimeMs}ms | ` +\n `Avg duration: ${averageDurationMs}ms`\n );\n }\n\n return additionalAds;\n }\n\n private async addAdaptiveAdsToQueue(): Promise<void> {\n if (!this.isAdaptiveMode || !this.apiVastTagUrl) {\n return;\n }\n\n const additionalAds = this.calculateAdditionalAdsNeeded();\n if (additionalAds <= 0) {\n return;\n }\n\n const newUrls = this.generateVastUrlsWithCorrelators(\n this.apiVastTagUrl,\n additionalAds\n );\n\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] 🔄 Adding ${newUrls.length} additional VAST URLs to queue (will be preloaded sequentially)`\n );\n }\n\n this.adPodAllUrls.push(...newUrls);\n this.adPodQueue.push(...newUrls);\n this.totalAdsInBreak += newUrls.length;\n }\n\n private async preloadMediaFile(mediaUrl: string): Promise<void> {\n if (this.preloadedMediaUrls.has(mediaUrl)) {\n return;\n }\n\n if (this.preloadingMediaUrls.has(mediaUrl)) {\n return;\n }\n\n this.preloadingMediaUrls.add(mediaUrl);\n\n try {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Preloading video file: ${mediaUrl}`\n );\n }\n\n const response = await fetch(mediaUrl, {\n mode: \"cors\",\n method: \"GET\",\n headers: {\n Range: \"bytes=0-1048576\",\n },\n });\n\n if (response.ok || response.status === 206) {\n this.preloadedMediaUrls.add(mediaUrl);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Successfully preloaded video file: ${mediaUrl}`\n );\n }\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to preload video file: ${mediaUrl}`,\n error\n );\n }\n } finally {\n this.preloadingMediaUrls.delete(mediaUrl);\n }\n }\n\n private async preloadAllAdsInBackground(): Promise<void> {\n if (this.adPodAllUrls.length === 0) {\n return;\n }\n\n if (this.isAdaptiveMode) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] 🔄 Starting sequential preload of remaining ads`\n );\n }\n\n const processedUrls = new Set<string>();\n \n for (const url of this.adPodAllUrls) {\n if (this.ima.hasPreloadedAd?.(url) || this.fetchedAdDurations.has(url)) {\n processedUrls.add(url);\n }\n }\n\n if (this.config.debugAdTiming && processedUrls.size > 0) {\n console.log(\n `[ADAPTIVE-POD] 📦 Skipping ${processedUrls.size} already-preloaded ads`\n );\n }\n\n while (true) {\n const nextUrl = this.adPodAllUrls.find(url => !processedUrls.has(url));\n \n if (!nextUrl) {\n if (this.config.debugAdTiming) {\n console.log(`[ADAPTIVE-POD] ✅ All queued ads processed (${processedUrls.size} total)`);\n }\n break;\n }\n\n processedUrls.add(nextUrl);\n\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] 📥 Preloading ad ${processedUrls.size}/${this.adPodAllUrls.length}...`\n );\n }\n\n try {\n await this.preloadSingleAd(nextUrl);\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[ADAPTIVE-POD] ⚠️ Preload failed for ad ${processedUrls.size}:`,\n error\n );\n }\n }\n\n if (this.calculateAdditionalAdsNeeded() === 0) {\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] ✅ Target duration reached (${processedUrls.size} ads preloaded), stopping`\n );\n }\n break;\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] ✅ Sequential preloading completed (${processedUrls.size} ads ready)`\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Starting parallel preload of ${this.adPodAllUrls.length} ads`\n );\n }\n\n const preloadPromises = this.adPodAllUrls.map((vastTagUrl) =>\n this.preloadSingleAd(vastTagUrl).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Preload failed for ${vastTagUrl}:`,\n error\n );\n }\n })\n );\n\n await Promise.all(preloadPromises);\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Background preloading completed for all ads`\n );\n }\n }\n }\n\n private async preloadSingleAd(vastTagUrl: string): Promise<void> {\n if (!vastTagUrl) return;\n\n try {\n if (this.isAdaptiveMode && !this.fetchedAdDurations.has(vastTagUrl)) {\n const duration = await this.fetchVastDuration(vastTagUrl);\n if (duration !== null) {\n this.fetchedAdDurations.set(vastTagUrl, duration);\n \n if (this.config.debugAdTiming) {\n console.log(\n `[ADAPTIVE-POD] ✓ Fetched ad duration: ${duration}s (${this.fetchedAdDurations.size} ads fetched so far)`\n );\n }\n\n await this.addAdaptiveAdsToQueue();\n }\n }\n\n if (this.ima.preloadAds && !this.ima.hasPreloadedAd(vastTagUrl)) {\n if (!this.preloadingAdUrls.has(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Preloading VAST: ${vastTagUrl}`\n );\n }\n\n this.preloadingAdUrls.add(vastTagUrl);\n\n await this.ima\n .preloadAds(vastTagUrl)\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA VAST preload complete: ${vastTagUrl}`\n );\n }\n })\n .catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] IMA VAST preload failed: ${vastTagUrl}`,\n error\n );\n }\n })\n .finally(() => {\n this.preloadingAdUrls.delete(vastTagUrl);\n });\n }\n }\n\n let mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);\n\n if (!mediaUrls) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Fetching and parsing VAST to extract media URLs: ${vastTagUrl}`\n );\n }\n\n mediaUrls = await this.fetchAndParseVastXml(vastTagUrl);\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs:`,\n mediaUrls\n );\n }\n\n if (mediaUrls.length > 0) {\n this.vastToMediaUrlMap.set(vastTagUrl, mediaUrls);\n }\n }\n\n if (mediaUrls && mediaUrls.length > 0) {\n const primaryMediaUrl = mediaUrls[0];\n if (primaryMediaUrl && !this.preloadedMediaUrls.has(primaryMediaUrl)) {\n await this.preloadMediaFile(primaryMediaUrl);\n }\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to preload ad: ${vastTagUrl}`,\n error\n );\n }\n }\n }\n\n private findNextPreloadedAd(): string | undefined {\n for (let i = 0; i < this.adPodQueue.length; i++) {\n const vastTagUrl = this.adPodQueue[i];\n if (!vastTagUrl) continue;\n\n if (this.failedVastUrls.has(vastTagUrl)) {\n console.warn(\"[AD-ERROR] Skipping failed URL in queue\");\n continue;\n }\n\n const hasImaPreload = this.ima.hasPreloadedAd?.(vastTagUrl) ?? false;\n const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);\n const hasMediaPreload =\n mediaUrls && mediaUrls.length > 0\n ? this.preloadedMediaUrls.has(mediaUrls[0]!)\n : false;\n\n if (hasImaPreload || hasMediaPreload) {\n this.adPodQueue.splice(0, i + 1);\n return vastTagUrl;\n }\n }\n\n return undefined;\n }\n\n private getRemainingAdMs(): number {\n if (\n this.expectedAdBreakDurationMs == null ||\n this.currentAdBreakStartWallClockMs == null\n )\n return 0;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n\n private findBreakForTime(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = [];\n for (const b of schedule) {\n const end = (b.startTimeMs || 0) + (b.durationMs || 0);\n if (\n nowMs >= (b.startTimeMs || 0) &&\n (b.durationMs ? nowMs < end : true)\n ) {\n return b;\n }\n }\n return undefined;\n }\n\n toggleMute(): void {\n if (this.ima.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n\n this.ima.updateOriginalMutedState(newMutedState, this.video.volume);\n this.ima.setAdVolume(newMutedState ? 0 : 1);\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n\n toggleFullscreen(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container\n .requestFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document\n .exitFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n\n isMuted(): boolean {\n if (this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n const adPlaying = this.ima.isAdPlaying();\n\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n\n this.video.muted = muted;\n\n if (adPlaying) {\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n this.ima.setAdVolume(muted ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted,\n });\n }\n return;\n }\n\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n\n setVolume(volume: number): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.ima.isAdPlaying();\n\n if (adPlaying) {\n this.ima.setAdVolume(clampedVolume);\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume,\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n\n isFullscreen(): boolean {\n return !!document.fullscreenElement;\n }\n\n isLive(): boolean {\n return this.isLiveStream;\n }\n\n get videoElement(): HTMLVideoElement {\n return this.video;\n }\n\n resize(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n\n if (this.ima && this.ima.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 360;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n\n this.ima.resize(width, height);\n }\n }\n\n destroy(): void {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n \n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n \n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n this.hls?.destroy();\n this.ima?.destroy();\n this.preloadingAdUrls.clear();\n this.vastToMediaUrlMap.clear();\n this.preloadedMediaUrls.clear();\n this.preloadingMediaUrls.clear();\n this.adPodAllUrls = [];\n this.adRequestQueue = [];\n this.successfulAdRequests = [];\n }\n}\n","interface NavigatorUAData {\n platform?: string;\n brands?: Array<{ brand: string; version: string }>;\n mobile?: boolean;\n}\n\ndeclare global {\n interface Navigator {\n userAgentData?: NavigatorUAData;\n }\n}\n\nexport interface BrowserInfo {\n name: string;\n version: string;\n majorVersion: number;\n isSmartTV: boolean;\n isLegacyTV: boolean;\n platform: string;\n supportsIMA: boolean;\n supportsModernJS: boolean;\n recommendedAdPlayer: 'ima' | 'hls';\n}\n\nfunction getChromeVersion(ua: string): number {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getWebKitVersion(ua: string): number {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getPlatform(): string {\n if ('userAgentData' in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? 'iPhone' : 'MacIntel';\n }\n if (/Win/i.test(ua)) {\n return 'Win32';\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? 'Linux armv8l' : 'Linux x86_64';\n }\n if (/CrOS/i.test(ua)) {\n return 'CrOS';\n }\n\n // eslint-disable-next-line deprecation/deprecation\n return (navigator as any).platform || 'Unknown';\n}\n\nexport function detectBrowser(): BrowserInfo {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n\n let name = 'Unknown';\n let version = '0';\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer: 'ima' | 'hls' = 'ima';\n\n if (/Web0S|webOS/i.test(ua)) {\n name = 'LG WebOS';\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = 'Samsung Tizen';\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n }\n\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n isLegacyTV = true;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n\n if (typeof URLSearchParams === 'undefined') {\n supportsModernJS = false;\n }\n\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n };\n}\n\nexport function supportsGoogleIMA(): boolean {\n const browser = detectBrowser();\n\n if (browser.isLegacyTV) {\n return false;\n }\n\n if (typeof document === 'undefined' ||\n typeof document.createElement !== 'function') {\n return false;\n }\n\n try {\n const video = document.createElement('video');\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n\n if (typeof Promise === 'undefined') {\n return false;\n }\n\n return browser.supportsIMA;\n}\n\nexport function getRecommendedAdPlayer(): 'ima' | 'hls' {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\n}\n\nexport function supportsModernJS(): boolean {\n try {\n return (\n typeof Promise !== 'undefined' &&\n typeof Map !== 'undefined' &&\n typeof Set !== 'undefined' &&\n typeof Array.from !== 'undefined' &&\n typeof Object.assign !== 'undefined' &&\n typeof Array.prototype.forEach !== 'undefined' &&\n typeof String.prototype.includes !== 'undefined'\n );\n } catch (e) {\n return false;\n }\n}\n\nexport function logBrowserInfo(debug: boolean = false): void {\n if (!debug) return;\n\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n\n console.log('[StormcloudVideoPlayer] Browser Compatibility Info:', {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n userAgent: navigator.userAgent,\n });\n}\n\nexport function getBrowserConfigOverrides(): {\n adPlayerType?: 'ima' | 'hls';\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: any = {};\n\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = 'hls';\n }\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'ima':\n return supportsGoogleIMA();\n case 'urlsearchparams':\n return typeof URLSearchParams !== 'undefined';\n case 'textencoder':\n return typeof TextEncoder !== 'undefined';\n case 'promises':\n return typeof Promise !== 'undefined';\n case 'fetch':\n return typeof fetch !== 'undefined';\n case 'crypto':\n return typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined';\n default:\n return false;\n }\n}\n\n","import type { ImaController } from \"../types\";\nimport { supportsGoogleIMA } from \"../utils/browserCompat\";\n\ndeclare global {\n interface Window {\n google?: any;\n }\n}\n\nexport function createImaController(\n video: HTMLVideoElement,\n options?: { continueLiveStreamDuringAds?: boolean }\n): ImaController {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume =\n typeof video.volume === \"number\" && !Number.isNaN(video.volume)\n ? Math.max(0, Math.min(1, video.volume))\n : 1;\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const preloadedVast = new Map<string, string>();\n const preloadingVast = new Map<string, Promise<void>>();\n let adVideoElement: HTMLVideoElement | undefined;\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n\n function hideContentVideo(): void {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n\n function showContentVideo(): void {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"15\";\n adVideo.playsInline = true;\n adVideo.muted = false;\n adVideo.volume = originalMutedState ? 0 : originalVolume;\n\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n\n return adVideo;\n }\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {}\n }\n }\n\n function ensureImaLoaded(): Promise<void> {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n\n try {\n const frameEl = window.frameElement as HTMLIFrameElement | null;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n // eslint-disable-next-line no-console\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {}\n\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n ) as HTMLScriptElement | null;\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 10000);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n\n let adsManager: any | undefined;\n let adsLoader: any | undefined;\n let adDisplayContainer: any | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let lastAdTagUrl: string | undefined;\n let retryAttempts = 0;\n const maxRetries = 2;\n const backoffBaseMs = 500;\n let adsLoadedPromise: Promise<void> | undefined;\n let adsLoadedResolve: (() => void) | undefined;\n let adsLoadedReject: ((error: Error) => void) | undefined;\n\n function makeAdsRequest(google: any, vastTagUrl: string) {\n const adsRequest = new google.ima.AdsRequest();\n \n console.log(\"[IMA] 📡 Requesting VAST from URL (letting IMA fetch fresh)\");\n adsRequest.adTagUrl = vastTagUrl;\n\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 360;\n\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n\n adsRequest.vastLoadTimeout = 10000;\n\n adsLoader.requestAds(adsRequest);\n }\n\n function ensurePlaceholderContainer(): void {\n if (adContainerEl) {\n return;\n }\n\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition =\n \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n async function fetchVastDocument(vastTagUrl: string): Promise<string> {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to preload VAST: ${response.status}`);\n }\n return response.text();\n }\n\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {}\n adsManager = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n\n return {\n initialize() {\n ensureImaLoaded()\n .then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {}\n }\n })\n .catch(() => {});\n },\n async requestAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n console.warn(\"[IMA] ❌\", error.message);\n return Promise.reject(error);\n }\n\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n console.warn(\"[IMA] ❌\", error.message);\n return Promise.reject(error);\n }\n\n if (adPlaying) {\n console.warn(\n \"[IMA] ⚠️ Cannot request new ads while an ad is playing. Call stop() first.\"\n );\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n\n destroyAdsManager();\n\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n\n let currentReject: ((error: Error) => void) | undefined;\n adsLoadedPromise = new Promise<void>((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n }, 10000);\n });\n\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n retryAttempts = 0;\n\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition =\n \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n\n video.parentElement.appendChild(container);\n adContainerEl = container;\n\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n\n }\n\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n\n if (\n !videoWidth ||\n !videoHeight ||\n videoWidth === 0 ||\n videoHeight === 0\n ) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n console.warn(\"[IMA]\", error.message);\n currentReject?.(error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt: any) => {\n try {\n const adsRenderingSettings =\n new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent: any) => {\n const error = errorEvent.getError();\n console.error(\"[DEBUG-ERROR] ❌ AD_ERROR:\", error.getMessage?.());\n\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n\n if (lastAdTagUrl && retryAttempts < maxRetries) {\n const delay =\n backoffBaseMs * Math.pow(2, retryAttempts++);\n window.setTimeout(() => {\n try {\n makeAdsRequest(google, lastAdTagUrl!);\n } catch {}\n }, delay);\n } else {\n emit(\"ad_error\");\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {});\n }\n }\n }\n }\n );\n\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n\n adPlaying = true;\n setAdPlayingFlag(true);\n \n emit(\"content_pause\");\n }\n );\n\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n\n hideContentVideo();\n\n if (adVideoElement) {\n adVideoElement.volume = originalMutedState\n ? 0\n : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n \n emit(\"content_resume\");\n }\n );\n\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (!options?.continueLiveStreamDuringAds && video.paused) {\n video.play().catch(() => {});\n }\n\n emit(\"all_ads_completed\");\n });\n\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = undefined;\n adsLoadedReject = undefined;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {});\n }\n }\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent: any) => {\n const error = adErrorEvent.getError();\n console.error(\"[DEBUG-ERROR] ❌ ADS_LOADER ERROR:\", error.getMessage?.());\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {});\n }\n }\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ads loader error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\");\n },\n false\n );\n }\n\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n\n currentReject?.(error as Error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n\n if (preloadedVast.has(vastTagUrl)) {\n return Promise.resolve();\n }\n\n const inflight = preloadingVast.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n\n const preloadPromise = fetchVastDocument(vastTagUrl)\n .then((xml) => {\n preloadedVast.set(vastTagUrl, xml);\n })\n .catch(() => {\n preloadedVast.delete(vastTagUrl);\n })\n .finally(() => {\n preloadingVast.delete(vastTagUrl);\n });\n\n preloadingVast.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl: string) {\n return preloadedVast.has(vastTagUrl);\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 360;\n\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n\n adPlaying = true;\n\n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n\n try {\n adsManager.setVolume(adVolume);\n } catch {}\n\n adsManager.start();\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[IMA] ❌ Error starting ad:\", error);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {});\n }\n return Promise.reject(error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n try {\n adsManager?.stop?.();\n } catch {}\n\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n adVideoElement = undefined;\n }\n }, 300);\n }\n\n showContentVideo();\n\n try {\n adsLoader?.destroy?.();\n } catch {}\n\n adDisplayContainer = undefined;\n adsLoader = undefined;\n contentVideoHidden = false;\n preloadedVast.clear();\n preloadingVast.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width: number, height: number) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume: number) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {}\n }\n },\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n \n hideContentVideo();\n \n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n \n if (!adPlaying) {\n showContentVideo();\n }\n },\n };\n}\n","import type { ImaController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): ImaController {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n const preloadedAds = new Map<string, VastAd>();\n const preloadingAds = new Map<string, Promise<void>>();\n let destroyed = false;\n let pendingTimeouts: number[] = [];\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n if (sessionId) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function getMainStreamQuality(): {\n width: number;\n height: number;\n bitrate: number;\n } | null {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level = mainHlsInstance.levels[autoLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n return null;\n }\n\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n\n const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n return { file, score, resolutionDiff, bitrateDiff };\n });\n\n scoredFiles.sort((a, b) => a.score - b.score);\n\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff,\n });\n\n return bestMatch.file;\n }\n\n function parseVastXml(xmlString: string): VastAd | null {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const isNoAdAvailable =\n adId === \"empty\" ||\n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\n\n const durationText =\n xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n\n if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n if (!url) {\n console.warn(\n `[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`\n );\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate:\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n\n console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not HLS)`\n );\n }\n });\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No HLS media files found in VAST XML\");\n }\n return null;\n }\n\n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string\n ): Promise<VastAd | null> {\n const response = await fetch(vastTagUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml);\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n\n video.volume = 1.0;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n emit(\"content_resume\");\n\n const timeoutId = window.setTimeout(() => {\n if (destroyed) {\n console.log(\"[HlsAdPlayer] Player destroyed, skipping post-completion check\");\n return;\n }\n \n const stillInPod = contentVideo.dataset.stormcloudAdPlaying === \"true\";\n if (stillInPod) {\n console.log(\n \"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)\"\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n }\n \n const idx = pendingTimeouts.indexOf(timeoutId);\n if (idx !== -1) {\n pendingTimeouts.splice(idx, 1);\n }\n }, 50);\n \n pendingTimeouts.push(timeoutId);\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`\n );\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (!options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n contentVideo.play().catch(() => {});\n }\n }\n\n emit(\"ad_error\");\n }\n\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(vastTagUrl: string) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n\n try {\n sessionId = generateSessionId();\n let ad: VastAd | null | undefined;\n\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.resolve();\n }\n\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n\n if (preloadedAds.has(vastTagUrl)) {\n return Promise.resolve();\n }\n\n const inflight = preloadingAds.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n\n const preloadPromise = fetchAndParseVastAd(vastTagUrl)\n .then((ad) => {\n if (ad) {\n preloadedAds.set(vastTagUrl, ad);\n console.log(\n \"[HlsAdPlayer] Cached VAST response for preloading:\",\n vastTagUrl\n );\n }\n })\n .catch((error) => {\n console.warn(\"[HlsAdPlayer] Failed to preload VAST response:\", error);\n preloadedAds.delete(vastTagUrl);\n })\n .finally(() => {\n preloadingAds.delete(vastTagUrl);\n });\n\n preloadingAds.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl: string) {\n return preloadedAds.has(vastTagUrl);\n },\n\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n // Capture content volume BEFORE muting\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);\n\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false,\n });\n\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement!.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (\n adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")\n ) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(\"HLS not supported\");\n }\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n\n currentAd = undefined;\n },\n\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n \n // Clear all pending timeouts\n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n \n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n \n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n },\n };\n}\n","import type { ClientInfo, TrackingData, HeartbeatData } from \"../types\";\n\nlet cachedBrowserId: string | null = null;\n\nexport function getClientInfo(): ClientInfo {\n const ua = navigator.userAgent;\n const platform = navigator.platform;\n const vendor = navigator.vendor || \"\";\n const maxTouchPoints = navigator.maxTouchPoints || 0;\n const memory = (navigator as any).deviceMemory || null;\n const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n\n const screenInfo = {\n width: screen?.width,\n height: screen?.height,\n availWidth: screen?.availWidth,\n availHeight: screen?.availHeight,\n orientation: (screen?.orientation as any)?.type || \"\",\n pixelDepth: screen?.pixelDepth,\n };\n\n let deviceType: \"tv\" | \"mobile\" | \"tablet\" | \"desktop\" = \"desktop\";\n let brand = \"Unknown\";\n let os = \"Unknown\";\n let model = \"\";\n let isSmartTV = false;\n let isAndroid = false;\n let isWebView = false;\n let isWebApp = false;\n\n if (ua.includes(\"Web0S\")) {\n brand = \"LG\";\n os = \"webOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n } else if (ua.includes(\"Tizen\")) {\n brand = \"Samsung\";\n os = \"Tizen\";\n isSmartTV = true;\n deviceType = \"tv\";\n const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n model = tizenMatch\n ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim()\n : \"Tizen TV\";\n } else if (ua.includes(\"Philips\")) {\n brand = \"Philips\";\n os = \"Saphi\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n brand = \"Sharp\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (\n ua.includes(\"Android\") &&\n (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))\n ) {\n brand = \"Sony\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (\n ua.includes(\"Android\") &&\n (ua.includes(\"NetCast\") || ua.includes(\"LG\"))\n ) {\n brand = \"LG\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n brand = \"Roku\";\n os = \"Roku OS\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"AppleTV\")) {\n brand = \"Apple\";\n os = \"tvOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n }\n\n if (ua.includes(\"Android\")) {\n isAndroid = true;\n os = \"Android\";\n deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n\n if (\n ua.includes(\"Android\") &&\n (maxTouchPoints === 0 ||\n ua.includes(\"Google TV\") ||\n ua.includes(\"XiaoMi\"))\n ) {\n deviceType = \"tv\";\n isSmartTV = true;\n brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n }\n\n const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n if (androidModelMatch && androidModelMatch[1]) {\n model = androidModelMatch[1];\n }\n }\n\n if (/iPad|iPhone|iPod/.test(ua)) {\n os = \"iOS\";\n deviceType = \"mobile\";\n brand = \"Apple\";\n if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n deviceType = \"tablet\";\n }\n }\n\n if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n if (ua.includes(\"Windows\")) {\n os = \"Windows\";\n deviceType = \"desktop\";\n } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n os = \"macOS\";\n deviceType = \"desktop\";\n if (maxTouchPoints > 1) deviceType = \"tablet\";\n } else if (ua.includes(\"Linux\")) {\n os = \"Linux\";\n deviceType = \"desktop\";\n }\n }\n\n if (brand === \"Unknown\") {\n if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n if (vendor.includes(\"Apple\")) brand = \"Apple\";\n if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n }\n\n isWebView = /wv|WebView|Linux; U;/.test(ua);\n\n if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n isWebView = true;\n }\n\n isWebApp =\n window.matchMedia(\"(display-mode: standalone)\").matches ||\n (window.navigator as any).standalone === true ||\n window.screen?.orientation?.angle !== undefined;\n\n return {\n brand,\n os,\n model: model || ua.substring(0, 50) + \"...\",\n deviceType,\n isSmartTV,\n isAndroid,\n isWebView,\n isWebApp,\n domain: window.location.hostname,\n origin: window.location.origin,\n path: window.location.pathname,\n userAgent: ua,\n vendor,\n platform,\n screen: screenInfo,\n hardwareConcurrency,\n deviceMemory: memory,\n maxTouchPoints,\n language: navigator.language,\n languages: navigator.languages?.join(\",\") || \"\",\n cookieEnabled: navigator.cookieEnabled,\n doNotTrack: navigator.doNotTrack || \"\",\n referrer: document.referrer,\n visibilityState: document.visibilityState,\n };\n}\n\nexport async function getBrowserID(clientInfo: ClientInfo): Promise<string> {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n\n const fingerprintString = JSON.stringify(clientInfo);\n\n if (typeof crypto !== \"undefined\" && crypto.subtle && crypto.subtle.digest) {\n try {\n await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n\n let encodedData: BufferSource;\n if (typeof TextEncoder !== \"undefined\") {\n encodedData = new TextEncoder().encode(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\n const buffer = new Uint8Array(utf8.length);\n for (let i = 0; i < utf8.length; i++) {\n buffer[i] = utf8.charCodeAt(i);\n }\n encodedData = buffer;\n }\n\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n\n const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n const timestamp = Date.now().toString(16).padStart(12, \"0\");\n const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n\n cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\n\nexport async function sendInitialTracking(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const trackingData: TrackingData = {\n browserId,\n ...clientInfo,\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\n\nexport async function sendHeartbeat(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const heartbeatData: HeartbeatData = {\n browserId,\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\n","export function polyfillURLSearchParams(): void {\n if (typeof URLSearchParams !== 'undefined') {\n return;\n }\n\n class URLSearchParamsPolyfill {\n private params: Map<string, string[]>;\n\n constructor(init?: string | URLSearchParamsPolyfill) {\n this.params = new Map();\n\n if (typeof init === 'string') {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n\n private parseQueryString(query: string): void {\n const cleanQuery = query.startsWith('?') ? query.slice(1) : query;\n if (!cleanQuery) return;\n\n cleanQuery.split('&').forEach((param) => {\n const [key, value] = param.split('=');\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : '';\n this.append(decodedKey, decodedValue);\n }\n });\n }\n\n private safeDecodeURIComponent(str: string): string {\n try {\n return decodeURIComponent(str.replace(/\\+/g, ' '));\n } catch (e) {\n return str;\n }\n }\n\n append(name: string, value: string): void {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n\n delete(name: string): void {\n this.params.delete(name);\n }\n\n get(name: string): string | null {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== undefined ? values[0] : null;\n }\n\n getAll(name: string): string[] {\n return this.params.get(name) || [];\n }\n\n has(name: string): boolean {\n return this.params.has(name);\n }\n\n set(name: string, value: string): void {\n this.params.set(name, [String(value)]);\n }\n\n forEach(callback: (value: string, key: string, parent: URLSearchParamsPolyfill) => void): void {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n\n toString(): string {\n const parts: string[] = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join('&');\n }\n }\n\n // @ts-ignore\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\n\nexport function polyfillTextEncoder(): void {\n if (typeof TextEncoder !== 'undefined') {\n return;\n }\n\n class TextEncoderPolyfill {\n encoding = 'utf-8';\n\n encode(str: string): Uint8Array {\n const utf8: number[] = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 0x80) {\n utf8.push(charcode);\n } else if (charcode < 0x800) {\n utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));\n } else if (charcode < 0xd800 || charcode >= 0xe000) {\n utf8.push(\n 0xe0 | (charcode >> 12),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n } else {\n i++;\n charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));\n utf8.push(\n 0xf0 | (charcode >> 18),\n 0x80 | ((charcode >> 12) & 0x3f),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n\n // @ts-ignore\n window.TextEncoder = TextEncoderPolyfill;\n}\n\nexport function polyfillPromiseFinally(): void {\n if (typeof Promise !== 'undefined' && !Promise.prototype.finally) {\n Promise.prototype.finally = function (callback: () => void) {\n const constructor = this.constructor as PromiseConstructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) =>\n constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\n\nexport function polyfillObjectAssign(): void {\n if (typeof Object.assign !== 'function') {\n Object.assign = function (target: any, ...sources: any[]) {\n if (target == null) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n const to = Object(target);\n\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n\n return to;\n };\n }\n}\n\nexport function polyfillArrayFrom(): void {\n if (!Array.from) {\n Array.from = function (arrayLike: any, mapFn?: any, thisArg?: any) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object');\n }\n\n const len = items.length >>> 0;\n const result = new Array(len);\n\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n\n return result;\n };\n }\n}\n\nexport function polyfillStringStartsWith(): void {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function (search: string, pos?: number) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\n\nexport function polyfillStringEndsWith(): void {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function (search: string, length?: number) {\n if (length === undefined || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\n\nexport function polyfillStringIncludes(): void {\n if (!String.prototype.includes) {\n String.prototype.includes = function (search: string, start?: number) {\n if (typeof start !== 'number') {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\n\nexport function initializePolyfills(): void {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n","import React, { Component, Suspense } from \"react\";\nimport type { BaseStormcloudPlayerProps } from \"./props\";\nimport { defaultProps } from \"./props\";\nimport { omit } from \"./utils\";\nimport players from \"./players\";\nimport type { PlayerConfig } from \"./players\";\nimport Player from \"./Player.js\";\n\nconst IS_BROWSER = typeof window !== \"undefined\" && window.document;\nconst IS_GLOBAL =\n typeof globalThis !== \"undefined\" &&\n globalThis.window &&\n globalThis.window.document;\nconst UniversalSuspense = IS_BROWSER || IS_GLOBAL ? Suspense : () => null;\n\nconst SUPPORTED_PROPS = [\n \"src\",\n \"playing\",\n \"loop\",\n \"controls\",\n \"volume\",\n \"muted\",\n \"playbackRate\",\n \"width\",\n \"height\",\n \"style\",\n \"progressInterval\",\n \"playsInline\",\n \"autoplay\",\n \"preload\",\n \"poster\",\n \"className\",\n \"wrapperClassName\",\n \"wrapperStyle\",\n \"allowNativeHls\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"immediateManifestAds\",\n \"debugAdTiming\",\n \"showCustomControls\",\n \"licenseKey\",\n \"adFailsafeTimeoutMs\",\n \"minSegmentsBeforePlay\",\n \"onReady\",\n \"onStart\",\n \"onPlay\",\n \"onPause\",\n \"onBuffer\",\n \"onBufferEnd\",\n \"onEnded\",\n \"onError\",\n \"onDuration\",\n \"onSeek\",\n \"onProgress\",\n \"onVolumeToggle\",\n \"onFullscreenToggle\",\n \"onControlClick\",\n];\n\nexport interface StormcloudPlayerProps extends BaseStormcloudPlayerProps {\n fallback?: React.ReactElement;\n wrapper?: React.ComponentType<{ children: React.ReactNode }> | string;\n}\n\ninterface StormcloudPlayerState {\n showPreview: boolean;\n}\n\nconst customPlayers: PlayerConfig[] = [];\n\nexport const createStormcloudPlayer = (\n playerList: PlayerConfig[],\n fallback?: PlayerConfig\n) => {\n return class StormcloudPlayerClass extends Component<\n StormcloudPlayerProps,\n StormcloudPlayerState\n > {\n static displayName = \"StormcloudPlayer\";\n\n static defaultProps = {\n ...defaultProps,\n fallback: null,\n wrapper: \"div\",\n };\n\n static addCustomPlayer = (player: PlayerConfig) => {\n customPlayers.push(player);\n };\n\n static removeCustomPlayers = () => {\n customPlayers.length = 0;\n };\n\n static canPlay = (src: string): boolean => {\n for (const Player of [...customPlayers, ...playerList]) {\n if (Player.canPlay(src)) {\n return true;\n }\n }\n return false;\n };\n\n static canEnablePIP = (src: string): boolean => {\n for (const Player of [...customPlayers, ...playerList]) {\n if (Player.canEnablePIP && Player.canEnablePIP(src)) {\n return true;\n }\n }\n return false;\n };\n\n state: StormcloudPlayerState = {\n showPreview: false,\n };\n\n public wrapper?: HTMLElement;\n public player?: any;\n\n references = {\n wrapper: (wrapper: HTMLElement) => {\n this.wrapper = wrapper;\n },\n player: (player: any) => {\n this.player = player;\n },\n };\n\n getActivePlayer = (src?: string): PlayerConfig | null => {\n if (!src) return null;\n\n for (const player of [...customPlayers, ...playerList]) {\n if (player.canPlay(src)) {\n return player;\n }\n }\n\n if (fallback) {\n return fallback;\n }\n\n return null;\n };\n\n getAttributes = (src?: string) => {\n return omit(this.props, SUPPORTED_PROPS as any);\n };\n\n handleReady = () => {\n this.props.onReady?.(this as any);\n };\n\n seekTo = (\n fraction: number,\n type?: \"seconds\" | \"fraction\",\n keepPlaying?: boolean\n ) => {\n if (!this.player) return null;\n this.player.seekTo(fraction, type, keepPlaying);\n };\n\n getCurrentTime = (): number | null => {\n if (!this.player) return null;\n return this.player.getCurrentTime();\n };\n\n getSecondsLoaded = (): number | null => {\n if (!this.player) return null;\n return this.player.getSecondsLoaded();\n };\n\n getDuration = (): number | null => {\n if (!this.player) return null;\n return this.player.getDuration();\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (!this.player) return null;\n return this.player.getInternalPlayer(key);\n };\n\n renderActivePlayer = (src?: string) => {\n if (!src) return null;\n\n const activePlayer = this.getActivePlayer(src);\n if (!activePlayer) return null;\n\n return React.createElement(Player, {\n ...this.props,\n key: activePlayer.key,\n ref: this.references.player,\n activePlayer: activePlayer.lazyPlayer || activePlayer,\n onReady: this.handleReady,\n });\n };\n\n render() {\n const {\n src,\n style,\n width,\n height,\n fallback: fallbackElement,\n wrapper: Wrapper,\n } = this.props;\n const attributes = this.getAttributes(src);\n const wrapperRef =\n typeof Wrapper === \"string\" ? this.references.wrapper : undefined;\n\n return React.createElement(\n Wrapper as any,\n {\n ref: wrapperRef,\n style: { ...style, width, height },\n ...attributes,\n },\n React.createElement(\n UniversalSuspense,\n { fallback: fallbackElement },\n this.renderActivePlayer(src)\n )\n );\n }\n };\n};\n\nconst StormcloudPlayer = createStormcloudPlayer(\n players,\n players[players.length - 1]\n);\n\nexport default StormcloudPlayer;\n","import type { CSSProperties } from \"react\";\nimport { StormcloudVideoPlayer } from \"./player/StormcloudVideoPlayer\";\n\nexport interface OnProgressProps {\n played: number;\n playedSeconds: number;\n loaded: number;\n loadedSeconds: number;\n}\n\nexport interface BaseStormcloudPlayerProps {\n src?: string;\n playing?: boolean;\n loop?: boolean;\n controls?: boolean;\n volume?: number;\n muted?: boolean;\n playbackRate?: number;\n width?: string | number;\n height?: string | number;\n style?: CSSProperties;\n progressInterval?: number;\n playsInline?: boolean;\n autoplay?: boolean;\n preload?: string;\n poster?: string;\n className?: string;\n wrapperClassName?: string;\n wrapperStyle?: CSSProperties;\n\n allowNativeHls?: boolean;\n lowLatencyMode?: boolean;\n driftToleranceMs?: number;\n immediateManifestAds?: boolean;\n debugAdTiming?: boolean;\n showCustomControls?: boolean;\n hideLoadingIndicator?: boolean;\n licenseKey?: string;\n adFailsafeTimeoutMs?: number;\n minSegmentsBeforePlay?: number;\n\n onReady?: (player: StormcloudVideoPlayer) => void;\n onStart?: () => void;\n onPlay?: () => void;\n onPause?: (e?: any) => void;\n onBuffer?: () => void;\n onBufferEnd?: () => void;\n onEnded?: () => void;\n onError?: (\n error: any,\n data?: any,\n hlsInstance?: any,\n hlsGlobal?: any\n ) => void;\n onDuration?: (duration: number) => void;\n onSeek?: (seconds: number) => void;\n onProgress?: (state: OnProgressProps) => void;\n onVolumeToggle?: () => void;\n onFullscreenToggle?: () => void;\n onControlClick?: () => void;\n\n [otherProps: string]: any;\n}\n\nconst noop = () => {};\n\nexport const defaultProps: Required<\n Omit<\n BaseStormcloudPlayerProps,\n | \"src\"\n | \"onReady\"\n | \"children\"\n | keyof React.VideoHTMLAttributes<HTMLVideoElement>\n >\n> = {\n playing: false,\n loop: false,\n controls: true,\n volume: 1,\n muted: false,\n playbackRate: 1,\n width: \"100%\",\n height: \"auto\",\n style: {},\n progressInterval: 1000,\n playsInline: false,\n autoplay: false,\n preload: \"metadata\",\n poster: \"\",\n className: \"\",\n wrapperClassName: \"\",\n wrapperStyle: {},\n\n allowNativeHls: false,\n lowLatencyMode: false,\n driftToleranceMs: 1000,\n immediateManifestAds: true,\n debugAdTiming: false,\n showCustomControls: false,\n hideLoadingIndicator: false,\n licenseKey: \"\",\n adFailsafeTimeoutMs: 10000,\n minSegmentsBeforePlay: 2,\n\n onStart: noop,\n onPlay: noop,\n onPause: noop,\n onBuffer: noop,\n onBufferEnd: noop,\n onEnded: noop,\n onError: noop,\n onDuration: noop,\n onSeek: noop,\n onProgress: noop,\n onVolumeToggle: noop,\n onFullscreenToggle: noop,\n onControlClick: noop,\n};\n","import { lazy as reactLazy } from \"react\";\n\nexport const lazy = reactLazy;\n\nexport const omit = <T extends Record<string, any>, K extends keyof T>(\n object: T,\n keys: K[]\n): Omit<T, K> => {\n const result = { ...object };\n keys.forEach((key) => {\n delete result[key];\n });\n return result;\n};\n\nexport const isMediaStream = (url: any): url is MediaStream => {\n return (\n typeof window !== \"undefined\" &&\n window.MediaStream &&\n url instanceof window.MediaStream\n );\n};\n\nexport const supportsWebKitPresentationMode = (): boolean => {\n if (typeof window === \"undefined\") return false;\n const video = document.createElement(\"video\");\n return \"webkitSupportsPresentationMode\" in video;\n};\n\nexport const randomString = (): string => {\n return Math.random().toString(36).substr(2, 9);\n};\n\nexport const parseQuery = (url: string): Record<string, string> => {\n const query: Record<string, string> = {};\n const queryString = url.split(\"?\")[1] || \"\";\n\n if (!queryString) return query;\n\n const manualParse = (qs: string) => {\n qs.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n try {\n query[decodeURIComponent(key)] = value\n ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n : \"\";\n } catch (e) {\n query[key] = value || \"\";\n }\n }\n });\n };\n\n if (typeof URLSearchParams !== \"undefined\") {\n try {\n const params = new URLSearchParams(queryString);\n params.forEach((value, key) => {\n query[key] = value;\n });\n return query;\n } catch (e) {\n manualParse(queryString);\n }\n } else {\n manualParse(queryString);\n }\n\n return query;\n};\n\nexport const merge = <T extends Record<string, any>>(\n target: T,\n ...sources: Partial<T>[]\n): T => {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n merge(target[key] as any, source[key] as any);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return merge(target, ...sources);\n};\n\nconst isObject = (item: any): item is Record<string, any> => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\n\nexport const IS_BROWSER = typeof window !== \"undefined\" && window.document;\nexport const IS_GLOBAL =\n typeof globalThis !== \"undefined\" &&\n globalThis.window &&\n globalThis.window.document;\nexport const IS_IOS =\n IS_BROWSER && /iPad|iPhone|iPod/.test(navigator.userAgent);\nexport const IS_SAFARI =\n IS_BROWSER && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n\nexport const SUPPORTS_HLS = (): boolean => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/vnd.apple.mpegurl\"));\n};\n\nexport const SUPPORTS_DASH = (): boolean => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/dash+xml\"));\n};\n","export const HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nexport const HLS_PATHS = /\\/hls\\//i;\nexport const DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nexport const VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nexport const AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\n\nexport const canPlay = {\n hls: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n\n dash: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n\n video: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n\n audio: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n\n file: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n },\n};\n","import { Component } from \"react\";\nimport { StormcloudVideoPlayer } from \"../player/StormcloudVideoPlayer\";\nimport type { StormcloudVideoPlayerConfig } from \"../types\";\nimport { canPlay } from \"../patterns\";\n\nexport interface HlsPlayerProps extends StormcloudVideoPlayerConfig {\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n}\n\nexport default class HlsPlayer extends Component<HlsPlayerProps> {\n static displayName = \"HlsPlayer\";\n\n static canPlay = canPlay.hls;\n\n private player: StormcloudVideoPlayer | null = null;\n private mounted = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n\n componentDidUpdate(prevProps: HlsPlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n\n const config: StormcloudVideoPlayerConfig = {\n src: this.props.src,\n videoElement: this.props.videoElement,\n };\n\n if (this.props.autoplay !== undefined)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== undefined)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== undefined)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== undefined)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== undefined)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== undefined)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== undefined)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== undefined)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== undefined)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== undefined)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== undefined)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== undefined)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== undefined)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n\n this.player = new StormcloudVideoPlayer(config);\n\n this.props.onMount?.(this);\n\n await this.player.load();\n\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n\n play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource =\n video.src ||\n (video.currentSrc && video.currentSrc !== \"\") ||\n video.readyState >= 1;\n\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return (this.player as any).hls;\n return null;\n };\n\n render() {\n return null;\n }\n}\n","import { Component } from \"react\";\nimport { canPlay } from \"../patterns\";\n\nexport interface FilePlayerProps {\n src: string;\n videoElement?: HTMLVideoElement;\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n autoplay?: boolean;\n muted?: boolean;\n loop?: boolean;\n controls?: boolean;\n playsInline?: boolean;\n preload?: string;\n poster?: string;\n}\n\nexport default class FilePlayer extends Component<FilePlayerProps> {\n static displayName = \"FilePlayer\";\n\n static canPlay = canPlay.file;\n\n private mounted = false;\n private ready = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n }\n\n componentDidUpdate(prevProps: FilePlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n const video = this.props.videoElement;\n\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n\n const handleError = (error: any) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\n };\n\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n\n video.src = this.props.src;\n if (this.props.autoplay !== undefined) video.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) video.muted = this.props.muted;\n if (this.props.loop !== undefined) video.loop = this.props.loop;\n if (this.props.controls !== undefined) video.controls = this.props.controls;\n if (this.props.playsInline !== undefined)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== undefined)\n video.preload = this.props.preload as \"\" | \"metadata\" | \"none\" | \"auto\";\n if (this.props.poster !== undefined) video.poster = this.props.poster;\n\n this.props.onMount?.(this);\n\n return () => {\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n };\n };\n\n play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource =\n video.src ||\n (video.currentSrc && video.currentSrc !== \"\") ||\n video.readyState >= 1;\n\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[FilePlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n } else {\n console.warn(\"[FilePlayer] Cannot play: video has no valid source\");\n }\n }\n };\n\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n setLoop = (loop: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n\n enablePIP = async () => {\n if (\n this.props.videoElement &&\n \"requestPictureInPicture\" in this.props.videoElement\n ) {\n try {\n await (this.props.videoElement as any).requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n\n disablePIP = async () => {\n if (document.pictureInPictureElement) {\n try {\n await document.exitPictureInPicture();\n } catch (error) {\n console.warn(\"Exit Picture-in-Picture failed:\", error);\n }\n }\n };\n\n render() {\n return null;\n }\n}\n","import { lazy } from \"../utils\";\nimport { canPlay } from \"../patterns\";\nimport HlsPlayer from \"./HlsPlayer\";\nimport FilePlayer from \"./FilePlayer\";\n\nexport interface PlayerConfig {\n key: string;\n name: string;\n canPlay: (url: string) => boolean;\n canEnablePIP?: (url: string) => boolean;\n lazyPlayer?: any;\n}\n\nconst players: PlayerConfig[] = [\n {\n key: \"hls\",\n name: \"HLS Player\",\n canPlay: canPlay.hls,\n lazyPlayer: lazy(() => Promise.resolve({ default: HlsPlayer })),\n },\n {\n key: \"file\",\n name: \"File Player\",\n canPlay: canPlay.file,\n canEnablePIP: (url: string) => {\n return (\n canPlay.file(url) &&\n (document.pictureInPictureEnabled ||\n typeof (document as any).webkitSupportsPresentationMode ===\n \"function\")\n );\n },\n lazyPlayer: lazy(() => Promise.resolve({ default: FilePlayer })),\n },\n];\n\nexport default players;\n","import React, { Component } from \"react\";\nimport type { BaseStormcloudPlayerProps, OnProgressProps } from \"./props\";\nimport { defaultProps } from \"./props\";\nimport { isMediaStream } from \"./utils\";\n\nconst SEEK_ON_PLAY_EXPIRY = 5000;\n\nexport interface PlayerProps extends BaseStormcloudPlayerProps {\n activePlayer: any;\n onReady: () => void;\n}\n\nexport default class Player extends Component<PlayerProps> {\n static displayName = \"Player\";\n static defaultProps = defaultProps;\n\n private mounted = false;\n private isReady = false;\n private isPlaying = false;\n private isLoading = true;\n private loadOnReady: string | null = null;\n private startOnPlay = true;\n private seekOnPlay: number | null = null;\n private onDurationCalled = false;\n private progressTimeout?: number;\n private durationCheckTimeout?: number;\n private prevPlayed?: number;\n private prevLoaded?: number;\n private player?: any;\n\n componentDidMount() {\n this.mounted = true;\n }\n\n componentWillUnmount() {\n clearTimeout(this.progressTimeout);\n clearTimeout(this.durationCheckTimeout);\n this.mounted = false;\n }\n\n componentDidUpdate(prevProps: PlayerProps) {\n if (!this.player) return;\n\n const { src, playing, volume, muted, playbackRate, loop, activePlayer } =\n this.props;\n\n if (prevProps.src !== src) {\n if (this.isLoading && !activePlayer.forceLoad && !isMediaStream(src)) {\n console.warn(\n `StormcloudPlayer: the attempt to load ${src} is being deferred until the player has loaded`\n );\n this.loadOnReady = src || null;\n return;\n }\n this.isLoading = true;\n this.startOnPlay = true;\n this.onDurationCalled = false;\n this.player.load(src, this.isReady);\n }\n\n if (!prevProps.playing && playing && !this.isPlaying) {\n this.player.play();\n }\n\n if (prevProps.playing && !playing && this.isPlaying) {\n this.player.pause();\n }\n\n if (prevProps.volume !== volume && volume !== null) {\n this.player.setVolume(volume);\n }\n\n if (prevProps.muted !== muted) {\n if (muted) {\n this.player.mute();\n } else {\n this.player.unmute();\n if (volume !== null) {\n setTimeout(() => this.player.setVolume(volume));\n }\n }\n }\n\n if (\n prevProps.playbackRate !== playbackRate &&\n this.player.setPlaybackRate\n ) {\n this.player.setPlaybackRate(playbackRate);\n }\n\n if (prevProps.loop !== loop && this.player.setLoop) {\n this.player.setLoop(loop);\n }\n }\n\n handlePlayerMount = (player: any) => {\n if (this.player) {\n this.progress();\n return;\n }\n\n this.player = player;\n this.player.load(this.props.src);\n this.progress();\n };\n\n getInternalPlayer = (key?: string) => {\n if (!this.player) return null;\n return this.player.getInternalPlayer(key);\n };\n\n progress = () => {\n if (this.props.src && this.player && this.isReady) {\n const playedSeconds = this.getCurrentTime() || 0;\n const loadedSeconds = this.getSecondsLoaded();\n const duration = this.getDuration();\n\n if (duration) {\n const progress: OnProgressProps = {\n playedSeconds,\n played: playedSeconds / duration,\n loaded: 0,\n loadedSeconds: 0,\n };\n\n if (loadedSeconds !== null) {\n progress.loadedSeconds = loadedSeconds;\n progress.loaded = loadedSeconds / duration;\n }\n\n if (\n progress.playedSeconds !== this.prevPlayed ||\n progress.loadedSeconds !== this.prevLoaded\n ) {\n this.props.onProgress?.(progress);\n }\n\n this.prevPlayed = progress.playedSeconds;\n this.prevLoaded = progress.loadedSeconds;\n }\n }\n\n this.progressTimeout = window.setTimeout(\n this.progress,\n this.props.progressInterval || 1000\n );\n };\n\n handleReady = () => {\n if (!this.mounted) return;\n\n this.isReady = true;\n this.isLoading = false;\n\n const { onReady, playing, volume, muted } = this.props;\n onReady();\n\n if (!muted && volume !== null) {\n this.player.setVolume(volume);\n }\n\n if (this.loadOnReady) {\n this.player.load(this.loadOnReady, true);\n this.loadOnReady = null;\n } else if (playing) {\n this.player.play();\n }\n\n this.handleDurationCheck();\n };\n\n handlePlay = () => {\n this.isPlaying = true;\n this.isLoading = false;\n\n const { onStart, onPlay, playbackRate } = this.props;\n\n if (this.startOnPlay) {\n if (this.player.setPlaybackRate && playbackRate !== 1) {\n this.player.setPlaybackRate(playbackRate);\n }\n onStart?.();\n this.startOnPlay = false;\n }\n\n onPlay?.();\n\n if (this.seekOnPlay) {\n this.seekTo(this.seekOnPlay);\n this.seekOnPlay = null;\n }\n\n this.handleDurationCheck();\n };\n\n handlePause = (e?: any) => {\n this.isPlaying = false;\n if (!this.isLoading) {\n this.props.onPause?.(e);\n }\n };\n\n handleEnded = () => {\n const { activePlayer, loop, onEnded } = this.props;\n if (activePlayer.loopOnEnded && loop) {\n this.seekTo(0);\n }\n if (!loop) {\n this.isPlaying = false;\n onEnded?.();\n }\n };\n\n handleError = (...args: any[]) => {\n this.isLoading = false;\n this.props.onError?.(args[0], args[1], args[2], args[3]);\n };\n\n handleDurationCheck = () => {\n clearTimeout(this.durationCheckTimeout);\n const duration = this.getDuration();\n if (duration) {\n if (!this.onDurationCalled) {\n this.props.onDuration?.(duration);\n this.onDurationCalled = true;\n }\n } else {\n this.durationCheckTimeout = window.setTimeout(\n this.handleDurationCheck,\n 100\n );\n }\n };\n\n handleLoaded = () => {\n this.isLoading = false;\n };\n\n getDuration(): number | null {\n if (!this.isReady) return null;\n return this.player.getDuration();\n }\n\n getCurrentTime(): number | null {\n if (!this.isReady) return null;\n return this.player.getCurrentTime();\n }\n\n getSecondsLoaded(): number | null {\n if (!this.isReady) return null;\n return this.player.getSecondsLoaded();\n }\n\n seekTo(amount: number, type?: \"seconds\" | \"fraction\", keepPlaying?: boolean) {\n if (!this.isReady) {\n if (amount !== 0) {\n this.seekOnPlay = amount;\n setTimeout(() => {\n this.seekOnPlay = null;\n }, SEEK_ON_PLAY_EXPIRY);\n }\n return;\n }\n\n const isFraction = !type ? amount > 0 && amount < 1 : type === \"fraction\";\n if (isFraction) {\n const duration = this.player.getDuration();\n if (!duration) {\n console.warn(\n \"StormcloudPlayer: could not seek using fraction – duration not yet available\"\n );\n return;\n }\n this.player.seekTo(duration * amount, keepPlaying);\n return;\n }\n this.player.seekTo(amount, keepPlaying);\n }\n\n render() {\n const Player = this.props.activePlayer;\n if (!Player) {\n return null;\n }\n\n return React.createElement(Player, {\n ...this.props,\n onMount: this.handlePlayerMount,\n onReady: this.handleReady,\n onPlay: this.handlePlay,\n onPause: this.handlePause,\n onEnded: this.handleEnded,\n onLoaded: this.handleLoaded,\n onError: this.handleError,\n });\n }\n}\n"]}
|