stormcloud-video-player 0.8.21 → 0.8.22
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 +18 -5
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +18 -5
- package/lib/index.js.map +1 -1
- package/lib/player/AdConfigManager.cjs +18 -5
- package/lib/player/AdConfigManager.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +18 -5
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +18 -5
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +18 -5
- package/lib/players/index.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +18 -5
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/utils/ctvVastSignals.cjs +18 -5
- package/lib/utils/ctvVastSignals.cjs.map +1 -1
- package/lib/utils/vastEnvironmentSignals.cjs +18 -5
- package/lib/utils/vastEnvironmentSignals.cjs.map +1 -1
- package/lib/utils/vastMacros.cjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/ui/StormcloudVideoPlayer.cjs","../../src/ui/StormcloudVideoPlayer.tsx","../../src/sdk/hlsAdPlayer.ts","../../src/sdk/pal.ts","../../src/utils/mqttConfig.ts","../../src/utils/mqttClient.ts","../../src/utils/tracking.ts","../../src/utils/polyfills.ts","../../src/utils/vastEnvironmentSignals.ts","../../src/utils/vastMacros.ts","../../src/utils/browserCompat.ts","../../src/player/Scte35Parser.ts","../../src/player/Scte35CueManager.ts","../../src/player/AdConfigManager.ts","../../src/player/AdTimingService.ts","../../src/player/AdPreloadPool.ts","../../src/player/PlaceholderLayer.ts","../../src/player/HlsEngine.ts","../../src/player/PlayerControls.ts","../../src/player/AdBreakOrchestrator.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","StormcloudVideoPlayer_exports","StormcloudVideoPlayerComponent","module","exports","import_react","require","import_hls","MAX_VAST_WRAPPER_DEPTH","createHlsAdPlayer","contentVideo","options","adPlaying","originalMutedState","originalVolume","Math","max","min","volume","listeners","Map","licenseKey","mainHlsInstance","adVideoElement","adHls","adContainerEl","currentAd","sessionId","preloadedAds","preloadingAds","destroyed","pendingTimeouts","trackingFired","impression","start","firstQuartile","midpoint","thirdQuartile","complete","emit","event","payload","set","Array","fn","error","console","warn","generateSessionId","Date","now","random","toString","substr","fireTrackingPixels","urls","length","forEach","url","trackingUrl","includes","img","Image","src","log","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","width","height","bitrate","selectBestMediaFile","mediaFiles","Error","firstFile","mainQuality","scoredFiles","widthDiff","map","abs","file","resolutionDiff","heightDiff","fileBitrate","score","bitrateDiff","bestMatch","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","el","isProgressiveMediaFile","createEmptyTrackingUrls","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","extractTrackingUrls","trackingUrls","xmlDoc","textContent","trim","push","querySelectorAll","getAttribute","eventKey","mergeTrackingUrls","source","keys","concat","parseVastXml","xmlString","parser","DOMParser","parseFromString","parserError","querySelector","adElement","adId","title","clickThrough","wrapperUri","vastAdTagUri","isNoAdAvailable","durationText","durationParts","split","duration","parseInt","mediaFileElements","mf","index","bitrateAttr","bitrateValue","ad","id","fetchVastXml","vastTagUrl","response","fetch","mode","credentials","headers","referrerPolicy","ok","statusText","text","fetchAndParseVastAd","depth","accumulatedTracking","vastXml","parsed","substring","createAdVideoElement","video","document","createElement","style","position","left","top","objectFit","backgroundColor","playsInline","muted","setupAdEventListeners","addEventListener","progress","currentTime","handleAdComplete","e","handleAdError","ended","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","continueLiveStreamDuringAds","paused","play","catch","initialize","right","bottom","container","alignItems","justifyContent","zIndex","parentElement","appendChild","requestAds","has","delete","Promise","reject","resolve","contentVolume","isHlsAd","Hls","isSupported","destroy","enableWorker","lowLatencyMode","loadSource","attachMedia","on","Events","MANIFEST_PARSED","ERROR","data","fatal","load","stop","previousMutedState","visibility","opacity","timeoutId","clearTimeout","remove","removeChild","clear","getOriginalMutedState","setAdVolume","isAdPlaying","listener","Set","add","off","updateOriginalMutedState","nextVolume","getOriginalVolume","clamped","getAdVolume","showPlaceholder","hidePlaceholder","getLoadedAdDuration","getLoadedAdId","window","PAL_SDK_URL","_nonceLoader","_palLoadPromise","loadPalSdk","goog","pal","existing","timeout","setTimeout","script","onload","head","consentSettings","ConsentSettings","allowStorage","NonceLoader","createPalNonceManager","currentNonce","currentNonceManager","generateNonce","loader","request","manager","getOrCreateNonceLoader","NonceRequest","adWillAutoPlay","adWillPlayMuted","playerVolume","continuousPlayback","descriptionUrl","location","href","iconsSupported","playerType","playerVersion","supportedApiFrameworks","videoWidth","videoHeight","ppid","loadNonceManager","getNonce","injectNonce","URL","searchParams","base","replace","sep","encodeURIComponent","sendPlaybackStart","sendPlaybackEnd","sendAdClick","sendAdTouch","reset","DEFAULT_MQTT_CONFIG","enabled","brokerAddress","brokerPort","wsPort","username","password","topicPrefix","qos","mqttConfig","isMQTTEnabled","buildMQTTBrokerUrl","brokerUrl","buildPlayerTopic","channel","import_mqtt","LOG","client","status","initMQTTClient","clientId","slice","mqtt","connect","keepalive","clean","reconnectPeriod","connectTimeout","queueQoSZero","err","info","message","ensureMQTTClient","publishMQTT","topic","publish","JSON","stringify","cachedBrowserId","getClientInfo","screen","navigator","ua","userAgent","platform","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isSmartTV","isAndroid","isWebView","isWebApp","webosMatch","match","tizenMatch","tvMatch","test","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","hostname","origin","path","pathname","language","languages","cookieEnabled","join","doNotTrack","referrer","visibilityState","getBrowserID","clientInfo","crypto","fingerprintString","encodedData","utf8","buffer","i","hashBuffer","hashHex","hash","char","fallbackHash","timestamp","subtle","digest","Uint8Array","TextEncoder","encode","unescape","charCodeAt","b","padStart","padEnd","canPublish","Boolean","buildPlayerMetricEvent","context","flags","playerId","captureAt","toISOString","player_id","device_type","ad_loaded","adLoaded","ad_detect","adDetect","capture_at","inputStreamType","input_stream_type","publishTracking","body","sendInitialTracking","metricEvent","events","sendAdDetectTracking","adDetectInfo","sendHeartbeat","sendAdLoadedTracking","adLoadedInfo","sendAdImpressionTracking","adImpressionInfo","ad_played_count","ad_url","adUrl","heartbeatData","polyfillURLSearchParams","URLSearchParams","URLSearchParamsPolyfill","init","params","parseQueryString","append","query","cleanQuery","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","values","String","getAll","callback","parts","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","finally","constructor","then","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","len","result","polyfillStringStartsWith","startsWith","search","pos","polyfillStringEndsWith","endsWith","polyfillStringIncludes","indexOf","initializePolyfills","AIRY_ANDROID_APP_ID","AIRY_WEBOS_APP_ID","AIRY_TIZEN_APP_ID","AIRY_ROKU_APP_ID","AIRY_APP_NAME","AIRY_DEFAULT_CONTENT_URL","CTV_SESSION_STORAGE_KEY","getDefaultAppId","DEVICE_ID_STORAGE_KEYS","ANDROID_ID_TYPES","resolveVastEnvironmentSignals","isCtv","bridgeSignals","readNativeBridgeSignals","deviceId","readStoredDeviceId","deviceIdType","readStoredString","inferDeviceIdType","contentUrl","appId","appName","getOrCreateCtvSessionId","limitAdTracking","deviceTypeHint","isEquivalentDeviceIdType","tagType","runtimeType","tag","runtime","localStorage","setItem","createUuid","randomUUID","floor","nibble","candidates","__STORMCLOUD_CTV_AD_INFO__","__STORMCLOUD_CTV__","stormcloudCtv","AiryTV","Android","webOS","tizen","amazon","filter","readBridgeValue","readBridgeBoolean","normalized","normalizeBoolean","getItem","readStoredLimitAdTracking","UNEXPANDED_MACRO_PATTERN","INVALID_VAST_PARAM_KEY","EXAMPLE_COM_URL","CTV_UNSUPPORTED_PARAMS","INLINE_DEVICE_MACRO_REPLACEMENTS","pattern","getValue","ctx","correlator","isMacroPlaceholder","trimmed","generateCorrelator","getRandomValues","buf","Uint32Array","Number","MAX_SAFE_INTEGER","expandInlineMacroPlaceholders","baseUrl","applyDeviceIdentityParams","runtimeId","tagRdid","tagLat","latValue","tagRdidValid","tagTypeValid","removeBrokenAppNameOrphans","toDelete","_value","suffix","trimStart","normalizeVastTagUrl","raw","anValue","orphanFragments","reconstructed","_match","prefix","val","expandedUrl","replaceCorrelatorFallback","streamCorrelator","pod","adPosition","requestUrl","pageUrl","existingUrl","consent","gdpr","gdprConsent","usPrivacy","adTest","staleKeys","correlatorRegex","fetchConsentSignals","timeoutMs","signals","tasks","tcfApi","__tcfapi","settled","tcData","success","eventStatus","gdprApplies","tcString","listenerId","uspApi","__uspapi","uspString","getChromeVersion","getWebKitVersion","userAgentData","detectBrowser","getPlatform","tizenVersion","supportsModernJS","version","majorVersion","isLegacyTV","chromeVersionNum","chromeVersion","webkitVersion","webOSVersion","getBrowserConfigOverrides","browser","overrides","allowNativeHls","logBrowserInfo","debug","parseCueOutDuration","num","parseFloat","dStr","d","parseCueOutCont","res","elapsedMatch","durationMatch","isNaN","elapsed","slashMatch","parseAttributeList","attrs","regex","exec","rawVal","toNumber","n","isManifestBasedMarker","marker","id3","splice_command_type","decodeId3ValueToText","decoder","TextDecoder","decode","out","fromCharCode","getFragmentStartSeconds","frag","startPTS","candidate","isFinite","parseScte35FromId3","cueOutMatch","arg","dur","ptsSeconds","durationSeconds","cueOutContMatch","cont","cueInMatch","daterangeMatch","hasScteOut","hasScteIn","klass","bin","parseScte35Binary","normalizeFragmentPayload","ArrayBuffer","isView","view","byteOffset","byteLength","detectTsPacketFormat","packetSizes","packetSize","tsPayloadOffset","offset","matchedPackets","packetStart","getPsiSectionStart","payloadUnitStart","pointerField","sectionStart","getPsiSectionLength","parsePatSection","pmtPids","sectionLength","sectionEnd","programNumber","pid","descriptorsIdentifyScte35","end","descriptorStart","descriptorEnd","registration","parsePmtSection","tsScte35Pids","programInfoLength","streamType","elementaryPid","esInfoLength","section","hasProcessedTsScte35Section","processedSections","checksum","firstKey","next","addScte35SectionMarker","markers","appendScte35Bytes","bytes","assemblers","assembler","expectedLength","collectScte35SectionsFromPayload","previousAssembler","subarray","tableId","totalLength","parseScte35FromTsPackets","packetInfo","sectionAssemblers","tsStart","secondByte","thirdByte","fourthByte","adaptationFieldControl","hasPayload","payloadStart","adaptationLength","payloadEnd","BitReader","bytePos","bitPos","readBits","numBits","remainingInByte","toRead","currentByte","shift","mask","bits","skipBits","bytePosition","readSpliceTime","r","ptsAdjustmentTicks","timeSpecifiedFlag","high","low","ptsTicks","markerTypeFromSegmentationTypeId","segmentationTypeId","parseScte35SegmentationDescriptor","descriptor","identifier","segmentationEventId","cancelIndicator","programSegmentationFlag","segmentationDurationFlag","componentCount","durationTicks","segmentationUpidLength","markerType","parseScte35SegmentationDescriptors","descriptorLoopLength","descriptorOffset","descriptorTag","descriptorDataStart","descriptorDataEnd","descriptorLength","descriptorMarker","commandBodyStart","ptsAdjHigh","ptsAdjLow","spliceCommandLength","spliceCommandType","spliceEventId","cancel","outOfNetwork","programSpliceFlag","durationFlag","spliceImmediateFlag","componentPtsSeconds","expectedDescriptorOffset","splice_event_id","segmentation_event_id","Scte35CueManager","callbacks","pendingScte35Cues","recentScte35CueKeys","recentScte35CueLimit","processedTsScte35Sections","pendingScte35CueKey","pendingScte35CueKeyValue","activeScte35BreakKey","activeScte35BreakKeyValue","scheduledScte35BreakKey","scheduledScte35BreakKeyValue","createScte35CueContext","readiness","sn","fragmentSn","fragmentStartSec","fragmentStartSeconds","onScte35Cue","cue","createScte35Cue","pendingKey","trimRecentScte35CueMaps","onEarlyStartCue","shouldAcceptScte35EndCue","inAdBreak","isInAdBreak","hasRecentlyHandledScte35Cue","markScte35CueHandled","onPlaybackCue","activatePendingScte35CuesForFragment","matchingCues","entries","getScte35CueKey","getScte35MarkerRaw","toIdentityString","daterangeId","ID","scteValue","round","getPendingScte35CueKey","isStrongScte35CueKey","recentKey","size","AdConfigManager","config","consumedVmapBreakIds","consentSignals","podCounter","podAssignedByPrefetch","adRequestPositionInBreak","lastHeartbeatTime","debugAdTiming","isVmapEnabled","isVmap","vmapUrl","fetchAdConfiguration","vastMode","vastEndpoint","apiUrl","imaPayload","decodedPayload","numberAds","fetchAndParseVmap","apiVastTagUrl","json","ima","vast","cue_tones","number_ads","apiNumberAds","vmapXml","vmapBreaks","parseVmapToBreaks","doc","VMAP_NS","adBreakNodes","getElementsByTagNameNS","getElementsByTagName","localName","node","timeOffsetRaw","startTimeMs","parseVmapTimeOffsetToMs","adTagNode","adTagUrl","breakId","sort","a","aStart","bStart","timeOffset","hms","hours","hh","mm","ss","ms","minutes","millis","seconds","percent","ratio","durationSec","getAdBreakKey","adBreak","resolveBreakStartMs","findCurrentOrNextBreak","nowMs","schedule","tol","driftToleranceMs","breakStartMs","findBreakForTime","durationMs","selectVastTagsForBreak","s","beginNewAdPod","generateVastUrlsWithCorrelators","count","adPlayer","palNonce","envSignals","ctvAdRequest","urlWithMacros","applyVastMacros","autoplay","finalUrl","initializeTracking","heartbeatInterval","setInterval","sendHeartbeatIfNeeded","destroyTracking","clearInterval","AdTimingService","adRequestWatchdogToken","adFailsafeToken","ptsDriftEmaMs","adBreakPlayedDurationMs","adBreakEpoch","adRequestTokenCounter","activeAdRequestToken","currentAdIndex","totalAdsInBreak","totalAdRequestsInBreak","maxTotalAdRequestsPerBreak","lastAdRequestTime","maxConsecutiveFailures","minAdRequestIntervalMs","backoffBaseMs","maxBackoffMs","defaultMinRemainingMsToStartAd","failedVastUrls","temporaryFailureUrls","temporaryFailureCooldownMs","globalConsecutiveNoFills","globalNoFillThreshold","globalNoFillCooldownUntil","globalNoFillBackoffBaseMs","globalNoFillBackoffMaxMs","globalLastGamRequestTime","globalMinGamIntervalMs","scheduleAdStopCountdown","remainingMs","clearAdStopTimer","ensureAdStoppedByTimer","adStopTimerId","onAdStopTimerFired","clearAdStartTimer","deltaMs","nowWallClockMs","estimatedCurrentPtsMs","getRemainingAdMs","expectedAdBreakDurationMs","scheduleAdStartIn","cueKey","delayMs","onAdStartTimerFired","adStartTimerId","updatePtsDrift","ptsSecondsSample","sampleMs","alpha","resolveScteBreakStartWallClockMs","setAdBreakDurationBoundary","currentAdBreakStartWallClockMs","scteAdBreakEndWallClockMs","scheduleAdStopAtBreakBoundary","getWallClockRemainingAdMs","endWallClockMs","getAdBreakEndWallClockMs","getDurationBudgetRemainingMs","getLoadedAdDurationMs","adController","adFitsRemainingBudget","logAdDurationDecision","accepted","remainingBudget","recordPlayedAdDuration","ensureLoadedAdFitsBudget","fits","rejectLoadedAdForDuration","markAdStarted","wallClockRemaining","budgetRemaining","getMinRemainingMsToStartAd","configured","minRemainingMsToStartAd","hasTimeToStartAnotherAd","minRemaining","isTemporaryAdError","isUrlInCooldown","failureTime","exponent","cleanupTemporaryFailures","isGamInCooldown","recordGamNoFill","backoff","pow","resetGamNoFillCounter","enforceGlobalRateLimit","waitMs","clearAdFailsafeTimer","startAdRequestWatchdog","token","clearAdRequestWatchdog","adFailsafeTimeoutMs","adRequestWatchdogId","logAdState","onWatchdogTimeout","startAdFailsafeTimer","failsafeMs","adFailsafeTimerId","videoPaused","onFailsafeTimeout","extra","showAds","resetForBreakEnd","isLoopRunning","loopRunning","deps","consecutiveFailures","AdPreloadPool","pool","maxPoolSize","poolActive","active","startPreloadPool","baseVastUrl","initialUrls","startLoopImmediately","preloadAdIntoPool","preloadPoolLoop","vastUrl","timing","epoch","loadPromise","some","entry","hasAdError","adErrorPayload","errorListenerCleanup","preloadAd","errorListener","isNoFill","poolEntry","loadedDuration","lateErrorListener","shouldContinueLiveStreamDuringAds","createAdPlayer","code","vastErrorCode","loadedAt","isReady","findIndex","splice","newUrls","newUrl","getPendingAdBreak","getPreloadedAd","PlaceholderLayer","ensureContainer","transition","show","wasHidden","offsetHeight","requestAnimationFrame","hide","HlsEngine","cueManager","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","shouldUseNativeHls","getStreamType","canNative","canPlayType","setupNativeHls","adBehavior","setupHls","hls","import_hls2","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","_","_data","minSegments","details","live","onManifestParsed","fragments","LEVEL_LOADED","_evt","hasPendingAdBreak","fragmentsToScan","tagList","isArray","idx","earlyDetection","FRAG_BUFFERED","minSegmentsBeforePlay","FRAG_PARSING_METADATA","id3Tags","samples","pts","onId3Tag","FRAG_LOADED","processFragmentScte35Payload","FRAG_DECRYPTED","FRAG_CHANGED","activatePendingCuesForFragment","prog","ErrorTypes","NETWORK_ERROR","MEDIA_ERROR","recoverMediaError","onFatalDestroy","payloadData","getAdAudioVolume","toggleMute","newMutedState","restoreVolume","toggleFullscreen","fullscreenElement","requestFullscreen","isMuted","setMuted","setVolume","clampedVolume","getVolume","isFullscreen","resizePlayer","clientWidth","clientHeight","resize","AdBreakOrchestrator","host","preloadPool","adConfig","placeholder","isShowingPlaceholder","adDetectSentForCurrentBreak","continuousFetchingActive","continuousFetchLoopRunning","adRequestQueue","adPodQueue","maxPlaceholderDurationMs","attachImaEventListeners","getAdPlayer","adIndex","remaining","queuedUrls","tryNextAvailableAdWithRateLimit","handleAdPodComplete","errorPayload","errorMessage","cause","innerError","errorCode","causeMessage","handleAdFailure","recreateAdController","shouldShowPlaceholder","preservedMutedState","preservedVolumeState","newAdPlayer","setAdPlayer","adBreakDurationMs","usePreloadedAd","preloaded","firstAdUrl","preloadedController","pendingAdBreak","vastUrls","firstAdUrlArray","generateVastUrls","startContinuousFetching","preservedMuted","preservedVolume","adVolume","currentMuted","currentVolume","fallbackPreloaded","swapToPreloadedAdPlayer","ap","fallbackError","continuousFetchLoop","maxQueueSize","newAdUrl","queuedUrlsPreview","generationDelay","stopContinuousFetching","backoffMultiplier","backoffDelay","effectiveMinInterval","timeSinceLastRequest","waitTime","tryNextAvailableAd","nextAdUrl","maxRetries","playSingleAd","retryCount","showPlaceholderAndWaitForAds","requestToken","playError","preloadedFallback","fbAp"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/ui/StormcloudVideoPlayer.tsx\nvar StormcloudVideoPlayer_exports = {};\n__export(StormcloudVideoPlayer_exports, {\n StormcloudVideoPlayerComponent: () => StormcloudVideoPlayerComponent\n});\nmodule.exports = __toCommonJS(StormcloudVideoPlayer_exports);\nvar import_react = __toESM(require(\"react\"), 1);\n\n// src/sdk/hlsAdPlayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar MAX_VAST_WRAPPER_DEPTH = 5;\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 isHlsMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type === \"application/x-mpegurl\" || type === \"application/vnd.apple.mpegurl\" || type.includes(\"mpegurl\") || url.includes(\".m3u8\");\n }\n function isProgressiveMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type.startsWith(\"video/\") || url.endsWith(\".mp4\") || url.includes(\".mp4?\");\n }\n function createEmptyTrackingUrls() {\n return {\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 function extractTrackingUrls(xmlDoc) {\n const trackingUrls = createEmptyTrackingUrls();\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 xmlDoc.querySelectorAll(\"Error\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.error.push(url);\n });\n return trackingUrls;\n }\n function mergeTrackingUrls(target, source) {\n Object.keys(target).forEach((key) => {\n if (source[key] && source[key].length > 0) {\n target[key] = target[key].concat(source[key]);\n }\n });\n return target;\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 { type: \"empty\" };\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return { type: \"empty\" };\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n const wrapperUri = xmlDoc.querySelector(\"VASTAdTagURI\")?.textContent?.trim();\n if (wrapperUri) {\n console.log(\n `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n );\n return {\n type: \"wrapper\",\n vastAdTagUri: wrapperUri,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough\n };\n }\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 const mediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: void 0\n };\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\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 supported media files found in VAST XML\");\n }\n return { type: \"empty\" };\n }\n return {\n type: \"inline\",\n ad: {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough\n }\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return { type: \"empty\" };\n }\n }\n async function fetchVastXml(vastTagUrl) {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\"\n },\n referrerPolicy: \"no-referrer-when-downgrade\"\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n return response.text();\n }\n async function fetchAndParseVastAd(vastTagUrl, depth = 0, accumulatedTracking = createEmptyTrackingUrls()) {\n const vastXml = await fetchVastXml(vastTagUrl);\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 const parsed = parseVastXml(vastXml);\n if (parsed.type === \"empty\") {\n return null;\n }\n if (parsed.type === \"wrapper\") {\n if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n console.warn(\n `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n );\n return null;\n }\n mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n return fetchAndParseVastAd(\n parsed.vastAdTagUri,\n depth + 1,\n accumulatedTracking\n );\n }\n mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n return parsed.ad;\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 if (!adPlaying) return;\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 contentVideo.muted = true;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {\n });\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n emit(\"content_resume\");\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\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 = \"30\";\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.reject(new Error(\"No ads available from VAST response\"));\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 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 adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n adVideoElement.volume = Math.max(0, Math.min(1, originalVolume));\n adVideoElement.muted = originalMutedState;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n if (isHlsAd && import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n adHls = new import_hls.default({\n enableWorker: true,\n lowLatencyMode: false\n });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.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(import_hls.default.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && 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 if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\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 pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {\n });\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}, volume: ${contentVideo.volume}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {\n });\n }\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 = Math.max(0, Math.min(1, 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 const clamped = Math.max(0, Math.min(1, volume));\n adVideoElement.volume = clamped;\n adVideoElement.muted = clamped === 0;\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 getLoadedAdDuration() {\n return currentAd?.duration;\n },\n getLoadedAdId() {\n return currentAd?.id;\n }\n };\n}\n\n// src/sdk/pal.ts\nvar PAL_SDK_URL = \"https://imasdk.googleapis.com/pal/sdkloader/pal.js\";\nvar _nonceLoader;\nvar _palLoadPromise;\nfunction loadPalSdk() {\n if (typeof window !== \"undefined\" && window.goog?.pal) {\n return Promise.resolve();\n }\n if (_palLoadPromise) return _palLoadPromise;\n _palLoadPromise = new Promise((resolve, reject) => {\n const existing = document.querySelector(\n 'script[data-pal=\"true\"]'\n );\n if (existing) {\n if (window.goog?.pal) {\n resolve();\n return;\n }\n const timeout = setTimeout(\n () => reject(new Error(\"PAL SDK load timeout\")),\n 1e4\n );\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"PAL SDK load failed\"));\n });\n return;\n }\n const script = document.createElement(\"script\");\n script.src = PAL_SDK_URL;\n script.async = true;\n script.setAttribute(\"data-pal\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"PAL SDK load failed\"));\n document.head.appendChild(script);\n });\n return _palLoadPromise;\n}\nfunction getOrCreateNonceLoader() {\n if (_nonceLoader) return _nonceLoader;\n const goog = window.goog;\n const consentSettings = new goog.pal.ConsentSettings();\n consentSettings.allowStorage = true;\n _nonceLoader = new goog.pal.NonceLoader(consentSettings);\n return _nonceLoader;\n}\nfunction createPalNonceManager() {\n let currentNonce = \"\";\n let currentNonceManager;\n return {\n async generateNonce(options = {}) {\n try {\n await loadPalSdk();\n const loader = getOrCreateNonceLoader();\n const goog = window.goog;\n const request = new goog.pal.NonceRequest();\n request.adWillAutoPlay = options.adWillAutoPlay ?? true;\n request.adWillPlayMuted = options.adWillPlayMuted ?? false;\n request.playerVolume = options.playerVolume ?? (request.adWillPlayMuted ? 0 : 1);\n request.continuousPlayback = options.continuousPlayback ?? true;\n request.descriptionUrl = options.descriptionUrl || (typeof window !== \"undefined\" ? window.location.href : \"\");\n request.iconsSupported = true;\n request.playerType = \"StormcloudVideoPlayer\";\n request.playerVersion = \"1.0\";\n request.supportedApiFrameworks = \"2,7,9\";\n request.url = options.descriptionUrl || (typeof window !== \"undefined\" ? window.location.href : \"\");\n request.videoWidth = options.videoWidth || 640;\n request.videoHeight = options.videoHeight || 480;\n if (options.ppid) request.ppid = options.ppid;\n if (options.sessionId) request.sessionId = options.sessionId;\n const manager = await loader.loadNonceManager(request);\n currentNonceManager = manager;\n currentNonce = manager.getNonce();\n console.log(\"[PAL] Nonce generated successfully\");\n return currentNonce;\n } catch (error) {\n console.warn(\"[PAL] Failed to generate nonce:\", error);\n currentNonce = \"\";\n currentNonceManager = void 0;\n return \"\";\n }\n },\n getCurrentNonce() {\n return currentNonce;\n },\n injectNonce(vastTagUrl) {\n if (!currentNonce || !vastTagUrl) return vastTagUrl;\n try {\n const url = new URL(vastTagUrl);\n url.searchParams.delete(\"paln\");\n url.searchParams.set(\"givn\", currentNonce);\n return url.toString();\n } catch {\n let base = vastTagUrl.replace(/([?&])paln=[^&]*/g, \"\").replace(/[?&]$/, \"\");\n const sep = base.includes(\"?\") ? \"&\" : \"?\";\n return `${base}${sep}givn=${encodeURIComponent(currentNonce)}`;\n }\n },\n sendPlaybackStart() {\n try {\n currentNonceManager?.sendPlaybackStart();\n } catch {\n }\n },\n sendPlaybackEnd() {\n try {\n currentNonceManager?.sendPlaybackEnd();\n } catch {\n }\n },\n sendAdClick() {\n try {\n currentNonceManager?.sendAdClick();\n } catch {\n }\n },\n sendAdTouch(event) {\n try {\n currentNonceManager?.sendAdTouch(event);\n } catch {\n }\n },\n reset() {\n currentNonce = \"\";\n currentNonceManager = void 0;\n }\n };\n}\n\n// src/utils/mqttConfig.ts\nvar DEFAULT_MQTT_CONFIG = {\n enabled: true,\n brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n brokerPort: 8883,\n wsPort: 8084,\n username: \"for-sonifi\",\n password: \"sonifi-mqtt\",\n topicPrefix: \"adstorm/players\",\n qos: 1\n};\nvar mqttConfig = { ...DEFAULT_MQTT_CONFIG };\nfunction isMQTTEnabled() {\n return mqttConfig.enabled;\n}\nfunction buildMQTTBrokerUrl() {\n if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\nfunction buildPlayerTopic(licenseKey, channel) {\n return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n\n// src/utils/mqttClient.ts\nvar import_mqtt = __toESM(require(\"mqtt\"), 1);\nvar LOG = \"[StormcloudVideoPlayer][MQTT]\";\nvar client = null;\nvar status = \"disconnected\";\nfunction initMQTTClient() {\n if (client || !isMQTTEnabled()) return;\n const url = buildMQTTBrokerUrl();\n status = \"connecting\";\n const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n try {\n client = import_mqtt.default.connect(url, {\n clientId,\n username: mqttConfig.username,\n password: mqttConfig.password,\n keepalive: 60,\n clean: true,\n reconnectPeriod: 5e3,\n connectTimeout: 1e4,\n queueQoSZero: false\n });\n } catch (err) {\n status = \"error\";\n console.warn(`${LOG} connect() threw:`, err);\n return;\n }\n client.on(\"connect\", () => {\n status = \"connected\";\n console.info(`${LOG} connected to ${url}`);\n });\n client.on(\"reconnect\", () => {\n status = \"connecting\";\n console.info(`${LOG} reconnecting\\u2026`);\n });\n client.on(\"offline\", () => {\n status = \"disconnected\";\n console.warn(`${LOG} offline`);\n });\n client.on(\"error\", (err) => {\n status = \"error\";\n console.warn(`${LOG} error:`, err.message);\n });\n client.on(\"close\", () => {\n if (status === \"connected\") {\n status = \"disconnected\";\n }\n });\n}\nfunction ensureMQTTClient() {\n if (isMQTTEnabled() && !client) {\n initMQTTClient();\n }\n}\nfunction publishMQTT(topic, payload) {\n if (!isMQTTEnabled()) {\n return false;\n }\n ensureMQTTClient();\n if (!client) {\n return false;\n }\n try {\n client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n return true;\n } catch (err) {\n console.warn(`${LOG} publish failed on ${topic}:`, err);\n return false;\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?.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 hashHex = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle 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}\nfunction canPublish(licenseKey) {\n return Boolean(isMQTTEnabled() && licenseKey);\n}\nasync function buildPlayerMetricEvent(context = {}, flags = {}) {\n const clientInfo = getClientInfo();\n const playerId = await getBrowserID(clientInfo);\n const captureAt = flags.captureAt ?? (/* @__PURE__ */ new Date()).toISOString();\n return {\n player_id: playerId,\n device_type: clientInfo.deviceType,\n os: clientInfo.os.toLowerCase(),\n ad_loaded: flags.adLoaded ?? false,\n ad_detect: flags.adDetect ?? false,\n capture_at: captureAt,\n ...context.inputStreamType ? { input_stream_type: context.inputStreamType } : {}\n };\n}\nfunction publishTracking(licenseKey, channel, body) {\n ensureMQTTClient();\n publishMQTT(buildPlayerTopic(licenseKey, channel), body);\n}\nasync function sendInitialTracking(licenseKey, context = {}) {\n if (!canPublish(licenseKey)) return;\n try {\n const metricEvent = await buildPlayerMetricEvent(context, {\n adLoaded: false,\n adDetect: false\n });\n publishTracking(licenseKey, \"metrics\", {\n events: [metricEvent]\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\nasync function sendAdDetectTracking(licenseKey, adDetectInfo, context = {}) {\n try {\n await sendHeartbeat(licenseKey, context, {\n adDetect: true,\n captureAt: adDetectInfo.timestamp\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n error\n );\n }\n}\nasync function sendAdLoadedTracking(licenseKey, adLoadedInfo, context = {}) {\n try {\n await sendHeartbeat(licenseKey, context, {\n adLoaded: true,\n captureAt: adLoadedInfo.timestamp\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n error\n );\n }\n}\nasync function sendAdImpressionTracking(licenseKey, adImpressionInfo, context = {}) {\n if (!canPublish(licenseKey)) return;\n try {\n const metricEvent = await buildPlayerMetricEvent(context, {\n captureAt: adImpressionInfo.timestamp\n });\n publishTracking(licenseKey, \"heartbeat\", metricEvent);\n publishTracking(licenseKey, \"impressions\", {\n events: [\n {\n player_id: metricEvent.player_id,\n ad_played_count: 1,\n ad_url: adImpressionInfo.adUrl,\n capture_at: adImpressionInfo.timestamp\n }\n ]\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\nasync function sendHeartbeat(licenseKey, context = {}, flags = {}) {\n if (!canPublish(licenseKey)) return;\n try {\n const heartbeatData = await buildPlayerMetricEvent(context, flags);\n publishTracking(licenseKey, \"heartbeat\", heartbeatData);\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/utils/vastEnvironmentSignals.ts\nvar AIRY_ANDROID_APP_ID = \"com.freeairytv.android\";\nvar AIRY_WEBOS_APP_ID = \"com.freeairytv.webos\";\nvar AIRY_TIZEN_APP_ID = \"com.freeairytv.samsung\";\nvar AIRY_ROKU_APP_ID = \"com.freeairytv.roku\";\nvar AIRY_APP_NAME = \"AiryTV Movies & TV\";\nvar AIRY_DEFAULT_CONTENT_URL = \"https://live.airy.tv\";\nvar CTV_SESSION_STORAGE_KEY = \"stormcloud.ctv.sid\";\nfunction getDefaultAppId() {\n if (typeof navigator === \"undefined\") return AIRY_ANDROID_APP_ID;\n const ua = navigator.userAgent;\n if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;\n if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;\n if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;\n return AIRY_ANDROID_APP_ID;\n}\nvar DEVICE_ID_STORAGE_KEYS = [\n \"rdid\",\n \"ifa\",\n \"advertisingId\",\n \"advertising_id\",\n \"deviceAdvertisingId\",\n \"aaid\",\n \"adid\",\n \"rida\",\n \"tifa\",\n \"lgudid\"\n];\nvar ANDROID_ID_TYPES = /* @__PURE__ */ new Set([\"aaid\", \"adid\"]);\nfunction resolveVastEnvironmentSignals(isCtv) {\n const bridgeSignals = readNativeBridgeSignals();\n const deviceId = bridgeSignals.deviceId || readStoredDeviceId();\n const deviceIdType = bridgeSignals.deviceIdType || readStoredString(\"deviceIdType\") || readStoredString(\"idtype\") || inferDeviceIdType();\n const limitAdTracking = deviceId != null ? bridgeSignals.limitAdTracking ?? readStoredLimitAdTracking() ?? false : void 0;\n if (isCtv) {\n return {\n isCtv: true,\n contentUrl: bridgeSignals.contentUrl || readStoredString(\"contentUrl\") || AIRY_DEFAULT_CONTENT_URL,\n appId: bridgeSignals.appId || readStoredString(\"appId\") || readStoredString(\"msid\") || getDefaultAppId(),\n appName: bridgeSignals.appName || readStoredString(\"appName\") || readStoredString(\"an\") || AIRY_APP_NAME,\n sessionId: getOrCreateCtvSessionId(),\n ...deviceId ? { deviceId } : {},\n ...deviceIdType ? { deviceIdType } : {},\n ...limitAdTracking != null ? { limitAdTracking } : {},\n deviceTypeHint: 5\n };\n }\n return {\n isCtv: false,\n ...deviceId ? { deviceId } : {},\n ...deviceIdType ? { deviceIdType } : {},\n ...limitAdTracking != null ? { limitAdTracking } : {}\n };\n}\nfunction inferDeviceIdType() {\n if (typeof navigator === \"undefined\") {\n return void 0;\n }\n const ua = navigator.userAgent;\n if (/Roku/i.test(ua)) return \"rida\";\n if (/Tizen|Samsung/i.test(ua)) return \"tifa\";\n if (/AppleTV|Apple TV/i.test(ua)) return \"tvOS\";\n if (/AFT|Fire TV|Amazon/i.test(ua)) return \"afai\";\n if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return \"lgudid\";\n if (/Android|Google TV/i.test(ua)) return \"aaid\";\n if (/iPhone|iPad|iPod/i.test(ua)) return \"idfa\";\n return void 0;\n}\nfunction isEquivalentDeviceIdType(tagType, runtimeType) {\n if (!tagType || !runtimeType) return false;\n const tag = tagType.toLowerCase();\n const runtime = runtimeType.toLowerCase();\n if (tag === runtime) return true;\n return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);\n}\nfunction getOrCreateCtvSessionId() {\n const existing = readStoredString(CTV_SESSION_STORAGE_KEY);\n if (existing) {\n return existing;\n }\n const sessionId = createUuid();\n try {\n window.localStorage?.setItem(CTV_SESSION_STORAGE_KEY, sessionId);\n } catch {\n }\n return sessionId;\n}\nfunction createUuid() {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const value = Math.floor(Math.random() * 16);\n const nibble = char === \"x\" ? value : value & 3 | 8;\n return nibble.toString(16);\n });\n}\nfunction readNativeBridgeSignals() {\n if (typeof window === \"undefined\") {\n return {};\n }\n const candidates = [\n window.__STORMCLOUD_CTV_AD_INFO__,\n window.__STORMCLOUD_CTV__,\n window.stormcloudCtv,\n window.AiryTV,\n window.Android,\n window.webOS,\n window.tizen,\n window.amazon\n ].filter(Boolean);\n for (const source of candidates) {\n const contentUrl = readBridgeValue(source, [\"contentUrl\", \"url\", \"videoUrl\", \"canonicalUrl\"]) || void 0;\n const appId = readBridgeValue(source, [\"appId\", \"msid\", \"applicationId\", \"packageName\"]) || void 0;\n const appName = readBridgeValue(source, [\"appName\", \"an\", \"applicationName\"]) || void 0;\n const deviceId = readBridgeValue(source, [\n \"rdid\",\n \"ifa\",\n \"advertisingId\",\n \"adId\",\n \"deviceId\",\n \"lgudid\",\n \"LGUDID\",\n \"tifa\",\n \"rida\",\n \"afai\",\n \"aaid\"\n ]) || void 0;\n if (!contentUrl && !deviceId && !appId && !appName) continue;\n const deviceIdType = readBridgeValue(source, [\n \"idtype\",\n \"deviceIdType\",\n \"advertisingIdType\",\n \"idType\"\n ]) || inferDeviceIdType();\n const limitAdTracking = readBridgeBoolean(source, [\n \"is_lat\",\n \"limitAdTracking\",\n \"limitedAdTracking\",\n \"lat\"\n ]);\n return {\n ...contentUrl ? { contentUrl } : {},\n ...appId ? { appId } : {},\n ...appName ? { appName } : {},\n ...deviceId ? { deviceId } : {},\n ...deviceId && deviceIdType ? { deviceIdType } : {},\n ...deviceId && limitAdTracking != null ? { limitAdTracking } : {}\n };\n }\n return {};\n}\nfunction readBridgeValue(source, keys) {\n for (const key of keys) {\n const value = source?.[key];\n if (typeof value === \"string\" && value) {\n return value;\n }\n if (typeof value === \"function\") {\n try {\n const result = value.call(source);\n if (typeof result === \"string\" && result) {\n return result;\n }\n } catch {\n }\n }\n }\n return void 0;\n}\nfunction readBridgeBoolean(source, keys) {\n for (const key of keys) {\n const value = source?.[key];\n const normalized = normalizeBoolean(value);\n if (normalized != null) {\n return normalized;\n }\n if (typeof value === \"function\") {\n try {\n const result = normalizeBoolean(value.call(source));\n if (result != null) {\n return result;\n }\n } catch {\n }\n }\n }\n return void 0;\n}\nfunction readStoredDeviceId() {\n for (const key of DEVICE_ID_STORAGE_KEYS) {\n const value = readStoredString(key);\n if (value) {\n return value;\n }\n }\n return void 0;\n}\nfunction readStoredString(key) {\n if (typeof window === \"undefined\") {\n return void 0;\n }\n try {\n const value = window.localStorage?.getItem(key);\n return value || void 0;\n } catch {\n return void 0;\n }\n}\nfunction readStoredLimitAdTracking() {\n return normalizeBoolean(\n readStoredString(\"limitAdTracking\") || readStoredString(\"limitedAdTracking\") || readStoredString(\"is_lat\")\n );\n}\nfunction normalizeBoolean(value) {\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"number\") {\n return value === 1;\n }\n if (typeof value === \"string\") {\n const normalized = value.toLowerCase();\n if (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\") {\n return true;\n }\n if (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n return false;\n }\n }\n return void 0;\n}\n\n// src/utils/vastMacros.ts\nvar UNEXPANDED_MACRO_PATTERN = /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/;\nvar INVALID_VAST_PARAM_KEY = /^\\s|\\s$/;\nvar EXAMPLE_COM_URL = /example\\.com/i;\nvar CTV_UNSUPPORTED_PARAMS = [\n \"description_url\",\n \"tfcd\",\n \"npa\",\n \"min_ad_duration\",\n \"max_ad_duration\",\n \"unviewed_position_start\",\n \"impl\",\n \"scor\",\n \"vad_type\",\n \"gdpr\",\n \"gdpr_consent\",\n \"us_privacy\"\n];\nvar INLINE_DEVICE_MACRO_REPLACEMENTS = [\n { pattern: /\\[RDID\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[IFA\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[ADVERTISING[_-]?ID(?:ENTIFIER)?\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[DEVICE[_-]?ID\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[IDTYPE\\]/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /\\{rdid\\}/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\{device[_-]?id\\}/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\{idtype\\}/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi, getValue: (ctx) => ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0 },\n { pattern: /%%ADVERTISING_ID_TYPE%%/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /%%ADVERTISING_ID%%/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /%%LIMIT_AD_TRACKING%%/gi, getValue: (ctx) => ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0 },\n { pattern: /%%MSID%%/gi, getValue: (ctx) => ctx.appId },\n { pattern: /%%APP_NAME%%/gi, getValue: (ctx) => ctx.appName },\n { pattern: /%%SESSION_ID%%/gi, getValue: (ctx) => ctx.sessionId },\n { pattern: /%%CORRELATOR%%/gi, getValue: (ctx) => ctx.correlator }\n];\nfunction isMacroPlaceholder(value) {\n if (value == null) return true;\n const trimmed = value.trim();\n if (!trimmed) return true;\n if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;\n return /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(trimmed);\n}\nfunction generateCorrelator() {\n if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n try {\n const buf = new Uint32Array(2);\n crypto.getRandomValues(buf);\n const value = (buf[0] ?? 0) * 2097152 + ((buf[1] ?? 0) & 2097151);\n if (value > 0) {\n return String(value);\n }\n } catch {\n }\n }\n return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);\n}\nfunction expandInlineMacroPlaceholders(baseUrl, ctx) {\n let url = baseUrl;\n for (const { pattern, getValue } of INLINE_DEVICE_MACRO_REPLACEMENTS) {\n const value = getValue(ctx);\n if (value != null && value !== \"\") {\n url = url.replace(pattern, encodeURIComponent(value));\n }\n }\n return url;\n}\nfunction applyDeviceIdentityParams(params, ctx) {\n const runtimeId = ctx.deviceId?.trim();\n const runtimeType = ctx.deviceIdType?.trim() || inferDeviceIdType();\n const tagRdid = params.get(\"rdid\");\n const tagType = params.get(\"idtype\");\n const tagLat = params.get(\"is_lat\");\n const latValue = ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0;\n if (runtimeId) {\n params.set(\"rdid\", runtimeId);\n params.set(\"idtype\", runtimeType || tagType || \"aaid\");\n params.set(\"is_lat\", latValue ?? (isMacroPlaceholder(tagLat) ? \"0\" : tagLat));\n return;\n }\n const tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));\n const tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));\n if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {\n params.delete(\"rdid\");\n params.delete(\"idtype\");\n params.delete(\"is_lat\");\n return;\n }\n if (tagRdidValid) {\n if (isMacroPlaceholder(tagType) && runtimeType) {\n params.set(\"idtype\", runtimeType);\n }\n if (isMacroPlaceholder(tagLat)) {\n params.set(\"is_lat\", latValue ?? \"0\");\n }\n return;\n }\n params.delete(\"rdid\");\n params.delete(\"idtype\");\n params.delete(\"is_lat\");\n}\nfunction removeBrokenAppNameOrphans(params, appName) {\n const toDelete = [];\n params.forEach((_value, key) => {\n if (!key || INVALID_VAST_PARAM_KEY.test(key)) {\n toDelete.push(key);\n }\n });\n if (appName && appName.includes(\"&\")) {\n for (const suffix of appName.split(\"&\").slice(1)) {\n const trimmed = suffix.trimStart();\n if (!trimmed) continue;\n toDelete.push(suffix, ` ${trimmed}`, trimmed);\n }\n }\n for (const key of new Set(toDelete)) {\n if (key) params.delete(key);\n }\n}\nfunction normalizeVastTagUrl(raw) {\n if (!raw) return raw;\n try {\n const url = new URL(raw);\n const anValue = url.searchParams.get(\"an\");\n if (anValue !== null) {\n const orphanFragments = [];\n url.searchParams.forEach((_value, key) => {\n if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n orphanFragments.push(key.trim());\n }\n });\n if (orphanFragments.length > 0) {\n const reconstructed = [anValue.trimEnd(), ...orphanFragments].filter(Boolean).join(\" & \");\n url.searchParams.forEach((_value, key) => {\n if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n url.searchParams.delete(key);\n }\n });\n url.searchParams.set(\"an\", reconstructed);\n return url.toString().replace(\n /([?&]an=)([^&]*)/,\n (_match, prefix, val) => prefix + val.replace(/\\+/g, \"%20\")\n );\n }\n }\n removeBrokenAppNameOrphans(url.searchParams);\n return url.toString();\n } catch {\n return raw;\n }\n}\nfunction applyVastMacros(baseUrl, ctx) {\n const expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);\n let url;\n try {\n url = new URL(normalizeVastTagUrl(expandedUrl));\n } catch {\n return replaceCorrelatorFallback(expandedUrl, ctx.correlator);\n }\n const params = url.searchParams;\n removeBrokenAppNameOrphans(params, ctx.appName);\n params.set(\"correlator\", ctx.correlator);\n if (ctx.isCtv) {\n for (const key of CTV_UNSUPPORTED_PARAMS) {\n params.delete(key);\n }\n } else {\n params.set(\"scor\", ctx.streamCorrelator);\n }\n if (ctx.pod != null) {\n params.set(\"pod\", String(ctx.pod));\n }\n if (ctx.adPosition != null) {\n params.set(\"ppos\", String(ctx.adPosition));\n }\n const requestUrl = ctx.contentUrl || ctx.pageUrl;\n if (requestUrl) {\n params.set(\"url\", requestUrl);\n if (!ctx.isCtv) {\n params.set(\"description_url\", requestUrl);\n }\n } else {\n const existingUrl = params.get(\"url\") || \"\";\n if (EXAMPLE_COM_URL.test(existingUrl)) {\n params.delete(\"url\");\n params.delete(\"description_url\");\n }\n }\n if (ctx.adWillPlayMuted != null) {\n params.set(\"vpmute\", ctx.adWillPlayMuted ? \"1\" : \"0\");\n }\n if (ctx.adWillAutoPlay != null) {\n params.set(\"vpa\", ctx.adWillAutoPlay ? \"auto\" : \"click\");\n }\n if (ctx.appId) {\n params.set(\"msid\", ctx.appId);\n }\n if (ctx.appName) {\n removeBrokenAppNameOrphans(params, ctx.appName);\n params.set(\"an\", ctx.appName);\n }\n if (ctx.sessionId) {\n params.set(\"sid\", ctx.sessionId);\n }\n if (ctx.deviceTypeHint != null) {\n params.set(\"dth\", String(ctx.deviceTypeHint));\n } else if (ctx.isCtv) {\n params.set(\"dth\", \"5\");\n }\n applyDeviceIdentityParams(params, ctx);\n if (!ctx.isCtv) {\n const consent = ctx.consent;\n if (consent?.gdpr != null) {\n params.set(\"gdpr\", consent.gdpr);\n }\n if (consent?.gdprConsent != null) {\n params.set(\"gdpr_consent\", consent.gdprConsent);\n }\n if (consent?.usPrivacy != null) {\n params.set(\"us_privacy\", consent.usPrivacy);\n }\n }\n if (ctx.adTest) {\n params.set(\"adtest\", \"on\");\n }\n const staleKeys = [];\n params.forEach((value, key) => {\n if (isMacroPlaceholder(value)) {\n staleKeys.push(key);\n }\n });\n for (const key of staleKeys) {\n params.delete(key);\n }\n removeBrokenAppNameOrphans(params, ctx.appName);\n return url.toString();\n}\nfunction replaceCorrelatorFallback(baseUrl, correlator) {\n const correlatorRegex = /([?&])correlator=([^&]*)/;\n if (correlatorRegex.test(baseUrl)) {\n return baseUrl.replace(correlatorRegex, `$1correlator=${correlator}`);\n }\n const sep = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${sep}correlator=${correlator}`;\n}\nfunction fetchConsentSignals(timeoutMs = 1500) {\n const signals = {};\n if (typeof window === \"undefined\") {\n return Promise.resolve(signals);\n }\n const tasks = [];\n const tcfApi = window.__tcfapi;\n if (typeof tcfApi === \"function\") {\n tasks.push(\n new Promise((resolve) => {\n let settled = false;\n try {\n tcfApi(\"addEventListener\", 2, (tcData, success) => {\n if (settled) return;\n if (success && tcData && (tcData.eventStatus === \"tcloaded\" || tcData.eventStatus === \"useractioncomplete\")) {\n settled = true;\n signals.gdpr = tcData.gdprApplies ? \"1\" : \"0\";\n if (typeof tcData.tcString === \"string\" && tcData.tcString) {\n signals.gdprConsent = tcData.tcString;\n }\n try {\n tcfApi(\"removeEventListener\", 2, () => {\n }, tcData.listenerId);\n } catch {\n }\n resolve();\n }\n });\n } catch {\n resolve();\n }\n setTimeout(() => {\n if (!settled) {\n settled = true;\n resolve();\n }\n }, timeoutMs);\n })\n );\n }\n const uspApi = window.__uspapi;\n if (typeof uspApi === \"function\") {\n tasks.push(\n new Promise((resolve) => {\n try {\n uspApi(\"getUSPData\", 1, (data, success) => {\n if (success && typeof data?.uspString === \"string\" && data.uspString) {\n signals.usPrivacy = data.uspString;\n }\n resolve();\n });\n } catch {\n resolve();\n }\n setTimeout(resolve, timeoutMs);\n })\n );\n }\n if (tasks.length === 0) {\n return Promise.resolve(signals);\n }\n return Promise.all(tasks).then(() => signals);\n}\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 supportsModernJS = true;\n let webOSVersion;\n let tizenVersion;\n let chromeVersionNum;\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n chromeVersionNum = chromeVersion > 0 ? chromeVersion : void 0;\n if (/Web0S|webOS|LG Browser|LGSTB/i.test(ua)) {\n name = \"LG WebOS\";\n isSmartTV = true;\n let match = ua.match(/Web0S[/\\s]*([\\d.]+)/i) || ua.match(/webOS[/\\s]*([\\d.]+)/i);\n if (!match || !match[1]) {\n match = ua.match(/webOSTV[/\\s-]*([\\d.]+)/i) || ua.match(/webOS\\.TV[/\\s-]*([\\d.]+)/i);\n }\n if (match && match[1]) {\n version = match[1];\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n webOSVersion = majorVersion;\n } else if (chromeVersion > 0) {\n if (chromeVersion >= 79) {\n webOSVersion = 6;\n version = \"6.0\";\n majorVersion = 6;\n } else if (chromeVersion >= 68) {\n webOSVersion = 5;\n version = \"5.0\";\n majorVersion = 5;\n } else if (chromeVersion >= 53) {\n webOSVersion = 4;\n version = \"4.0\";\n majorVersion = 4;\n } else if (chromeVersion >= 38) {\n webOSVersion = 3;\n version = \"3.0\";\n majorVersion = 3;\n } else {\n webOSVersion = 2;\n version = \"2.0\";\n majorVersion = 2;\n }\n } else {\n version = \"Unknown\";\n webOSVersion = void 0;\n }\n isLegacyTV = webOSVersion !== void 0 && webOSVersion < 3;\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 tizenVersion = majorVersion;\n }\n isLegacyTV = tizenVersion !== void 0 && tizenVersion < 3;\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\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 isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\n } else {\n if (chromeVersion > 0) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n if (chromeVersion < 50) {\n supportsModernJS = false;\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n }\n if (typeof URLSearchParams === \"undefined\") {\n supportsModernJS = false;\n }\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsModernJS,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum\n };\n}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\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 supportsModernJS: browser.supportsModernJS,\n ...browser.webOSVersion !== void 0 ? { webOSVersion: browser.webOSVersion } : {},\n ...browser.tizenVersion !== void 0 ? { tizenVersion: browser.tizenVersion } : {},\n ...browser.chromeVersion !== void 0 ? { chromeVersion: browser.chromeVersion } : {},\n userAgent: navigator.userAgent\n });\n}\n\n// src/player/Scte35Parser.ts\nfunction 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}\nfunction parseCueOutCont(value) {\n const res = {};\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\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)) {\n const slashMatch = value.match(/([0-9.]+)\\s*\\/\\s*([0-9.]+)/);\n if (slashMatch && slashMatch[1] && slashMatch[2]) {\n const elapsed = parseFloat(slashMatch[1]);\n const duration = parseFloat(slashMatch[2]);\n if (!Number.isNaN(elapsed) && !(\"elapsed\" in res)) res.elapsed = elapsed;\n if (!Number.isNaN(duration) && !(\"duration\" in res)) res.duration = duration;\n }\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return void 0;\n}\nfunction 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}\nfunction 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}\nfunction 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}\nfunction 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}\nfunction getFragmentStartSeconds(frag) {\n const candidates = [frag?.start, frag?.startPTS];\n for (const candidate of candidates) {\n if (typeof candidate === \"number\" && Number.isFinite(candidate)) {\n return candidate;\n }\n }\n return void 0;\n}\nfunction parseScte35FromId3(tag) {\n const text = 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 = 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 = 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 = 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 = 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 = parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n}\nfunction normalizeFragmentPayload(payload) {\n if (payload instanceof Uint8Array) {\n return payload;\n }\n if (payload instanceof ArrayBuffer) {\n return new Uint8Array(payload);\n }\n if (ArrayBuffer.isView(payload)) {\n const view = payload;\n return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n }\n return void 0;\n}\nfunction detectTsPacketFormat(data) {\n const packetSizes = [188, 192, 204];\n for (const packetSize of packetSizes) {\n const tsPayloadOffset = packetSize === 192 ? 4 : 0;\n for (let offset = 0; offset < packetSize; offset++) {\n let matchedPackets = 0;\n for (let packetStart = offset; packetStart + tsPayloadOffset < data.length && matchedPackets < 5; packetStart += packetSize) {\n if (data[packetStart + tsPayloadOffset] !== 71) {\n break;\n }\n matchedPackets++;\n }\n if (matchedPackets >= 2) {\n return { offset, packetSize, tsPayloadOffset };\n }\n }\n }\n return void 0;\n}\nfunction getPsiSectionStart(payload, payloadUnitStart) {\n if (!payloadUnitStart) {\n return void 0;\n }\n const pointerField = payload[0];\n if (pointerField == null) {\n return void 0;\n }\n const sectionStart = 1 + pointerField;\n return sectionStart < payload.length ? sectionStart : void 0;\n}\nfunction getPsiSectionLength(data, offset) {\n return ((data[offset + 1] ?? 0) & 15) << 8 | (data[offset + 2] ?? 0);\n}\nfunction parsePatSection(payload, payloadUnitStart, pmtPids) {\n const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n if (sectionStart == null || sectionStart + 8 >= payload.length) {\n return;\n }\n if (payload[sectionStart] !== 0) {\n return;\n }\n const sectionLength = getPsiSectionLength(payload, sectionStart);\n const sectionEnd = Math.min(\n payload.length,\n sectionStart + 3 + sectionLength\n );\n for (let offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4) {\n const programNumber = (payload[offset] ?? 0) << 8 | (payload[offset + 1] ?? 0);\n const pid = ((payload[offset + 2] ?? 0) & 31) << 8 | (payload[offset + 3] ?? 0);\n if (programNumber !== 0) {\n pmtPids.add(pid);\n }\n }\n}\nfunction descriptorsIdentifyScte35(data, start, end) {\n let offset = start;\n while (offset + 2 <= end) {\n const tag = data[offset] ?? 0;\n const length = data[offset + 1] ?? 0;\n const descriptorStart = offset + 2;\n const descriptorEnd = descriptorStart + length;\n if (descriptorEnd > end) {\n return false;\n }\n const registration = length >= 4 ? String.fromCharCode(\n data[descriptorStart] ?? 0,\n data[descriptorStart + 1] ?? 0,\n data[descriptorStart + 2] ?? 0,\n data[descriptorStart + 3] ?? 0\n ) : \"\";\n if (tag === 138 || registration === \"CUEI\" || registration === \"SCTE\") {\n return true;\n }\n offset = descriptorEnd;\n }\n return false;\n}\nfunction parsePmtSection(payload, payloadUnitStart, tsScte35Pids) {\n const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n if (sectionStart == null || sectionStart + 12 >= payload.length) {\n return;\n }\n if (payload[sectionStart] !== 2) {\n return;\n }\n const sectionLength = getPsiSectionLength(payload, sectionStart);\n const sectionEnd = Math.min(\n payload.length,\n sectionStart + 3 + sectionLength\n );\n const programInfoLength = ((payload[sectionStart + 10] ?? 0) & 15) << 8 | (payload[sectionStart + 11] ?? 0);\n let offset = sectionStart + 12 + programInfoLength;\n while (offset + 5 <= sectionEnd - 4) {\n const streamType = payload[offset] ?? 0;\n const elementaryPid = ((payload[offset + 1] ?? 0) & 31) << 8 | (payload[offset + 2] ?? 0);\n const esInfoLength = ((payload[offset + 3] ?? 0) & 15) << 8 | (payload[offset + 4] ?? 0);\n const descriptorStart = offset + 5;\n const descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);\n if (streamType === 134 || streamType === 6 && descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd)) {\n tsScte35Pids.add(elementaryPid);\n }\n offset = descriptorStart + esInfoLength;\n }\n}\nfunction hasProcessedTsScte35Section(section, processedSections) {\n let checksum = 0;\n for (let i = 0; i < section.length; i++) {\n checksum = checksum * 31 + (section[i] ?? 0) >>> 0;\n }\n const key = `${section.length}:${checksum}`;\n if (processedSections.has(key)) {\n return true;\n }\n processedSections.add(key);\n if (processedSections.size > 200) {\n const firstKey = processedSections.values().next().value;\n if (firstKey) {\n processedSections.delete(firstKey);\n }\n }\n return false;\n}\nfunction addScte35SectionMarker(section, markers, processedSections) {\n if (section[0] !== 252 || hasProcessedTsScte35Section(section, processedSections)) {\n return;\n }\n const marker = parseScte35Binary(section);\n if (!marker) {\n return;\n }\n marker.raw = {\n ...typeof marker.raw === \"object\" && marker.raw ? marker.raw : {},\n source: \"ts-packet\"\n };\n markers.push(marker);\n}\nfunction appendScte35Bytes(pid, bytes, assemblers, markers, processedSections) {\n const assembler = assemblers.get(pid);\n if (!assembler) {\n return;\n }\n for (let i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++) {\n assembler.bytes.push(bytes[i] ?? 0);\n }\n if (assembler.bytes.length >= assembler.expectedLength) {\n assemblers.delete(pid);\n addScte35SectionMarker(new Uint8Array(assembler.bytes), markers, processedSections);\n }\n}\nfunction collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, assemblers, markers, processedSections) {\n if (payload.length === 0) {\n return;\n }\n let offset = 0;\n if (payloadUnitStart) {\n const pointerField = payload[0] ?? 0;\n const previousAssembler = assemblers.get(pid);\n if (previousAssembler && pointerField > 0) {\n appendScte35Bytes(\n pid,\n payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n assemblers,\n markers,\n processedSections\n );\n }\n assemblers.delete(pid);\n offset = 1 + pointerField;\n } else {\n appendScte35Bytes(pid, payload, assemblers, markers, processedSections);\n return;\n }\n while (offset + 3 <= payload.length) {\n const tableId = payload[offset];\n if (tableId == null || tableId === 255) {\n return;\n }\n const sectionLength = getPsiSectionLength(payload, offset);\n const totalLength = 3 + sectionLength;\n if (sectionLength <= 0 || totalLength <= 3) {\n return;\n }\n if (offset + totalLength <= payload.length) {\n addScte35SectionMarker(\n payload.subarray(offset, offset + totalLength),\n markers,\n processedSections\n );\n offset += totalLength;\n } else {\n assemblers.set(pid, {\n bytes: Array.from(payload.subarray(offset)),\n expectedLength: totalLength\n });\n return;\n }\n }\n}\nfunction parseScte35FromTsPackets(data, tsScte35Pids, pmtPids, processedSections) {\n const packetInfo = detectTsPacketFormat(data);\n if (!packetInfo) {\n return [];\n }\n const markers = [];\n const sectionAssemblers = /* @__PURE__ */ new Map();\n for (let packetStart = packetInfo.offset; packetStart + packetInfo.packetSize <= data.length; packetStart += packetInfo.packetSize) {\n const tsStart = packetStart + packetInfo.tsPayloadOffset;\n if (data[tsStart] !== 71) {\n continue;\n }\n const secondByte = data[tsStart + 1];\n const thirdByte = data[tsStart + 2];\n const fourthByte = data[tsStart + 3];\n if (secondByte == null || thirdByte == null || fourthByte == null || (secondByte & 128) !== 0) {\n continue;\n }\n const payloadUnitStart = (secondByte & 64) !== 0;\n const pid = (secondByte & 31) << 8 | thirdByte;\n const adaptationFieldControl = fourthByte >> 4 & 3;\n const hasPayload = adaptationFieldControl === 1 || adaptationFieldControl === 3;\n if (!hasPayload) {\n continue;\n }\n let payloadStart = tsStart + 4;\n if (adaptationFieldControl === 3) {\n const adaptationLength = data[payloadStart];\n if (adaptationLength == null) {\n continue;\n }\n payloadStart += 1 + adaptationLength;\n }\n const payloadEnd = Math.min(tsStart + 188, data.length);\n if (payloadStart >= payloadEnd || payloadStart >= data.length) {\n continue;\n }\n const payload = data.subarray(payloadStart, payloadEnd);\n if (pid === 0) {\n parsePatSection(payload, payloadUnitStart, pmtPids);\n } else if (pmtPids.has(pid)) {\n parsePmtSection(payload, payloadUnitStart, tsScte35Pids);\n } else if (tsScte35Pids.has(pid)) {\n collectScte35SectionsFromPayload(\n pid,\n payload,\n payloadUnitStart,\n sectionAssemblers,\n markers,\n processedSections\n );\n }\n }\n return markers;\n}\nvar BitReader = class {\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 get bytePosition() {\n return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n }\n};\nfunction readSpliceTime(r, ptsAdjustmentTicks) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (!timeSpecifiedFlag) {\n r.readBits(7);\n return void 0;\n }\n r.readBits(6);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const ptsTicks = (high * 4294967296 + low + ptsAdjustmentTicks) % 8589934592;\n return ptsTicks / 9e4;\n}\nfunction markerTypeFromSegmentationTypeId(segmentationTypeId) {\n switch (segmentationTypeId) {\n case 16:\n case 34:\n case 48:\n case 50:\n case 52:\n case 54:\n return \"start\";\n case 17:\n case 35:\n case 49:\n case 51:\n case 53:\n case 55:\n return \"end\";\n default:\n return void 0;\n }\n}\nfunction parseScte35SegmentationDescriptor(descriptor) {\n if (descriptor.length < 11) {\n return void 0;\n }\n const identifier = String.fromCharCode(\n descriptor[0] ?? 0,\n descriptor[1] ?? 0,\n descriptor[2] ?? 0,\n descriptor[3] ?? 0\n );\n if (identifier !== \"CUEI\") {\n return void 0;\n }\n const segmentationEventId = (descriptor[4] ?? 0) * 16777216 + ((descriptor[5] ?? 0) << 16) + ((descriptor[6] ?? 0) << 8) + (descriptor[7] ?? 0);\n const cancelIndicator = ((descriptor[8] ?? 0) & 128) !== 0;\n if (cancelIndicator) {\n return void 0;\n }\n const flags = descriptor[9] ?? 0;\n const programSegmentationFlag = (flags & 128) !== 0;\n const segmentationDurationFlag = (flags & 64) !== 0;\n let offset = 10;\n if (!programSegmentationFlag) {\n const componentCount = descriptor[offset] ?? 0;\n offset += 1 + componentCount * 6;\n if (offset > descriptor.length) {\n return void 0;\n }\n }\n let durationSeconds = void 0;\n if (segmentationDurationFlag) {\n if (offset + 5 > descriptor.length) {\n return void 0;\n }\n const durationTicks = (descriptor[offset] ?? 0) * 4294967296 + (descriptor[offset + 1] ?? 0) * 16777216 + ((descriptor[offset + 2] ?? 0) << 16) + ((descriptor[offset + 3] ?? 0) << 8) + (descriptor[offset + 4] ?? 0);\n durationSeconds = durationTicks / 9e4;\n offset += 5;\n }\n if (offset + 2 > descriptor.length) {\n return void 0;\n }\n offset += 1;\n const segmentationUpidLength = descriptor[offset] ?? 0;\n offset += 1 + segmentationUpidLength;\n if (offset >= descriptor.length) {\n return void 0;\n }\n const segmentationTypeId = descriptor[offset] ?? 0;\n const markerType = markerTypeFromSegmentationTypeId(segmentationTypeId);\n if (!markerType) {\n return void 0;\n }\n return {\n type: markerType,\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n segmentationEventId\n };\n}\nfunction parseScte35SegmentationDescriptors(data, offset) {\n if (offset + 2 > data.length) {\n return void 0;\n }\n const descriptorLoopLength = (data[offset] ?? 0) << 8 | (data[offset + 1] ?? 0);\n let descriptorOffset = offset + 2;\n const descriptorEnd = Math.min(\n data.length,\n descriptorOffset + descriptorLoopLength\n );\n while (descriptorOffset + 2 <= descriptorEnd) {\n const descriptorTag = data[descriptorOffset] ?? 0;\n const descriptorLength = data[descriptorOffset + 1] ?? 0;\n const descriptorDataStart = descriptorOffset + 2;\n const descriptorDataEnd = descriptorDataStart + descriptorLength;\n if (descriptorDataEnd > descriptorEnd) {\n return void 0;\n }\n if (descriptorTag === 2) {\n const descriptorMarker = parseScte35SegmentationDescriptor(\n data.subarray(descriptorDataStart, descriptorDataEnd)\n );\n if (descriptorMarker) {\n return descriptorMarker;\n }\n }\n descriptorOffset = descriptorDataEnd;\n }\n return void 0;\n}\nfunction parseScte35Binary(data) {\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 if (sectionLength <= 0 || data.length < 3 + sectionLength) {\n return void 0;\n }\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 const ptsAdjustmentTicks = ptsAdjHigh * 4294967296 + ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n let markerType;\n let durationSeconds = void 0;\n let ptsSeconds = void 0;\n let spliceEventId = void 0;\n const commandBodyStart = r.bytePosition;\n if (spliceCommandType === 5) {\n spliceEventId = 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 markerType = outOfNetwork ? \"start\" : \"end\";\n if (programSpliceFlag && !spliceImmediateFlag) {\n ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\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 componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n if (ptsSeconds === void 0) {\n ptsSeconds = componentPtsSeconds;\n }\n }\n }\n }\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 } else if (spliceCommandType === 6) {\n ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n } else {\n return void 0;\n }\n const expectedDescriptorOffset = spliceCommandLength === 4095 ? r.bytePosition : commandBodyStart + spliceCommandLength;\n const descriptorMarker = parseScte35SegmentationDescriptors(\n data,\n expectedDescriptorOffset\n );\n if (descriptorMarker) {\n markerType = descriptorMarker.type;\n if (durationSeconds === void 0) {\n durationSeconds = descriptorMarker.durationSeconds;\n }\n }\n if (!markerType) {\n return void 0;\n }\n const marker = {\n type: markerType,\n ...ptsSeconds !== void 0 ? { ptsSeconds } : {},\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: {\n splice_command_type: spliceCommandType,\n ...spliceEventId !== void 0 ? { splice_event_id: spliceEventId } : {},\n ...descriptorMarker?.segmentationEventId !== void 0 ? { segmentation_event_id: descriptorMarker.segmentationEventId } : {}\n }\n };\n return marker;\n}\n\n// src/player/Scte35CueManager.ts\nvar Scte35CueManager = class {\n constructor(debug, callbacks) {\n this.pendingScte35Cues = /* @__PURE__ */ new Map();\n this.recentScte35CueKeys = /* @__PURE__ */ new Map();\n this.recentScte35CueLimit = 200;\n this.tsScte35Pids = /* @__PURE__ */ new Set();\n this.pmtPids = /* @__PURE__ */ new Set();\n this.processedTsScte35Sections = /* @__PURE__ */ new Set();\n this.debug = debug;\n this.callbacks = callbacks;\n }\n get pendingScte35CueKey() {\n return this.pendingScte35CueKeyValue;\n }\n set pendingScte35CueKey(value) {\n this.pendingScte35CueKeyValue = value;\n }\n get activeScte35BreakKey() {\n return this.activeScte35BreakKeyValue;\n }\n set activeScte35BreakKey(value) {\n this.activeScte35BreakKeyValue = value;\n }\n get scheduledScte35BreakKey() {\n return this.scheduledScte35BreakKeyValue;\n }\n set scheduledScte35BreakKey(value) {\n this.scheduledScte35BreakKeyValue = value;\n }\n createScte35CueContext(source, readiness, frag) {\n const context = { source, readiness };\n if (typeof frag?.sn === \"number\") {\n context.fragmentSn = frag.sn;\n }\n const fragmentStartSec = getFragmentStartSeconds(frag);\n if (fragmentStartSec !== void 0) {\n context.fragmentStartSeconds = fragmentStartSec;\n }\n return context;\n }\n onScte35Cue(marker, context) {\n const cue = this.createScte35Cue(marker, context);\n const pendingKey = this.getPendingScte35CueKey(cue);\n if (context.readiness === \"early\") {\n this.pendingScte35Cues.set(pendingKey, cue);\n this.trimRecentScte35CueMaps();\n if (marker.type === \"start\") {\n this.callbacks.onEarlyStartCue(marker, context.fragmentSn, cue.key);\n }\n return;\n }\n if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n key: cue.key,\n activeScte35BreakKey: this.activeScte35BreakKeyValue,\n inAdBreak: this.callbacks.isInAdBreak(),\n source: cue.source\n });\n }\n return;\n }\n if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue\", {\n key: cue.key,\n source: cue.source\n });\n }\n return;\n }\n this.pendingScte35Cues.delete(pendingKey);\n this.markScte35CueHandled(cue);\n this.callbacks.onPlaybackCue(marker, cue.key);\n }\n activatePendingScte35CuesForFragment(frag) {\n const fragmentSn = typeof frag?.sn === \"number\" ? frag.sn : void 0;\n if (fragmentSn === void 0) {\n return;\n }\n const matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(\n ([, cue]) => cue.fragmentSn === fragmentSn\n );\n matchingCues.forEach(([pendingKey, cue]) => {\n this.pendingScte35Cues.delete(pendingKey);\n const context = {\n source: cue.source,\n readiness: \"playback\"\n };\n context.fragmentSn = fragmentSn;\n const fragmentStartSec = cue.fragmentStartSeconds ?? getFragmentStartSeconds(frag);\n if (fragmentStartSec !== void 0) {\n context.fragmentStartSeconds = fragmentStartSec;\n }\n this.onScte35Cue(cue.marker, context);\n });\n }\n createScte35Cue(marker, context) {\n const cue = {\n marker,\n source: context.source,\n readiness: context.readiness,\n key: this.getScte35CueKey(marker, context)\n };\n if (context.fragmentSn !== void 0) {\n cue.fragmentSn = context.fragmentSn;\n }\n if (context.fragmentStartSeconds !== void 0) {\n cue.fragmentStartSeconds = context.fragmentStartSeconds;\n }\n return cue;\n }\n getScte35CueKey(marker, context) {\n const raw = this.getScte35MarkerRaw(marker);\n const spliceEventId = this.toIdentityString(raw?.splice_event_id);\n if (spliceEventId) {\n return `splice:${spliceEventId}`;\n }\n const segmentationEventId = this.toIdentityString(raw?.segmentation_event_id);\n if (segmentationEventId) {\n return `segmentation:${segmentationEventId}`;\n }\n const daterangeId = this.toIdentityString(raw?.attrs?.ID);\n if (daterangeId) {\n return `daterange:${daterangeId}`;\n }\n const scteValue = this.toIdentityString(raw?.attrs?.[\"SCTE35-OUT\"]) || this.toIdentityString(raw?.attrs?.[\"SCTE35-IN\"]);\n if (scteValue) {\n return `daterange-scte:${scteValue}`;\n }\n if (typeof marker.ptsSeconds === \"number\" && Number.isFinite(marker.ptsSeconds)) {\n return `pts:${Math.round(marker.ptsSeconds * 2) / 2}`;\n }\n if (context.fragmentSn !== void 0) {\n return `fragment:${context.fragmentSn}`;\n }\n return `${context.source}:wallclock:${Math.floor(Date.now() / 1e3)}`;\n }\n getPendingScte35CueKey(cue) {\n return `${cue.marker.type}:${cue.key}:${cue.fragmentSn !== void 0 ? cue.fragmentSn : \"unknown\"}`;\n }\n getScte35MarkerRaw(marker) {\n return typeof marker.raw === \"object\" && marker.raw !== null ? marker.raw : {};\n }\n toIdentityString(value) {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value);\n }\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n return void 0;\n }\n isStrongScte35CueKey(key) {\n return !!(key && (key.startsWith(\"splice:\") || key.startsWith(\"segmentation:\") || key.startsWith(\"daterange:\") || key.startsWith(\"daterange-scte:\")));\n }\n hasRecentlyHandledScte35Cue(cue) {\n if (this.activeScte35BreakKeyValue === cue.key || this.scheduledScte35BreakKeyValue === cue.key) {\n return true;\n }\n const recentKey = `${cue.marker.type}:${cue.key}`;\n return this.recentScte35CueKeys.has(recentKey);\n }\n markScte35CueHandled(cue) {\n this.recentScte35CueKeys.set(`${cue.marker.type}:${cue.key}`, Date.now());\n this.trimRecentScte35CueMaps();\n }\n trimRecentScte35CueMaps() {\n while (this.recentScte35CueKeys.size > this.recentScte35CueLimit) {\n const firstKey = this.recentScte35CueKeys.keys().next().value;\n if (!firstKey) {\n break;\n }\n this.recentScte35CueKeys.delete(firstKey);\n }\n while (this.pendingScte35Cues.size > this.recentScte35CueLimit) {\n const firstKey = this.pendingScte35Cues.keys().next().value;\n if (!firstKey) {\n break;\n }\n this.pendingScte35Cues.delete(firstKey);\n }\n }\n shouldAcceptScte35EndCue(cue) {\n if (!this.callbacks.isInAdBreak()) {\n return false;\n }\n if (this.isStrongScte35CueKey(this.activeScte35BreakKeyValue) && this.isStrongScte35CueKey(cue.key) && this.activeScte35BreakKeyValue !== cue.key) {\n return false;\n }\n return true;\n }\n};\n\n// src/player/AdConfigManager.ts\nvar AdConfigManager = class {\n constructor(config, video) {\n this.vmapBreaks = [];\n this.consumedVmapBreakIds = /* @__PURE__ */ new Set();\n this.streamCorrelator = generateCorrelator();\n this.consentSignals = {};\n this.podCounter = 0;\n this.podAssignedByPrefetch = false;\n this.adRequestPositionInBreak = 0;\n this.lastHeartbeatTime = 0;\n this.config = config;\n this.video = video;\n }\n get debug() {\n return !!this.config.debugAdTiming;\n }\n isVmapEnabled() {\n return !!(this.config.isVmap && this.config.vmapUrl?.trim());\n }\n async fetchAdConfiguration() {\n if (this.isVmapEnabled()) {\n await this.fetchAndParseVmap(this.config.vmapUrl);\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] VMAP mode enabled\");\n }\n return;\n }\n const vastMode = this.config.vastMode || \"default\";\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.debug) {\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.debug) {\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 = normalizeVastTagUrl(this.config.vastTagUrl);\n if (this.debug) {\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.debug) {\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.debug) {\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 let decodedPayload = imaPayload;\n try {\n decodedPayload = decodeURIComponent(imaPayload);\n } catch {\n console.warn(\"[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:\", imaPayload);\n }\n console.log(\"[StormcloudVideoPlayer] Raw VAST tag URL (from API):\", decodedPayload);\n this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);\n if (this.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Normalized VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.debug) {\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.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n async fetchAndParseVmap(vmapUrl) {\n if (!vmapUrl.trim()) {\n return;\n }\n try {\n const response = await fetch(vmapUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VMAP (${response.status})`);\n }\n const vmapXml = await response.text();\n this.vmapBreaks = this.parseVmapToBreaks(vmapXml);\n this.consumedVmapBreakIds.clear();\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Loaded ${this.vmapBreaks.length} VMAP ad break(s) from:`,\n vmapUrl\n );\n }\n } catch (error) {\n this.vmapBreaks = [];\n this.consumedVmapBreakIds.clear();\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Failed to load VMAP:\", error);\n }\n }\n }\n parseVmapToBreaks(vmapXml) {\n if (typeof DOMParser === \"undefined\") {\n return [];\n }\n const doc = new DOMParser().parseFromString(vmapXml, \"application/xml\");\n if (doc.querySelector(\"parsererror\")) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n }\n return [];\n }\n const VMAP_NS = \"http://www.iab.net/videosuite/vmap\";\n let adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, \"AdBreak\"));\n if (adBreakNodes.length === 0) {\n adBreakNodes = Array.from(\n doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\n );\n }\n if (adBreakNodes.length === 0) {\n adBreakNodes = Array.from(doc.getElementsByTagName(\"*\")).filter(\n (el) => el.localName === \"AdBreak\"\n );\n }\n const parsed = [];\n adBreakNodes.forEach((node, index) => {\n const timeOffsetRaw = (node.getAttribute(\"timeOffset\") || \"\").trim();\n const startTimeMs = this.parseVmapTimeOffsetToMs(timeOffsetRaw);\n if (startTimeMs == null) {\n return;\n }\n let adTagNode = node.getElementsByTagNameNS(VMAP_NS, \"AdTagURI\")[0];\n if (!adTagNode) {\n adTagNode = node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\") ?? void 0;\n }\n const adTagUrl = (adTagNode?.textContent || \"\").trim();\n if (!adTagUrl) {\n return;\n }\n const breakId = node.getAttribute(\"breakId\") || `vmap-break-${index}-${timeOffsetRaw || \"unknown\"}`;\n parsed.push({\n id: breakId,\n startTimeMs,\n vastTagUrl: adTagUrl\n });\n });\n parsed.sort((a, b) => {\n const aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;\n const bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;\n return aStart - bStart;\n });\n return parsed;\n }\n parseVmapTimeOffsetToMs(timeOffset) {\n if (!timeOffset) {\n return void 0;\n }\n const normalized = timeOffset.trim().toLowerCase();\n if (normalized === \"start\") {\n return 0;\n }\n if (normalized === \"end\") {\n return -1;\n }\n const hms = timeOffset.match(\n /^(\\d{1,2}):(\\d{2}):(\\d{2})(?:\\.(\\d{1,3}))?$/\n );\n if (hms) {\n const [, hh, mm, ss, ms = \"0\"] = hms;\n const hours = Number(hh);\n const minutes = Number(mm);\n const seconds = Number(ss);\n const millis = Number(ms.padEnd(3, \"0\").slice(0, 3));\n return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;\n }\n const percent = timeOffset.match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (percent) {\n const ratio = Number(percent[1]) / 100;\n const durationSec = this.video.duration;\n if (Number.isFinite(durationSec) && durationSec > 0) {\n return Math.floor(durationSec * 1e3 * ratio);\n }\n return void 0;\n }\n return void 0;\n }\n getAdBreakKey(adBreak) {\n if (adBreak.id) {\n return adBreak.id;\n }\n return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n }\n resolveBreakStartMs(adBreak) {\n if (adBreak.startTimeMs >= 0) {\n return adBreak.startTimeMs;\n }\n if (adBreak.startTimeMs === -1) {\n const durationSec = this.video.duration;\n if (Number.isFinite(durationSec) && durationSec > 0) {\n return Math.floor(durationSec * 1e3);\n }\n }\n return void 0;\n }\n findCurrentOrNextBreak(nowMs) {\n const schedule = this.vmapBreaks;\n let candidate;\n const tol = this.config.driftToleranceMs ?? 1e3;\n for (const b of schedule) {\n if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n continue;\n }\n const breakStartMs = this.resolveBreakStartMs(b);\n if (breakStartMs == null) {\n continue;\n }\n if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))) {\n candidate = b;\n }\n }\n return candidate;\n }\n findBreakForTime(nowMs) {\n const schedule = this.vmapBreaks;\n for (const b of schedule) {\n if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n continue;\n }\n const breakStartMs = this.resolveBreakStartMs(b);\n if (breakStartMs == null) {\n continue;\n }\n if (b.durationMs) {\n const end = breakStartMs + b.durationMs;\n if (nowMs >= breakStartMs && nowMs < end) {\n return b;\n }\n continue;\n }\n if (nowMs >= breakStartMs) {\n return b;\n }\n }\n return void 0;\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 beginNewAdPod() {\n this.podCounter++;\n this.adRequestPositionInBreak = 0;\n }\n generateVastUrlsWithCorrelators(baseUrl, count, adPlayer, palNonce, inAdBreak) {\n const urls = [];\n for (let i = 0; i < count; i++) {\n this.adRequestPositionInBreak++;\n const adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;\n const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n const urlWithMacros = applyVastMacros(baseUrl, {\n correlator: generateCorrelator(),\n streamCorrelator: this.streamCorrelator,\n pod: this.podCounter > 0 ? this.podCounter : void 0,\n adPosition: this.adRequestPositionInBreak,\n isCtv: envSignals.isCtv,\n contentUrl: envSignals.contentUrl,\n pageUrl: !envSignals.isCtv && typeof window !== \"undefined\" ? window.location.href : void 0,\n adWillPlayMuted,\n adWillAutoPlay: !!this.config.autoplay,\n appId: envSignals.appId,\n appName: envSignals.appName,\n sessionId: envSignals.sessionId,\n deviceId: envSignals.deviceId,\n deviceIdType: envSignals.deviceIdType,\n limitAdTracking: envSignals.limitAdTracking,\n deviceTypeHint: envSignals.deviceTypeHint,\n adTest: this.config.adTest,\n consent: this.consentSignals\n });\n const finalUrl = palNonce.injectNonce(urlWithMacros);\n console.log(\n `[StormcloudVideoPlayer] Resolved ad request URL (pod=${this.podCounter}, pos=${this.adRequestPositionInBreak}):`,\n finalUrl\n );\n urls.push(finalUrl);\n }\n return urls;\n }\n // --- Tracking ---\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.debug) {\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.debug) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n destroyTracking() {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = void 0;\n }\n }\n};\n\n// src/player/AdTimingService.ts\nvar AdTimingService = class {\n constructor(config, video, callbacks) {\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.ptsDriftEmaMs = 0;\n this.adBreakPlayedDurationMs = 0;\n this.adBreakEpoch = 0;\n this.adRequestTokenCounter = 0;\n this.activeAdRequestToken = null;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.totalAdRequestsInBreak = 0;\n this.maxTotalAdRequestsPerBreak = 10;\n this.lastAdRequestTime = 0;\n this.consecutiveFailures = 0;\n this.maxConsecutiveFailures = 5;\n this.minAdRequestIntervalMs = 3e3;\n this.backoffBaseMs = 1e3;\n this.maxBackoffMs = 15e3;\n this.defaultMinRemainingMsToStartAd = 4e3;\n this.failedVastUrls = /* @__PURE__ */ new Set();\n this.temporaryFailureUrls = /* @__PURE__ */ new Map();\n this.temporaryFailureCooldownMs = 3e4;\n this.globalConsecutiveNoFills = 0;\n this.globalNoFillThreshold = 3;\n this.globalNoFillCooldownUntil = 0;\n this.globalNoFillBackoffBaseMs = 5e3;\n this.globalNoFillBackoffMaxMs = 6e4;\n this.globalLastGamRequestTime = 0;\n this.globalMinGamIntervalMs = 3e3;\n this.config = config;\n this.video = video;\n this.callbacks = callbacks;\n }\n get debug() {\n return !!this.config.debugAdTiming;\n }\n // --- Ad stop timer ---\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 this.adStopTimerId = void 0;\n this.callbacks.onAdStopTimerFired();\n }\n // --- Ad start timer ---\n scheduleAdStartIn(delayMs, marker = { type: \"start\" }, cueKey) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.callbacks.onAdStartTimerFired(marker, cueKey);\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.callbacks.onAdStartTimerFired(marker, cueKey);\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\n // --- PTS drift ---\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 resolveScteBreakStartWallClockMs(marker) {\n const nowWallClockMs = Date.now();\n if (typeof marker.ptsSeconds !== \"number\") {\n return nowWallClockMs;\n }\n const nowMs = this.video.currentTime * 1e3;\n const estimatedCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = marker.ptsSeconds * 1e3 - estimatedCurrentPtsMs;\n if (!Number.isFinite(deltaMs)) {\n return nowWallClockMs;\n }\n return nowWallClockMs + Math.floor(deltaMs);\n }\n // --- Duration boundary ---\n setAdBreakDurationBoundary(durationMs) {\n this.expectedAdBreakDurationMs = durationMs;\n if (durationMs != null && this.currentAdBreakStartWallClockMs != null) {\n this.scteAdBreakEndWallClockMs = this.currentAdBreakStartWallClockMs + durationMs;\n } else {\n this.scteAdBreakEndWallClockMs = void 0;\n }\n }\n scheduleAdStopAtBreakBoundary() {\n if (this.expectedAdBreakDurationMs == null) {\n return;\n }\n this.scheduleAdStopCountdown(this.getWallClockRemainingAdMs());\n }\n // --- Duration budget ---\n getWallClockRemainingAdMs() {\n const endWallClockMs = this.getAdBreakEndWallClockMs();\n if (endWallClockMs != null) {\n return Math.max(0, endWallClockMs - Date.now());\n }\n return 0;\n }\n getAdBreakEndWallClockMs() {\n if (this.scteAdBreakEndWallClockMs != null) {\n return this.scteAdBreakEndWallClockMs;\n }\n if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null) {\n return void 0;\n }\n return this.currentAdBreakStartWallClockMs + this.expectedAdBreakDurationMs;\n }\n getDurationBudgetRemainingMs() {\n if (this.expectedAdBreakDurationMs == null) {\n return 0;\n }\n return Math.max(0, this.expectedAdBreakDurationMs - this.adBreakPlayedDurationMs);\n }\n getLoadedAdDurationMs(adController) {\n const durationSec = adController.getLoadedAdDuration?.();\n if (durationSec == null || durationSec <= 0) {\n return 0;\n }\n return Math.round(durationSec * 1e3);\n }\n adFitsRemainingBudget(durationMs) {\n if (durationMs <= 0) {\n return true;\n }\n return durationMs <= this.getDurationBudgetRemainingMs();\n }\n logAdDurationDecision(accepted, durationMs, adController) {\n if (!this.debug) {\n return;\n }\n const remainingBudget = this.getDurationBudgetRemainingMs();\n const adId = adController.getLoadedAdId?.() ?? \"unknown\";\n if (accepted) {\n console.log(\n `[AD-DURATION] Accepted ad id=${adId}, duration=${durationMs}ms, budget remaining after play=${Math.max(0, remainingBudget - durationMs)}ms`\n );\n } else {\n console.log(\n `[AD-DURATION] Rejected ad id=${adId}, duration=${durationMs}ms exceeds remaining budget=${remainingBudget}ms \\u2014 requesting another ad`\n );\n }\n }\n recordPlayedAdDuration(adController) {\n const durationMs = this.getLoadedAdDurationMs(adController);\n if (durationMs <= 0) {\n return;\n }\n this.adBreakPlayedDurationMs += durationMs;\n if (this.debug) {\n console.log(\n `[AD-DURATION] Played ${durationMs}ms \\u2014 total played=${this.adBreakPlayedDurationMs}ms / ${this.expectedAdBreakDurationMs ?? \"?\"}ms`\n );\n }\n }\n ensureLoadedAdFitsBudget(adController) {\n const durationMs = this.getLoadedAdDurationMs(adController);\n const fits = this.adFitsRemainingBudget(durationMs);\n this.logAdDurationDecision(fits, durationMs, adController);\n return fits;\n }\n rejectLoadedAdForDuration(adController) {\n try {\n adController.destroy();\n } catch {\n }\n }\n markAdStarted() {\n this.currentAdIndex++;\n this.totalAdsInBreak = this.currentAdIndex;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n }\n getRemainingAdMs() {\n const wallClockRemaining = this.getWallClockRemainingAdMs();\n const budgetRemaining = this.getDurationBudgetRemainingMs();\n if (this.expectedAdBreakDurationMs == null) {\n return wallClockRemaining;\n }\n return Math.min(wallClockRemaining, budgetRemaining);\n }\n getMinRemainingMsToStartAd() {\n const configured = this.config.minRemainingMsToStartAd;\n if (typeof configured === \"number\" && configured >= 0) {\n return configured;\n }\n return this.defaultMinRemainingMsToStartAd;\n }\n hasTimeToStartAnotherAd() {\n const minRemaining = this.getMinRemainingMsToStartAd();\n return this.getWallClockRemainingAdMs() > minRemaining && this.getDurationBudgetRemainingMs() > minRemaining;\n }\n // --- Circuit breaker ---\n isTemporaryAdError(error) {\n const message = error?.message?.toLowerCase() || \"\";\n if (message.includes(\"no ads available\") || message.includes(\"no fill\") || message.includes(\"nofill\")) {\n return true;\n }\n if (message.includes(\"timeout\")) {\n return true;\n }\n if (message.includes(\"rate limit\") || message.includes(\"too many requests\")) {\n return true;\n }\n if (message.includes(\"ad playback error\")) {\n return true;\n }\n return false;\n }\n isUrlInCooldown(vastTagUrl) {\n const failureTime = this.temporaryFailureUrls.get(vastTagUrl);\n if (failureTime == null) {\n return false;\n }\n const elapsed = Date.now() - failureTime;\n if (elapsed >= this.temporaryFailureCooldownMs) {\n this.temporaryFailureUrls.delete(vastTagUrl);\n return false;\n }\n return true;\n }\n cleanupTemporaryFailures() {\n const now = Date.now();\n for (const [url, timestamp] of this.temporaryFailureUrls) {\n if (now - timestamp >= this.temporaryFailureCooldownMs) {\n this.temporaryFailureUrls.delete(url);\n }\n }\n }\n isGamInCooldown() {\n return Date.now() < this.globalNoFillCooldownUntil;\n }\n recordGamNoFill() {\n this.globalConsecutiveNoFills++;\n if (this.globalConsecutiveNoFills >= this.globalNoFillThreshold) {\n const exponent = this.globalConsecutiveNoFills - this.globalNoFillThreshold;\n const backoff = Math.min(\n this.globalNoFillBackoffBaseMs * Math.pow(2, exponent),\n this.globalNoFillBackoffMaxMs\n );\n this.globalNoFillCooldownUntil = Date.now() + backoff;\n if (this.debug) {\n console.log(\n `[CIRCUIT-BREAKER] GAM cooldown activated: ${backoff}ms (${this.globalConsecutiveNoFills} consecutive no-fills)`\n );\n }\n }\n }\n resetGamNoFillCounter() {\n if (this.globalConsecutiveNoFills > 0 && this.debug) {\n console.log(\n `[CIRCUIT-BREAKER] Resetting no-fill counter (was ${this.globalConsecutiveNoFills})`\n );\n }\n this.globalConsecutiveNoFills = 0;\n this.globalNoFillCooldownUntil = 0;\n }\n async enforceGlobalRateLimit() {\n const now = Date.now();\n const elapsed = now - this.globalLastGamRequestTime;\n if (elapsed < this.globalMinGamIntervalMs) {\n const waitMs = this.globalMinGamIntervalMs - elapsed;\n if (this.debug) {\n console.log(`[RATE-LIMIT] Waiting ${waitMs}ms before next GAM request`);\n }\n await new Promise((resolve) => setTimeout(resolve, waitMs));\n }\n this.globalLastGamRequestTime = Date.now();\n }\n // --- Watchdog ---\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.callbacks.onWatchdogTimeout();\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 // --- Failsafe ---\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 });\n this.callbacks.onFailsafeTimeout();\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 logAdState(event, extra = {}, adPlayer, inAdBreak, showAds) {\n if (!this.debug) {\n return;\n }\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n showAds: showAds ?? false,\n adPlaying: adPlayer?.isAdPlaying() ?? false,\n inAdBreak: inAdBreak ?? false,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n // --- Reset for ad break end ---\n resetForBreakEnd() {\n this.clearAdStopTimer();\n this.clearAdStartTimer();\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.scteAdBreakEndWallClockMs = void 0;\n this.adBreakPlayedDurationMs = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.consecutiveFailures = 0;\n this.globalConsecutiveNoFills = 0;\n this.adBreakEpoch++;\n }\n destroy() {\n this.clearAdStopTimer();\n this.clearAdStartTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n }\n};\n\n// src/player/AdPreloadPool.ts\nvar AdPreloadPool = class {\n constructor(deps) {\n this.pool = [];\n this.maxPoolSize = 2;\n this.poolActive = false;\n this.loopRunning = false;\n this.deps = deps;\n }\n get active() {\n return this.poolActive;\n }\n set active(value) {\n this.poolActive = value;\n }\n get isLoopRunning() {\n return this.loopRunning;\n }\n startPreloadPool(baseVastUrl, initialUrls, startLoopImmediately = true) {\n if (this.poolActive) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n }\n return;\n }\n this.poolActive = true;\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Starting preload pool EARLY (target size: ${this.maxPoolSize})`);\n console.log(`[PRELOAD-POOL] Ad break hasn't started yet, but preloading ads in advance`);\n }\n for (const url of initialUrls) {\n if (this.pool.length < this.maxPoolSize) {\n this.preloadAdIntoPool(url);\n }\n }\n if (startLoopImmediately) {\n this.preloadPoolLoop(baseVastUrl);\n } else if (this.deps.debug) {\n console.log(\n \"[PRELOAD-POOL] Pre-break mode: preloaded once, waiting for SCTE start to continue fetching\"\n );\n }\n }\n async preloadAdIntoPool(vastUrl) {\n const timing = this.deps.timing;\n if (timing.isGamInCooldown()) {\n if (this.deps.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n }\n return;\n }\n if (this.pool.some((entry) => entry.vastUrl === vastUrl) || timing.failedVastUrls.has(vastUrl) || timing.isUrlInCooldown(vastUrl)) {\n return;\n }\n if (this.pool.length >= this.maxPoolSize) {\n return;\n }\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Preloading ad into pool: ${vastUrl}`);\n }\n const epoch = timing.adBreakEpoch;\n const loadPromise = (async () => {\n let hasAdError = false;\n let adErrorPayload = null;\n let errorListenerCleanup = null;\n try {\n const continueLiveStreamDuringAds = this.deps.shouldContinueLiveStreamDuringAds();\n const preloadAd = this.deps.createAdPlayer(continueLiveStreamDuringAds);\n preloadAd.initialize();\n const errorListener = (payload) => {\n hasAdError = true;\n adErrorPayload = payload;\n };\n preloadAd.on(\"ad_error\", errorListener);\n errorListenerCleanup = () => preloadAd.off(\"ad_error\", errorListener);\n await timing.enforceGlobalRateLimit();\n await preloadAd.requestAds(vastUrl);\n preloadAd.pause();\n await new Promise((resolve) => setTimeout(resolve, 1500));\n preloadAd.pause();\n if (hasAdError) {\n const isNoFill = adErrorPayload?.isNoFill || adErrorPayload?.code === 303 || adErrorPayload?.vastErrorCode === 303;\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n preloadAd.destroy();\n timing.recordGamNoFill();\n if (isNoFill) {\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preload returned no-fill: ${vastUrl}`);\n }\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n } else {\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n }\n if (adErrorPayload && !timing.isTemporaryAdError(adErrorPayload)) {\n timing.failedVastUrls.add(vastUrl);\n } else {\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n return;\n }\n if (!this.poolActive || epoch !== timing.adBreakEpoch) {\n if (this.deps.debug) {\n console.log(\n \"[PRELOAD-POOL] Discarding preloaded ad - break ended during fetch\"\n );\n }\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n try {\n preloadAd.destroy();\n } catch {\n }\n return;\n }\n const poolEntry = {\n vastUrl,\n adController: preloadAd,\n loadedAt: Date.now(),\n isReady: true,\n loadPromise: Promise.resolve()\n };\n const loadedDuration = preloadAd.getLoadedAdDuration?.();\n if (loadedDuration != null && loadedDuration > 0) {\n poolEntry.durationSeconds = loadedDuration;\n }\n const lateErrorListener = (payload) => {\n const index = this.pool.findIndex((entry) => entry.vastUrl === vastUrl);\n if (index >= 0) {\n this.pool.splice(index, 1);\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Late error detected, removed from pool: ${vastUrl}`, payload);\n }\n try {\n preloadAd.destroy();\n } catch {\n }\n }\n };\n preloadAd.on(\"ad_error\", lateErrorListener);\n this.pool.push(poolEntry);\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preloaded (no errors detected within timeout) (pool size: ${this.pool.length}/${this.maxPoolSize}, duration=${poolEntry.durationSeconds ?? \"?\"}s)`);\n }\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n } catch (error) {\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n timing.recordGamNoFill();\n if (this.deps.debug) {\n console.warn(`[PRELOAD-POOL] Failed to preload ad: ${vastUrl}`, error);\n }\n if (error instanceof Error && !timing.isTemporaryAdError(error)) {\n timing.failedVastUrls.add(vastUrl);\n } else if (error instanceof Error && timing.isTemporaryAdError(error)) {\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n })();\n loadPromise.catch(() => {\n });\n }\n async preloadPoolLoop(baseVastUrl) {\n if (this.loopRunning) {\n return;\n }\n this.loopRunning = true;\n const epoch = this.deps.timing.adBreakEpoch;\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Starting continuous preload loop\");\n }\n while (this.poolActive && epoch === this.deps.timing.adBreakEpoch) {\n if (this.deps.timing.isGamInCooldown()) {\n if (this.deps.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n }\n break;\n }\n if (!this.deps.isInAdBreak() && this.pool.length >= this.maxPoolSize) {\n await new Promise((resolve) => setTimeout(resolve, 2e3));\n continue;\n }\n if (!this.deps.isInAdBreak() && this.deps.getPendingAdBreak() === null) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n }\n break;\n }\n while (this.pool.length < this.maxPoolSize) {\n if (!this.poolActive || epoch !== this.deps.timing.adBreakEpoch || this.deps.timing.isGamInCooldown()) {\n break;\n }\n if (this.deps.isInAdBreak() && !this.deps.timing.hasTimeToStartAnotherAd()) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Not enough ad break time left, stopping preload\");\n }\n break;\n }\n const newUrls = this.deps.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const newUrl = newUrls[0];\n if (newUrl && !this.deps.timing.failedVastUrls.has(newUrl) && !this.deps.timing.isUrlInCooldown(newUrl)) {\n await this.preloadAdIntoPool(newUrl);\n }\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n }\n await new Promise((resolve) => setTimeout(resolve, 2e3));\n }\n this.loopRunning = false;\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Preload loop ended\");\n }\n }\n getPreloadedAd() {\n if (this.pool.length === 0) {\n return null;\n }\n const entry = this.pool.shift();\n if (!entry || !entry.isReady) {\n return null;\n }\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Using preloaded ad from pool (${this.pool.length} remaining)`);\n }\n return {\n vastUrl: entry.vastUrl,\n adController: entry.adController\n };\n }\n stop() {\n this.poolActive = false;\n this.loopRunning = false;\n for (const entry of this.pool) {\n try {\n entry.adController.destroy();\n } catch (error) {\n if (this.deps.debug) {\n console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n }\n }\n }\n this.pool = [];\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Preload pool stopped and cleaned up\");\n }\n }\n};\n\n// src/player/PlaceholderLayer.ts\nvar PlaceholderLayer = class {\n constructor(video, debug) {\n this.video = video;\n this.debug = debug;\n }\n ensureContainer() {\n if (this.container) {\n return;\n }\n const el = document.createElement(\"div\");\n el.style.position = \"absolute\";\n el.style.left = \"0\";\n el.style.top = \"0\";\n el.style.right = \"0\";\n el.style.bottom = \"0\";\n el.style.display = \"none\";\n el.style.alignItems = \"center\";\n el.style.justifyContent = \"center\";\n el.style.pointerEvents = \"none\";\n el.style.zIndex = \"5\";\n el.style.backgroundColor = \"#000\";\n el.style.transition = \"opacity 0.3s ease-in-out\";\n el.style.opacity = \"0\";\n if (!this.video.parentElement) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n this.video.parentElement.appendChild(el);\n this.container = el;\n }\n show() {\n this.ensureContainer();\n if (!this.container) {\n return;\n }\n if (!this.video.muted) {\n this.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n const wasHidden = this.container.style.display === \"none\" || this.container.style.opacity === \"0\";\n if (wasHidden) {\n this.container.style.transition = \"none\";\n } else {\n this.container.style.transition = \"opacity 0.3s ease-in-out\";\n }\n this.container.style.backgroundColor = \"#000\";\n this.container.style.display = \"flex\";\n this.container.offsetHeight;\n this.container.style.opacity = \"1\";\n this.container.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.container) {\n this.container.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and ad layer)\");\n }\n }\n hide() {\n if (!this.container) {\n return;\n }\n this.container.style.opacity = \"0\";\n setTimeout(() => {\n if (this.container) {\n this.container.style.display = \"none\";\n this.container.style.pointerEvents = \"none\";\n this.container.style.backgroundColor = \"#000\";\n }\n }, 300);\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n destroy() {\n if (this.container) {\n if (this.container.parentElement) {\n this.container.parentElement.removeChild(this.container);\n }\n this.container = void 0;\n }\n }\n};\n\n// src/player/HlsEngine.ts\nvar import_hls2 = __toESM(require(\"hls.js\"), 1);\nvar HlsEngine = class {\n constructor(config, video, cueManager, timing, callbacks) {\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.config = config;\n this.video = video;\n this.cueManager = cueManager;\n this.timing = timing;\n this.callbacks = callbacks;\n }\n get debug() {\n return !!this.config.debugAdTiming;\n }\n shouldUseNativeHls(getStreamType) {\n const streamType = 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 async setupNativeHls() {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.isLiveStream ?? (this.config.lowLatencyMode ?? false);\n if (this.debug) {\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 if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n }\n setupHls() {\n this.hls = new import_hls2.default({\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(import_hls2.default.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, _data) => {\n this.isLiveStream = this.config.isLiveStream ?? (this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false);\n await this.callbacks.onManifestParsed(this.isLiveStream);\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.debug) {\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(import_hls2.default.Events.LEVEL_LOADED, (_evt, data) => {\n if (this.callbacks.isInAdBreak() || this.callbacks.hasPendingAdBreak()) {\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\") ? parseAttributeList(value) : {};\n const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") || \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n if (hasScteOut) {\n const durationSeconds = parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value, earlyDetection: true }\n };\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n }\n this.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"early\", frag)\n });\n return;\n }\n }\n }\n }\n });\n this.hls.on(import_hls2.default.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.debug) {\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.debug) {\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.debug) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n this.hls.on(import_hls2.default.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(import_hls2.default.Events.FRAG_LOADED, (_evt, data) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : void 0,\n getFragmentStartSeconds(data?.frag)\n );\n });\n this.hls.on(import_hls2.default.Events.FRAG_DECRYPTED, (_evt, data) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : void 0,\n getFragmentStartSeconds(data?.frag)\n );\n });\n this.hls.on(import_hls2.default.Events.FRAG_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) {\n this.callbacks.activatePendingCuesForFragment(frag);\n 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 if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = 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.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.callbacks.onScte35Cue(\n { type: \"end\", raw: { tag, value } },\n {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n }\n );\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = 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 = 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.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n }\n if (hasScteIn) {\n this.callbacks.onScte35Cue(\n { type: \"end\", raw: { tag, value, attrs } },\n {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n }\n );\n }\n }\n }\n this.callbacks.activatePendingCuesForFragment(frag);\n });\n this.hls.on(import_hls2.default.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case import_hls2.default.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case import_hls2.default.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.callbacks.onFatalDestroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.timing.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = parseScte35FromId3(tag);\n if (marker) {\n this.callbacks.onScte35Cue(marker, {\n source: \"id3\",\n readiness: \"playback\"\n });\n }\n }\n processFragmentScte35Payload(payloadData, fragmentSn, fragmentStartSeconds) {\n const payload = normalizeFragmentPayload(payloadData);\n if (!payload) {\n return;\n }\n const markers = parseScte35FromTsPackets(\n payload,\n this.cueManager.tsScte35Pids,\n this.cueManager.pmtPids,\n this.cueManager.processedTsScte35Sections\n );\n markers.forEach((marker) => {\n const context = {\n source: \"ts\",\n readiness: \"early\"\n };\n if (fragmentSn !== void 0) {\n context.fragmentSn = fragmentSn;\n }\n if (fragmentStartSeconds !== void 0) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n this.callbacks.onScte35Cue(marker, context);\n });\n }\n destroy() {\n this.hls?.destroy();\n this.hls = void 0;\n }\n};\n\n// src/player/PlayerControls.ts\nfunction getAdAudioVolume(adPlayer) {\n return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();\n}\nfunction toggleMute(video, adPlayer, debug) {\n if (adPlayer.isAdPlaying()) {\n const newMutedState = !adPlayer.getOriginalMutedState();\n const restoreVolume = adPlayer.getOriginalVolume() || 1;\n adPlayer.updateOriginalMutedState(newMutedState, video.volume);\n adPlayer.setAdVolume(newMutedState ? 0 : restoreVolume);\n if (debug) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n video.muted = !video.muted;\n adPlayer.updateOriginalMutedState(video.muted, video.volume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", video.muted);\n }\n }\n}\nfunction toggleFullscreen(video, debug) {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (debug) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document.exitFullscreen().then(() => {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (debug) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n}\nfunction isMuted(video, adPlayer) {\n if (adPlayer.isAdPlaying()) {\n return adPlayer.getOriginalMutedState();\n }\n return video.muted;\n}\nfunction setMuted(video, adPlayer, muted, debug) {\n const adPlaying = adPlayer.isAdPlaying();\n if (adPlaying && muted === video.muted) {\n if (debug) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n video.muted = muted;\n if (adPlaying) {\n adPlayer.updateOriginalMutedState(muted, video.volume);\n adPlayer.setAdVolume(muted ? 0 : 1);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted\n });\n }\n return;\n }\n adPlayer.updateOriginalMutedState(muted, video.volume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n}\nfunction setVolume(video, adPlayer, volume, debug) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = adPlayer.isAdPlaying();\n if (adPlaying) {\n adPlayer.setAdVolume(clampedVolume);\n adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume\n });\n }\n } else {\n video.volume = clampedVolume;\n video.muted = clampedVolume === 0;\n adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n}\nfunction getVolume(video, adPlayer) {\n const adPlaying = adPlayer.isAdPlaying();\n if (adPlaying) {\n return adPlayer.getAdVolume();\n }\n return video.volume;\n}\nfunction isFullscreen() {\n return !!document.fullscreenElement;\n}\nfunction resizePlayer(video, adPlayer, debug) {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n if (adPlayer && adPlayer.isAdPlaying()) {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 480;\n if (debug) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n adPlayer.resize(width, height);\n }\n}\n\n// src/player/AdBreakOrchestrator.ts\nvar AdBreakOrchestrator = class {\n constructor(host, timing, preloadPool, adConfig, cueManager, placeholder) {\n this.inAdBreak = false;\n this.showAds = false;\n this.isShowingPlaceholder = false;\n this.adDetectSentForCurrentBreak = false;\n this.continuousFetchingActive = false;\n this.continuousFetchLoopRunning = false;\n this.adRequestQueue = [];\n this.adPodQueue = [];\n this.maxPlaceholderDurationMs = 5e3;\n this.pendingAdBreak = null;\n this.host = host;\n this.timing = timing;\n this.preloadPool = preloadPool;\n this.adConfig = adConfig;\n this.cueManager = cueManager;\n this.placeholder = placeholder;\n }\n get debug() {\n return !!this.host.config.debugAdTiming;\n }\n // ───────────────────────────────────────────────────────────────\n // IMA event listeners\n // ───────────────────────────────────────────────────────────────\n attachImaEventListeners() {\n const adPlayer = this.host.getAdPlayer();\n adPlayer.on(\"all_ads_completed\", () => {\n sendAdImpressionTracking(\n this.host.config.licenseKey,\n { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n const remaining = this.timing.getRemainingAdMs();\n this.timing.consecutiveFailures = 0;\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.inAdBreak) {\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n adPlayer.on(\"ad_error\", (errorPayload) => {\n let errorMessage = \"Ad playback failed\";\n if (errorPayload) {\n const errorCode = errorPayload.code || errorPayload.errorCode || \"unknown\";\n const vastErrorCode = errorPayload.vastErrorCode;\n const message = errorPayload.message || errorPayload.errorMessage || \"Unknown error\";\n const cause = errorPayload.cause || errorPayload.innerError || errorPayload.error;\n errorMessage = `Ad error: AdError ${errorCode}: ${message}`;\n if (vastErrorCode && vastErrorCode !== \"N/A\" && vastErrorCode !== errorCode) {\n errorMessage += ` (VAST Error Code: ${vastErrorCode})`;\n }\n if (cause) {\n const causeMessage = typeof cause === \"string\" ? cause : cause.message || String(cause);\n errorMessage += `. Caused by: ${causeMessage}`;\n }\n }\n console.error(\"[AD-ERROR]\", errorMessage, errorPayload || \"\");\n this.handleAdFailure();\n });\n adPlayer.on(\"content_pause\", () => {\n this.timing.clearAdFailsafeTimer();\n this.timing.clearAdRequestWatchdog();\n this.timing.activeAdRequestToken = null;\n this.showAds = true;\n this.timing.resetGamNoFillCounter();\n if (this.inAdBreak && this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n this.host.getAdPlayer().setAdVolume(getAdAudioVolume(this.host.getAdPlayer()));\n if (this.isShowingPlaceholder) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.host.getAdPlayer().hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n adPlayer.on(\"content_resume\", () => {\n sendAdImpressionTracking(\n this.host.config.licenseKey,\n { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n if (!this.host.video.muted) {\n this.host.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n }\n }\n this.timing.clearAdFailsafeTimer();\n this.timing.clearAdRequestWatchdog();\n this.timing.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n return;\n }\n this.timing.consecutiveFailures = 0;\n this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n const remaining = this.timing.getRemainingAdMs();\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n });\n }\n recreateAdController() {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Recreating AdController for new ad\");\n }\n const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n const adPlayer = this.host.getAdPlayer();\n if (shouldShowPlaceholder && adPlayer) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old AdController\");\n }\n this.placeholder.show();\n adPlayer.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n const preservedMutedState = adPlayer.getOriginalMutedState();\n const preservedVolumeState = adPlayer.getOriginalVolume();\n if (adPlayer) {\n try {\n adPlayer.destroy();\n this.host.video.muted = true;\n } catch (error) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Error destroying old AdController:\", error);\n }\n }\n }\n const continueLiveStreamDuringAds = this.host.shouldContinueLiveStreamDuringAds();\n const newAdPlayer = this.host.createAdPlayer(continueLiveStreamDuringAds);\n this.host.setAdPlayer(newAdPlayer);\n newAdPlayer.initialize();\n newAdPlayer.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n this.attachImaEventListeners();\n if (shouldShowPlaceholder) {\n this.placeholder.show();\n newAdPlayer.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n }\n clearPendingAdBreak() {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = void 0;\n }\n this.pendingAdBreak = null;\n this.cueManager.pendingScte35CueKey = void 0;\n this.adConfig.podAssignedByPrefetch = false;\n }\n // ───────────────────────────────────────────────────────────────\n // Ad break start\n // ───────────────────────────────────────────────────────────────\n async handleAdStart(_marker) {\n const scheduled = this.adConfig.findCurrentOrNextBreak(\n this.host.video.currentTime * 1e3\n );\n if (scheduled) {\n this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));\n }\n const tags = this.adConfig.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.adConfig.apiVastTagUrl) {\n baseVastUrl = this.adConfig.apiVastTagUrl;\n } else {\n this.clearPendingAdBreak();\n return;\n }\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled?.durationMs;\n if (this.debug) {\n const mode = this.host.config.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n this.timing.failedVastUrls.clear();\n this.timing.temporaryFailureUrls.clear();\n this.timing.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.timing.totalAdRequestsInBreak = 0;\n if (this.adConfig.podAssignedByPrefetch) {\n this.adConfig.podAssignedByPrefetch = false;\n } else {\n this.adConfig.beginNewAdPod();\n }\n const currentMuted = this.host.video.muted;\n const currentVolume = this.host.video.volume;\n this.host.getAdPlayer().updateOriginalMutedState(currentMuted, currentVolume);\n this.inAdBreak = true;\n this.timing.adBreakPlayedDurationMs = 0;\n this.timing.currentAdIndex = 0;\n this.timing.totalAdsInBreak = 0;\n this.adPodQueue = [];\n this.showAds = false;\n if (this.timing.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.timing.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n let firstAdUrl;\n let usePreloadedAd = false;\n let preloadedController;\n const preloaded = this.preloadPool.getPreloadedAd();\n if (preloaded) {\n firstAdUrl = preloaded.vastUrl;\n preloadedController = preloaded.adController;\n usePreloadedAd = true;\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: firstAdUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n }\n } else if (this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0) {\n this.adRequestQueue = [...this.pendingAdBreak.vastUrls];\n firstAdUrl = this.adRequestQueue.shift();\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Pool empty, using prefetched URLs (${this.adRequestQueue.length + 1} available)`);\n }\n this.clearPendingAdBreak();\n } else {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Generating new ad URLs...\");\n }\n const firstAdUrlArray = this.host.generateVastUrls(baseVastUrl, 1);\n firstAdUrl = firstAdUrlArray[0];\n this.adRequestQueue = [];\n }\n if (!firstAdUrl) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Failed to get first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First VAST URL:\", firstAdUrl);\n }\n try {\n if (usePreloadedAd && preloadedController) {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedController)) {\n this.timing.rejectLoadedAdForDuration(preloadedController);\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n const adPlayer = this.host.getAdPlayer();\n const preservedMuted = adPlayer.getOriginalMutedState();\n const preservedVolume = adPlayer.getOriginalVolume();\n adPlayer.destroy();\n this.host.video.muted = true;\n this.host.setAdPlayer(preloadedController);\n preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n this.attachImaEventListeners();\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n }\n preloadedController.resume();\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPool.active) {\n this.preloadPool.active = true;\n }\n if (!this.preloadPool.isLoopRunning) {\n this.preloadPool.preloadPoolLoop(baseVastUrl);\n }\n await preloadedController.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n preloadedController.setAdVolume(adVolume);\n } else {\n const adPlayer = this.host.getAdPlayer();\n await this.timing.enforceGlobalRateLimit();\n this.timing.lastAdRequestTime = Date.now();\n await adPlayer.requestAds(firstAdUrl);\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: firstAdUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad request successful, starting playback\");\n }\n if (!this.timing.ensureLoadedAdFitsBudget(adPlayer)) {\n this.timing.rejectLoadedAdForDuration(adPlayer);\n this.recreateAdController();\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPool.active) {\n this.preloadPool.startPreloadPool(baseVastUrl, []);\n }\n await adPlayer.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n adPlayer.setAdVolume(adVolume);\n }\n } catch (error) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] First ad request failed:\", error);\n }\n if (!usePreloadedAd) {\n const fallbackPreloaded = this.preloadPool.getPreloadedAd();\n if (fallbackPreloaded) {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad failed, using preloaded fallback\");\n }\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(fallbackPreloaded.adController)) {\n this.timing.rejectLoadedAdForDuration(fallbackPreloaded.adController);\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n this.swapToPreloadedAdPlayer(fallbackPreloaded.adController);\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPool.active) {\n this.preloadPool.active = true;\n this.preloadPool.preloadPoolLoop(baseVastUrl);\n }\n const ap = this.host.getAdPlayer();\n await ap.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n ap.setAdVolume(adVolume);\n return;\n } catch (fallbackError) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n }\n if (this.timing.isTemporaryAdError(error)) {\n this.timing.temporaryFailureUrls.set(firstAdUrl, Date.now());\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n }\n } else {\n this.timing.failedVastUrls.add(firstAdUrl);\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n }\n }\n this.timing.consecutiveFailures++;\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n }\n }\n swapToPreloadedAdPlayer(preloadedController) {\n const adPlayer = this.host.getAdPlayer();\n const preservedMuted = adPlayer.getOriginalMutedState();\n const preservedVolume = adPlayer.getOriginalVolume();\n adPlayer.destroy();\n this.host.video.muted = true;\n this.host.setAdPlayer(preloadedController);\n this.attachImaEventListeners();\n preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n preloadedController.resume();\n }\n // ───────────────────────────────────────────────────────────────\n // Continuous fetching\n // ───────────────────────────────────────────────────────────────\n startContinuousFetching(baseVastUrl) {\n if (!this.continuousFetchingActive) {\n return;\n }\n if (this.continuousFetchLoopRunning) {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Fetch loop already running, skipping duplicate start\");\n }\n return;\n }\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Starting continuous ad fetching loop\");\n }\n this.continuousFetchLoopRunning = true;\n this.continuousFetchLoop(baseVastUrl);\n }\n async continuousFetchLoop(baseVastUrl) {\n const epoch = this.timing.adBreakEpoch;\n while (this.continuousFetchingActive && this.inAdBreak && epoch === this.timing.adBreakEpoch) {\n const remaining = Math.min(\n this.timing.getWallClockRemainingAdMs(),\n this.timing.getDurationBudgetRemainingMs()\n );\n if (remaining <= this.timing.getMinRemainingMsToStartAd()) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Not enough ad break time left (wall=${this.timing.getWallClockRemainingAdMs()}ms, budget=${this.timing.getDurationBudgetRemainingMs()}ms), stopping URL generation`);\n }\n break;\n }\n if (this.timing.isGamInCooldown()) {\n if (this.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n }\n break;\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), stopping URL generation`);\n }\n break;\n }\n if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Maximum ad requests reached (${this.timing.maxTotalAdRequestsPerBreak}), stopping`);\n }\n break;\n }\n const maxQueueSize = 5;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] URL queue full (${this.adRequestQueue.length}), waiting...`);\n }\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n continue;\n }\n const newAdUrl = this.host.generateVastUrls(baseVastUrl, 1)[0];\n if (!newAdUrl || this.timing.failedVastUrls.has(newAdUrl) || this.timing.isUrlInCooldown(newAdUrl)) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n continue;\n }\n if (this.debug) {\n const queuedUrlsPreview = [...this.adRequestQueue, newAdUrl];\n console.log(\n `[CONTINUOUS-FETCH] Queued VAST URL (queue size: ${queuedUrlsPreview.length})`,\n { queuedUrls: queuedUrlsPreview }\n );\n }\n this.adRequestQueue.push(newAdUrl);\n const generationDelay = this.timing.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, this.timing.consecutiveFailures), 5e3) : 500;\n await new Promise((resolve) => setTimeout(resolve, generationDelay));\n }\n this.continuousFetchLoopRunning = false;\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] URL generation loop ended (queued: ${this.adRequestQueue.length})`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n }\n stopContinuousFetching() {\n this.continuousFetchingActive = false;\n this.continuousFetchLoopRunning = false;\n this.placeholder.hide();\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Stopping continuous ad fetching\");\n }\n }\n // ───────────────────────────────────────────────────────────────\n // Ad iteration\n // ───────────────────────────────────────────────────────────────\n async tryNextAvailableAdWithRateLimit() {\n if (!this.inAdBreak) {\n return;\n }\n const epoch = this.timing.adBreakEpoch;\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n const backoffMultiplier = Math.pow(2, this.timing.consecutiveFailures);\n const backoffDelay = Math.min(this.timing.backoffBaseMs * backoffMultiplier, this.timing.maxBackoffMs);\n const effectiveMinInterval = this.timing.minAdRequestIntervalMs + (this.timing.consecutiveFailures > 0 ? backoffDelay : 0);\n const timeSinceLastRequest = Date.now() - this.timing.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.timing.consecutiveFailures} failures)`);\n }\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) {\n return;\n }\n return this.tryNextAvailableAd(0);\n }\n async tryNextAvailableAd(retryCount = 0) {\n if (!this.inAdBreak) {\n return;\n }\n const remaining = this.timing.getRemainingAdMs();\n if (!this.timing.hasTimeToStartAnotherAd()) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Not enough time remaining (${remaining}ms) to start another ad, ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.timing.isGamInCooldown()) {\n if (this.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n this.timing.cleanupTemporaryFailures();\n const preloaded = this.preloadPool.getPreloadedAd();\n if (preloaded) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Using preloaded ad from pool`);\n }\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: preloaded.vastUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloaded.adController)) {\n this.timing.rejectLoadedAdForDuration(preloaded.adController);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n this.swapToPreloadedAdPlayer(preloaded.adController);\n const ap = this.host.getAdPlayer();\n await ap.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n ap.setAdVolume(getAdAudioVolume(ap));\n this.timing.consecutiveFailures = 0;\n return;\n } catch (error) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Preloaded ad failed to play:\", error);\n }\n }\n }\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) continue;\n if (this.timing.failedVastUrls.has(nextAdUrl)) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping permanently-failed URL, trying next...\");\n continue;\n }\n if (this.timing.isUrlInCooldown(nextAdUrl)) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping URL in cooldown (recent no-fill), trying next...\");\n continue;\n }\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Requesting next ad via HLS ad player (${this.timing.currentAdIndex + 1}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n try {\n await this.playSingleAd(nextAdUrl);\n this.timing.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = error.message;\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad request failed:\", errorMessage);\n if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.timing.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n const maxRetries = 3;\n if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2e3) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Queue empty, waiting for URLs... (${retryCount + 1}/${maxRetries})`);\n }\n await new Promise((resolve) => setTimeout(resolve, 500));\n await this.tryNextAvailableAd(retryCount + 1);\n return;\n }\n if (!this.isShowingPlaceholder && remaining > 1e3) {\n this.showPlaceholderAndWaitForAds();\n } else {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] No more ads available, ending ad break\");\n this.handleAdPodComplete();\n }\n }\n // ───────────────────────────────────────────────────────────────\n // Single ad playback\n // ───────────────────────────────────────────────────────────────\n async playSingleAd(vastTagUrl) {\n const adPlayer = this.host.getAdPlayer();\n if (adPlayer.isAdPlaying()) return;\n if (this.timing.failedVastUrls.has(vastTagUrl)) {\n if (this.debug) console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n throw new Error(\"VAST URL permanently failed\");\n }\n if (this.timing.isUrlInCooldown(vastTagUrl)) {\n if (this.debug) console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n throw new Error(\"VAST URL in cooldown after no-fill\");\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n throw new Error(\"Too many consecutive failures\");\n }\n if (this.timing.isGamInCooldown()) {\n if (this.debug) console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n throw new Error(\"GAM in cooldown\");\n }\n this.recreateAdController();\n const requestToken = ++this.timing.adRequestTokenCounter;\n this.timing.activeAdRequestToken = requestToken;\n this.timing.startAdRequestWatchdog(requestToken);\n try {\n await this.timing.enforceGlobalRateLimit();\n this.timing.lastAdRequestTime = Date.now();\n const ap = this.host.getAdPlayer();\n await ap.requestAds(vastTagUrl);\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: vastTagUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n this.timing.clearAdRequestWatchdog();\n if (this.timing.activeAdRequestToken !== requestToken) return;\n if (!this.timing.ensureLoadedAdFitsBudget(ap)) {\n this.timing.rejectLoadedAdForDuration(ap);\n this.recreateAdController();\n throw new Error(\"ad_duration_exceeds_budget\");\n }\n try {\n this.timing.startAdFailsafeTimer(requestToken);\n await ap.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n ap.setAdVolume(getAdAudioVolume(ap));\n this.timing.consecutiveFailures = 0;\n this.timing.temporaryFailureUrls.delete(vastTagUrl);\n } catch (playError) {\n if (this.debug) console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n const preloadedFallback = this.preloadPool.getPreloadedAd();\n if (preloadedFallback) {\n if (this.debug) console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n throw playError;\n }\n this.timing.clearAdFailsafeTimer();\n this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n this.timing.consecutiveFailures = 0;\n const fbAp = this.host.getAdPlayer();\n await fbAp.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n fbAp.setAdVolume(getAdAudioVolume(fbAp));\n return;\n } catch (fallbackError) {\n if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n if (this.timing.isTemporaryAdError(playError)) {\n this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.debug) console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n } else {\n this.timing.failedVastUrls.add(vastTagUrl);\n if (this.debug) console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n }\n this.timing.clearAdFailsafeTimer();\n if (this.timing.activeAdRequestToken === requestToken) {\n this.timing.activeAdRequestToken = null;\n }\n throw playError;\n }\n } catch (error) {\n const errorMessage = error?.message || \"\";\n if (this.debug) console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n const preloadedFallback = this.preloadPool.getPreloadedAd();\n if (preloadedFallback) {\n if (this.debug) console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n throw error;\n }\n this.timing.clearAdRequestWatchdog();\n this.timing.clearAdFailsafeTimer();\n this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n this.timing.consecutiveFailures = 0;\n const fbAp = this.host.getAdPlayer();\n await fbAp.play();\n this.timing.markAdStarted();\n fbAp.setAdVolume(getAdAudioVolume(fbAp));\n return;\n } catch (fallbackError) {\n if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n if (this.timing.isTemporaryAdError(error)) {\n this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.debug) console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n } else {\n this.timing.failedVastUrls.add(vastTagUrl);\n if (this.debug) console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n }\n this.timing.clearAdRequestWatchdog();\n this.timing.clearAdFailsafeTimer();\n if (this.timing.activeAdRequestToken === requestToken) {\n this.timing.activeAdRequestToken = null;\n }\n throw error;\n }\n }\n // ───────────────────────────────────────────────────────────────\n // Placeholder wait\n // ───────────────────────────────────────────────────────────────\n async showPlaceholderAndWaitForAds() {\n const remaining = this.timing.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n if (this.timing.isGamInCooldown()) {\n if (this.debug) console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n this.handleAdPodComplete();\n return;\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping placeholder - too many consecutive failures\");\n this.handleAdPodComplete();\n return;\n }\n if (waitTime < 1e3) {\n this.handleAdPodComplete();\n return;\n }\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n }\n this.isShowingPlaceholder = true;\n this.host.getAdPlayer().showPlaceholder();\n const checkInterval = 300;\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) return;\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Too many failures during placeholder wait\");\n break;\n }\n if (!this.timing.hasTimeToStartAnotherAd()) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Not enough time remaining during placeholder wait, ending ad break\");\n break;\n }\n while (this.adRequestQueue.length > 0) {\n if (!this.timing.hasTimeToStartAnotherAd()) break;\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) continue;\n if (this.timing.failedVastUrls.has(nextAdUrl)) continue;\n if (this.timing.isUrlInCooldown(nextAdUrl)) continue;\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad URL available, requesting via HLS ad player\");\n this.isShowingPlaceholder = false;\n this.host.getAdPlayer().hidePlaceholder();\n try {\n await this.playSingleAd(nextAdUrl);\n this.timing.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = error.message;\n if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.timing.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n }\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Placeholder timeout, ending ad break\");\n this.isShowingPlaceholder = false;\n this.host.getAdPlayer().hidePlaceholder();\n this.handleAdPodComplete();\n }\n // ───────────────────────────────────────────────────────────────\n // Ad break completion\n // ───────────────────────────────────────────────────────────────\n handleAdPodComplete() {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ad pod complete - cleaning up\");\n }\n this.timing.resetForBreakEnd();\n this.stopContinuousFetching();\n this.preloadPool.stop();\n this.clearPendingAdBreak();\n if (this.isShowingPlaceholder) {\n this.host.getAdPlayer().hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n this.adRequestQueue = [];\n this.inAdBreak = false;\n this.adDetectSentForCurrentBreak = false;\n this.cueManager.activeScte35BreakKey = void 0;\n this.cueManager.scheduledScte35BreakKey = void 0;\n this.adPodQueue = [];\n this.showAds = false;\n this.host.getAdPlayer().stop().catch(() => {\n });\n const restoredMuted = this.host.getAdPlayer().getOriginalMutedState();\n const restoredVolume = this.host.getAdPlayer().getOriginalVolume();\n if (this.host.video.muted !== restoredMuted) {\n this.host.video.muted = restoredMuted;\n }\n if (Math.abs(this.host.video.volume - restoredVolume) > 0.01) {\n this.host.video.volume = restoredVolume;\n }\n if (this.host.shouldContinueLiveStreamDuringAds()) {\n if (this.host.video.paused) {\n if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n this.host.video.play()?.catch(() => {\n });\n } else {\n if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n } else if (this.host.video.paused) {\n this.host.video.play()?.catch(() => {\n });\n }\n }\n handleAdFailure() {\n this.timing.consecutiveFailures++;\n this.timing.recordGamNoFill();\n const remaining = this.timing.getRemainingAdMs();\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.timing.consecutiveFailures}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(`[CONTINUOUS-FETCH] Max consecutive failures reached (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n this.handleAdPodComplete();\n return;\n }\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n if (this.debug) console.log(\"[AD-ERROR] Ad failed and not enough time remaining for another ad. Failed URLs:\", this.timing.failedVastUrls.size);\n this.handleAdPodComplete();\n }\n }\n};\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.attached = false;\n this.palPlaybackStarted = false;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.adPlayer = this.createAdPlayer(false);\n this.palNonce = createPalNonceManager();\n this.cueManager = new Scte35CueManager(!!this.config.debugAdTiming, {\n onEarlyStartCue: (marker, fragmentSn, cueKey) => {\n this.startAdPrefetch(marker, fragmentSn, cueKey);\n },\n onPlaybackCue: (marker, cueKey) => {\n this.onScte35Marker(marker, cueKey);\n },\n isInAdBreak: () => this.adBreak.inAdBreak\n });\n this.adConfig = new AdConfigManager(this.config, this.video);\n this.timing = new AdTimingService(this.config, this.video, {\n onAdStopTimerFired: () => this.onAdStopTimerFired(),\n onAdStartTimerFired: (marker, cueKey) => {\n this.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.timing.expectedAdBreakDurationMs\n );\n },\n onWatchdogTimeout: () => this.adBreak.handleAdFailure(),\n onFailsafeTimeout: () => this.adBreak.handleAdFailure()\n });\n this.preloadPool = new AdPreloadPool({\n debug: !!this.config.debugAdTiming,\n createAdPlayer: (c) => this.createAdPlayer(c),\n shouldContinueLiveStreamDuringAds: () => this.shouldContinueLiveStreamDuringAds(),\n timing: this.timing,\n generateVastUrlsWithCorrelators: (base, count) => this.generateVastUrls(base, count),\n isInAdBreak: () => this.adBreak.inAdBreak,\n getPendingAdBreak: () => this.adBreak.pendingAdBreak\n });\n this.placeholder = new PlaceholderLayer(this.video, !!this.config.debugAdTiming);\n this.hlsEngine = new HlsEngine(this.config, this.video, this.cueManager, this.timing, {\n onManifestParsed: async (isLive) => this.onManifestParsed(isLive),\n onScte35Cue: (marker, context) => this.cueManager.onScte35Cue(marker, context),\n activatePendingCuesForFragment: (frag) => this.cueManager.activatePendingScte35CuesForFragment(frag),\n onFatalDestroy: () => this.destroy(),\n isInAdBreak: () => this.adBreak.inAdBreak,\n hasPendingAdBreak: () => this.adBreak.pendingAdBreak !== null\n });\n this.adBreak = new AdBreakOrchestrator(\n {\n config: this.config,\n video: this.video,\n getAdPlayer: () => this.adPlayer,\n setAdPlayer: (p) => {\n this.adPlayer = p;\n },\n createAdPlayer: (c) => this.createAdPlayer(c),\n shouldContinueLiveStreamDuringAds: () => this.shouldContinueLiveStreamDuringAds(),\n generateVastUrls: (base, count) => this.generateVastUrls(base, count)\n },\n this.timing,\n this.preloadPool,\n this.adConfig,\n this.cueManager,\n this.placeholder\n );\n }\n get debug() {\n return !!this.config.debugAdTiming;\n }\n createAdPlayer(continueLiveStreamDuringAds) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Creating HLS ad player\");\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},\n ...this.hlsEngine?.hls ? { mainHlsInstance: this.hlsEngine.hls } : {}\n });\n }\n generateVastUrls(baseUrl, count) {\n return this.adConfig.generateVastUrlsWithCorrelators(\n baseUrl,\n count,\n this.adPlayer,\n this.palNonce,\n this.adBreak.inAdBreak\n );\n }\n // ───────────────────────────────────────────────────────────────\n // Lifecycle\n // ───────────────────────────────────────────────────────────────\n async load() {\n if (!this.attached) {\n this.attach();\n }\n try {\n await this.adConfig.fetchAdConfiguration();\n } catch (error) {\n if (this.debug) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n this.palNonce.generateNonce({\n videoWidth: this.video.offsetWidth || this.video.clientWidth || 640,\n videoHeight: this.video.offsetHeight || this.video.clientHeight || 480,\n adWillAutoPlay: !!this.config.autoplay,\n adWillPlayMuted: true,\n playerVolume: 0,\n continuousPlayback: this.config.lowLatencyMode ?? false\n }).catch(() => {\n });\n fetchConsentSignals().then((signals) => {\n this.adConfig.consentSignals = signals;\n }).catch(() => {\n });\n this.adConfig.initializeTracking();\n if (this.hlsEngine.shouldUseNativeHls(() => this.getStreamType())) {\n this.adPlayer.destroy();\n this.adPlayer = this.createAdPlayer(false);\n this.adPlayer.initialize();\n await this.hlsEngine.setupNativeHls();\n return;\n }\n this.hlsEngine.setupHls();\n }\n async onManifestParsed(isLive) {\n if (!this.adConfig.isVmapEnabled() && !isLive && this.adConfig.vmapBreaks.length === 0 && this.adConfig.apiVastTagUrl) {\n const prerollKey = \"synthetic-vod-preroll\";\n if (!this.adConfig.consumedVmapBreakIds.has(prerollKey)) {\n this.adConfig.vmapBreaks = [\n { id: prerollKey, startTimeMs: 0, vastTagUrl: this.adConfig.apiVastTagUrl }\n ];\n if (this.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Injected synthetic VOD preroll from apiVastTagUrl\"\n );\n }\n }\n }\n if (this.debug) {\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,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior\n });\n }\n this.adPlayer.destroy();\n this.adPlayer = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.adPlayer.initialize();\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.adPlayer.initialize();\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.adBreak.attachImaEventListeners();\n this.video.addEventListener(\"play\", () => {\n if (!this.palPlaybackStarted && !this.adPlayer.isAdPlaying()) {\n this.palPlaybackStarted = true;\n this.palNonce.sendPlaybackStart();\n }\n });\n this.endedHandler = () => {\n if (this.palPlaybackStarted) {\n this.palPlaybackStarted = false;\n this.palNonce.sendPlaybackEnd();\n }\n this.onVideoEnded();\n };\n this.video.addEventListener(\"ended\", this.endedHandler);\n this.video.addEventListener(\"mousedown\", (e) => {\n this.palNonce.sendAdTouch(e);\n });\n this.video.addEventListener(\"touchstart\", (e) => {\n this.palNonce.sendAdTouch(e);\n });\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.hlsEngine.nativeHlsMode && this.hlsEngine.videoSrcProtection && !this.adPlayer.isAdPlaying()) {\n if (this.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.hlsEngine.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.hlsEngine.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 shouldContinueLiveStreamDuringAds() {\n if (this.config.allowNativeHls) return false;\n if (!this.hlsEngine.isLiveStream) return false;\n return true;\n }\n // ───────────────────────────────────────────────────────────────\n // SCTE-35 marker orchestration\n // ───────────────────────────────────────────────────────────────\n onScte35Marker(marker, cueKey) {\n if (this.debug) {\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 hasPendingAdBreak: !!this.adBreak.pendingAdBreak\n });\n }\n if (marker.type === \"start\") {\n if (this.adBreak.inAdBreak) {\n if (marker.durationSeconds != null) {\n const newDurationMs = marker.durationSeconds * 1e3;\n if (this.timing.expectedAdBreakDurationMs == null || newDurationMs > this.timing.expectedAdBreakDurationMs) {\n this.timing.setAdBreakDurationBoundary(newDurationMs);\n this.timing.scheduleAdStopAtBreakBoundary();\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${newDurationMs}ms, remaining: ${this.timing.getWallClockRemainingAdMs()}ms`\n );\n }\n }\n }\n return;\n }\n if (!this.adBreak.adDetectSentForCurrentBreak) {\n this.adBreak.adDetectSentForCurrentBreak = true;\n const detectPayload = {};\n if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;\n if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;\n sendAdDetectTracking(this.config.licenseKey, { source: \"scte35\", timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...detectPayload }).catch(() => {\n });\n }\n const hasPrefetchedAds = this.adBreak.pendingAdBreak && this.adBreak.pendingAdBreak.vastUrls.length > 0;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.adBreak.pendingAdBreak?.marker.durationSeconds != null ? this.adBreak.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;\n const isManifest = isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker: isManifest,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n hasPrefetchedAds\n });\n }\n if (isManifest && forceImmediate) {\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Starting ad immediately (manifest-based)${hasPrefetchedAds ? \" with prefetched ads\" : \"\"}`\n );\n }\n this.timing.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\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.timing.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.debug) {\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.debug) {\n console.log(`[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`);\n }\n this.timing.expectedAdBreakDurationMs = durationMs;\n this.cueManager.scheduledScte35BreakKey = cueKey;\n this.timing.scheduleAdStartIn(deltaMs, marker, cueKey);\n } else {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\");\n }\n this.timing.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n } else {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Starting ad immediately (fallback)\");\n }\n this.timing.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.adBreak.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.timing.setAdBreakDurationBoundary(marker.durationSeconds * 1e3);\n }\n this.timing.scheduleAdStopAtBreakBoundary();\n if (!this.adPlayer.isAdPlaying() && this.timing.activeAdRequestToken === null && this.adBreak.adRequestQueue.length > 0 && this.timing.hasTimeToStartAnotherAd()) {\n this.adBreak.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n const remaining = this.timing.getRemainingAdMs();\n const adPlaying = this.adPlayer.isAdPlaying();\n const hasQueuedAds = this.adBreak.adRequestQueue.length > 0;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.timing.activeAdRequestToken !== null\n });\n }\n this.timing.scteAdBreakEndWallClockMs = Date.now();\n this.timing.clearAdStartTimer();\n this.timing.clearAdStopTimer();\n if (adPlaying) {\n this.adPlayer.stop().catch(() => {\n });\n }\n this.adBreak.handleAdPodComplete();\n return;\n }\n }\n startScte35AdBreak(marker, cueKey, durationMs) {\n this.adBreak.inAdBreak = true;\n this.cueManager.activeScte35BreakKey = cueKey ?? this.cueManager.pendingScte35CueKey;\n this.cueManager.scheduledScte35BreakKey = void 0;\n this.timing.currentAdBreakStartWallClockMs = this.timing.resolveScteBreakStartWallClockMs(marker);\n this.timing.setAdBreakDurationBoundary(durationMs);\n this.adBreak.handleAdStart(marker);\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n onAdStopTimerFired() {\n if (!this.adBreak.inAdBreak) return;\n const adPlaying = this.adPlayer.isAdPlaying();\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 : 0;\n const endWallClockMs = this.timing.getAdBreakEndWallClockMs() ?? Date.now();\n const overrunMs = Math.max(0, Date.now() - endWallClockMs);\n const shouldExtendAdBreak = adPlaying && overrunMs < maxExtensionMs;\n if (shouldExtendAdBreak) {\n this.timing.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Ad break boundary reached (overrun=${overrunMs}ms) - hard-stopping ads and resuming stream`\n );\n }\n if (adPlaying) {\n this.adPlayer.stop().catch(() => {\n });\n }\n this.adBreak.handleAdPodComplete();\n }\n // ───────────────────────────────────────────────────────────────\n // Ad prefetch\n // ───────────────────────────────────────────────────────────────\n startAdPrefetch(marker, fragmentSn, cueKey) {\n if (this.adBreak.pendingAdBreak || this.adBreak.inAdBreak) return;\n const scheduled = this.adConfig.findCurrentOrNextBreak(this.video.currentTime * 1e3);\n const tags = this.adConfig.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.adConfig.apiVastTagUrl) {\n baseVastUrl = this.adConfig.apiVastTagUrl;\n } else {\n if (this.debug) console.warn(\"[StormcloudVideoPlayer] No VAST URL available for prefetch\");\n return;\n }\n this.adConfig.beginNewAdPod();\n this.adConfig.podAssignedByPrefetch = true;\n const generatedUrls = this.generateVastUrls(baseVastUrl, 1);\n this.adBreak.pendingAdBreak = {\n marker,\n ...fragmentSn !== void 0 ? { detectedAtFragmentSn: fragmentSn } : {},\n vastUrls: generatedUrls,\n isFetching: false,\n fetchStartTime: Date.now()\n };\n this.cueManager.pendingScte35CueKey = cueKey;\n this.adBreak.adDetectSentForCurrentBreak = true;\n const detectPayload = {};\n if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;\n if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;\n if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;\n sendAdDetectTracking(this.config.licenseKey, { source: \"scte35\", timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...detectPayload }).catch(() => {\n });\n if (this.debug) {\n console.log(\"[PREFETCH] Starting ad prefetch for upcoming ad break\");\n console.log(`[PREFETCH] Pre-generated ${generatedUrls.length} VAST URLs`);\n }\n this.preloadPool.startPreloadPool(baseVastUrl, generatedUrls.slice(0, 1), false);\n }\n // ───────────────────────────────────────────────────────────────\n // VMAP time-based ad breaks\n // ───────────────────────────────────────────────────────────────\n onTimeUpdate(currentTimeSec) {\n if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;\n if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;\n const nowMs = currentTimeSec * 1e3;\n const breakToPlay = this.adConfig.findBreakForTime(nowMs);\n if (breakToPlay) {\n void this.handleVmapAdBreak(breakToPlay, nowMs).catch((error) => {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] VMAP ad break failed gracefully:\", error);\n }\n });\n }\n }\n onVideoEnded() {\n if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;\n if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;\n const durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;\n const postroll = this.adConfig.vmapBreaks.find(\n (b) => b.startTimeMs === -1 && !this.adConfig.consumedVmapBreakIds.has(this.adConfig.getAdBreakKey(b))\n );\n if (postroll) {\n void this.handleVmapAdBreak(postroll, durationMs).catch((error) => {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] VMAP post-roll failed gracefully:\", error);\n }\n });\n }\n }\n async handleVmapAdBreak(adBreak, nowMs) {\n const key = this.adConfig.getAdBreakKey(adBreak);\n if (this.adConfig.consumedVmapBreakIds.has(key)) return;\n const breakStartMs = this.adConfig.resolveBreakStartMs(adBreak);\n if (breakStartMs == null) return;\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = breakStartMs + durationMs;\n const inWindow = durationMs > 0 ? nowMs >= breakStartMs && nowMs < endMs : nowMs >= breakStartMs;\n if (inWindow) {\n this.adConfig.consumedVmapBreakIds.add(key);\n const tags = this.adConfig.selectVastTagsForBreak(adBreak);\n if (!tags || tags.length === 0) return;\n const first = tags[0];\n const rest = tags.slice(1);\n this.adBreak.adPodQueue = rest;\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.adBreak.showAds = true;\n this.adBreak.inAdBreak = true;\n this.timing.currentAdBreakStartWallClockMs = Date.now();\n if (!this.video.paused) {\n this.video.pause();\n }\n try {\n await this.adBreak.playSingleAd(first);\n } catch (error) {\n this.adBreak.adPodQueue = [];\n this.adBreak.inAdBreak = false;\n this.adBreak.showAds = false;\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] VMAP ad request failed:\", error);\n }\n }\n }\n }\n // ───────────────────────────────────────────────────────────────\n // Public API\n // ───────────────────────────────────────────────────────────────\n getCurrentAdIndex() {\n return this.timing.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.timing.totalAdsInBreak;\n }\n getAdRemainingMs() {\n return this.timing.getRemainingAdMs();\n }\n isAdPlaying() {\n return this.adBreak.inAdBreak && this.adPlayer.isAdPlaying();\n }\n isShowingAds() {\n return this.adBreak.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 isLive() {\n return this.hlsEngine.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n toggleMute() {\n toggleMute(this.video, this.adPlayer, this.debug);\n }\n toggleFullscreen() {\n return toggleFullscreen(this.video, this.debug);\n }\n isMuted() {\n return isMuted(this.video, this.adPlayer);\n }\n setMuted(muted) {\n setMuted(this.video, this.adPlayer, muted, this.debug);\n }\n setVolume(volume) {\n setVolume(this.video, this.adPlayer, volume, this.debug);\n }\n getVolume() {\n return getVolume(this.video, this.adPlayer);\n }\n isFullscreen() {\n return isFullscreen();\n }\n resize() {\n resizePlayer(this.video, this.adPlayer, this.debug);\n }\n // ───────────────────────────────────────────────────────────────\n // Destroy\n // ───────────────────────────────────────────────────────────────\n destroy() {\n this.adBreak.stopContinuousFetching();\n this.preloadPool.stop();\n this.timing.destroy();\n this.adBreak.clearPendingAdBreak();\n this.placeholder.destroy();\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.endedHandler) {\n this.video.removeEventListener(\"ended\", this.endedHandler);\n delete this.endedHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n this.adConfig.destroyTracking();\n this.hlsEngine.destroy();\n this.adPlayer?.destroy();\n if (this.palPlaybackStarted) {\n this.palPlaybackStarted = false;\n this.palNonce.sendPlaybackEnd();\n }\n this.palNonce.reset();\n this.adBreak.adRequestQueue = [];\n this.timing.consecutiveFailures = 0;\n }\n};\n\n// src/ui/StormcloudVideoPlayer.tsx\nvar import_fa = require(\"react-icons/fa\");\nvar import_jsx_runtime = require(\"react/jsx-runtime\");\nvar CRITICAL_PROPS = [\n \"src\",\n \"allowNativeHls\",\n \"isLiveStream\",\n \"licenseKey\",\n \"isVmap\",\n \"vmapUrl\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"vastMode\",\n \"ctvAdRequest\"\n];\nvar CONTROLS_HIDE_DELAY = 3e3;\nvar DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;\nvar StormcloudVideoPlayerComponent = import_react.default.memo(\n (props) => {\n const {\n src,\n autoplay,\n muted,\n lowLatencyMode,\n allowNativeHls,\n isLiveStream,\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 isVmap,\n vmapUrl,\n minSegmentsBeforePlay,\n ctvAdRequest,\n ...restVideoAttrs\n } = props;\n const videoRef = (0, import_react.useRef)(null);\n const playerRef = (0, import_react.useRef)(null);\n const bufferingTimeoutRef = (0, import_react.useRef)(null);\n const controlsTimerRef = (0, import_react.useRef)(null);\n const wrapperRef = (0, import_react.useRef)(null);\n const [adStatus, setAdStatus] = import_react.default.useState({ showAds: false, currentIndex: 0, totalAds: 0, remainingSeconds: 0 });\n const [shouldShowNativeControls, setShouldShowNativeControls] = import_react.default.useState(true);\n const [isMuted2, setIsMuted] = import_react.default.useState(false);\n const [isFullscreen2, setIsFullscreen] = import_react.default.useState(false);\n const [isPlaying, setIsPlaying] = import_react.default.useState(false);\n const [currentTime, setCurrentTime] = import_react.default.useState(0);\n const [duration, setDuration] = import_react.default.useState(0);\n const [volume, setVolume2] = import_react.default.useState(1);\n const [playbackRate, setPlaybackRate] = import_react.default.useState(1);\n const [showVolumeSlider, setShowVolumeSlider] = import_react.default.useState(false);\n const [showSpeedMenu, setShowSpeedMenu] = import_react.default.useState(false);\n const [isLoading, setIsLoading] = import_react.default.useState(true);\n const [isBuffering, setIsBuffering] = import_react.default.useState(false);\n const [showCenterPlay, setShowCenterPlay] = import_react.default.useState(false);\n const [showLicenseWarning, setShowLicenseWarning] = import_react.default.useState(false);\n const [controlsVisible, setControlsVisible] = import_react.default.useState(true);\n const [viewportWidth, setViewportWidth] = import_react.default.useState(\n typeof window !== \"undefined\" ? window.innerWidth : 1920\n );\n const [isPortrait, setIsPortrait] = import_react.default.useState(\n typeof window !== \"undefined\" ? window.innerHeight > window.innerWidth : false\n );\n const [playerAspectRatio, setPlayerAspectRatio] = import_react.default.useState(\n DEFAULT_PLAYER_ASPECT_RATIO\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 resetControlsTimer = (0, import_react.useCallback)(() => {\n if (controlsTimerRef.current) {\n clearTimeout(controlsTimerRef.current);\n }\n setControlsVisible(true);\n controlsTimerRef.current = window.setTimeout(() => {\n if (!showVolumeSlider && !showSpeedMenu) {\n setControlsVisible(false);\n }\n }, CONTROLS_HIDE_DELAY);\n }, [showVolumeSlider, showSpeedMenu]);\n const handleWrapperMouseMove = (0, import_react.useCallback)(() => {\n resetControlsTimer();\n }, [resetControlsTimer]);\n const handleWrapperMouseLeave = (0, import_react.useCallback)(() => {\n if (!showVolumeSlider && !showSpeedMenu) {\n setControlsVisible(false);\n }\n }, [showVolumeSlider, showSpeedMenu]);\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 resetControlsTimer();\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 resetControlsTimer();\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 || isLiveStream === false : true);\n const criticalPropsKey = (0, import_react.useMemo)(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n isLiveStream,\n licenseKey,\n isVmap,\n vmapUrl,\n lowLatencyMode,\n driftToleranceMs,\n vastMode\n ]);\n (0, import_react.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 (isLiveStream !== void 0) cfg.isLiveStream = isLiveStream;\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 (isVmap !== void 0) cfg.isVmap = isVmap;\n if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;\n if (minSegmentsBeforePlay !== void 0)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n if (ctvAdRequest !== void 0) cfg.ctvAdRequest = ctvAdRequest;\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 (0, import_react.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 (0, import_react.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 const remainingMs = playerRef.current.getAdRemainingMs();\n const remainingSeconds = showAds ? Math.max(0, Math.ceil(remainingMs / 1e3)) : 0;\n setAdStatus((prev) => {\n if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds || prev.remainingSeconds !== remainingSeconds) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds, remainingSeconds };\n }\n return prev;\n });\n }\n };\n const interval = setInterval(checkAdStatus, 50);\n return () => clearInterval(interval);\n }, []);\n (0, import_react.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 (0, import_react.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 = playerRef.current.getVolume();\n setVolume2(\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 === wrapperRef.current\n );\n };\n const interval = setInterval(updateStates, 200);\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === wrapperRef.current\n );\n };\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n return () => {\n clearInterval(interval);\n document.removeEventListener(\n \"fullscreenchange\",\n handleFullscreenChange\n );\n };\n }, []);\n (0, import_react.useEffect)(() => {\n if (!videoRef.current) return;\n const handleLoadedMetadata = () => {\n const video2 = videoRef.current;\n if (video2) {\n if (video2.videoWidth > 0 && video2.videoHeight > 0) {\n setPlayerAspectRatio(video2.videoWidth / video2.videoHeight);\n }\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 (0, import_react.useEffect)(() => {\n setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);\n }, [src]);\n (0, import_react.useEffect)(() => {\n return () => {\n if (controlsTimerRef.current) {\n clearTimeout(controlsTimerRef.current);\n }\n };\n }, []);\n const progressPercent = duration > 0 ? currentTime / duration * 100 : 0;\n const VolumeIcon = isMuted2 || volume === 0 ? import_fa.FaVolumeMute : volume < 0.5 ? import_fa.FaVolumeDown : import_fa.FaVolumeUp;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"style\", { children: `\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-loading-glow {\n 0%, 100% { opacity: 0.85; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.05); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-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 .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n ` }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n ref: wrapperRef,\n className: `sc-wrapper ${wrapperClassName || \"\"}`,\n onMouseMove: handleWrapperMouseMove,\n onMouseLeave: handleWrapperMouseLeave,\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n position: isFullscreen2 ? \"fixed\" : \"relative\",\n top: isFullscreen2 ? 0 : void 0,\n left: isFullscreen2 ? 0 : void 0,\n overflow: \"hidden\",\n width: isFullscreen2 ? \"100vw\" : \"100%\",\n height: isFullscreen2 ? \"100vh\" : \"auto\",\n minHeight: isFullscreen2 ? \"100vh\" : \"auto\",\n aspectRatio: isFullscreen2 ? void 0 : playerAspectRatio,\n maxWidth: isFullscreen2 ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen2 ? \"100vh\" : \"none\",\n zIndex: isFullscreen2 ? 999999 : void 0,\n backgroundColor: \"#000\",\n borderRadius: isFullscreen2 ? 0 : void 0,\n boxShadow: isFullscreen2 ? \"none\" : void 0,\n ...wrapperStyle\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"video\",\n {\n ref: videoRef,\n className,\n style: {\n display: \"block\",\n width: \"100%\",\n height: \"100%\",\n maxWidth: \"100%\",\n maxHeight: isFullscreen2 ? \"100%\" : \"none\",\n objectFit: isFullscreen2 ? \"cover\" : \"contain\",\n backgroundColor: \"#000\",\n aspectRatio: isFullscreen2 ? \"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__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: \"sc-loading-indicator\",\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 20,\n width: `${Math.max(34, 38 * responsiveScale)}px`,\n height: `${Math.max(34, 38 * responsiveScale)}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n animation: \"sc-loading-glow 1.4s ease-in-out infinite\",\n filter: \"drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n inset: 0,\n borderRadius: \"50%\",\n border: \"3px solid rgba(255, 255, 255, 0.25)\",\n borderTopColor: \"#ff0000\",\n borderRightColor: \"rgba(255, 255, 255, 0.85)\",\n animation: \"sc-spin 0.8s linear infinite\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: \"7px\",\n height: \"7px\",\n borderRadius: \"50%\",\n background: \"#ff0000\",\n boxShadow: \"0 0 10px rgba(255, 0, 0, 0.65)\"\n }\n }\n )\n ]\n }\n ),\n showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.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: \"rgba(220, 38, 38, 0.92)\",\n backdropFilter: \"blur(24px)\",\n color: \"white\",\n padding: \"28px 36px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n boxShadow: \"0 24px 64px rgba(0, 0, 0, 0.5)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"18px\", fontWeight: \"700\", marginBottom: \"10px\", letterSpacing: \"-0.02em\" }, children: \"License Key Required\" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { fontSize: \"13px\", lineHeight: \"1.6\", color: \"rgba(255, 255, 255, 0.85)\" }, children: [\n \"Please provide a valid license key to use the Stormcloud Video Player.\",\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"br\", {}),\n \"Contact your administrator for licensing information.\"\n ] })\n ]\n }\n ),\n adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: `${12 * responsiveScale}px`,\n left: `${12 * responsiveScale}px`,\n zIndex: 50,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n pointerEvents: \"none\",\n animation: \"sc-fade-in 0.3s ease\"\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n background: \"rgba(234, 179, 8, 0.95)\",\n color: \"#111\",\n padding: `${4 * responsiveScale}px ${12 * responsiveScale}px`,\n borderRadius: \"6px\",\n fontSize: `${11 * responsiveScale}px`,\n fontWeight: 700,\n letterSpacing: \"0.08em\",\n textTransform: \"uppercase\",\n boxShadow: \"0 2px 12px rgba(234, 179, 8, 0.35)\"\n },\n children: `Ad ${Math.max(1, adStatus.currentIndex)}`\n }\n )\n }\n ),\n showCenterPlay && !isLoading && !isBuffering && !showLicenseWarning && !adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.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: \"rgba(0, 0, 0, 0.55)\",\n backdropFilter: \"blur(8px)\",\n borderRadius: \"50%\",\n width: `${92 * responsiveScale}px`,\n height: `${92 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"background 0.2s ease, transform 0.2s ease\",\n animation: \"sc-fade-in 0.2s ease\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.background = \"rgba(0, 0, 0, 0.72)\";\n e.currentTarget.style.transform = \"translate(-50%, -50%) scale(1.06)\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.background = \"rgba(0, 0, 0, 0.55)\";\n e.currentTarget.style.transform = \"translate(-50%, -50%) scale(1)\";\n },\n title: \"Play\",\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaPlay,\n {\n size: Math.max(24, 32 * responsiveScale),\n color: \"white\",\n style: { marginLeft: \"4px\" }\n }\n )\n }\n ),\n shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: \"sc-controls-bar\",\n style: {\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background: \"linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.35) 60%, transparent 100%)\",\n padding: `${20 * responsiveScale}px ${12 * responsiveScale}px ${8 * responsiveScale}px`,\n zIndex: 10,\n opacity: controlsVisible || adStatus.showAds ? 1 : 0,\n transform: controlsVisible || adStatus.showAds ? \"translateY(0)\" : \"translateY(6px)\",\n pointerEvents: controlsVisible || adStatus.showAds ? \"auto\" : \"none\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: \"sc-progress-track\",\n style: {\n width: \"100%\",\n height: \"3px\",\n background: \"rgba(255, 255, 255, 0.2)\",\n borderRadius: \"1.5px\",\n marginBottom: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n position: \"relative\",\n transition: \"height 0.1s ease\"\n },\n onClick: handleTimelineSeek,\n onMouseEnter: (e) => {\n e.currentTarget.style.height = \"5px\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.height = \"3px\";\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: 0,\n left: 0,\n bottom: 0,\n background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n borderRadius: \"1.5px\",\n width: `${progressPercent}%`,\n transition: \"width 0.15s linear\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n className: \"sc-progress-thumb\",\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: `${progressPercent}%`,\n transform: \"translate(-50%, -50%) scale(0)\",\n width: \"13px\",\n height: \"13px\",\n background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 4px rgba(0, 0, 0, 0.3)\",\n transition: \"transform 0.1s ease, left 0.15s linear\"\n }\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n gap: `${8 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: `${8 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: handlePlayPause,\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`\n },\n title: isPlaying ? \"Pause\" : \"Play\",\n children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPause, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPlay, { size: Math.max(14, 18 * responsiveScale), style: { marginLeft: \"2px\" } })\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n paddingRight: `${6 * responsiveScale}px`\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n if (playerRef.current) playerRef.current.toggleMute();\n onVolumeToggle?.();\n resetControlsTimer();\n },\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`\n },\n title: isMuted2 ? \"Unmute\" : \"Mute\",\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, { size: Math.max(14, 18 * responsiveScale) })\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n overflow: \"hidden\",\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n display: \"flex\",\n alignItems: \"center\",\n paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n paddingRight: showVolumeSlider ? `${8 * responsiveScale}px` : \"0\"\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: `${56 * responsiveScale}px`,\n height: \"3px\",\n cursor: \"pointer\",\n borderRadius: \"1.5px\"\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const el = e.currentTarget;\n const move = (ev) => {\n const r2 = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));\n };\n const up = () => {\n document.removeEventListener(\"mousemove\", move);\n document.removeEventListener(\"mouseup\", up);\n };\n document.addEventListener(\"mousemove\", move);\n document.addEventListener(\"mouseup\", up);\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n },\n onClick: (e) => {\n e.stopPropagation();\n const r = e.currentTarget.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: 0,\n left: 0,\n bottom: 0,\n width: `${(isMuted2 ? 0 : volume) * 100}%`,\n background: \"#fff\",\n borderRadius: \"1.5px\",\n transition: \"width 0.1s ease-out\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: `${(isMuted2 ? 0 : volume) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n width: \"12px\",\n height: \"12px\",\n background: \"#fff\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n transition: \"left 0.1s ease-out\"\n }\n }\n )\n ]\n }\n )\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: `${13 * responsiveScale}px`,\n fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\",\n fontVariantNumeric: \"tabular-nums\",\n userSelect: \"none\",\n marginLeft: `${4 * responsiveScale}px`\n },\n children: [\n formatTime(currentTime),\n \" \",\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { color: \"rgba(255,255,255,0.5)\" }, children: \"/\" }),\n \" \",\n formatTime(duration)\n ]\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: `${8 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { position: \"relative\", display: viewportWidth < 600 ? \"none\" : \"block\" }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n setShowSpeedMenu(!showSpeedMenu);\n resetControlsTimer();\n },\n style: {\n padding: `${6 * responsiveScale}px ${10 * responsiveScale}px`,\n borderRadius: `${6 * responsiveScale}px`,\n fontSize: `${13 * responsiveScale}px`,\n fontFamily: \"'SF Mono', 'Cascadia Code', monospace\",\n fontWeight: \"600\",\n minHeight: `${32 * responsiveScale}px`\n },\n title: \"Playback Speed\",\n children: [\n playbackRate,\n \"x\"\n ]\n }\n ),\n showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n right: 0,\n marginBottom: \"8px\",\n background: \"rgba(0, 0, 0, 0.8)\",\n backdropFilter: \"blur(24px)\",\n WebkitBackdropFilter: \"blur(24px)\",\n borderRadius: \"10px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"80px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5)\",\n animation: \"sc-fade-in 0.15s ease\"\n },\n children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map((speed) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"button\",\n {\n onClick: () => handlePlaybackRateChange(speed),\n style: {\n display: \"block\",\n width: \"100%\",\n padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n background: playbackRate === speed ? \"rgba(255, 255, 255, 0.12)\" : \"transparent\",\n border: \"none\",\n color: playbackRate === speed ? \"#fff\" : \"rgba(255, 255, 255, 0.7)\",\n cursor: \"pointer\",\n fontSize: `${12 * responsiveScale}px`,\n fontFamily: \"'SF Mono', monospace\",\n fontWeight: playbackRate === speed ? \"700\" : \"500\",\n textAlign: \"center\",\n transition: \"background 0.15s ease, color 0.15s ease\"\n },\n onMouseEnter: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"rgba(255, 255, 255, 0.08)\";\n e.target.style.color = \"#fff\";\n }\n },\n onMouseLeave: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"transparent\";\n e.target.style.color = \"rgba(255, 255, 255, 0.7)\";\n }\n },\n children: [\n speed,\n \"x\"\n ]\n },\n speed\n ))\n }\n )\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (wrapperRef.current) {\n if (!document.fullscreenElement) {\n wrapperRef.current.requestFullscreen().catch(() => {\n });\n } else {\n document.exitFullscreen().catch(() => {\n });\n }\n }\n resetControlsTimer();\n },\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`\n },\n title: isFullscreen2 ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, { size: Math.max(14, 18 * responsiveScale) })\n }\n )\n ]\n }\n )\n ]\n }\n )\n ]\n }\n ) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: `${10 * responsiveScale}px`,\n left: `${10 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n zIndex: 10,\n opacity: controlsVisible ? 1 : 0,\n transition: \"opacity 0.35s ease\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n background: \"#ff3b30\",\n animation: \"sc-pulse 1.5s ease-in-out infinite\",\n flexShrink: 0\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"span\",\n {\n style: {\n fontSize: `${12 * responsiveScale}px`,\n fontFamily: \"'SF Pro Display', 'Segoe UI', Arial, sans-serif\",\n fontWeight: 700,\n letterSpacing: \"0.08em\",\n color: \"#fff\",\n textShadow: \"0 1px 3px rgba(0,0,0,0.6)\",\n userSelect: \"none\"\n },\n children: \"LIVE\"\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: \"sc-controls-bar\",\n style: {\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n alignItems: isPortrait ? \"flex-end\" : \"center\",\n gap: `${8 * responsiveScale}px`,\n zIndex: 10,\n opacity: controlsVisible ? 1 : 0,\n transform: controlsVisible ? \"translateY(0)\" : \"translateY(4px)\",\n pointerEvents: controlsVisible ? \"auto\" : \"none\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n background: \"rgba(0, 0, 0, 0.6)\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: \"2px\",\n paddingRight: `${8 * responsiveScale}px`\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n if (playerRef.current) playerRef.current.toggleMute();\n onVolumeToggle?.();\n resetControlsTimer();\n },\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`\n },\n title: isMuted2 ? \"Unmute\" : \"Mute\",\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, { size: Math.max(14, 18 * responsiveScale) })\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n overflow: \"hidden\",\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n display: \"flex\",\n alignItems: \"center\",\n paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n paddingRight: showVolumeSlider ? `${10 * responsiveScale}px` : \"0\"\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: `${56 * responsiveScale}px`,\n height: \"3px\",\n cursor: \"pointer\",\n borderRadius: \"1.5px\"\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const el = e.currentTarget;\n const move = (ev) => {\n const r2 = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));\n };\n const up = () => {\n document.removeEventListener(\"mousemove\", move);\n document.removeEventListener(\"mouseup\", up);\n };\n document.addEventListener(\"mousemove\", move);\n document.addEventListener(\"mouseup\", up);\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n },\n onClick: (e) => {\n e.stopPropagation();\n const r = e.currentTarget.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: 0,\n left: 0,\n bottom: 0,\n width: `${(isMuted2 ? 0 : volume) * 100}%`,\n background: \"#fff\",\n borderRadius: \"1.5px\",\n transition: \"width 0.1s ease-out\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: `${(isMuted2 ? 0 : volume) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n width: \"12px\",\n height: \"12px\",\n background: \"#fff\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n transition: \"left 0.1s ease-out\"\n }\n }\n )\n ]\n }\n )\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (wrapperRef.current) {\n if (!document.fullscreenElement) {\n wrapperRef.current.requestFullscreen().catch(() => {\n });\n } else {\n document.exitFullscreen().catch(() => {\n });\n }\n }\n resetControlsTimer();\n },\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n background: \"rgba(0, 0, 0, 0.6)\"\n },\n title: isFullscreen2 ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, { size: Math.max(14, 18 * responsiveScale) })\n }\n )\n ]\n }\n )\n ] }),\n onControlClick && /* @__PURE__ */ (0, import_jsx_runtime.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// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n StormcloudVideoPlayerComponent\n});\n","import React, { useEffect, useRef, useMemo, useCallback } 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} 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 \"isLiveStream\",\n \"licenseKey\",\n \"isVmap\",\n \"vmapUrl\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"vastMode\",\n \"ctvAdRequest\",\n] as const;\n\nconst CONTROLS_HIDE_DELAY = 3000;\nconst DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;\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 isLiveStream,\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 isVmap,\n vmapUrl,\n minSegmentsBeforePlay,\n ctvAdRequest,\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 controlsTimerRef = useRef<number | null>(null);\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n const [adStatus, setAdStatus] = React.useState<{\n showAds: boolean;\n currentIndex: number;\n totalAds: number;\n remainingSeconds: number;\n }>({ showAds: false, currentIndex: 0, totalAds: 0, remainingSeconds: 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 [controlsVisible, setControlsVisible] = React.useState(true);\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 const [playerAspectRatio, setPlayerAspectRatio] = React.useState(\n DEFAULT_PLAYER_ASPECT_RATIO\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 resetControlsTimer = useCallback(() => {\n if (controlsTimerRef.current) {\n clearTimeout(controlsTimerRef.current);\n }\n setControlsVisible(true);\n controlsTimerRef.current = window.setTimeout(() => {\n if (!showVolumeSlider && !showSpeedMenu) {\n setControlsVisible(false);\n }\n }, CONTROLS_HIDE_DELAY);\n }, [showVolumeSlider, showSpeedMenu]);\n\n const handleWrapperMouseMove = useCallback(() => {\n resetControlsTimer();\n }, [resetControlsTimer]);\n\n const handleWrapperMouseLeave = useCallback(() => {\n if (!showVolumeSlider && !showSpeedMenu) {\n setControlsVisible(false);\n }\n }, [showVolumeSlider, showSpeedMenu]);\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 resetControlsTimer();\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 resetControlsTimer();\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 &&\n (isHlsStream ? (allowNativeHls || isLiveStream === false) : true);\n\n const criticalPropsKey = useMemo(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n isLiveStream,\n licenseKey,\n isVmap,\n vmapUrl,\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 (isLiveStream !== undefined) cfg.isLiveStream = isLiveStream;\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 (isVmap !== undefined) cfg.isVmap = isVmap;\n if (vmapUrl !== undefined) cfg.vmapUrl = vmapUrl;\n if (minSegmentsBeforePlay !== undefined)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n if (ctvAdRequest !== undefined) cfg.ctvAdRequest = ctvAdRequest;\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 const remainingMs = playerRef.current.getAdRemainingMs();\n const remainingSeconds = showAds\n ? Math.max(0, Math.ceil(remainingMs / 1000))\n : 0;\n\n setAdStatus((prev) => {\n if (\n prev.showAds !== showAds ||\n prev.currentIndex !== currentIndex ||\n prev.totalAds !== totalAds ||\n prev.remainingSeconds !== remainingSeconds\n ) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds, remainingSeconds };\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 = playerRef.current.getVolume();\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 === wrapperRef.current\n );\n };\n\n const interval = setInterval(updateStates, 200);\n\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === wrapperRef.current\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 const video = videoRef.current;\n if (video) {\n if (video.videoWidth > 0 && video.videoHeight > 0) {\n setPlayerAspectRatio(video.videoWidth / video.videoHeight);\n }\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 useEffect(() => {\n setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);\n }, [src]);\n\n useEffect(() => {\n return () => {\n if (controlsTimerRef.current) {\n clearTimeout(controlsTimerRef.current);\n }\n };\n }, []);\n\n const progressPercent = duration > 0 ? (currentTime / duration) * 100 : 0;\n\n const VolumeIcon = isMuted || volume === 0\n ? FaVolumeMute\n : volume < 0.5\n ? FaVolumeDown\n : FaVolumeUp;\n\n return (\n <>\n <style>\n {`\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-loading-glow {\n 0%, 100% { opacity: 0.85; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.05); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-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 .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n `}\n </style>\n <div\n ref={wrapperRef}\n className={`sc-wrapper ${wrapperClassName || \"\"}`}\n onMouseMove={handleWrapperMouseMove}\n onMouseLeave={handleWrapperMouseLeave}\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 aspectRatio: isFullscreen ? undefined : playerAspectRatio,\n maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : undefined,\n backgroundColor: \"#000\",\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: \"100%\",\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 <div\n className=\"sc-loading-indicator\"\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 20,\n width: `${Math.max(34, 38 * responsiveScale)}px`,\n height: `${Math.max(34, 38 * responsiveScale)}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n animation: \"sc-loading-glow 1.4s ease-in-out infinite\",\n filter: \"drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))\",\n }}\n >\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n borderRadius: \"50%\",\n border: \"3px solid rgba(255, 255, 255, 0.25)\",\n borderTopColor: \"#ff0000\",\n borderRightColor: \"rgba(255, 255, 255, 0.85)\",\n animation: \"sc-spin 0.8s linear infinite\",\n }}\n />\n <div\n style={{\n width: \"7px\",\n height: \"7px\",\n borderRadius: \"50%\",\n background: \"#ff0000\",\n boxShadow: \"0 0 10px rgba(255, 0, 0, 0.65)\",\n }}\n />\n </div>\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: \"rgba(220, 38, 38, 0.92)\",\n backdropFilter: \"blur(24px)\",\n color: \"white\",\n padding: \"28px 36px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n boxShadow: \"0 24px 64px rgba(0, 0, 0, 0.5)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\",\n }}\n >\n <div style={{ fontSize: \"18px\", fontWeight: \"700\", marginBottom: \"10px\", letterSpacing: \"-0.02em\" }}>\n License Key Required\n </div>\n <div style={{ fontSize: \"13px\", lineHeight: \"1.6\", color: \"rgba(255, 255, 255, 0.85)\" }}>\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 {adStatus.showAds && (\n <div\n style={{\n position: \"absolute\",\n top: `${12 * responsiveScale}px`,\n left: `${12 * responsiveScale}px`,\n zIndex: 50,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n pointerEvents: \"none\",\n animation: \"sc-fade-in 0.3s ease\",\n }}\n >\n <div\n style={{\n background: \"rgba(234, 179, 8, 0.95)\",\n color: \"#111\",\n padding: `${4 * responsiveScale}px ${12 * responsiveScale}px`,\n borderRadius: \"6px\",\n fontSize: `${11 * responsiveScale}px`,\n fontWeight: 700,\n letterSpacing: \"0.08em\",\n textTransform: \"uppercase\" as const,\n boxShadow: \"0 2px 12px rgba(234, 179, 8, 0.35)\",\n }}\n >\n {`Ad ${Math.max(1, adStatus.currentIndex)}`}\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: \"rgba(0, 0, 0, 0.55)\",\n backdropFilter: \"blur(8px)\",\n borderRadius: \"50%\",\n width: `${92 * responsiveScale}px`,\n height: `${92 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"background 0.2s ease, transform 0.2s ease\",\n animation: \"sc-fade-in 0.2s ease\",\n }}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLElement).style.background = \"rgba(0, 0, 0, 0.72)\";\n (e.currentTarget as HTMLElement).style.transform = \"translate(-50%, -50%) scale(1.06)\";\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLElement).style.background = \"rgba(0, 0, 0, 0.55)\";\n (e.currentTarget as HTMLElement).style.transform = \"translate(-50%, -50%) scale(1)\";\n }}\n title=\"Play\"\n >\n <FaPlay\n size={Math.max(24, 32 * responsiveScale)}\n color=\"white\"\n style={{ marginLeft: \"4px\" }}\n />\n </div>\n )}\n\n {shouldShowEnhancedControls && !showLicenseWarning ? (\n <div\n className=\"sc-controls-bar\"\n style={{\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background: \"linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.35) 60%, transparent 100%)\",\n padding: `${20 * responsiveScale}px ${12 * responsiveScale}px ${8 * responsiveScale}px`,\n zIndex: 10,\n opacity: controlsVisible || adStatus.showAds ? 1 : 0,\n transform: controlsVisible || adStatus.showAds ? \"translateY(0)\" : \"translateY(6px)\",\n pointerEvents: controlsVisible || adStatus.showAds ? \"auto\" : \"none\",\n }}\n >\n {/* Progress Bar */}\n <div\n className=\"sc-progress-track\"\n style={{\n width: \"100%\",\n height: \"3px\",\n background: \"rgba(255, 255, 255, 0.2)\",\n borderRadius: \"1.5px\",\n marginBottom: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n position: \"relative\",\n transition: \"height 0.1s ease\",\n }}\n onClick={handleTimelineSeek}\n onMouseEnter={(e) => { e.currentTarget.style.height = \"5px\"; }}\n onMouseLeave={(e) => { e.currentTarget.style.height = \"3px\"; }}\n >\n <div\n style={{\n position: \"absolute\",\n top: 0, left: 0, bottom: 0,\n background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n borderRadius: \"1.5px\",\n width: `${progressPercent}%`,\n transition: \"width 0.15s linear\",\n }}\n />\n <div\n className=\"sc-progress-thumb\"\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: `${progressPercent}%`,\n transform: \"translate(-50%, -50%) scale(0)\",\n width: \"13px\",\n height: \"13px\",\n background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 4px rgba(0, 0, 0, 0.3)\",\n transition: \"transform 0.1s ease, left 0.15s linear\",\n }}\n />\n </div>\n\n {/* Controls Row */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n {/* Left Group */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n {/* Play/Pause */}\n <button\n className=\"sc-ctrl-btn\"\n onClick={handlePlayPause}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n }}\n title={isPlaying ? \"Pause\" : \"Play\"}\n >\n {isPlaying ? (\n <FaPause size={Math.max(14, 18 * responsiveScale)} />\n ) : (\n <FaPlay size={Math.max(14, 18 * responsiveScale)} style={{ marginLeft: \"2px\" }} />\n )}\n </button>\n\n {/* Volume Group - YouTube Style */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n paddingRight: `${6 * responsiveScale}px`,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => {\n if (playerRef.current) playerRef.current.toggleMute();\n onVolumeToggle?.();\n resetControlsTimer();\n }}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n <VolumeIcon size={Math.max(14, 18 * responsiveScale)} />\n </button>\n <div\n style={{\n width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n overflow: \"hidden\",\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n display: \"flex\",\n alignItems: \"center\",\n paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n paddingRight: showVolumeSlider ? `${8 * responsiveScale}px` : \"0\",\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: `${56 * responsiveScale}px`,\n height: \"3px\",\n cursor: \"pointer\",\n borderRadius: \"1.5px\",\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const el = e.currentTarget;\n const move = (ev: MouseEvent) => {\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r.left) / r.width)));\n };\n const up = () => { document.removeEventListener(\"mousemove\", move); document.removeEventListener(\"mouseup\", up); };\n document.addEventListener(\"mousemove\", move);\n document.addEventListener(\"mouseup\", up);\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n }}\n onClick={(e) => {\n e.stopPropagation();\n const r = e.currentTarget.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n }}\n >\n <div style={{ position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" }} />\n <div\n style={{\n position: \"absolute\",\n top: 0, left: 0, bottom: 0,\n width: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"#fff\",\n borderRadius: \"1.5px\",\n transition: \"width 0.1s ease-out\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: `${(isMuted ? 0 : volume) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n width: \"12px\",\n height: \"12px\",\n background: \"#fff\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n transition: \"left 0.1s ease-out\",\n }}\n />\n </div>\n </div>\n </div>\n\n {/* Time Display */}\n <div\n style={{\n fontSize: `${13 * responsiveScale}px`,\n fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\",\n fontVariantNumeric: \"tabular-nums\",\n userSelect: \"none\",\n marginLeft: `${4 * responsiveScale}px`,\n }}\n >\n {formatTime(currentTime)}{\" \"}\n <span style={{ color: \"rgba(255,255,255,0.5)\" }}>/</span>{\" \"}\n {formatTime(duration)}\n </div>\n </div>\n\n {/* Right Group */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n {/* Speed Selector */}\n <div style={{ position: \"relative\", display: viewportWidth < 600 ? \"none\" : \"block\" }}>\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => { setShowSpeedMenu(!showSpeedMenu); resetControlsTimer(); }}\n style={{\n padding: `${6 * responsiveScale}px ${10 * responsiveScale}px`,\n borderRadius: `${6 * responsiveScale}px`,\n fontSize: `${13 * responsiveScale}px`,\n fontFamily: \"'SF Mono', 'Cascadia Code', monospace\",\n fontWeight: \"600\",\n minHeight: `${32 * responsiveScale}px`,\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: \"8px\",\n background: \"rgba(0, 0, 0, 0.8)\",\n backdropFilter: \"blur(24px)\",\n WebkitBackdropFilter: \"blur(24px)\",\n borderRadius: \"10px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"80px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5)\",\n animation: \"sc-fade-in 0.15s ease\",\n }}\n >\n {[0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map((speed) => (\n <button\n key={speed}\n onClick={() => handlePlaybackRateChange(speed)}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n background: playbackRate === speed\n ? \"rgba(255, 255, 255, 0.12)\"\n : \"transparent\",\n border: \"none\",\n color: playbackRate === speed ? \"#fff\" : \"rgba(255, 255, 255, 0.7)\",\n cursor: \"pointer\",\n fontSize: `${12 * responsiveScale}px`,\n fontFamily: \"'SF Mono', monospace\",\n fontWeight: playbackRate === speed ? \"700\" : \"500\",\n textAlign: \"center\",\n transition: \"background 0.15s ease, color 0.15s ease\",\n }}\n onMouseEnter={(e) => {\n if (playbackRate !== speed) {\n (e.target as HTMLElement).style.background = \"rgba(255, 255, 255, 0.08)\";\n (e.target as HTMLElement).style.color = \"#fff\";\n }\n }}\n onMouseLeave={(e) => {\n if (playbackRate !== speed) {\n (e.target as HTMLElement).style.background = \"transparent\";\n (e.target as HTMLElement).style.color = \"rgba(255, 255, 255, 0.7)\";\n }\n }}\n >\n {speed}x\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Fullscreen */}\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (wrapperRef.current) {\n if (!document.fullscreenElement) {\n wrapperRef.current.requestFullscreen().catch(() => {});\n } else {\n document.exitFullscreen().catch(() => {});\n }\n }\n resetControlsTimer();\n }}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n }}\n title={isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"}\n >\n {isFullscreen ? (\n <FaCompress size={Math.max(14, 18 * responsiveScale)} />\n ) : (\n <FaExpand size={Math.max(14, 18 * responsiveScale)} />\n )}\n </button>\n </div>\n </div>\n </div>\n ) : (\n showCustomControls && !showLicenseWarning && (\n <>\n <div\n style={{\n position: \"absolute\",\n top: `${10 * responsiveScale}px`,\n left: `${10 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n zIndex: 10,\n opacity: controlsVisible ? 1 : 0,\n transition: \"opacity 0.35s ease\",\n }}\n >\n <div\n style={{\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n background: \"#ff3b30\",\n animation: \"sc-pulse 1.5s ease-in-out infinite\",\n flexShrink: 0,\n }}\n />\n <span\n style={{\n fontSize: `${12 * responsiveScale}px`,\n fontFamily: \"'SF Pro Display', 'Segoe UI', Arial, sans-serif\",\n fontWeight: 700,\n letterSpacing: \"0.08em\",\n color: \"#fff\",\n textShadow: \"0 1px 3px rgba(0,0,0,0.6)\",\n userSelect: \"none\",\n }}\n >\n LIVE\n </span>\n </div>\n\n <div\n className=\"sc-controls-bar\"\n style={{\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n alignItems: isPortrait ? \"flex-end\" : \"center\",\n gap: `${8 * responsiveScale}px`,\n zIndex: 10,\n opacity: controlsVisible ? 1 : 0,\n transform: controlsVisible ? \"translateY(0)\" : \"translateY(4px)\",\n pointerEvents: controlsVisible ? \"auto\" : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n background: \"rgba(0, 0, 0, 0.6)\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: \"2px\",\n paddingRight: `${8 * responsiveScale}px`,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => {\n if (playerRef.current) playerRef.current.toggleMute();\n onVolumeToggle?.();\n resetControlsTimer();\n }}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n <VolumeIcon size={Math.max(14, 18 * responsiveScale)} />\n </button>\n <div\n style={{\n width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n overflow: \"hidden\",\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n display: \"flex\",\n alignItems: \"center\",\n paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n paddingRight: showVolumeSlider ? `${10 * responsiveScale}px` : \"0\",\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: `${56 * responsiveScale}px`,\n height: \"3px\",\n cursor: \"pointer\",\n borderRadius: \"1.5px\",\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const el = e.currentTarget;\n const move = (ev: MouseEvent) => {\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r.left) / r.width)));\n };\n const up = () => { document.removeEventListener(\"mousemove\", move); document.removeEventListener(\"mouseup\", up); };\n document.addEventListener(\"mousemove\", move);\n document.addEventListener(\"mouseup\", up);\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n }}\n onClick={(e) => {\n e.stopPropagation();\n const r = e.currentTarget.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n }}\n >\n <div style={{ position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" }} />\n <div\n style={{\n position: \"absolute\",\n top: 0, left: 0, bottom: 0,\n width: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"#fff\",\n borderRadius: \"1.5px\",\n transition: \"width 0.1s ease-out\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: `${(isMuted ? 0 : volume) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n width: \"12px\",\n height: \"12px\",\n background: \"#fff\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n transition: \"left 0.1s ease-out\",\n }}\n />\n </div>\n </div>\n </div>\n\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (wrapperRef.current) {\n if (!document.fullscreenElement) {\n wrapperRef.current.requestFullscreen().catch(() => {});\n } else {\n document.exitFullscreen().catch(() => {});\n }\n }\n resetControlsTimer();\n }}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n background: \"rgba(0, 0, 0, 0.6)\",\n }}\n title={isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"}\n >\n {isFullscreen ? (\n <FaCompress size={Math.max(14, 18 * responsiveScale)} />\n ) : (\n <FaExpand size={Math.max(14, 18 * responsiveScale)} />\n )}\n </button>\n </div>\n </>\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 type { AdController } 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\ntype VastParseResult =\n | { type: \"inline\"; ad: VastAd }\n | {\n type: \"wrapper\";\n vastAdTagUri: string;\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n }\n | { type: \"empty\" };\n\nconst MAX_VAST_WRAPPER_DEPTH = 5;\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): AdController {\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 isHlsMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type === \"application/x-mpegurl\" ||\n type === \"application/vnd.apple.mpegurl\" ||\n type.includes(\"mpegurl\") ||\n url.includes(\".m3u8\")\n );\n }\n\n function isProgressiveMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type.startsWith(\"video/\") ||\n url.endsWith(\".mp4\") ||\n url.includes(\".mp4?\")\n );\n }\n\n function createEmptyTrackingUrls(): VastTrackingUrls {\n return {\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\n function extractTrackingUrls(xmlDoc: Document): VastTrackingUrls {\n const trackingUrls = createEmptyTrackingUrls();\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 xmlDoc.querySelectorAll(\"Error\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.error.push(url);\n });\n\n return trackingUrls;\n }\n\n function mergeTrackingUrls(\n target: VastTrackingUrls,\n source: VastTrackingUrls\n ): VastTrackingUrls {\n (Object.keys(target) as Array<keyof VastTrackingUrls>).forEach((key) => {\n if (source[key] && source[key].length > 0) {\n target[key] = target[key].concat(source[key]);\n }\n });\n return target;\n }\n\n function parseVastXml(xmlString: string): VastParseResult {\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 { type: \"empty\" };\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return { type: \"empty\" };\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n const wrapperUri = xmlDoc\n .querySelector(\"VASTAdTagURI\")\n ?.textContent?.trim();\n if (wrapperUri) {\n console.log(\n `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n );\n return {\n type: \"wrapper\",\n vastAdTagUri: wrapperUri,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough,\n };\n }\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 const mediaFile: VastMediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: undefined,\n };\n\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n mediaFile.bitrate =\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined;\n\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\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 supported media files found in VAST XML\");\n }\n return { type: \"empty\" };\n }\n\n return {\n type: \"inline\",\n ad: {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough,\n },\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return { type: \"empty\" };\n }\n }\n\n async function fetchVastXml(vastTagUrl: string): Promise<string> {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\",\n },\n referrerPolicy: \"no-referrer-when-downgrade\",\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n return response.text();\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string,\n depth = 0,\n accumulatedTracking: VastTrackingUrls = createEmptyTrackingUrls()\n ): Promise<VastAd | null> {\n const vastXml = await fetchVastXml(vastTagUrl);\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 const parsed = parseVastXml(vastXml);\n\n if (parsed.type === \"empty\") {\n return null;\n }\n\n if (parsed.type === \"wrapper\") {\n if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n console.warn(\n `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n );\n return null;\n }\n\n mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n return fetchAndParseVastAd(\n parsed.vastAdTagUri,\n depth + 1,\n accumulatedTracking\n );\n }\n\n mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n return parsed.ad;\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 if (!adPlaying) return;\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 contentVideo.muted = true;\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 console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {});\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\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 = \"30\";\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.reject(new Error(\"No ads available from VAST response\"));\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 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 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 adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n adVideoElement.volume = Math.max(0, Math.min(1, originalVolume));\n adVideoElement.muted = originalMutedState;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n\n if (isHlsAd && 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 (isHlsAd && (\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 if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\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 pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {});\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}, volume: ${contentVideo.volume}`\n );\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {});\n }\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 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 = Math.max(0, Math.min(1, 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 const clamped = Math.max(0, Math.min(1, volume));\n adVideoElement.volume = clamped;\n adVideoElement.muted = clamped === 0;\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 getLoadedAdDuration() {\n return currentAd?.duration;\n },\n getLoadedAdId() {\n return currentAd?.id;\n },\n };\n}\n","declare global {\n interface Window {\n goog?: any;\n }\n}\n\nconst PAL_SDK_URL =\n \"https://imasdk.googleapis.com/pal/sdkloader/pal.js\";\n\nlet _nonceLoader: any | undefined;\nlet _palLoadPromise: Promise<void> | undefined;\n\nfunction loadPalSdk(): Promise<void> {\n if (typeof window !== \"undefined\" && window.goog?.pal) {\n return Promise.resolve();\n }\n\n if (_palLoadPromise) return _palLoadPromise;\n\n _palLoadPromise = new Promise<void>((resolve, reject) => {\n const existing = document.querySelector(\n 'script[data-pal=\"true\"]'\n ) as HTMLScriptElement | null;\n\n if (existing) {\n if (window.goog?.pal) {\n resolve();\n return;\n }\n const timeout = setTimeout(\n () => reject(new Error(\"PAL SDK load timeout\")),\n 10000\n );\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"PAL SDK load failed\"));\n });\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = PAL_SDK_URL;\n script.async = true;\n script.setAttribute(\"data-pal\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"PAL SDK load failed\"));\n document.head.appendChild(script);\n });\n\n return _palLoadPromise;\n}\n\nfunction getOrCreateNonceLoader(): any {\n if (_nonceLoader) return _nonceLoader;\n const goog = window.goog;\n const consentSettings = new goog.pal.ConsentSettings();\n consentSettings.allowStorage = true;\n _nonceLoader = new goog.pal.NonceLoader(consentSettings);\n return _nonceLoader;\n}\n\nexport interface PalNonceOptions {\n videoWidth?: number;\n videoHeight?: number;\n descriptionUrl?: string;\n ppid?: string;\n sessionId?: string;\n adWillAutoPlay?: boolean;\n adWillPlayMuted?: boolean;\n playerVolume?: number;\n continuousPlayback?: boolean;\n}\n\nexport interface PalNonceManager {\n generateNonce(options?: PalNonceOptions): Promise<string>;\n\n getCurrentNonce(): string;\n\n injectNonce(vastTagUrl: string): string;\n\n sendPlaybackStart(): void;\n\n sendPlaybackEnd(): void;\n\n sendAdClick(): void;\n\n sendAdTouch(event: MouseEvent | TouchEvent): void;\n\n reset(): void;\n}\n\nexport function createPalNonceManager(): PalNonceManager {\n let currentNonce = \"\";\n let currentNonceManager: any | undefined;\n\n return {\n async generateNonce(options: PalNonceOptions = {}): Promise<string> {\n try {\n await loadPalSdk();\n\n const loader = getOrCreateNonceLoader();\n const goog = window.goog;\n\n const request = new goog.pal.NonceRequest();\n request.adWillAutoPlay = options.adWillAutoPlay ?? true;\n request.adWillPlayMuted = options.adWillPlayMuted ?? false;\n request.playerVolume =\n options.playerVolume ?? (request.adWillPlayMuted ? 0 : 1);\n request.continuousPlayback = options.continuousPlayback ?? true;\n request.descriptionUrl =\n options.descriptionUrl ||\n (typeof window !== \"undefined\" ? window.location.href : \"\");\n request.iconsSupported = true;\n request.playerType = \"StormcloudVideoPlayer\";\n request.playerVersion = \"1.0\";\n request.supportedApiFrameworks = \"2,7,9\";\n request.url =\n options.descriptionUrl ||\n (typeof window !== \"undefined\" ? window.location.href : \"\");\n request.videoWidth = options.videoWidth || 640;\n request.videoHeight = options.videoHeight || 480;\n\n if (options.ppid) request.ppid = options.ppid;\n if (options.sessionId) request.sessionId = options.sessionId;\n\n const manager = await loader.loadNonceManager(request);\n currentNonceManager = manager;\n currentNonce = manager.getNonce() as string;\n\n console.log(\"[PAL] Nonce generated successfully\");\n return currentNonce;\n } catch (error) {\n console.warn(\"[PAL] Failed to generate nonce:\", error);\n currentNonce = \"\";\n currentNonceManager = undefined;\n return \"\";\n }\n },\n\n getCurrentNonce(): string {\n return currentNonce;\n },\n\n injectNonce(vastTagUrl: string): string {\n if (!currentNonce || !vastTagUrl) return vastTagUrl;\n\n try {\n const url = new URL(vastTagUrl);\n url.searchParams.delete(\"paln\");\n url.searchParams.set(\"givn\", currentNonce);\n return url.toString();\n } catch {\n let base = vastTagUrl\n .replace(/([?&])paln=[^&]*/g, \"\")\n .replace(/[?&]$/, \"\");\n const sep = base.includes(\"?\") ? \"&\" : \"?\";\n return `${base}${sep}givn=${encodeURIComponent(currentNonce)}`;\n }\n },\n\n sendPlaybackStart(): void {\n try {\n currentNonceManager?.sendPlaybackStart();\n } catch {}\n },\n\n sendPlaybackEnd(): void {\n try {\n currentNonceManager?.sendPlaybackEnd();\n } catch {}\n },\n\n sendAdClick(): void {\n try {\n currentNonceManager?.sendAdClick();\n } catch {}\n },\n\n sendAdTouch(event: MouseEvent | TouchEvent): void {\n try {\n currentNonceManager?.sendAdTouch(event);\n } catch {}\n },\n\n reset(): void {\n currentNonce = \"\";\n currentNonceManager = undefined;\n },\n };\n}\n","export const MQTT_CA_CERT_FILE = \"src/certs/emqxsl-ca.crt\";\n\nexport type MQTTConfig = {\n enabled: boolean;\n brokerAddress: string;\n brokerPort: number;\n wsPort: number;\n username: string;\n password: string;\n topicPrefix: string;\n qos: 0 | 1 | 2;\n brokerUrl?: string;\n};\n\nexport const DEFAULT_MQTT_CONFIG: MQTTConfig = {\n enabled: true,\n brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n brokerPort: 8883,\n wsPort: 8084,\n username: \"for-sonifi\",\n password: \"sonifi-mqtt\",\n topicPrefix: \"adstorm/players\",\n qos: 1,\n};\n\nexport const mqttConfig: MQTTConfig = { ...DEFAULT_MQTT_CONFIG };\n\nexport function applyMQTTConfig(overrides: Partial<MQTTConfig>): void {\n Object.assign(mqttConfig, overrides);\n}\n\nexport function isMQTTEnabled(): boolean {\n return mqttConfig.enabled;\n}\n\nexport function buildMQTTBrokerUrl(): string {\n if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\n\nexport function buildPlayerTopic(\n licenseKey: string,\n channel: \"metrics\" | \"impressions\" | \"heartbeat\"\n): string {\n return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n","import mqtt from \"mqtt\";\nimport type { MqttClient } from \"mqtt\";\nimport {\n applyMQTTConfig,\n buildMQTTBrokerUrl,\n isMQTTEnabled,\n mqttConfig,\n} from \"./mqttConfig\";\nimport type { MQTTConfig } from \"./mqttConfig\";\n\nconst LOG = \"[StormcloudVideoPlayer][MQTT]\";\n\nexport type MQTTStatus = \"disconnected\" | \"connecting\" | \"connected\" | \"error\";\n\nlet client: MqttClient | null = null;\nlet status: MQTTStatus = \"disconnected\";\n\nexport function getMQTTStatus(): MQTTStatus {\n return status;\n}\n\nexport function isMQTTConnected(): boolean {\n return status === \"connected\" && client !== null && client.connected;\n}\n\nexport function isMQTTConfigured(): boolean {\n return isMQTTEnabled();\n}\n\nexport function configureMQTT(overrides: Partial<MQTTConfig>): void {\n applyMQTTConfig(overrides);\n disconnectMQTT();\n}\n\nexport function initMQTTClient(): void {\n if (client || !isMQTTEnabled()) return;\n\n const url = buildMQTTBrokerUrl();\n status = \"connecting\";\n\n const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n\n try {\n client = mqtt.connect(url, {\n clientId,\n username: mqttConfig.username,\n password: mqttConfig.password,\n keepalive: 60,\n clean: true,\n reconnectPeriod: 5000,\n connectTimeout: 10_000,\n queueQoSZero: false,\n });\n } catch (err) {\n status = \"error\";\n console.warn(`${LOG} connect() threw:`, err);\n return;\n }\n\n client.on(\"connect\", () => {\n status = \"connected\";\n console.info(`${LOG} connected to ${url}`);\n });\n\n client.on(\"reconnect\", () => {\n status = \"connecting\";\n console.info(`${LOG} reconnecting…`);\n });\n\n client.on(\"offline\", () => {\n status = \"disconnected\";\n console.warn(`${LOG} offline`);\n });\n\n client.on(\"error\", (err) => {\n status = \"error\";\n console.warn(`${LOG} error:`, err.message);\n });\n\n client.on(\"close\", () => {\n if (status === \"connected\") {\n status = \"disconnected\";\n }\n });\n}\n\nexport function ensureMQTTClient(): void {\n if (isMQTTEnabled() && !client) {\n initMQTTClient();\n }\n}\n\nexport function publishMQTT(\n topic: string,\n payload: Record<string, unknown>\n): boolean {\n if (!isMQTTEnabled()) {\n return false;\n }\n\n ensureMQTTClient();\n\n if (!client) {\n return false;\n }\n\n try {\n client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n return true;\n } catch (err) {\n console.warn(`${LOG} publish failed on ${topic}:`, err);\n return false;\n }\n}\n\nexport function disconnectMQTT(): void {\n if (client) {\n client.end(true);\n client = null;\n status = \"disconnected\";\n }\n}\n","import type {\n ClientInfo,\n AdDetectInfo,\n AdLoadedInfo,\n AdImpressionInfo,\n PlayerAnalyticsContext,\n} from \"../types\";\nimport { buildPlayerTopic, isMQTTEnabled } from \"./mqttConfig\";\nimport { ensureMQTTClient, publishMQTT } from \"./mqttClient\";\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?.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 hashHex = Array.from(new Uint8Array(hashBuffer))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle 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\ntype PlayerMetricFlags = {\n adLoaded?: boolean;\n adDetect?: boolean;\n captureAt?: string;\n};\n\nfunction canPublish(licenseKey: string | undefined): licenseKey is string {\n return Boolean(isMQTTEnabled() && licenseKey);\n}\n\nasync function buildPlayerMetricEvent(\n context: PlayerAnalyticsContext = {},\n flags: PlayerMetricFlags = {}\n): Promise<Record<string, unknown>> {\n const clientInfo = getClientInfo();\n const playerId = await getBrowserID(clientInfo);\n const captureAt = flags.captureAt ?? new Date().toISOString();\n\n return {\n player_id: playerId,\n device_type: clientInfo.deviceType,\n os: clientInfo.os.toLowerCase(),\n ad_loaded: flags.adLoaded ?? false,\n ad_detect: flags.adDetect ?? false,\n capture_at: captureAt,\n ...(context.inputStreamType\n ? { input_stream_type: context.inputStreamType }\n : {}),\n };\n}\n\nfunction publishTracking(\n licenseKey: string,\n channel: \"metrics\" | \"impressions\" | \"heartbeat\",\n body: Record<string, unknown>\n): void {\n ensureMQTTClient();\n publishMQTT(buildPlayerTopic(licenseKey, channel), body);\n}\n\nexport async function sendInitialTracking(\n licenseKey?: string,\n context: PlayerAnalyticsContext = {}\n): Promise<void> {\n if (!canPublish(licenseKey)) return;\n\n try {\n const metricEvent = await buildPlayerMetricEvent(context, {\n adLoaded: false,\n adDetect: false,\n });\n\n publishTracking(licenseKey, \"metrics\", {\n events: [metricEvent],\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\n\nexport async function sendAdDetectTracking(\n licenseKey: string | undefined,\n adDetectInfo: AdDetectInfo,\n context: PlayerAnalyticsContext = {}\n): Promise<void> {\n try {\n await sendHeartbeat(licenseKey, context, {\n adDetect: true,\n captureAt: adDetectInfo.timestamp,\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n error\n );\n }\n}\n\nexport async function sendAdLoadedTracking(\n licenseKey: string | undefined,\n adLoadedInfo: AdLoadedInfo,\n context: PlayerAnalyticsContext = {}\n): Promise<void> {\n try {\n await sendHeartbeat(licenseKey, context, {\n adLoaded: true,\n captureAt: adLoadedInfo.timestamp,\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n error\n );\n }\n}\n\nexport async function sendAdImpressionTracking(\n licenseKey: string | undefined,\n adImpressionInfo: AdImpressionInfo,\n context: PlayerAnalyticsContext = {}\n): Promise<void> {\n if (!canPublish(licenseKey)) return;\n\n try {\n const metricEvent = await buildPlayerMetricEvent(context, {\n captureAt: adImpressionInfo.timestamp,\n });\n\n publishTracking(licenseKey, \"heartbeat\", metricEvent);\n publishTracking(licenseKey, \"impressions\", {\n events: [\n {\n player_id: metricEvent.player_id,\n ad_played_count: 1,\n ad_url: adImpressionInfo.adUrl,\n capture_at: adImpressionInfo.timestamp,\n },\n ],\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\n\nexport async function sendHeartbeat(\n licenseKey?: string,\n context: PlayerAnalyticsContext = {},\n flags: PlayerMetricFlags = {}\n): Promise<void> {\n if (!canPublish(licenseKey)) return;\n\n try {\n const heartbeatData = await buildPlayerMetricEvent(context, flags);\n publishTracking(licenseKey, \"heartbeat\", heartbeatData);\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","export interface VastEnvironmentSignals {\n isCtv: boolean;\n contentUrl?: string;\n appId?: string;\n appName?: string;\n sessionId?: string;\n deviceId?: string;\n deviceIdType?: string;\n limitAdTracking?: boolean;\n deviceTypeHint?: number;\n}\n\nconst AIRY_ANDROID_APP_ID = \"com.freeairytv.android\";\nconst AIRY_WEBOS_APP_ID = \"com.freeairytv.webos\";\nconst AIRY_TIZEN_APP_ID = \"com.freeairytv.samsung\";\nconst AIRY_ROKU_APP_ID = \"com.freeairytv.roku\";\nconst AIRY_APP_NAME = \"AiryTV Movies & TV\";\nconst AIRY_DEFAULT_CONTENT_URL = \"https://live.airy.tv\";\nconst CTV_SESSION_STORAGE_KEY = \"stormcloud.ctv.sid\";\n\nfunction getDefaultAppId(): string {\n if (typeof navigator === \"undefined\") return AIRY_ANDROID_APP_ID;\n const ua = navigator.userAgent;\n if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;\n if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;\n if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;\n return AIRY_ANDROID_APP_ID;\n}\n\nconst DEVICE_ID_STORAGE_KEYS = [\n \"rdid\",\n \"ifa\",\n \"advertisingId\",\n \"advertising_id\",\n \"deviceAdvertisingId\",\n \"aaid\",\n \"adid\",\n \"rida\",\n \"tifa\",\n \"lgudid\",\n];\n\nconst ANDROID_ID_TYPES = new Set([\"aaid\", \"adid\"]);\n\nexport function resolveVastEnvironmentSignals(isCtv: boolean): VastEnvironmentSignals {\n const bridgeSignals = readNativeBridgeSignals();\n const deviceId = bridgeSignals.deviceId || readStoredDeviceId();\n const deviceIdType =\n bridgeSignals.deviceIdType ||\n readStoredString(\"deviceIdType\") ||\n readStoredString(\"idtype\") ||\n inferDeviceIdType();\n const limitAdTracking =\n deviceId != null\n ? bridgeSignals.limitAdTracking ?? readStoredLimitAdTracking() ?? false\n : undefined;\n\n if (isCtv) {\n return {\n isCtv: true,\n contentUrl:\n bridgeSignals.contentUrl ||\n readStoredString(\"contentUrl\") ||\n AIRY_DEFAULT_CONTENT_URL,\n appId:\n bridgeSignals.appId ||\n readStoredString(\"appId\") ||\n readStoredString(\"msid\") ||\n getDefaultAppId(),\n appName:\n bridgeSignals.appName ||\n readStoredString(\"appName\") ||\n readStoredString(\"an\") ||\n AIRY_APP_NAME,\n sessionId: getOrCreateCtvSessionId(),\n ...(deviceId ? { deviceId } : {}),\n ...(deviceIdType ? { deviceIdType } : {}),\n ...(limitAdTracking != null ? { limitAdTracking } : {}),\n deviceTypeHint: 5,\n };\n }\n\n return {\n isCtv: false,\n ...(deviceId ? { deviceId } : {}),\n ...(deviceIdType ? { deviceIdType } : {}),\n ...(limitAdTracking != null ? { limitAdTracking } : {}),\n };\n}\n\nexport function inferDeviceIdType(): string | undefined {\n if (typeof navigator === \"undefined\") {\n return undefined;\n }\n\n const ua = navigator.userAgent;\n if (/Roku/i.test(ua)) return \"rida\";\n if (/Tizen|Samsung/i.test(ua)) return \"tifa\";\n if (/AppleTV|Apple TV/i.test(ua)) return \"tvOS\";\n if (/AFT|Fire TV|Amazon/i.test(ua)) return \"afai\";\n if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return \"lgudid\";\n if (/Android|Google TV/i.test(ua)) return \"aaid\";\n if (/iPhone|iPad|iPod/i.test(ua)) return \"idfa\";\n return undefined;\n}\n\nexport function isEquivalentDeviceIdType(\n tagType: string | undefined,\n runtimeType: string | undefined\n): boolean {\n if (!tagType || !runtimeType) return false;\n const tag = tagType.toLowerCase();\n const runtime = runtimeType.toLowerCase();\n if (tag === runtime) return true;\n return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);\n}\n\nfunction getOrCreateCtvSessionId(): string {\n const existing = readStoredString(CTV_SESSION_STORAGE_KEY);\n if (existing) {\n return existing;\n }\n\n const sessionId = createUuid();\n try {\n window.localStorage?.setItem(CTV_SESSION_STORAGE_KEY, sessionId);\n } catch {}\n return sessionId;\n}\n\nfunction createUuid(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const value = Math.floor(Math.random() * 16);\n const nibble = char === \"x\" ? value : (value & 0x3) | 0x8;\n return nibble.toString(16);\n });\n}\n\nfunction readNativeBridgeSignals(): {\n contentUrl?: string;\n appId?: string;\n appName?: string;\n deviceId?: string;\n deviceIdType?: string;\n limitAdTracking?: boolean;\n} {\n if (typeof window === \"undefined\") {\n return {};\n }\n\n const candidates = [\n (window as any).__STORMCLOUD_CTV_AD_INFO__,\n (window as any).__STORMCLOUD_CTV__,\n (window as any).stormcloudCtv,\n (window as any).AiryTV,\n (window as any).Android,\n (window as any).webOS,\n (window as any).tizen,\n (window as any).amazon,\n ].filter(Boolean);\n\n for (const source of candidates) {\n const contentUrl =\n readBridgeValue(source, [\"contentUrl\", \"url\", \"videoUrl\", \"canonicalUrl\"]) ||\n undefined;\n const appId =\n readBridgeValue(source, [\"appId\", \"msid\", \"applicationId\", \"packageName\"]) ||\n undefined;\n const appName =\n readBridgeValue(source, [\"appName\", \"an\", \"applicationName\"]) || undefined;\n const deviceId =\n readBridgeValue(source, [\n \"rdid\",\n \"ifa\",\n \"advertisingId\",\n \"adId\",\n \"deviceId\",\n \"lgudid\",\n \"LGUDID\",\n \"tifa\",\n \"rida\",\n \"afai\",\n \"aaid\",\n ]) || undefined;\n\n if (!contentUrl && !deviceId && !appId && !appName) continue;\n\n const deviceIdType =\n readBridgeValue(source, [\n \"idtype\",\n \"deviceIdType\",\n \"advertisingIdType\",\n \"idType\",\n ]) || inferDeviceIdType();\n const limitAdTracking = readBridgeBoolean(source, [\n \"is_lat\",\n \"limitAdTracking\",\n \"limitedAdTracking\",\n \"lat\",\n ]);\n\n return {\n ...(contentUrl ? { contentUrl } : {}),\n ...(appId ? { appId } : {}),\n ...(appName ? { appName } : {}),\n ...(deviceId ? { deviceId } : {}),\n ...(deviceId && deviceIdType ? { deviceIdType } : {}),\n ...(deviceId && limitAdTracking != null ? { limitAdTracking } : {}),\n };\n }\n\n return {};\n}\n\nfunction readBridgeValue(source: any, keys: string[]): string | undefined {\n for (const key of keys) {\n const value = source?.[key];\n if (typeof value === \"string\" && value) {\n return value;\n }\n if (typeof value === \"function\") {\n try {\n const result = value.call(source);\n if (typeof result === \"string\" && result) {\n return result;\n }\n } catch {}\n }\n }\n return undefined;\n}\n\nfunction readBridgeBoolean(source: any, keys: string[]): boolean | undefined {\n for (const key of keys) {\n const value = source?.[key];\n const normalized = normalizeBoolean(value);\n if (normalized != null) {\n return normalized;\n }\n if (typeof value === \"function\") {\n try {\n const result = normalizeBoolean(value.call(source));\n if (result != null) {\n return result;\n }\n } catch {}\n }\n }\n return undefined;\n}\n\nfunction readStoredDeviceId(): string | undefined {\n for (const key of DEVICE_ID_STORAGE_KEYS) {\n const value = readStoredString(key);\n if (value) {\n return value;\n }\n }\n return undefined;\n}\n\nfunction readStoredString(key: string): string | undefined {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n\n try {\n const value = window.localStorage?.getItem(key);\n return value || undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction readStoredLimitAdTracking(): boolean | undefined {\n return normalizeBoolean(\n readStoredString(\"limitAdTracking\") ||\n readStoredString(\"limitedAdTracking\") ||\n readStoredString(\"is_lat\")\n );\n}\n\nfunction normalizeBoolean(value: unknown): boolean | undefined {\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"number\") {\n return value === 1;\n }\n if (typeof value === \"string\") {\n const normalized = value.toLowerCase();\n if (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\") {\n return true;\n }\n if (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n return false;\n }\n }\n return undefined;\n}\n","import {\n inferDeviceIdType,\n isEquivalentDeviceIdType,\n} from \"./vastEnvironmentSignals\";\n\nexport interface VastConsentSignals {\n gdpr?: string | undefined;\n gdprConsent?: string | undefined;\n usPrivacy?: string | undefined;\n}\n\nexport interface VastMacroContext {\n correlator: string;\n streamCorrelator: string;\n pod?: number | undefined;\n adPosition?: number | undefined;\n isCtv?: boolean | undefined;\n contentUrl?: string | undefined;\n pageUrl?: string | undefined;\n adWillPlayMuted?: boolean | undefined;\n adWillAutoPlay?: boolean | undefined;\n appId?: string | undefined;\n appName?: string | undefined;\n sessionId?: string | undefined;\n deviceId?: string | undefined;\n deviceIdType?: string | undefined;\n limitAdTracking?: boolean | undefined;\n deviceTypeHint?: number | undefined;\n adTest?: boolean | undefined;\n consent?: VastConsentSignals | undefined;\n}\n\nconst UNEXPANDED_MACRO_PATTERN = /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/;\nconst INVALID_VAST_PARAM_KEY = /^\\s|\\s$/;\nconst EXAMPLE_COM_URL = /example\\.com/i;\nconst CTV_UNSUPPORTED_PARAMS = [\n \"description_url\",\n \"tfcd\",\n \"npa\",\n \"min_ad_duration\",\n \"max_ad_duration\",\n \"unviewed_position_start\",\n \"impl\",\n \"vad_type\",\n \"gdpr\",\n \"gdpr_consent\",\n \"us_privacy\",\n];\n\nconst INLINE_DEVICE_MACRO_REPLACEMENTS: Array<{\n pattern: RegExp;\n getValue: (ctx: VastMacroContext) => string | undefined;\n}> = [\n { pattern: /\\[RDID\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[IFA\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[ADVERTISING[_-]?ID(?:ENTIFIER)?\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[DEVICE[_-]?ID\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[IDTYPE\\]/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /\\{rdid\\}/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\{device[_-]?id\\}/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\{idtype\\}/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi, getValue: (ctx) =>\n ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined },\n { pattern: /%%ADVERTISING_ID_TYPE%%/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /%%ADVERTISING_ID%%/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /%%LIMIT_AD_TRACKING%%/gi, getValue: (ctx) =>\n ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined },\n { pattern: /%%MSID%%/gi, getValue: (ctx) => ctx.appId },\n { pattern: /%%APP_NAME%%/gi, getValue: (ctx) => ctx.appName },\n { pattern: /%%SESSION_ID%%/gi, getValue: (ctx) => ctx.sessionId },\n { pattern: /%%CORRELATOR%%/gi, getValue: (ctx) => ctx.correlator },\n];\n\nexport function isMacroPlaceholder(value: string | null | undefined): boolean {\n if (value == null) return true;\n const trimmed = value.trim();\n if (!trimmed) return true;\n if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;\n return /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(trimmed);\n}\n\nexport function generateCorrelator(): string {\n if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n try {\n const buf = new Uint32Array(2);\n crypto.getRandomValues(buf);\n const value = (buf[0] ?? 0) * 0x200000 + ((buf[1] ?? 0) & 0x1fffff);\n if (value > 0) {\n return String(value);\n }\n } catch {\n }\n }\n return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);\n}\n\nfunction expandInlineMacroPlaceholders(baseUrl: string, ctx: VastMacroContext): string {\n let url = baseUrl;\n for (const { pattern, getValue } of INLINE_DEVICE_MACRO_REPLACEMENTS) {\n const value = getValue(ctx);\n if (value != null && value !== \"\") {\n url = url.replace(pattern, encodeURIComponent(value));\n }\n }\n return url;\n}\n\nfunction applyDeviceIdentityParams(\n params: URLSearchParams,\n ctx: VastMacroContext\n): void {\n const runtimeId = ctx.deviceId?.trim();\n const runtimeType = ctx.deviceIdType?.trim() || inferDeviceIdType();\n const tagRdid = params.get(\"rdid\");\n const tagType = params.get(\"idtype\");\n const tagLat = params.get(\"is_lat\");\n const latValue =\n ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined;\n\n if (runtimeId) {\n params.set(\"rdid\", runtimeId);\n params.set(\"idtype\", runtimeType || tagType || \"aaid\");\n params.set(\"is_lat\", latValue ?? (isMacroPlaceholder(tagLat) ? \"0\" : tagLat!));\n return;\n }\n\n const tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));\n const tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));\n\n if (\n tagRdidValid &&\n tagTypeValid &&\n runtimeType &&\n !isEquivalentDeviceIdType(tagType!, runtimeType)\n ) {\n params.delete(\"rdid\");\n params.delete(\"idtype\");\n params.delete(\"is_lat\");\n return;\n }\n\n if (tagRdidValid) {\n if (isMacroPlaceholder(tagType) && runtimeType) {\n params.set(\"idtype\", runtimeType);\n }\n if (isMacroPlaceholder(tagLat)) {\n params.set(\"is_lat\", latValue ?? \"0\");\n }\n return;\n }\n\n params.delete(\"rdid\");\n params.delete(\"idtype\");\n params.delete(\"is_lat\");\n}\n\nfunction removeBrokenAppNameOrphans(\n params: URLSearchParams,\n appName?: string\n): void {\n const toDelete: string[] = [];\n\n params.forEach((_value, key) => {\n if (!key || INVALID_VAST_PARAM_KEY.test(key)) {\n toDelete.push(key);\n }\n });\n\n if (appName && appName.includes(\"&\")) {\n for (const suffix of appName.split(\"&\").slice(1)) {\n const trimmed = suffix.trimStart();\n if (!trimmed) continue;\n toDelete.push(suffix, ` ${trimmed}`, trimmed);\n }\n }\n\n for (const key of new Set(toDelete)) {\n if (key) params.delete(key);\n }\n}\n\nexport function normalizeVastTagUrl(raw: string): string {\n if (!raw) return raw;\n\n try {\n const url = new URL(raw);\n\n const anValue = url.searchParams.get(\"an\");\n if (anValue !== null) {\n const orphanFragments: string[] = [];\n url.searchParams.forEach((_value, key) => {\n if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n orphanFragments.push(key.trim());\n }\n });\n if (orphanFragments.length > 0) {\n const reconstructed = [anValue.trimEnd(), ...orphanFragments]\n .filter(Boolean)\n .join(\" & \");\n\n url.searchParams.forEach((_value, key) => {\n if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n url.searchParams.delete(key);\n }\n });\n url.searchParams.set(\"an\", reconstructed);\n\n return url.toString().replace(\n /([?&]an=)([^&]*)/,\n (_match, prefix, val) => prefix + val.replace(/\\+/g, \"%20\")\n );\n }\n }\n\n removeBrokenAppNameOrphans(url.searchParams);\n return url.toString();\n } catch {\n return raw;\n }\n}\n\nexport function applyVastMacros(\n baseUrl: string,\n ctx: VastMacroContext\n): string {\n const expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);\n let url: URL;\n try {\n url = new URL(normalizeVastTagUrl(expandedUrl));\n } catch {\n return replaceCorrelatorFallback(expandedUrl, ctx.correlator);\n }\n\n const params = url.searchParams;\n\n removeBrokenAppNameOrphans(params, ctx.appName);\n\n params.set(\"correlator\", ctx.correlator);\n params.set(\"scor\", ctx.streamCorrelator);\n if (ctx.isCtv) {\n for (const key of CTV_UNSUPPORTED_PARAMS) {\n params.delete(key);\n }\n }\n\n if (ctx.pod != null) {\n params.set(\"pod\", String(ctx.pod));\n }\n if (ctx.adPosition != null) {\n params.set(\"ppos\", String(ctx.adPosition));\n }\n\n const requestUrl = ctx.contentUrl || ctx.pageUrl;\n if (requestUrl) {\n params.set(\"url\", requestUrl);\n if (!ctx.isCtv) {\n params.set(\"description_url\", requestUrl);\n }\n } else {\n const existingUrl = params.get(\"url\") || \"\";\n if (EXAMPLE_COM_URL.test(existingUrl)) {\n params.delete(\"url\");\n params.delete(\"description_url\");\n }\n }\n\n if (ctx.adWillPlayMuted != null) {\n params.set(\"vpmute\", ctx.adWillPlayMuted ? \"1\" : \"0\");\n }\n if (ctx.adWillAutoPlay != null) {\n params.set(\"vpa\", ctx.adWillAutoPlay ? \"auto\" : \"click\");\n }\n\n if (ctx.appId) {\n params.set(\"msid\", ctx.appId);\n }\n if (ctx.appName) {\n removeBrokenAppNameOrphans(params, ctx.appName);\n params.set(\"an\", ctx.appName);\n }\n if (ctx.sessionId) {\n params.set(\"sid\", ctx.sessionId);\n }\n if (ctx.deviceTypeHint != null) {\n params.set(\"dth\", String(ctx.deviceTypeHint));\n } else if (ctx.isCtv) {\n params.set(\"dth\", \"5\");\n }\n\n applyDeviceIdentityParams(params, ctx);\n\n if (!ctx.isCtv) {\n const consent = ctx.consent;\n if (consent?.gdpr != null) {\n params.set(\"gdpr\", consent.gdpr);\n }\n if (consent?.gdprConsent != null) {\n params.set(\"gdpr_consent\", consent.gdprConsent);\n }\n if (consent?.usPrivacy != null) {\n params.set(\"us_privacy\", consent.usPrivacy);\n }\n }\n\n if (ctx.adTest) {\n params.set(\"adtest\", \"on\");\n }\n\n const staleKeys: string[] = [];\n params.forEach((value, key) => {\n if (isMacroPlaceholder(value)) {\n staleKeys.push(key);\n }\n });\n for (const key of staleKeys) {\n params.delete(key);\n }\n\n removeBrokenAppNameOrphans(params, ctx.appName);\n\n return url.toString();\n}\n\nfunction replaceCorrelatorFallback(baseUrl: string, correlator: string): string {\n const correlatorRegex = /([?&])correlator=([^&]*)/;\n if (correlatorRegex.test(baseUrl)) {\n return baseUrl.replace(correlatorRegex, `$1correlator=${correlator}`);\n }\n const sep = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${sep}correlator=${correlator}`;\n}\n\nexport function fetchConsentSignals(\n timeoutMs: number = 1500\n): Promise<VastConsentSignals> {\n const signals: VastConsentSignals = {};\n if (typeof window === \"undefined\") {\n return Promise.resolve(signals);\n }\n\n const tasks: Promise<void>[] = [];\n\n const tcfApi = (window as any).__tcfapi;\n if (typeof tcfApi === \"function\") {\n tasks.push(\n new Promise<void>((resolve) => {\n let settled = false;\n try {\n tcfApi(\"addEventListener\", 2, (tcData: any, success: boolean) => {\n if (settled) return;\n if (\n success &&\n tcData &&\n (tcData.eventStatus === \"tcloaded\" ||\n tcData.eventStatus === \"useractioncomplete\")\n ) {\n settled = true;\n signals.gdpr = tcData.gdprApplies ? \"1\" : \"0\";\n if (typeof tcData.tcString === \"string\" && tcData.tcString) {\n signals.gdprConsent = tcData.tcString;\n }\n try {\n tcfApi(\"removeEventListener\", 2, () => {}, tcData.listenerId);\n } catch {}\n resolve();\n }\n });\n } catch {\n resolve();\n }\n setTimeout(() => {\n if (!settled) {\n settled = true;\n resolve();\n }\n }, timeoutMs);\n })\n );\n }\n\n const uspApi = (window as any).__uspapi;\n if (typeof uspApi === \"function\") {\n tasks.push(\n new Promise<void>((resolve) => {\n try {\n uspApi(\"getUSPData\", 1, (data: any, success: boolean) => {\n if (success && typeof data?.uspString === \"string\" && data.uspString) {\n signals.usPrivacy = data.uspString;\n }\n resolve();\n });\n } catch {\n resolve();\n }\n setTimeout(resolve, timeoutMs);\n })\n );\n }\n\n if (tasks.length === 0) {\n return Promise.resolve(signals);\n }\n\n return Promise.all(tasks).then(() => signals);\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 supportsModernJS: boolean;\n webOSVersion?: number | undefined;\n tizenVersion?: number | undefined;\n chromeVersion?: number | undefined;\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 supportsModernJS = true;\n let webOSVersion: number | undefined;\n let tizenVersion: number | undefined;\n let chromeVersionNum: number | undefined;\n\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n chromeVersionNum = chromeVersion > 0 ? chromeVersion : undefined;\n\n if (/Web0S|webOS|LG Browser|LGSTB/i.test(ua)) {\n name = 'LG WebOS';\n isSmartTV = true;\n\n let match = ua.match(/Web0S[/\\s]*([\\d.]+)/i) || ua.match(/webOS[/\\s]*([\\d.]+)/i);\n\n if (!match || !match[1]) {\n match = ua.match(/webOSTV[/\\s-]*([\\d.]+)/i) || ua.match(/webOS\\.TV[/\\s-]*([\\d.]+)/i);\n }\n\n if (match && match[1]) {\n version = match[1];\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n webOSVersion = majorVersion;\n } else if (chromeVersion > 0) {\n if (chromeVersion >= 79) {\n webOSVersion = 6;\n version = '6.0';\n majorVersion = 6;\n } else if (chromeVersion >= 68) {\n webOSVersion = 5;\n version = '5.0';\n majorVersion = 5;\n } else if (chromeVersion >= 53) {\n webOSVersion = 4;\n version = '4.0';\n majorVersion = 4;\n } else if (chromeVersion >= 38) {\n webOSVersion = 3;\n version = '3.0';\n majorVersion = 3;\n } else {\n webOSVersion = 2;\n version = '2.0';\n majorVersion = 2;\n }\n } else {\n version = 'Unknown';\n webOSVersion = undefined;\n }\n\n isLegacyTV = webOSVersion !== undefined && webOSVersion < 3;\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 tizenVersion = majorVersion;\n }\n\n isLegacyTV = tizenVersion !== undefined && tizenVersion < 3;\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\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 isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\n } else {\n if (chromeVersion > 0) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n\n if (chromeVersion < 50) {\n supportsModernJS = false;\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\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 supportsModernJS,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum,\n };\n}\n\nexport function getBrowserConfigOverrides(): {\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: { allowNativeHls?: boolean } = {};\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\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\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 supportsModernJS: browser.supportsModernJS,\n ...(browser.webOSVersion !== undefined ? { webOSVersion: browser.webOSVersion } : {}),\n ...(browser.tizenVersion !== undefined ? { tizenVersion: browser.tizenVersion } : {}),\n ...(browser.chromeVersion !== undefined ? { chromeVersion: browser.chromeVersion } : {}),\n userAgent: navigator.userAgent,\n });\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\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","import type { Scte35Marker, Id3TagInfo } from \"../types\";\n\nexport function 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\nexport function parseCueOutCont(\n value: string\n): { elapsed?: number; duration?: number } | undefined {\n const res: { elapsed?: number; duration?: number } = {};\n\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\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\n if (!(\"elapsed\" in res) || !(\"duration\" in res)) {\n const slashMatch = value.match(/([0-9.]+)\\s*\\/\\s*([0-9.]+)/);\n if (slashMatch && slashMatch[1] && slashMatch[2]) {\n const elapsed = parseFloat(slashMatch[1]);\n const duration = parseFloat(slashMatch[2]);\n if (!Number.isNaN(elapsed) && !(\"elapsed\" in res)) res.elapsed = elapsed;\n if (!Number.isNaN(duration) && !(\"duration\" in res)) res.duration = duration;\n }\n }\n\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return undefined;\n}\n\nexport function 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\nexport function 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\nexport function 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\nexport function 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\nexport function getFragmentStartSeconds(frag: any): number | undefined {\n const candidates = [frag?.start, frag?.startPTS];\n for (const candidate of candidates) {\n if (typeof candidate === \"number\" && Number.isFinite(candidate)) {\n return candidate;\n }\n }\n return undefined;\n}\n\nexport function parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = 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 = 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 = 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 = 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 = 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 = parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n}\n\nexport function normalizeFragmentPayload(payload: unknown): Uint8Array | undefined {\n if (payload instanceof Uint8Array) {\n return payload;\n }\n if (payload instanceof ArrayBuffer) {\n return new Uint8Array(payload);\n }\n if (ArrayBuffer.isView(payload)) {\n const view = payload as ArrayBufferView;\n return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n }\n return undefined;\n}\n\n// --- Transport Stream SCTE-35 parsing ---\n\nexport function detectTsPacketFormat(\n data: Uint8Array\n): { offset: number; packetSize: number; tsPayloadOffset: number } | undefined {\n const packetSizes = [188, 192, 204];\n for (const packetSize of packetSizes) {\n const tsPayloadOffset = packetSize === 192 ? 4 : 0;\n for (let offset = 0; offset < packetSize; offset++) {\n let matchedPackets = 0;\n for (\n let packetStart = offset;\n packetStart + tsPayloadOffset < data.length &&\n matchedPackets < 5;\n packetStart += packetSize\n ) {\n if (data[packetStart + tsPayloadOffset] !== 0x47) {\n break;\n }\n matchedPackets++;\n }\n if (matchedPackets >= 2) {\n return { offset, packetSize, tsPayloadOffset };\n }\n }\n }\n return undefined;\n}\n\nfunction getPsiSectionStart(\n payload: Uint8Array,\n payloadUnitStart: boolean\n): number | undefined {\n if (!payloadUnitStart) {\n return undefined;\n }\n const pointerField = payload[0];\n if (pointerField == null) {\n return undefined;\n }\n const sectionStart = 1 + pointerField;\n return sectionStart < payload.length ? sectionStart : undefined;\n}\n\nfunction getPsiSectionLength(data: Uint8Array, offset: number): number {\n return (((data[offset + 1] ?? 0) & 0x0f) << 8) | (data[offset + 2] ?? 0);\n}\n\nfunction parsePatSection(\n payload: Uint8Array,\n payloadUnitStart: boolean,\n pmtPids: Set<number>\n): void {\n const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n if (sectionStart == null || sectionStart + 8 >= payload.length) {\n return;\n }\n if (payload[sectionStart] !== 0x00) {\n return;\n }\n\n const sectionLength = getPsiSectionLength(payload, sectionStart);\n const sectionEnd = Math.min(\n payload.length,\n sectionStart + 3 + sectionLength\n );\n\n for (let offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4) {\n const programNumber =\n ((payload[offset] ?? 0) << 8) | (payload[offset + 1] ?? 0);\n const pid =\n (((payload[offset + 2] ?? 0) & 0x1f) << 8) |\n (payload[offset + 3] ?? 0);\n if (programNumber !== 0) {\n pmtPids.add(pid);\n }\n }\n}\n\nfunction descriptorsIdentifyScte35(\n data: Uint8Array,\n start: number,\n end: number\n): boolean {\n let offset = start;\n while (offset + 2 <= end) {\n const tag = data[offset] ?? 0;\n const length = data[offset + 1] ?? 0;\n const descriptorStart = offset + 2;\n const descriptorEnd = descriptorStart + length;\n if (descriptorEnd > end) {\n return false;\n }\n\n const registration =\n length >= 4\n ? String.fromCharCode(\n data[descriptorStart] ?? 0,\n data[descriptorStart + 1] ?? 0,\n data[descriptorStart + 2] ?? 0,\n data[descriptorStart + 3] ?? 0\n )\n : \"\";\n if (tag === 0x8a || registration === \"CUEI\" || registration === \"SCTE\") {\n return true;\n }\n\n offset = descriptorEnd;\n }\n return false;\n}\n\nfunction parsePmtSection(\n payload: Uint8Array,\n payloadUnitStart: boolean,\n tsScte35Pids: Set<number>\n): void {\n const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n if (sectionStart == null || sectionStart + 12 >= payload.length) {\n return;\n }\n if (payload[sectionStart] !== 0x02) {\n return;\n }\n\n const sectionLength = getPsiSectionLength(payload, sectionStart);\n const sectionEnd = Math.min(\n payload.length,\n sectionStart + 3 + sectionLength\n );\n const programInfoLength =\n (((payload[sectionStart + 10] ?? 0) & 0x0f) << 8) |\n (payload[sectionStart + 11] ?? 0);\n\n let offset = sectionStart + 12 + programInfoLength;\n while (offset + 5 <= sectionEnd - 4) {\n const streamType = payload[offset] ?? 0;\n const elementaryPid =\n (((payload[offset + 1] ?? 0) & 0x1f) << 8) |\n (payload[offset + 2] ?? 0);\n const esInfoLength =\n (((payload[offset + 3] ?? 0) & 0x0f) << 8) |\n (payload[offset + 4] ?? 0);\n const descriptorStart = offset + 5;\n const descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);\n\n if (\n streamType === 0x86 ||\n (streamType === 0x06 &&\n descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd))\n ) {\n tsScte35Pids.add(elementaryPid);\n }\n\n offset = descriptorStart + esInfoLength;\n }\n}\n\nfunction hasProcessedTsScte35Section(\n section: Uint8Array,\n processedSections: Set<string>\n): boolean {\n let checksum = 0;\n for (let i = 0; i < section.length; i++) {\n checksum = (checksum * 31 + (section[i] ?? 0)) >>> 0;\n }\n\n const key = `${section.length}:${checksum}`;\n if (processedSections.has(key)) {\n return true;\n }\n\n processedSections.add(key);\n if (processedSections.size > 200) {\n const firstKey = processedSections.values().next().value;\n if (firstKey) {\n processedSections.delete(firstKey);\n }\n }\n return false;\n}\n\nfunction addScte35SectionMarker(\n section: Uint8Array,\n markers: Scte35Marker[],\n processedSections: Set<string>\n): void {\n if (section[0] !== 0xfc || hasProcessedTsScte35Section(section, processedSections)) {\n return;\n }\n\n const marker = parseScte35Binary(section);\n if (!marker) {\n return;\n }\n\n marker.raw = {\n ...(typeof marker.raw === \"object\" && marker.raw ? marker.raw : {}),\n source: \"ts-packet\",\n };\n markers.push(marker);\n}\n\nfunction appendScte35Bytes(\n pid: number,\n bytes: Uint8Array,\n assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n markers: Scte35Marker[],\n processedSections: Set<string>\n): void {\n const assembler = assemblers.get(pid);\n if (!assembler) {\n return;\n }\n\n for (let i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++) {\n assembler.bytes.push(bytes[i] ?? 0);\n }\n\n if (assembler.bytes.length >= assembler.expectedLength) {\n assemblers.delete(pid);\n addScte35SectionMarker(new Uint8Array(assembler.bytes), markers, processedSections);\n }\n}\n\nfunction collectScte35SectionsFromPayload(\n pid: number,\n payload: Uint8Array,\n payloadUnitStart: boolean,\n assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n markers: Scte35Marker[],\n processedSections: Set<string>\n): void {\n if (payload.length === 0) {\n return;\n }\n\n let offset = 0;\n if (payloadUnitStart) {\n const pointerField = payload[0] ?? 0;\n const previousAssembler = assemblers.get(pid);\n if (previousAssembler && pointerField > 0) {\n appendScte35Bytes(\n pid,\n payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n assemblers,\n markers,\n processedSections\n );\n }\n assemblers.delete(pid);\n offset = 1 + pointerField;\n } else {\n appendScte35Bytes(pid, payload, assemblers, markers, processedSections);\n return;\n }\n\n while (offset + 3 <= payload.length) {\n const tableId = payload[offset];\n if (tableId == null || tableId === 0xff) {\n return;\n }\n\n const sectionLength = getPsiSectionLength(payload, offset);\n const totalLength = 3 + sectionLength;\n if (sectionLength <= 0 || totalLength <= 3) {\n return;\n }\n\n if (offset + totalLength <= payload.length) {\n addScte35SectionMarker(\n payload.subarray(offset, offset + totalLength),\n markers,\n processedSections\n );\n offset += totalLength;\n } else {\n assemblers.set(pid, {\n bytes: Array.from(payload.subarray(offset)),\n expectedLength: totalLength,\n });\n return;\n }\n }\n}\n\nexport function parseScte35FromTsPackets(\n data: Uint8Array,\n tsScte35Pids: Set<number>,\n pmtPids: Set<number>,\n processedSections: Set<string>\n): Scte35Marker[] {\n const packetInfo = detectTsPacketFormat(data);\n if (!packetInfo) {\n return [];\n }\n\n const markers: Scte35Marker[] = [];\n const sectionAssemblers = new Map<\n number,\n { bytes: number[]; expectedLength: number }\n >();\n\n for (\n let packetStart = packetInfo.offset;\n packetStart + packetInfo.packetSize <= data.length;\n packetStart += packetInfo.packetSize\n ) {\n const tsStart = packetStart + packetInfo.tsPayloadOffset;\n if (data[tsStart] !== 0x47) {\n continue;\n }\n\n const secondByte = data[tsStart + 1];\n const thirdByte = data[tsStart + 2];\n const fourthByte = data[tsStart + 3];\n if (\n secondByte == null ||\n thirdByte == null ||\n fourthByte == null ||\n (secondByte & 0x80) !== 0\n ) {\n continue;\n }\n\n const payloadUnitStart = (secondByte & 0x40) !== 0;\n const pid = ((secondByte & 0x1f) << 8) | thirdByte;\n const adaptationFieldControl = (fourthByte >> 4) & 0x03;\n const hasPayload =\n adaptationFieldControl === 1 || adaptationFieldControl === 3;\n if (!hasPayload) {\n continue;\n }\n\n let payloadStart = tsStart + 4;\n if (adaptationFieldControl === 3) {\n const adaptationLength = data[payloadStart];\n if (adaptationLength == null) {\n continue;\n }\n payloadStart += 1 + adaptationLength;\n }\n\n const payloadEnd = Math.min(tsStart + 188, data.length);\n if (payloadStart >= payloadEnd || payloadStart >= data.length) {\n continue;\n }\n\n const payload = data.subarray(payloadStart, payloadEnd);\n if (pid === 0) {\n parsePatSection(payload, payloadUnitStart, pmtPids);\n } else if (pmtPids.has(pid)) {\n parsePmtSection(payload, payloadUnitStart, tsScte35Pids);\n } else if (tsScte35Pids.has(pid)) {\n collectScte35SectionsFromPayload(\n pid,\n payload,\n payloadUnitStart,\n sectionAssemblers,\n markers,\n processedSections\n );\n }\n }\n\n return markers;\n}\n\n// --- Binary SCTE-35 parsing ---\n\nclass 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 get bytePosition(): number {\n return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n }\n}\n\nfunction readSpliceTime(\n r: BitReader,\n ptsAdjustmentTicks: number\n): number | undefined {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (!timeSpecifiedFlag) {\n r.readBits(7);\n return undefined;\n }\n r.readBits(6);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const ptsTicks =\n (high * 0x100000000 + low + ptsAdjustmentTicks) % 0x200000000;\n return ptsTicks / 90000;\n}\n\nfunction markerTypeFromSegmentationTypeId(\n segmentationTypeId: number\n): Scte35Marker[\"type\"] | undefined {\n switch (segmentationTypeId) {\n case 0x10:\n case 0x22:\n case 0x30:\n case 0x32:\n case 0x34:\n case 0x36:\n return \"start\";\n case 0x11:\n case 0x23:\n case 0x31:\n case 0x33:\n case 0x35:\n case 0x37:\n return \"end\";\n default:\n return undefined;\n }\n}\n\nfunction parseScte35SegmentationDescriptor(\n descriptor: Uint8Array\n):\n | {\n type: Scte35Marker[\"type\"];\n durationSeconds?: number;\n segmentationEventId?: number;\n }\n | undefined {\n if (descriptor.length < 11) {\n return undefined;\n }\n\n const identifier = String.fromCharCode(\n descriptor[0] ?? 0,\n descriptor[1] ?? 0,\n descriptor[2] ?? 0,\n descriptor[3] ?? 0\n );\n if (identifier !== \"CUEI\") {\n return undefined;\n }\n\n const segmentationEventId =\n ((descriptor[4] ?? 0) * 0x1000000) +\n ((descriptor[5] ?? 0) << 16) +\n ((descriptor[6] ?? 0) << 8) +\n (descriptor[7] ?? 0);\n const cancelIndicator = ((descriptor[8] ?? 0) & 0x80) !== 0;\n if (cancelIndicator) {\n return undefined;\n }\n\n const flags = descriptor[9] ?? 0;\n const programSegmentationFlag = (flags & 0x80) !== 0;\n const segmentationDurationFlag = (flags & 0x40) !== 0;\n let offset = 10;\n\n if (!programSegmentationFlag) {\n const componentCount = descriptor[offset] ?? 0;\n offset += 1 + componentCount * 6;\n if (offset > descriptor.length) {\n return undefined;\n }\n }\n\n let durationSeconds: number | undefined = undefined;\n if (segmentationDurationFlag) {\n if (offset + 5 > descriptor.length) {\n return undefined;\n }\n const durationTicks =\n ((descriptor[offset] ?? 0) * 0x100000000) +\n ((descriptor[offset + 1] ?? 0) * 0x1000000) +\n ((descriptor[offset + 2] ?? 0) << 16) +\n ((descriptor[offset + 3] ?? 0) << 8) +\n (descriptor[offset + 4] ?? 0);\n durationSeconds = durationTicks / 90000;\n offset += 5;\n }\n\n if (offset + 2 > descriptor.length) {\n return undefined;\n }\n offset += 1;\n const segmentationUpidLength = descriptor[offset] ?? 0;\n offset += 1 + segmentationUpidLength;\n if (offset >= descriptor.length) {\n return undefined;\n }\n\n const segmentationTypeId = descriptor[offset] ?? 0;\n const markerType = markerTypeFromSegmentationTypeId(segmentationTypeId);\n if (!markerType) {\n return undefined;\n }\n\n return {\n type: markerType,\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n segmentationEventId,\n };\n}\n\nfunction parseScte35SegmentationDescriptors(\n data: Uint8Array,\n offset: number\n):\n | {\n type: Scte35Marker[\"type\"];\n durationSeconds?: number;\n segmentationEventId?: number;\n }\n | undefined {\n if (offset + 2 > data.length) {\n return undefined;\n }\n\n const descriptorLoopLength =\n ((data[offset] ?? 0) << 8) | (data[offset + 1] ?? 0);\n let descriptorOffset = offset + 2;\n const descriptorEnd = Math.min(\n data.length,\n descriptorOffset + descriptorLoopLength\n );\n\n while (descriptorOffset + 2 <= descriptorEnd) {\n const descriptorTag = data[descriptorOffset] ?? 0;\n const descriptorLength = data[descriptorOffset + 1] ?? 0;\n const descriptorDataStart = descriptorOffset + 2;\n const descriptorDataEnd = descriptorDataStart + descriptorLength;\n if (descriptorDataEnd > descriptorEnd) {\n return undefined;\n }\n\n if (descriptorTag === 0x02) {\n const descriptorMarker = parseScte35SegmentationDescriptor(\n data.subarray(descriptorDataStart, descriptorDataEnd)\n );\n if (descriptorMarker) {\n return descriptorMarker;\n }\n }\n\n descriptorOffset = descriptorDataEnd;\n }\n\n return undefined;\n}\n\nexport function parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\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 if (sectionLength <= 0 || data.length < 3 + sectionLength) {\n return undefined;\n }\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 const ptsAdjustmentTicks = ptsAdjHigh * 0x100000000 + ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n\n let markerType: Scte35Marker[\"type\"] | undefined;\n let durationSeconds: number | undefined = undefined;\n let ptsSeconds: number | undefined = undefined;\n let spliceEventId: number | undefined = undefined;\n const commandBodyStart = r.bytePosition;\n\n if (spliceCommandType === 5) {\n spliceEventId = 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 markerType = outOfNetwork ? \"start\" : \"end\";\n\n if (programSpliceFlag && !spliceImmediateFlag) {\n ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\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 componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n if (ptsSeconds === undefined) {\n ptsSeconds = componentPtsSeconds;\n }\n }\n }\n }\n\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 } else if (spliceCommandType === 6) {\n ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n } else {\n return undefined;\n }\n\n const expectedDescriptorOffset =\n spliceCommandLength === 0x0fff\n ? r.bytePosition\n : commandBodyStart + spliceCommandLength;\n const descriptorMarker = parseScte35SegmentationDescriptors(\n data,\n expectedDescriptorOffset\n );\n\n if (descriptorMarker) {\n markerType = descriptorMarker.type;\n if (durationSeconds === undefined) {\n durationSeconds = descriptorMarker.durationSeconds;\n }\n }\n\n if (!markerType) {\n return undefined;\n }\n\n const marker: Scte35Marker = {\n type: markerType,\n ...(ptsSeconds !== undefined ? { ptsSeconds } : {}),\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: {\n splice_command_type: spliceCommandType,\n ...(spliceEventId !== undefined ? { splice_event_id: spliceEventId } : {}),\n ...(descriptorMarker?.segmentationEventId !== undefined\n ? { segmentation_event_id: descriptorMarker.segmentationEventId }\n : {}),\n },\n } as Scte35Marker;\n return marker;\n}\n","import type { Scte35Marker } from \"../types\";\nimport type {\n NormalizedScte35Cue,\n Scte35CueContext,\n Scte35CueSource,\n Scte35CueReadiness,\n} from \"./playerTypes\";\nimport { getFragmentStartSeconds } from \"./Scte35Parser\";\n\nexport interface Scte35CueManagerCallbacks {\n onEarlyStartCue(marker: Scte35Marker, fragmentSn: number | undefined, cueKey: string): void;\n onPlaybackCue(marker: Scte35Marker, cueKey?: string): void;\n isInAdBreak(): boolean;\n}\n\nexport class Scte35CueManager {\n private readonly pendingScte35Cues: Map<string, NormalizedScte35Cue> = new Map();\n private readonly recentScte35CueKeys: Map<string, number> = new Map();\n private readonly recentScte35CueLimit: number = 200;\n private pendingScte35CueKeyValue: string | undefined;\n private activeScte35BreakKeyValue: string | undefined;\n private scheduledScte35BreakKeyValue: string | undefined;\n\n readonly tsScte35Pids: Set<number> = new Set();\n readonly pmtPids: Set<number> = new Set();\n readonly processedTsScte35Sections: Set<string> = new Set();\n\n private debug: boolean;\n private callbacks: Scte35CueManagerCallbacks;\n\n constructor(debug: boolean, callbacks: Scte35CueManagerCallbacks) {\n this.debug = debug;\n this.callbacks = callbacks;\n }\n\n get pendingScte35CueKey(): string | undefined {\n return this.pendingScte35CueKeyValue;\n }\n set pendingScte35CueKey(value: string | undefined) {\n this.pendingScte35CueKeyValue = value;\n }\n\n get activeScte35BreakKey(): string | undefined {\n return this.activeScte35BreakKeyValue;\n }\n set activeScte35BreakKey(value: string | undefined) {\n this.activeScte35BreakKeyValue = value;\n }\n\n get scheduledScte35BreakKey(): string | undefined {\n return this.scheduledScte35BreakKeyValue;\n }\n set scheduledScte35BreakKey(value: string | undefined) {\n this.scheduledScte35BreakKeyValue = value;\n }\n\n createScte35CueContext(\n source: Scte35CueSource,\n readiness: Scte35CueReadiness,\n frag?: any\n ): Scte35CueContext {\n const context: Scte35CueContext = { source, readiness };\n if (typeof frag?.sn === \"number\") {\n context.fragmentSn = frag.sn;\n }\n const fragmentStartSec = getFragmentStartSeconds(frag);\n if (fragmentStartSec !== undefined) {\n context.fragmentStartSeconds = fragmentStartSec;\n }\n return context;\n }\n\n onScte35Cue(marker: Scte35Marker, context: Scte35CueContext): void {\n const cue = this.createScte35Cue(marker, context);\n const pendingKey = this.getPendingScte35CueKey(cue);\n\n if (context.readiness === \"early\") {\n this.pendingScte35Cues.set(pendingKey, cue);\n this.trimRecentScte35CueMaps();\n\n if (marker.type === \"start\") {\n this.callbacks.onEarlyStartCue(marker, context.fragmentSn, cue.key);\n }\n return;\n }\n\n if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n key: cue.key,\n activeScte35BreakKey: this.activeScte35BreakKeyValue,\n inAdBreak: this.callbacks.isInAdBreak(),\n source: cue.source,\n });\n }\n return;\n }\n\n if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue\", {\n key: cue.key,\n source: cue.source,\n });\n }\n return;\n }\n\n this.pendingScte35Cues.delete(pendingKey);\n this.markScte35CueHandled(cue);\n this.callbacks.onPlaybackCue(marker, cue.key);\n }\n\n activatePendingScte35CuesForFragment(frag: any): void {\n const fragmentSn = typeof frag?.sn === \"number\" ? frag.sn : undefined;\n if (fragmentSn === undefined) {\n return;\n }\n\n const matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(\n ([, cue]) => cue.fragmentSn === fragmentSn\n );\n\n matchingCues.forEach(([pendingKey, cue]) => {\n this.pendingScte35Cues.delete(pendingKey);\n const context: Scte35CueContext = {\n source: cue.source,\n readiness: \"playback\",\n };\n context.fragmentSn = fragmentSn;\n const fragmentStartSec =\n cue.fragmentStartSeconds ?? getFragmentStartSeconds(frag);\n if (fragmentStartSec !== undefined) {\n context.fragmentStartSeconds = fragmentStartSec;\n }\n this.onScte35Cue(cue.marker, context);\n });\n }\n\n private createScte35Cue(\n marker: Scte35Marker,\n context: Scte35CueContext\n ): NormalizedScte35Cue {\n const cue: NormalizedScte35Cue = {\n marker,\n source: context.source,\n readiness: context.readiness,\n key: this.getScte35CueKey(marker, context),\n };\n if (context.fragmentSn !== undefined) {\n cue.fragmentSn = context.fragmentSn;\n }\n if (context.fragmentStartSeconds !== undefined) {\n cue.fragmentStartSeconds = context.fragmentStartSeconds;\n }\n return cue;\n }\n\n private getScte35CueKey(\n marker: Scte35Marker,\n context: Scte35CueContext\n ): string {\n const raw = this.getScte35MarkerRaw(marker);\n const spliceEventId = this.toIdentityString(raw?.splice_event_id);\n if (spliceEventId) {\n return `splice:${spliceEventId}`;\n }\n\n const segmentationEventId = this.toIdentityString(raw?.segmentation_event_id);\n if (segmentationEventId) {\n return `segmentation:${segmentationEventId}`;\n }\n\n const daterangeId = this.toIdentityString(raw?.attrs?.ID);\n if (daterangeId) {\n return `daterange:${daterangeId}`;\n }\n\n const scteValue =\n this.toIdentityString(raw?.attrs?.[\"SCTE35-OUT\"]) ||\n this.toIdentityString(raw?.attrs?.[\"SCTE35-IN\"]);\n if (scteValue) {\n return `daterange-scte:${scteValue}`;\n }\n\n if (typeof marker.ptsSeconds === \"number\" && Number.isFinite(marker.ptsSeconds)) {\n return `pts:${Math.round(marker.ptsSeconds * 2) / 2}`;\n }\n\n if (context.fragmentSn !== undefined) {\n return `fragment:${context.fragmentSn}`;\n }\n\n return `${context.source}:wallclock:${Math.floor(Date.now() / 1000)}`;\n }\n\n private getPendingScte35CueKey(cue: NormalizedScte35Cue): string {\n return `${cue.marker.type}:${cue.key}:${\n cue.fragmentSn !== undefined ? cue.fragmentSn : \"unknown\"\n }`;\n }\n\n private getScte35MarkerRaw(marker: Scte35Marker): any {\n return typeof marker.raw === \"object\" && marker.raw !== null\n ? (marker.raw as any)\n : {};\n }\n\n private toIdentityString(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value);\n }\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n return undefined;\n }\n\n isStrongScte35CueKey(key: string | undefined): boolean {\n return !!(\n key &&\n (key.startsWith(\"splice:\") ||\n key.startsWith(\"segmentation:\") ||\n key.startsWith(\"daterange:\") ||\n key.startsWith(\"daterange-scte:\"))\n );\n }\n\n private hasRecentlyHandledScte35Cue(cue: NormalizedScte35Cue): boolean {\n if (\n this.activeScte35BreakKeyValue === cue.key ||\n this.scheduledScte35BreakKeyValue === cue.key\n ) {\n return true;\n }\n\n const recentKey = `${cue.marker.type}:${cue.key}`;\n return this.recentScte35CueKeys.has(recentKey);\n }\n\n private markScte35CueHandled(cue: NormalizedScte35Cue): void {\n this.recentScte35CueKeys.set(`${cue.marker.type}:${cue.key}`, Date.now());\n this.trimRecentScte35CueMaps();\n }\n\n private trimRecentScte35CueMaps(): void {\n while (this.recentScte35CueKeys.size > this.recentScte35CueLimit) {\n const firstKey = this.recentScte35CueKeys.keys().next().value;\n if (!firstKey) {\n break;\n }\n this.recentScte35CueKeys.delete(firstKey);\n }\n\n while (this.pendingScte35Cues.size > this.recentScte35CueLimit) {\n const firstKey = this.pendingScte35Cues.keys().next().value;\n if (!firstKey) {\n break;\n }\n this.pendingScte35Cues.delete(firstKey);\n }\n }\n\n private shouldAcceptScte35EndCue(cue: NormalizedScte35Cue): boolean {\n if (!this.callbacks.isInAdBreak()) {\n return false;\n }\n\n if (\n this.isStrongScte35CueKey(this.activeScte35BreakKeyValue) &&\n this.isStrongScte35CueKey(cue.key) &&\n this.activeScte35BreakKeyValue !== cue.key\n ) {\n return false;\n }\n\n return true;\n }\n}\n","import type {\n StormcloudVideoPlayerConfig,\n AdBreak,\n StormcloudApiResponse,\n AdController,\n} from \"../types\";\nimport type { PalNonceManager } from \"../sdk/pal\";\nimport { applyVastMacros, generateCorrelator, normalizeVastTagUrl } from \"../utils/vastMacros\";\nimport type { VastConsentSignals } from \"../utils/vastMacros\";\nimport { resolveVastEnvironmentSignals } from \"../utils/vastEnvironmentSignals\";\nimport { sendHeartbeat, sendInitialTracking } from \"../utils/tracking\";\n\nexport class AdConfigManager {\n vmapBreaks: AdBreak[] = [];\n consumedVmapBreakIds: Set<string> = new Set();\n apiVastTagUrl: string | undefined;\n apiNumberAds: number | undefined;\n readonly streamCorrelator: string = generateCorrelator();\n consentSignals: VastConsentSignals = {};\n podCounter: number = 0;\n podAssignedByPrefetch: boolean = false;\n adRequestPositionInBreak: number = 0;\n\n private lastHeartbeatTime: number = 0;\n private heartbeatInterval: number | undefined;\n\n private config: StormcloudVideoPlayerConfig;\n private video: HTMLVideoElement;\n\n constructor(config: StormcloudVideoPlayerConfig, video: HTMLVideoElement) {\n this.config = config;\n this.video = video;\n }\n\n get debug(): boolean {\n return !!this.config.debugAdTiming;\n }\n\n isVmapEnabled(): boolean {\n return !!(this.config.isVmap && this.config.vmapUrl?.trim());\n }\n\n async fetchAdConfiguration(): Promise<void> {\n if (this.isVmapEnabled()) {\n await this.fetchAndParseVmap(this.config.vmapUrl!);\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] VMAP mode enabled\");\n }\n return;\n }\n\n const vastMode = this.config.vastMode || \"default\";\n\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.debug) {\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.debug) {\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 = normalizeVastTagUrl(this.config.vastTagUrl);\n if (this.debug) {\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.debug) {\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.debug) {\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 let decodedPayload = imaPayload;\n try {\n decodedPayload = decodeURIComponent(imaPayload);\n } catch {\n console.warn(\"[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:\", imaPayload);\n }\n console.log(\"[StormcloudVideoPlayer] Raw VAST tag URL (from API):\", decodedPayload);\n this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);\n if (this.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Normalized VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.debug) {\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.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n\n private async fetchAndParseVmap(vmapUrl: string): Promise<void> {\n if (!vmapUrl.trim()) {\n return;\n }\n\n try {\n const response = await fetch(vmapUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VMAP (${response.status})`);\n }\n\n const vmapXml = await response.text();\n this.vmapBreaks = this.parseVmapToBreaks(vmapXml);\n this.consumedVmapBreakIds.clear();\n\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Loaded ${this.vmapBreaks.length} VMAP ad break(s) from:`,\n vmapUrl\n );\n }\n } catch (error) {\n this.vmapBreaks = [];\n this.consumedVmapBreakIds.clear();\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Failed to load VMAP:\", error);\n }\n }\n }\n\n private parseVmapToBreaks(vmapXml: string): AdBreak[] {\n if (typeof DOMParser === \"undefined\") {\n return [];\n }\n\n const doc = new DOMParser().parseFromString(vmapXml, \"application/xml\");\n if (doc.querySelector(\"parsererror\")) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n }\n return [];\n }\n\n const VMAP_NS = \"http://www.iab.net/videosuite/vmap\";\n let adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, \"AdBreak\"));\n if (adBreakNodes.length === 0) {\n adBreakNodes = Array.from(\n doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\n );\n }\n if (adBreakNodes.length === 0) {\n adBreakNodes = Array.from(doc.getElementsByTagName(\"*\")).filter(\n (el) => el.localName === \"AdBreak\"\n );\n }\n const parsed: AdBreak[] = [];\n\n adBreakNodes.forEach((node, index) => {\n const timeOffsetRaw = (node.getAttribute(\"timeOffset\") || \"\").trim();\n const startTimeMs = this.parseVmapTimeOffsetToMs(timeOffsetRaw);\n if (startTimeMs == null) {\n return;\n }\n\n let adTagNode = node.getElementsByTagNameNS(VMAP_NS, \"AdTagURI\")[0];\n if (!adTagNode) {\n adTagNode =\n (node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\") as Element | null) ??\n undefined;\n }\n const adTagUrl = (adTagNode?.textContent || \"\").trim();\n if (!adTagUrl) {\n return;\n }\n\n const breakId =\n node.getAttribute(\"breakId\") ||\n `vmap-break-${index}-${timeOffsetRaw || \"unknown\"}`;\n parsed.push({\n id: breakId,\n startTimeMs,\n vastTagUrl: adTagUrl,\n });\n });\n\n parsed.sort((a, b) => {\n const aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;\n const bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;\n return aStart - bStart;\n });\n\n return parsed;\n }\n\n private parseVmapTimeOffsetToMs(timeOffset: string): number | undefined {\n if (!timeOffset) {\n return undefined;\n }\n\n const normalized = timeOffset.trim().toLowerCase();\n if (normalized === \"start\") {\n return 0;\n }\n\n if (normalized === \"end\") {\n return -1;\n }\n\n const hms = timeOffset.match(\n /^(\\d{1,2}):(\\d{2}):(\\d{2})(?:\\.(\\d{1,3}))?$/\n );\n if (hms) {\n const [, hh, mm, ss, ms = \"0\"] = hms;\n const hours = Number(hh);\n const minutes = Number(mm);\n const seconds = Number(ss);\n const millis = Number(ms.padEnd(3, \"0\").slice(0, 3));\n return ((hours * 3600 + minutes * 60 + seconds) * 1000) + millis;\n }\n\n const percent = timeOffset.match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (percent) {\n const ratio = Number(percent[1]) / 100;\n const durationSec = this.video.duration;\n if (Number.isFinite(durationSec) && durationSec > 0) {\n return Math.floor(durationSec * 1000 * ratio);\n }\n return undefined;\n }\n\n return undefined;\n }\n\n getAdBreakKey(adBreak: AdBreak): string {\n if (adBreak.id) {\n return adBreak.id;\n }\n return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n }\n\n resolveBreakStartMs(adBreak: AdBreak): number | undefined {\n if (adBreak.startTimeMs >= 0) {\n return adBreak.startTimeMs;\n }\n\n if (adBreak.startTimeMs === -1) {\n const durationSec = this.video.duration;\n if (Number.isFinite(durationSec) && durationSec > 0) {\n return Math.floor(durationSec * 1000);\n }\n }\n\n return undefined;\n }\n\n findCurrentOrNextBreak(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = this.vmapBreaks;\n let candidate: AdBreak | undefined;\n const tol = this.config.driftToleranceMs ?? 1000;\n for (const b of schedule) {\n if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n continue;\n }\n const breakStartMs = this.resolveBreakStartMs(b);\n if (breakStartMs == null) {\n continue;\n }\n if (\n breakStartMs <= nowMs + tol &&\n (candidate == null ||\n breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))\n ) {\n candidate = b;\n }\n }\n return candidate;\n }\n\n findBreakForTime(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = this.vmapBreaks;\n for (const b of schedule) {\n if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n continue;\n }\n const breakStartMs = this.resolveBreakStartMs(b);\n if (breakStartMs == null) {\n continue;\n }\n\n if (b.durationMs) {\n const end = breakStartMs + b.durationMs;\n if (nowMs >= breakStartMs && nowMs < end) {\n return b;\n }\n continue;\n }\n\n if (nowMs >= breakStartMs) {\n return b;\n }\n }\n return undefined;\n }\n\n 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 beginNewAdPod(): void {\n this.podCounter++;\n this.adRequestPositionInBreak = 0;\n }\n\n generateVastUrlsWithCorrelators(\n baseUrl: string,\n count: number,\n adPlayer: AdController,\n palNonce: PalNonceManager,\n inAdBreak: boolean\n ): string[] {\n const urls: string[] = [];\n\n for (let i = 0; i < count; i++) {\n this.adRequestPositionInBreak++;\n\n const adWillPlayMuted = inAdBreak\n ? adPlayer.getOriginalMutedState()\n : this.video.muted;\n const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n\n const urlWithMacros = applyVastMacros(baseUrl, {\n correlator: generateCorrelator(),\n streamCorrelator: this.streamCorrelator,\n pod: this.podCounter > 0 ? this.podCounter : undefined,\n adPosition: this.adRequestPositionInBreak,\n isCtv: envSignals.isCtv,\n contentUrl: envSignals.contentUrl,\n pageUrl:\n !envSignals.isCtv && typeof window !== \"undefined\"\n ? window.location.href\n : undefined,\n adWillPlayMuted,\n adWillAutoPlay: !!this.config.autoplay,\n appId: envSignals.appId,\n appName: envSignals.appName,\n sessionId: envSignals.sessionId,\n deviceId: envSignals.deviceId,\n deviceIdType: envSignals.deviceIdType,\n limitAdTracking: envSignals.limitAdTracking,\n deviceTypeHint: envSignals.deviceTypeHint,\n adTest: this.config.adTest,\n consent: this.consentSignals,\n });\n\n const finalUrl = palNonce.injectNonce(urlWithMacros);\n console.log(\n `[StormcloudVideoPlayer] Resolved ad request URL (pod=${this.podCounter}, pos=${this.adRequestPositionInBreak}):`,\n finalUrl\n );\n urls.push(finalUrl);\n }\n\n return urls;\n }\n\n // --- Tracking ---\n\n 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.debug) {\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.debug) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n destroyTracking(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n }\n}\n","import type { AdController, StormcloudVideoPlayerConfig, Scte35Marker } from \"../types\";\n\nexport interface AdTimingCallbacks {\n onAdStopTimerFired(): void;\n onAdStartTimerFired(marker: Scte35Marker, cueKey: string | undefined): void;\n onWatchdogTimeout(): void;\n onFailsafeTimeout(): void;\n}\n\nexport class AdTimingService {\n private adStopTimerId: number | undefined;\n private adStartTimerId: number | undefined;\n private adFailsafeTimerId: number | undefined;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n\n ptsDriftEmaMs = 0;\n expectedAdBreakDurationMs: number | undefined;\n currentAdBreakStartWallClockMs: number | undefined;\n scteAdBreakEndWallClockMs: number | undefined;\n adBreakPlayedDurationMs: number = 0;\n adBreakEpoch: number = 0;\n\n adRequestTokenCounter = 0;\n activeAdRequestToken: number | null = null;\n currentAdIndex: number = 0;\n totalAdsInBreak: number = 0;\n totalAdRequestsInBreak: number = 0;\n readonly maxTotalAdRequestsPerBreak: number = 10;\n lastAdRequestTime: number = 0;\n consecutiveFailures: number = 0;\n readonly maxConsecutiveFailures: number = 5;\n readonly minAdRequestIntervalMs: number = 3000;\n readonly backoffBaseMs: number = 1000;\n readonly maxBackoffMs: number = 15000;\n private readonly defaultMinRemainingMsToStartAd: number = 4000;\n\n failedVastUrls: Set<string> = new Set();\n temporaryFailureUrls: Map<string, number> = new Map();\n private readonly temporaryFailureCooldownMs: number = 30000;\n\n private globalConsecutiveNoFills: number = 0;\n private readonly globalNoFillThreshold: number = 3;\n private globalNoFillCooldownUntil: number = 0;\n private readonly globalNoFillBackoffBaseMs: number = 5000;\n private readonly globalNoFillBackoffMaxMs: number = 60000;\n private globalLastGamRequestTime: number = 0;\n private readonly globalMinGamIntervalMs: number = 3000;\n\n private config: StormcloudVideoPlayerConfig;\n private video: HTMLVideoElement;\n private callbacks: AdTimingCallbacks;\n\n constructor(\n config: StormcloudVideoPlayerConfig,\n video: HTMLVideoElement,\n callbacks: AdTimingCallbacks\n ) {\n this.config = config;\n this.video = video;\n this.callbacks = callbacks;\n }\n\n get debug(): boolean {\n return !!this.config.debugAdTiming;\n }\n\n // --- Ad stop timer ---\n\n 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 clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private ensureAdStoppedByTimer(): void {\n this.adStopTimerId = undefined;\n this.callbacks.onAdStopTimerFired();\n }\n\n // --- Ad start timer ---\n\n scheduleAdStartIn(\n delayMs: number,\n marker: Scte35Marker = { type: \"start\" } as Scte35Marker,\n cueKey?: string\n ): void {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.callbacks.onAdStartTimerFired(marker, cueKey);\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.callbacks.onAdStartTimerFired(marker, cueKey);\n }, ms) as unknown as number;\n }\n\n clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n // --- PTS drift ---\n\n 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 resolveScteBreakStartWallClockMs(marker: Scte35Marker): number {\n const nowWallClockMs = Date.now();\n if (typeof marker.ptsSeconds !== \"number\") {\n return nowWallClockMs;\n }\n\n const nowMs = this.video.currentTime * 1000;\n const estimatedCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = marker.ptsSeconds * 1000 - estimatedCurrentPtsMs;\n if (!Number.isFinite(deltaMs)) {\n return nowWallClockMs;\n }\n\n return nowWallClockMs + Math.floor(deltaMs);\n }\n\n // --- Duration boundary ---\n\n setAdBreakDurationBoundary(durationMs: number | undefined): void {\n this.expectedAdBreakDurationMs = durationMs;\n if (\n durationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n this.scteAdBreakEndWallClockMs =\n this.currentAdBreakStartWallClockMs + durationMs;\n } else {\n this.scteAdBreakEndWallClockMs = undefined;\n }\n }\n\n scheduleAdStopAtBreakBoundary(): void {\n if (this.expectedAdBreakDurationMs == null) {\n return;\n }\n this.scheduleAdStopCountdown(this.getWallClockRemainingAdMs());\n }\n\n // --- Duration budget ---\n\n getWallClockRemainingAdMs(): number {\n const endWallClockMs = this.getAdBreakEndWallClockMs();\n if (endWallClockMs != null) {\n return Math.max(0, endWallClockMs - Date.now());\n }\n return 0;\n }\n\n getAdBreakEndWallClockMs(): number | undefined {\n if (this.scteAdBreakEndWallClockMs != null) {\n return this.scteAdBreakEndWallClockMs;\n }\n if (\n this.expectedAdBreakDurationMs == null ||\n this.currentAdBreakStartWallClockMs == null\n ) {\n return undefined;\n }\n return this.currentAdBreakStartWallClockMs + this.expectedAdBreakDurationMs;\n }\n\n getDurationBudgetRemainingMs(): number {\n if (this.expectedAdBreakDurationMs == null) {\n return 0;\n }\n return Math.max(0, this.expectedAdBreakDurationMs - this.adBreakPlayedDurationMs);\n }\n\n getLoadedAdDurationMs(adController: AdController): number {\n const durationSec = adController.getLoadedAdDuration?.();\n if (durationSec == null || durationSec <= 0) {\n return 0;\n }\n return Math.round(durationSec * 1000);\n }\n\n adFitsRemainingBudget(durationMs: number): boolean {\n if (durationMs <= 0) {\n return true;\n }\n return durationMs <= this.getDurationBudgetRemainingMs();\n }\n\n logAdDurationDecision(\n accepted: boolean,\n durationMs: number,\n adController: AdController\n ): void {\n if (!this.debug) {\n return;\n }\n const remainingBudget = this.getDurationBudgetRemainingMs();\n const adId = adController.getLoadedAdId?.() ?? \"unknown\";\n if (accepted) {\n console.log(\n `[AD-DURATION] Accepted ad id=${adId}, duration=${durationMs}ms, budget remaining after play=${Math.max(0, remainingBudget - durationMs)}ms`\n );\n } else {\n console.log(\n `[AD-DURATION] Rejected ad id=${adId}, duration=${durationMs}ms exceeds remaining budget=${remainingBudget}ms — requesting another ad`\n );\n }\n }\n\n recordPlayedAdDuration(adController: AdController): void {\n const durationMs = this.getLoadedAdDurationMs(adController);\n if (durationMs <= 0) {\n return;\n }\n this.adBreakPlayedDurationMs += durationMs;\n if (this.debug) {\n console.log(\n `[AD-DURATION] Played ${durationMs}ms — total played=${this.adBreakPlayedDurationMs}ms / ${this.expectedAdBreakDurationMs ?? \"?\"}ms`\n );\n }\n }\n\n ensureLoadedAdFitsBudget(adController: AdController): boolean {\n const durationMs = this.getLoadedAdDurationMs(adController);\n const fits = this.adFitsRemainingBudget(durationMs);\n this.logAdDurationDecision(fits, durationMs, adController);\n return fits;\n }\n\n rejectLoadedAdForDuration(adController: AdController): void {\n try {\n adController.destroy();\n } catch {}\n }\n\n markAdStarted(): void {\n this.currentAdIndex++;\n this.totalAdsInBreak = this.currentAdIndex;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n }\n\n getRemainingAdMs(): number {\n const wallClockRemaining = this.getWallClockRemainingAdMs();\n const budgetRemaining = this.getDurationBudgetRemainingMs();\n if (this.expectedAdBreakDurationMs == null) {\n return wallClockRemaining;\n }\n return Math.min(wallClockRemaining, budgetRemaining);\n }\n\n getMinRemainingMsToStartAd(): number {\n const configured = this.config.minRemainingMsToStartAd;\n if (typeof configured === \"number\" && configured >= 0) {\n return configured;\n }\n return this.defaultMinRemainingMsToStartAd;\n }\n\n hasTimeToStartAnotherAd(): boolean {\n const minRemaining = this.getMinRemainingMsToStartAd();\n return (\n this.getWallClockRemainingAdMs() > minRemaining &&\n this.getDurationBudgetRemainingMs() > minRemaining\n );\n }\n\n // --- Circuit breaker ---\n\n isTemporaryAdError(error: Error): boolean {\n const message = error?.message?.toLowerCase() || \"\";\n\n if (message.includes(\"no ads available\") || message.includes(\"no fill\") || message.includes(\"nofill\")) {\n return true;\n }\n if (message.includes(\"timeout\")) {\n return true;\n }\n if (message.includes(\"rate limit\") || message.includes(\"too many requests\")) {\n return true;\n }\n if (message.includes(\"ad playback error\")) {\n return true;\n }\n return false;\n }\n\n isUrlInCooldown(vastTagUrl: string): boolean {\n const failureTime = this.temporaryFailureUrls.get(vastTagUrl);\n if (failureTime == null) {\n return false;\n }\n\n const elapsed = Date.now() - failureTime;\n if (elapsed >= this.temporaryFailureCooldownMs) {\n this.temporaryFailureUrls.delete(vastTagUrl);\n return false;\n }\n\n return true;\n }\n\n cleanupTemporaryFailures(): void {\n const now = Date.now();\n for (const [url, timestamp] of this.temporaryFailureUrls) {\n if (now - timestamp >= this.temporaryFailureCooldownMs) {\n this.temporaryFailureUrls.delete(url);\n }\n }\n }\n\n isGamInCooldown(): boolean {\n return Date.now() < this.globalNoFillCooldownUntil;\n }\n\n recordGamNoFill(): void {\n this.globalConsecutiveNoFills++;\n\n if (this.globalConsecutiveNoFills >= this.globalNoFillThreshold) {\n const exponent = this.globalConsecutiveNoFills - this.globalNoFillThreshold;\n const backoff = Math.min(\n this.globalNoFillBackoffBaseMs * Math.pow(2, exponent),\n this.globalNoFillBackoffMaxMs\n );\n this.globalNoFillCooldownUntil = Date.now() + backoff;\n\n if (this.debug) {\n console.log(\n `[CIRCUIT-BREAKER] GAM cooldown activated: ${backoff}ms (${this.globalConsecutiveNoFills} consecutive no-fills)`\n );\n }\n }\n }\n\n resetGamNoFillCounter(): void {\n if (this.globalConsecutiveNoFills > 0 && this.debug) {\n console.log(\n `[CIRCUIT-BREAKER] Resetting no-fill counter (was ${this.globalConsecutiveNoFills})`\n );\n }\n this.globalConsecutiveNoFills = 0;\n this.globalNoFillCooldownUntil = 0;\n }\n\n async enforceGlobalRateLimit(): Promise<void> {\n const now = Date.now();\n const elapsed = now - this.globalLastGamRequestTime;\n if (elapsed < this.globalMinGamIntervalMs) {\n const waitMs = this.globalMinGamIntervalMs - elapsed;\n if (this.debug) {\n console.log(`[RATE-LIMIT] Waiting ${waitMs}ms before next GAM request`);\n }\n await new Promise(resolve => setTimeout(resolve, waitMs));\n }\n this.globalLastGamRequestTime = Date.now();\n }\n\n // --- Watchdog ---\n\n 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.callbacks.onWatchdogTimeout();\n }, timeoutMs) as unknown as number;\n\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n\n 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 // --- Failsafe ---\n\n 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 });\n\n this.callbacks.onFailsafeTimeout();\n }, failsafeMs) as unknown as number;\n\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n\n 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 logAdState(event: string, extra: Record<string, unknown> = {}, adPlayer?: AdController, inAdBreak?: boolean, showAds?: boolean): void {\n if (!this.debug) {\n return;\n }\n\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: new Date().toISOString(),\n showAds: showAds ?? false,\n adPlaying: adPlayer?.isAdPlaying() ?? false,\n inAdBreak: inAdBreak ?? false,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n // --- Reset for ad break end ---\n\n resetForBreakEnd(): void {\n this.clearAdStopTimer();\n this.clearAdStartTimer();\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.scteAdBreakEndWallClockMs = undefined;\n this.adBreakPlayedDurationMs = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.consecutiveFailures = 0;\n this.globalConsecutiveNoFills = 0;\n this.adBreakEpoch++;\n }\n\n destroy(): void {\n this.clearAdStopTimer();\n this.clearAdStartTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n }\n}\n","import type { AdController, Scte35Marker } from \"../types\";\nimport type { AdTimingService } from \"./AdTimingService\";\n\nexport interface AdPreloadPoolDeps {\n debug: boolean;\n createAdPlayer(continueLiveStreamDuringAds: boolean): AdController;\n shouldContinueLiveStreamDuringAds(): boolean;\n timing: AdTimingService;\n generateVastUrlsWithCorrelators(baseUrl: string, count: number): string[];\n isInAdBreak(): boolean;\n getPendingAdBreak(): { marker: Scte35Marker; vastUrls: string[]; isFetching: boolean } | null;\n}\n\nexport class AdPreloadPool {\n private pool: Array<{\n vastUrl: string;\n adController: AdController;\n loadedAt: number;\n isReady: boolean;\n loadPromise: Promise<void>;\n durationSeconds?: number;\n }> = [];\n private readonly maxPoolSize: number = 2;\n private poolActive: boolean = false;\n private loopRunning: boolean = false;\n\n private deps: AdPreloadPoolDeps;\n\n constructor(deps: AdPreloadPoolDeps) {\n this.deps = deps;\n }\n\n get active(): boolean {\n return this.poolActive;\n }\n\n set active(value: boolean) {\n this.poolActive = value;\n }\n\n get isLoopRunning(): boolean {\n return this.loopRunning;\n }\n\n startPreloadPool(\n baseVastUrl: string,\n initialUrls: string[],\n startLoopImmediately: boolean = true\n ): void {\n if (this.poolActive) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n }\n return;\n }\n\n this.poolActive = true;\n\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Starting preload pool EARLY (target size: ${this.maxPoolSize})`);\n console.log(`[PRELOAD-POOL] Ad break hasn't started yet, but preloading ads in advance`);\n }\n\n for (const url of initialUrls) {\n if (this.pool.length < this.maxPoolSize) {\n this.preloadAdIntoPool(url);\n }\n }\n\n if (startLoopImmediately) {\n this.preloadPoolLoop(baseVastUrl);\n } else if (this.deps.debug) {\n console.log(\n \"[PRELOAD-POOL] Pre-break mode: preloaded once, waiting for SCTE start to continue fetching\"\n );\n }\n }\n\n private async preloadAdIntoPool(vastUrl: string): Promise<void> {\n const timing = this.deps.timing;\n\n if (timing.isGamInCooldown()) {\n if (this.deps.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n }\n return;\n }\n\n if (\n this.pool.some(entry => entry.vastUrl === vastUrl) ||\n timing.failedVastUrls.has(vastUrl) ||\n timing.isUrlInCooldown(vastUrl)\n ) {\n return;\n }\n\n if (this.pool.length >= this.maxPoolSize) {\n return;\n }\n\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Preloading ad into pool: ${vastUrl}`);\n }\n\n const epoch = timing.adBreakEpoch;\n const loadPromise = (async () => {\n let hasAdError = false;\n let adErrorPayload: any = null;\n let errorListenerCleanup: (() => void) | null = null;\n\n try {\n const continueLiveStreamDuringAds = this.deps.shouldContinueLiveStreamDuringAds();\n const preloadAd = this.deps.createAdPlayer(continueLiveStreamDuringAds);\n preloadAd.initialize();\n\n const errorListener = (payload?: any) => {\n hasAdError = true;\n adErrorPayload = payload;\n };\n preloadAd.on(\"ad_error\", errorListener);\n errorListenerCleanup = () => preloadAd.off(\"ad_error\", errorListener);\n\n await timing.enforceGlobalRateLimit();\n await preloadAd.requestAds(vastUrl);\n\n preloadAd.pause();\n\n await new Promise(resolve => setTimeout(resolve, 1500));\n\n preloadAd.pause();\n\n if (hasAdError) {\n const isNoFill = adErrorPayload?.isNoFill ||\n adErrorPayload?.code === 303 ||\n adErrorPayload?.vastErrorCode === 303;\n\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n preloadAd.destroy();\n\n timing.recordGamNoFill();\n\n if (isNoFill) {\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preload returned no-fill: ${vastUrl}`);\n }\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n } else {\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n }\n if (adErrorPayload && !timing.isTemporaryAdError(adErrorPayload as Error)) {\n timing.failedVastUrls.add(vastUrl);\n } else {\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n return;\n }\n\n if (!this.poolActive || epoch !== timing.adBreakEpoch) {\n if (this.deps.debug) {\n console.log(\n \"[PRELOAD-POOL] Discarding preloaded ad - break ended during fetch\"\n );\n }\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n try {\n preloadAd.destroy();\n } catch {}\n return;\n }\n\n const poolEntry: {\n vastUrl: string;\n adController: AdController;\n loadedAt: number;\n isReady: boolean;\n loadPromise: Promise<void>;\n durationSeconds?: number;\n } = {\n vastUrl,\n adController: preloadAd,\n loadedAt: Date.now(),\n isReady: true,\n loadPromise: Promise.resolve(),\n };\n const loadedDuration = preloadAd.getLoadedAdDuration?.();\n if (loadedDuration != null && loadedDuration > 0) {\n poolEntry.durationSeconds = loadedDuration;\n }\n\n const lateErrorListener = (payload?: any) => {\n const index = this.pool.findIndex(entry => entry.vastUrl === vastUrl);\n if (index >= 0) {\n this.pool.splice(index, 1);\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Late error detected, removed from pool: ${vastUrl}`, payload);\n }\n try {\n preloadAd.destroy();\n } catch {}\n }\n };\n preloadAd.on(\"ad_error\", lateErrorListener);\n\n this.pool.push(poolEntry);\n\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preloaded (no errors detected within timeout) (pool size: ${this.pool.length}/${this.maxPoolSize}, duration=${poolEntry.durationSeconds ?? \"?\"}s)`);\n }\n\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n } catch (error) {\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n\n timing.recordGamNoFill();\n\n if (this.deps.debug) {\n console.warn(`[PRELOAD-POOL] Failed to preload ad: ${vastUrl}`, error);\n }\n\n if (error instanceof Error && !timing.isTemporaryAdError(error)) {\n timing.failedVastUrls.add(vastUrl);\n } else if (error instanceof Error && timing.isTemporaryAdError(error)) {\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n })();\n\n loadPromise.catch(() => {});\n }\n\n async preloadPoolLoop(baseVastUrl: string): Promise<void> {\n if (this.loopRunning) {\n return;\n }\n\n this.loopRunning = true;\n const epoch = this.deps.timing.adBreakEpoch;\n\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Starting continuous preload loop\");\n }\n\n while (this.poolActive && epoch === this.deps.timing.adBreakEpoch) {\n if (this.deps.timing.isGamInCooldown()) {\n if (this.deps.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n }\n break;\n }\n\n if (!this.deps.isInAdBreak() && this.pool.length >= this.maxPoolSize) {\n await new Promise(resolve => setTimeout(resolve, 2000));\n continue;\n }\n\n if (!this.deps.isInAdBreak() && this.deps.getPendingAdBreak() === null) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n }\n break;\n }\n\n while (this.pool.length < this.maxPoolSize) {\n if (\n !this.poolActive ||\n epoch !== this.deps.timing.adBreakEpoch ||\n this.deps.timing.isGamInCooldown()\n ) {\n break;\n }\n\n if (this.deps.isInAdBreak() && !this.deps.timing.hasTimeToStartAnotherAd()) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Not enough ad break time left, stopping preload\");\n }\n break;\n }\n\n const newUrls = this.deps.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const newUrl = newUrls[0];\n\n if (newUrl && !this.deps.timing.failedVastUrls.has(newUrl) && !this.deps.timing.isUrlInCooldown(newUrl)) {\n await this.preloadAdIntoPool(newUrl);\n }\n\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n\n await new Promise(resolve => setTimeout(resolve, 2000));\n }\n\n this.loopRunning = false;\n\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Preload loop ended\");\n }\n }\n\n getPreloadedAd(): { vastUrl: string; adController: AdController } | null {\n if (this.pool.length === 0) {\n return null;\n }\n\n const entry = this.pool.shift();\n if (!entry || !entry.isReady) {\n return null;\n }\n\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Using preloaded ad from pool (${this.pool.length} remaining)`);\n }\n\n return {\n vastUrl: entry.vastUrl,\n adController: entry.adController,\n };\n }\n\n stop(): void {\n this.poolActive = false;\n this.loopRunning = false;\n\n for (const entry of this.pool) {\n try {\n entry.adController.destroy();\n } catch (error) {\n if (this.deps.debug) {\n console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n }\n }\n }\n\n this.pool = [];\n\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Preload pool stopped and cleaned up\");\n }\n }\n}\n","export class PlaceholderLayer {\n private container: HTMLDivElement | undefined;\n private debug: boolean;\n private video: HTMLVideoElement;\n\n constructor(video: HTMLVideoElement, debug: boolean) {\n this.video = video;\n this.debug = debug;\n }\n\n private ensureContainer(): void {\n if (this.container) {\n return;\n }\n\n const el = document.createElement(\"div\");\n el.style.position = \"absolute\";\n el.style.left = \"0\";\n el.style.top = \"0\";\n el.style.right = \"0\";\n el.style.bottom = \"0\";\n el.style.display = \"none\";\n el.style.alignItems = \"center\";\n el.style.justifyContent = \"center\";\n el.style.pointerEvents = \"none\";\n el.style.zIndex = \"5\";\n el.style.backgroundColor = \"#000\";\n el.style.transition = \"opacity 0.3s ease-in-out\";\n el.style.opacity = \"0\";\n\n if (!this.video.parentElement) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n\n this.video.parentElement.appendChild(el);\n this.container = el;\n }\n\n show(): void {\n this.ensureContainer();\n\n if (!this.container) {\n return;\n }\n\n if (!this.video.muted) {\n this.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n\n const wasHidden = this.container.style.display === \"none\" || this.container.style.opacity === \"0\";\n if (wasHidden) {\n this.container.style.transition = \"none\";\n } else {\n this.container.style.transition = \"opacity 0.3s ease-in-out\";\n }\n\n this.container.style.backgroundColor = \"#000\";\n this.container.style.display = \"flex\";\n this.container.offsetHeight;\n this.container.style.opacity = \"1\";\n this.container.style.pointerEvents = \"auto\";\n\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.container) {\n this.container.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and ad layer)\");\n }\n }\n\n hide(): void {\n if (!this.container) {\n return;\n }\n\n this.container.style.opacity = \"0\";\n setTimeout(() => {\n if (this.container) {\n this.container.style.display = \"none\";\n this.container.style.pointerEvents = \"none\";\n this.container.style.backgroundColor = \"#000\";\n }\n }, 300);\n\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n\n destroy(): void {\n if (this.container) {\n if (this.container.parentElement) {\n this.container.parentElement.removeChild(this.container);\n }\n this.container = undefined;\n }\n }\n}\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n} from \"../types\";\nimport type { Scte35CueContext } from \"./playerTypes\";\nimport {\n parseScte35FromId3,\n parseScte35FromTsPackets,\n normalizeFragmentPayload,\n getFragmentStartSeconds,\n parseCueOutDuration,\n parseCueOutCont,\n parseAttributeList,\n toNumber,\n} from \"./Scte35Parser\";\nimport type { Scte35CueManager } from \"./Scte35CueManager\";\nimport type { AdTimingService } from \"./AdTimingService\";\n\nexport interface HlsEngineCallbacks {\n onManifestParsed(isLive: boolean): Promise<void>;\n onScte35Cue(marker: Scte35Marker, context: Scte35CueContext): void;\n activatePendingCuesForFragment(frag: any): void;\n onFatalDestroy(): void;\n isInAdBreak(): boolean;\n hasPendingAdBreak(): boolean;\n}\n\nexport class HlsEngine {\n hls: Hls | undefined;\n isLiveStream: boolean = false;\n nativeHlsMode: boolean = false;\n videoSrcProtection: string | null = null;\n\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n\n private readonly config: StormcloudVideoPlayerConfig;\n private readonly video: HTMLVideoElement;\n private readonly cueManager: Scte35CueManager;\n private readonly timing: AdTimingService;\n private readonly callbacks: HlsEngineCallbacks;\n\n constructor(\n config: StormcloudVideoPlayerConfig,\n video: HTMLVideoElement,\n cueManager: Scte35CueManager,\n timing: AdTimingService,\n callbacks: HlsEngineCallbacks\n ) {\n this.config = config;\n this.video = video;\n this.cueManager = cueManager;\n this.timing = timing;\n this.callbacks = callbacks;\n }\n\n private get debug(): boolean {\n return !!this.config.debugAdTiming;\n }\n\n shouldUseNativeHls(getStreamType: () => \"hls\" | \"other\"): boolean {\n const streamType = 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\n async setupNativeHls(): Promise<void> {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.isLiveStream ?? (this.config.lowLatencyMode ?? false);\n\n if (this.debug) {\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 if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n }\n\n setupHls(): void {\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.config.isLiveStream ??\n (this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false);\n\n await this.callbacks.onManifestParsed(this.isLiveStream);\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.debug) {\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.callbacks.isInAdBreak() || this.callbacks.hasPendingAdBreak()) {\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 ? 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 const durationSeconds = parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value, earlyDetection: true },\n } as Scte35Marker;\n\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n }\n\n this.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"early\", frag),\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.debug) {\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.debug) {\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.debug) {\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_LOADED, (_evt, data: any) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : undefined,\n getFragmentStartSeconds(data?.frag)\n );\n });\n\n this.hls.on(Hls.Events.FRAG_DECRYPTED, (_evt, data: any) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : undefined,\n getFragmentStartSeconds(data?.frag)\n );\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)) {\n this.callbacks.activatePendingCuesForFragment(frag);\n return;\n }\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-CONT\")) {\n const prog = 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.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.callbacks.onScte35Cue(\n { type: \"end\", raw: { tag, value } },\n {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n }\n );\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = 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 = 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.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n }\n if (hasScteIn) {\n this.callbacks.onScte35Cue(\n { type: \"end\", raw: { tag, value, attrs } },\n {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n }\n );\n }\n }\n }\n this.callbacks.activatePendingCuesForFragment(frag);\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.callbacks.onFatalDestroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.timing.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = parseScte35FromId3(tag);\n if (marker) {\n this.callbacks.onScte35Cue(marker, {\n source: \"id3\",\n readiness: \"playback\",\n });\n }\n }\n\n private processFragmentScte35Payload(\n payloadData: unknown,\n fragmentSn?: number,\n fragmentStartSeconds?: number\n ): void {\n const payload = normalizeFragmentPayload(payloadData);\n if (!payload) {\n return;\n }\n\n const markers = parseScte35FromTsPackets(\n payload,\n this.cueManager.tsScte35Pids,\n this.cueManager.pmtPids,\n this.cueManager.processedTsScte35Sections\n );\n markers.forEach((marker) => {\n const context: Scte35CueContext = {\n source: \"ts\",\n readiness: \"early\",\n };\n if (fragmentSn !== undefined) {\n context.fragmentSn = fragmentSn;\n }\n if (fragmentStartSeconds !== undefined) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n this.callbacks.onScte35Cue(marker, context);\n });\n }\n\n destroy(): void {\n this.hls?.destroy();\n this.hls = undefined;\n }\n}\n","import type { AdController } from \"../types\";\n\nexport function getAdAudioVolume(adPlayer: AdController): number {\n return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();\n}\n\nexport function toggleMute(\n video: HTMLVideoElement,\n adPlayer: AdController,\n debug: boolean\n): void {\n if (adPlayer.isAdPlaying()) {\n const newMutedState = !adPlayer.getOriginalMutedState();\n const restoreVolume = adPlayer.getOriginalVolume() || 1;\n\n adPlayer.updateOriginalMutedState(newMutedState, video.volume);\n adPlayer.setAdVolume(newMutedState ? 0 : restoreVolume);\n\n if (debug) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n video.muted = !video.muted;\n adPlayer.updateOriginalMutedState(video.muted, video.volume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", video.muted);\n }\n }\n}\n\nexport function toggleFullscreen(\n video: HTMLVideoElement,\n debug: boolean\n): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = 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 (debug) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (debug) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document\n .exitFullscreen()\n .then(() => {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (debug) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n}\n\nexport function isMuted(\n video: HTMLVideoElement,\n adPlayer: AdController\n): boolean {\n if (adPlayer.isAdPlaying()) {\n return adPlayer.getOriginalMutedState();\n }\n return video.muted;\n}\n\nexport function setMuted(\n video: HTMLVideoElement,\n adPlayer: AdController,\n muted: boolean,\n debug: boolean\n): void {\n const adPlaying = adPlayer.isAdPlaying();\n\n if (adPlaying && muted === video.muted) {\n if (debug) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n\n video.muted = muted;\n\n if (adPlaying) {\n adPlayer.updateOriginalMutedState(muted, video.volume);\n adPlayer.setAdVolume(muted ? 0 : 1);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted,\n });\n }\n return;\n }\n\n adPlayer.updateOriginalMutedState(muted, video.volume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n}\n\nexport function setVolume(\n video: HTMLVideoElement,\n adPlayer: AdController,\n volume: number,\n debug: boolean\n): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = adPlayer.isAdPlaying();\n\n if (adPlaying) {\n adPlayer.setAdVolume(clampedVolume);\n adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume,\n });\n }\n } else {\n video.volume = clampedVolume;\n video.muted = clampedVolume === 0;\n adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n}\n\nexport function getVolume(\n video: HTMLVideoElement,\n adPlayer: AdController\n): number {\n const adPlaying = adPlayer.isAdPlaying();\n if (adPlaying) {\n return adPlayer.getAdVolume();\n }\n return video.volume;\n}\n\nexport function isFullscreen(): boolean {\n return !!document.fullscreenElement;\n}\n\nexport function resizePlayer(\n video: HTMLVideoElement,\n adPlayer: AdController,\n debug: boolean\n): void {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n\n if (adPlayer && adPlayer.isAdPlaying()) {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 480;\n\n if (debug) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n\n adPlayer.resize(width, height);\n }\n}\n","import type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n AdController,\n} from \"../types\";\nimport {\n sendAdLoadedTracking,\n sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport type { AdTimingService } from \"./AdTimingService\";\nimport type { AdPreloadPool } from \"./AdPreloadPool\";\nimport type { AdConfigManager } from \"./AdConfigManager\";\nimport type { Scte35CueManager } from \"./Scte35CueManager\";\nimport type { PlaceholderLayer } from \"./PlaceholderLayer\";\nimport { getAdAudioVolume } from \"./PlayerControls\";\n\nexport interface AdBreakOrchestratorHost {\n readonly config: StormcloudVideoPlayerConfig;\n readonly video: HTMLVideoElement;\n getAdPlayer(): AdController;\n setAdPlayer(player: AdController): void;\n createAdPlayer(continueLiveStreamDuringAds: boolean): AdController;\n shouldContinueLiveStreamDuringAds(): boolean;\n generateVastUrls(baseUrl: string, count: number): string[];\n}\n\nexport class AdBreakOrchestrator {\n inAdBreak = false;\n showAds: boolean = false;\n isShowingPlaceholder: boolean = false;\n adDetectSentForCurrentBreak: boolean = false;\n\n private continuousFetchingActive: boolean = false;\n private continuousFetchLoopRunning = false;\n adRequestQueue: string[] = [];\n adPodQueue: string[] = [];\n private readonly maxPlaceholderDurationMs: number = 5000;\n\n pendingAdBreak: {\n marker: Scte35Marker;\n detectedAtFragmentSn?: number;\n vastUrls: string[];\n isFetching: boolean;\n fetchStartTime?: number;\n } | null = null;\n prefetchTimerId: number | undefined;\n\n private readonly host: AdBreakOrchestratorHost;\n private readonly timing: AdTimingService;\n private readonly preloadPool: AdPreloadPool;\n private readonly adConfig: AdConfigManager;\n private readonly cueManager: Scte35CueManager;\n private readonly placeholder: PlaceholderLayer;\n\n constructor(\n host: AdBreakOrchestratorHost,\n timing: AdTimingService,\n preloadPool: AdPreloadPool,\n adConfig: AdConfigManager,\n cueManager: Scte35CueManager,\n placeholder: PlaceholderLayer\n ) {\n this.host = host;\n this.timing = timing;\n this.preloadPool = preloadPool;\n this.adConfig = adConfig;\n this.cueManager = cueManager;\n this.placeholder = placeholder;\n }\n\n private get debug(): boolean {\n return !!this.host.config.debugAdTiming;\n }\n\n // ───────────────────────────────────────────────────────────────\n // IMA event listeners\n // ───────────────────────────────────────────────────────────────\n\n attachImaEventListeners(): void {\n const adPlayer = this.host.getAdPlayer();\n adPlayer.on(\"all_ads_completed\", () => {\n sendAdImpressionTracking(\n this.host.config.licenseKey,\n { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n const remaining = this.timing.getRemainingAdMs();\n\n this.timing.consecutiveFailures = 0;\n\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n\n if (this.inAdBreak) {\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n adPlayer.on(\"ad_error\", (errorPayload?: any) => {\n let errorMessage = \"Ad playback failed\";\n\n if (errorPayload) {\n const errorCode = errorPayload.code || errorPayload.errorCode || \"unknown\";\n const vastErrorCode = errorPayload.vastErrorCode;\n const message = errorPayload.message || errorPayload.errorMessage || \"Unknown error\";\n const cause = errorPayload.cause || errorPayload.innerError || errorPayload.error;\n\n errorMessage = `Ad error: AdError ${errorCode}: ${message}`;\n\n if (vastErrorCode && vastErrorCode !== \"N/A\" && vastErrorCode !== errorCode) {\n errorMessage += ` (VAST Error Code: ${vastErrorCode})`;\n }\n\n if (cause) {\n const causeMessage = typeof cause === \"string\" ? cause : (cause.message || String(cause));\n errorMessage += `. Caused by: ${causeMessage}`;\n }\n }\n\n console.error(\"[AD-ERROR]\", errorMessage, errorPayload || \"\");\n this.handleAdFailure();\n });\n adPlayer.on(\"content_pause\", () => {\n this.timing.clearAdFailsafeTimer();\n this.timing.clearAdRequestWatchdog();\n this.timing.activeAdRequestToken = null;\n this.showAds = true;\n this.timing.resetGamNoFillCounter();\n\n if (this.inAdBreak && this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n\n this.host.getAdPlayer().setAdVolume(getAdAudioVolume(this.host.getAdPlayer()));\n\n if (this.isShowingPlaceholder) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.host.getAdPlayer().hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n adPlayer.on(\"content_resume\", () => {\n sendAdImpressionTracking(\n this.host.config.licenseKey,\n { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n if (!this.host.video.muted) {\n this.host.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n }\n }\n\n this.timing.clearAdFailsafeTimer();\n this.timing.clearAdRequestWatchdog();\n this.timing.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n return;\n }\n\n this.timing.consecutiveFailures = 0;\n\n this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n const remaining = this.timing.getRemainingAdMs();\n\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n });\n }\n\n recreateAdController(): void {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Recreating AdController for new ad\");\n }\n\n const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n const adPlayer = this.host.getAdPlayer();\n if (shouldShowPlaceholder && adPlayer) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old AdController\");\n }\n this.placeholder.show();\n adPlayer.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n\n const preservedMutedState = adPlayer.getOriginalMutedState();\n const preservedVolumeState = adPlayer.getOriginalVolume();\n\n if (adPlayer) {\n try {\n adPlayer.destroy();\n this.host.video.muted = true;\n } catch (error) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Error destroying old AdController:\", error);\n }\n }\n }\n\n const continueLiveStreamDuringAds = this.host.shouldContinueLiveStreamDuringAds();\n const newAdPlayer = this.host.createAdPlayer(continueLiveStreamDuringAds);\n this.host.setAdPlayer(newAdPlayer);\n\n newAdPlayer.initialize();\n newAdPlayer.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n this.attachImaEventListeners();\n\n if (shouldShowPlaceholder) {\n this.placeholder.show();\n newAdPlayer.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n }\n\n clearPendingAdBreak(): void {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = undefined;\n }\n this.pendingAdBreak = null;\n this.cueManager.pendingScte35CueKey = undefined;\n this.adConfig.podAssignedByPrefetch = false;\n }\n\n // ───────────────────────────────────────────────────────────────\n // Ad break start\n // ───────────────────────────────────────────────────────────────\n\n async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const scheduled = this.adConfig.findCurrentOrNextBreak(\n this.host.video.currentTime * 1000\n );\n if (scheduled) {\n this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));\n }\n const tags = this.adConfig.selectVastTagsForBreak(scheduled);\n\n let baseVastUrl: string;\n\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.adConfig.apiVastTagUrl) {\n baseVastUrl = this.adConfig.apiVastTagUrl;\n } else {\n this.clearPendingAdBreak();\n return;\n }\n\n const adBreakDurationMs =\n _marker.durationSeconds != null\n ? _marker.durationSeconds * 1000\n : scheduled?.durationMs;\n\n if (this.debug) {\n const mode = this.host.config.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n\n this.timing.failedVastUrls.clear();\n this.timing.temporaryFailureUrls.clear();\n this.timing.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.timing.totalAdRequestsInBreak = 0;\n\n if (this.adConfig.podAssignedByPrefetch) {\n this.adConfig.podAssignedByPrefetch = false;\n } else {\n this.adConfig.beginNewAdPod();\n }\n\n const currentMuted = this.host.video.muted;\n const currentVolume = this.host.video.volume;\n this.host.getAdPlayer().updateOriginalMutedState(currentMuted, currentVolume);\n\n this.inAdBreak = true;\n this.timing.adBreakPlayedDurationMs = 0;\n this.timing.currentAdIndex = 0;\n this.timing.totalAdsInBreak = 0;\n this.adPodQueue = [];\n this.showAds = false;\n\n if (\n this.timing.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.timing.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n\n let firstAdUrl: string | undefined;\n let usePreloadedAd = false;\n let preloadedController: AdController | undefined;\n\n const preloaded = this.preloadPool.getPreloadedAd();\n if (preloaded) {\n firstAdUrl = preloaded.vastUrl;\n preloadedController = preloaded.adController;\n usePreloadedAd = true;\n\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: firstAdUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n }\n } else if (this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0) {\n this.adRequestQueue = [...this.pendingAdBreak.vastUrls];\n firstAdUrl = this.adRequestQueue.shift();\n\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Pool empty, using prefetched URLs (${this.adRequestQueue.length + 1} available)`);\n }\n\n this.clearPendingAdBreak();\n } else {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Generating new ad URLs...\");\n }\n\n const firstAdUrlArray = this.host.generateVastUrls(baseVastUrl, 1);\n firstAdUrl = firstAdUrlArray[0];\n this.adRequestQueue = [];\n }\n\n if (!firstAdUrl) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Failed to get first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First VAST URL:\", firstAdUrl);\n }\n\n try {\n if (usePreloadedAd && preloadedController) {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedController)) {\n this.timing.rejectLoadedAdForDuration(preloadedController);\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n const adPlayer = this.host.getAdPlayer();\n const preservedMuted = adPlayer.getOriginalMutedState();\n const preservedVolume = adPlayer.getOriginalVolume();\n adPlayer.destroy();\n this.host.video.muted = true;\n this.host.setAdPlayer(preloadedController);\n preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n\n this.attachImaEventListeners();\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n }\n\n preloadedController.resume();\n\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n\n if (!this.preloadPool.active) {\n this.preloadPool.active = true;\n }\n if (!this.preloadPool.isLoopRunning) {\n this.preloadPool.preloadPoolLoop(baseVastUrl);\n }\n\n await preloadedController.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n const adVolume = currentMuted ? 0 : currentVolume;\n preloadedController.setAdVolume(adVolume);\n } else {\n const adPlayer = this.host.getAdPlayer();\n await this.timing.enforceGlobalRateLimit();\n this.timing.lastAdRequestTime = Date.now();\n await adPlayer.requestAds(firstAdUrl);\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: firstAdUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad request successful, starting playback\");\n }\n\n if (!this.timing.ensureLoadedAdFitsBudget(adPlayer)) {\n this.timing.rejectLoadedAdForDuration(adPlayer);\n this.recreateAdController();\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n\n if (!this.preloadPool.active) {\n this.preloadPool.startPreloadPool(baseVastUrl, []);\n }\n\n await adPlayer.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n const adVolume = currentMuted ? 0 : currentVolume;\n adPlayer.setAdVolume(adVolume);\n }\n } catch (error) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] First ad request failed:\", error);\n }\n\n if (!usePreloadedAd) {\n const fallbackPreloaded = this.preloadPool.getPreloadedAd();\n if (fallbackPreloaded) {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad failed, using preloaded fallback\");\n }\n\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(fallbackPreloaded.adController)) {\n this.timing.rejectLoadedAdForDuration(fallbackPreloaded.adController);\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n this.swapToPreloadedAdPlayer(fallbackPreloaded.adController);\n\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n\n if (!this.preloadPool.active) {\n this.preloadPool.active = true;\n this.preloadPool.preloadPoolLoop(baseVastUrl);\n }\n\n const ap = this.host.getAdPlayer();\n await ap.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n const adVolume = currentMuted ? 0 : currentVolume;\n ap.setAdVolume(adVolume);\n\n return;\n } catch (fallbackError) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n }\n\n if (this.timing.isTemporaryAdError(error as Error)) {\n this.timing.temporaryFailureUrls.set(firstAdUrl, Date.now());\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n }\n } else {\n this.timing.failedVastUrls.add(firstAdUrl);\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n }\n }\n this.timing.consecutiveFailures++;\n\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n }\n }\n\n private swapToPreloadedAdPlayer(preloadedController: AdController): void {\n const adPlayer = this.host.getAdPlayer();\n const preservedMuted = adPlayer.getOriginalMutedState();\n const preservedVolume = adPlayer.getOriginalVolume();\n adPlayer.destroy();\n this.host.video.muted = true;\n this.host.setAdPlayer(preloadedController);\n this.attachImaEventListeners();\n preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n preloadedController.resume();\n }\n\n // ───────────────────────────────────────────────────────────────\n // Continuous fetching\n // ───────────────────────────────────────────────────────────────\n\n private startContinuousFetching(baseVastUrl: string): void {\n if (!this.continuousFetchingActive) {\n return;\n }\n\n if (this.continuousFetchLoopRunning) {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Fetch loop already running, skipping duplicate start\");\n }\n return;\n }\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Starting continuous ad fetching loop\");\n }\n\n this.continuousFetchLoopRunning = true;\n this.continuousFetchLoop(baseVastUrl);\n }\n\n private async continuousFetchLoop(baseVastUrl: string): Promise<void> {\n const epoch = this.timing.adBreakEpoch;\n while (\n this.continuousFetchingActive &&\n this.inAdBreak &&\n epoch === this.timing.adBreakEpoch\n ) {\n const remaining = Math.min(\n this.timing.getWallClockRemainingAdMs(),\n this.timing.getDurationBudgetRemainingMs()\n );\n\n if (remaining <= this.timing.getMinRemainingMsToStartAd()) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Not enough ad break time left (wall=${this.timing.getWallClockRemainingAdMs()}ms, budget=${this.timing.getDurationBudgetRemainingMs()}ms), stopping URL generation`);\n }\n break;\n }\n\n if (this.timing.isGamInCooldown()) {\n if (this.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n }\n break;\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), stopping URL generation`);\n }\n break;\n }\n\n if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Maximum ad requests reached (${this.timing.maxTotalAdRequestsPerBreak}), stopping`);\n }\n break;\n }\n\n const maxQueueSize = 5;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] URL queue full (${this.adRequestQueue.length}), waiting...`);\n }\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n const newAdUrl = this.host.generateVastUrls(baseVastUrl, 1)[0];\n\n if (!newAdUrl || this.timing.failedVastUrls.has(newAdUrl) || this.timing.isUrlInCooldown(newAdUrl)) {\n await new Promise(resolve => setTimeout(resolve, 500));\n continue;\n }\n\n if (this.debug) {\n const queuedUrlsPreview = [...this.adRequestQueue, newAdUrl];\n console.log(\n `[CONTINUOUS-FETCH] Queued VAST URL (queue size: ${queuedUrlsPreview.length})`,\n { queuedUrls: queuedUrlsPreview }\n );\n }\n\n this.adRequestQueue.push(newAdUrl);\n\n const generationDelay = this.timing.consecutiveFailures > 0\n ? Math.min(1000 * Math.pow(2, this.timing.consecutiveFailures), 5000)\n : 500;\n await new Promise(resolve => setTimeout(resolve, generationDelay));\n }\n\n this.continuousFetchLoopRunning = false;\n\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] URL generation loop ended (queued: ${this.adRequestQueue.length})`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n }\n\n stopContinuousFetching(): void {\n this.continuousFetchingActive = false;\n this.continuousFetchLoopRunning = false;\n\n this.placeholder.hide();\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Stopping continuous ad fetching\");\n }\n }\n\n // ───────────────────────────────────────────────────────────────\n // Ad iteration\n // ───────────────────────────────────────────────────────────────\n\n async tryNextAvailableAdWithRateLimit(): Promise<void> {\n if (!this.inAdBreak) {\n return;\n }\n\n const epoch = this.timing.adBreakEpoch;\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n const backoffMultiplier = Math.pow(2, this.timing.consecutiveFailures);\n const backoffDelay = Math.min(this.timing.backoffBaseMs * backoffMultiplier, this.timing.maxBackoffMs);\n const effectiveMinInterval = this.timing.minAdRequestIntervalMs + (this.timing.consecutiveFailures > 0 ? backoffDelay : 0);\n\n const timeSinceLastRequest = Date.now() - this.timing.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.timing.consecutiveFailures} failures)`);\n }\n await new Promise(resolve => setTimeout(resolve, waitTime));\n }\n\n if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) {\n return;\n }\n\n return this.tryNextAvailableAd(0);\n }\n\n private async tryNextAvailableAd(retryCount: number = 0): Promise<void> {\n if (!this.inAdBreak) {\n return;\n }\n\n const remaining = this.timing.getRemainingAdMs();\n\n if (!this.timing.hasTimeToStartAnotherAd()) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Not enough time remaining (${remaining}ms) to start another ad, ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.timing.isGamInCooldown()) {\n if (this.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n this.timing.cleanupTemporaryFailures();\n\n const preloaded = this.preloadPool.getPreloadedAd();\n if (preloaded) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Using preloaded ad from pool`);\n }\n\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: preloaded.vastUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloaded.adController)) {\n this.timing.rejectLoadedAdForDuration(preloaded.adController);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n this.swapToPreloadedAdPlayer(preloaded.adController);\n\n const ap = this.host.getAdPlayer();\n await ap.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n ap.setAdVolume(getAdAudioVolume(ap));\n\n this.timing.consecutiveFailures = 0;\n return;\n } catch (error) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Preloaded ad failed to play:\", error);\n }\n }\n }\n\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n\n if (!nextAdUrl) continue;\n\n if (this.timing.failedVastUrls.has(nextAdUrl)) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping permanently-failed URL, trying next...\");\n continue;\n }\n\n if (this.timing.isUrlInCooldown(nextAdUrl)) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping URL in cooldown (recent no-fill), trying next...\");\n continue;\n }\n\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Requesting next ad via HLS ad player (${this.timing.currentAdIndex + 1}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n\n try {\n await this.playSingleAd(nextAdUrl);\n this.timing.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = (error as Error).message;\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad request failed:\", errorMessage);\n\n if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.timing.consecutiveFailures++;\n }\n\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n\n const maxRetries = 3;\n if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2000) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Queue empty, waiting for URLs... (${retryCount + 1}/${maxRetries})`);\n }\n await new Promise(resolve => setTimeout(resolve, 500));\n await this.tryNextAvailableAd(retryCount + 1);\n return;\n }\n\n if (!this.isShowingPlaceholder && remaining > 1000) {\n this.showPlaceholderAndWaitForAds();\n } else {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] No more ads available, ending ad break\");\n this.handleAdPodComplete();\n }\n }\n\n // ───────────────────────────────────────────────────────────────\n // Single ad playback\n // ───────────────────────────────────────────────────────────────\n\n async playSingleAd(vastTagUrl: string): Promise<void> {\n const adPlayer = this.host.getAdPlayer();\n if (adPlayer.isAdPlaying()) return;\n\n if (this.timing.failedVastUrls.has(vastTagUrl)) {\n if (this.debug) console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n throw new Error(\"VAST URL permanently failed\");\n }\n\n if (this.timing.isUrlInCooldown(vastTagUrl)) {\n if (this.debug) console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n throw new Error(\"VAST URL in cooldown after no-fill\");\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n throw new Error(\"Too many consecutive failures\");\n }\n\n if (this.timing.isGamInCooldown()) {\n if (this.debug) console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n throw new Error(\"GAM in cooldown\");\n }\n\n this.recreateAdController();\n\n const requestToken = ++this.timing.adRequestTokenCounter;\n this.timing.activeAdRequestToken = requestToken;\n this.timing.startAdRequestWatchdog(requestToken);\n\n try {\n await this.timing.enforceGlobalRateLimit();\n this.timing.lastAdRequestTime = Date.now();\n const ap = this.host.getAdPlayer();\n await ap.requestAds(vastTagUrl);\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: vastTagUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n this.timing.clearAdRequestWatchdog();\n\n if (this.timing.activeAdRequestToken !== requestToken) return;\n\n if (!this.timing.ensureLoadedAdFitsBudget(ap)) {\n this.timing.rejectLoadedAdForDuration(ap);\n this.recreateAdController();\n throw new Error(\"ad_duration_exceeds_budget\");\n }\n\n try {\n this.timing.startAdFailsafeTimer(requestToken);\n await ap.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n ap.setAdVolume(getAdAudioVolume(ap));\n this.timing.consecutiveFailures = 0;\n this.timing.temporaryFailureUrls.delete(vastTagUrl);\n } catch (playError) {\n if (this.debug) console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n\n const preloadedFallback = this.preloadPool.getPreloadedAd();\n if (preloadedFallback) {\n if (this.debug) console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n throw playError;\n }\n this.timing.clearAdFailsafeTimer();\n this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n this.timing.consecutiveFailures = 0;\n const fbAp = this.host.getAdPlayer();\n await fbAp.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n fbAp.setAdVolume(getAdAudioVolume(fbAp));\n return;\n } catch (fallbackError) {\n if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n\n if (this.timing.isTemporaryAdError(playError as Error)) {\n this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.debug) console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n } else {\n this.timing.failedVastUrls.add(vastTagUrl);\n if (this.debug) console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n }\n\n this.timing.clearAdFailsafeTimer();\n if (this.timing.activeAdRequestToken === requestToken) {\n this.timing.activeAdRequestToken = null;\n }\n throw playError;\n }\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"\";\n if (this.debug) console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n\n const preloadedFallback = this.preloadPool.getPreloadedAd();\n if (preloadedFallback) {\n if (this.debug) console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n throw error;\n }\n this.timing.clearAdRequestWatchdog();\n this.timing.clearAdFailsafeTimer();\n this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n this.timing.consecutiveFailures = 0;\n const fbAp = this.host.getAdPlayer();\n await fbAp.play();\n this.timing.markAdStarted();\n fbAp.setAdVolume(getAdAudioVolume(fbAp));\n return;\n } catch (fallbackError) {\n if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n\n if (this.timing.isTemporaryAdError(error as Error)) {\n this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.debug) console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n } else {\n this.timing.failedVastUrls.add(vastTagUrl);\n if (this.debug) console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n }\n\n this.timing.clearAdRequestWatchdog();\n this.timing.clearAdFailsafeTimer();\n if (this.timing.activeAdRequestToken === requestToken) {\n this.timing.activeAdRequestToken = null;\n }\n throw error;\n }\n }\n\n // ───────────────────────────────────────────────────────────────\n // Placeholder wait\n // ───────────────────────────────────────────────────────────────\n\n private async showPlaceholderAndWaitForAds(): Promise<void> {\n const remaining = this.timing.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n\n if (this.timing.isGamInCooldown()) {\n if (this.debug) console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n this.handleAdPodComplete();\n return;\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping placeholder - too many consecutive failures\");\n this.handleAdPodComplete();\n return;\n }\n\n if (waitTime < 1000) {\n this.handleAdPodComplete();\n return;\n }\n\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n }\n\n this.isShowingPlaceholder = true;\n this.host.getAdPlayer().showPlaceholder();\n\n const checkInterval = 300;\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) return;\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Too many failures during placeholder wait\");\n break;\n }\n\n if (!this.timing.hasTimeToStartAnotherAd()) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Not enough time remaining during placeholder wait, ending ad break\");\n break;\n }\n\n while (this.adRequestQueue.length > 0) {\n if (!this.timing.hasTimeToStartAnotherAd()) break;\n\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) continue;\n if (this.timing.failedVastUrls.has(nextAdUrl)) continue;\n if (this.timing.isUrlInCooldown(nextAdUrl)) continue;\n\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad URL available, requesting via HLS ad player\");\n\n this.isShowingPlaceholder = false;\n this.host.getAdPlayer().hidePlaceholder();\n\n try {\n await this.playSingleAd(nextAdUrl);\n this.timing.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = (error as Error).message;\n if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.timing.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n }\n\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Placeholder timeout, ending ad break\");\n\n this.isShowingPlaceholder = false;\n this.host.getAdPlayer().hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n // ───────────────────────────────────────────────────────────────\n // Ad break completion\n // ───────────────────────────────────────────────────────────────\n\n handleAdPodComplete(): void {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ad pod complete - cleaning up\");\n }\n\n this.timing.resetForBreakEnd();\n\n this.stopContinuousFetching();\n this.preloadPool.stop();\n this.clearPendingAdBreak();\n\n if (this.isShowingPlaceholder) {\n this.host.getAdPlayer().hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n\n this.adRequestQueue = [];\n\n this.inAdBreak = false;\n this.adDetectSentForCurrentBreak = false;\n this.cueManager.activeScte35BreakKey = undefined;\n this.cueManager.scheduledScte35BreakKey = undefined;\n this.adPodQueue = [];\n this.showAds = false;\n\n this.host.getAdPlayer().stop().catch(() => {});\n\n const restoredMuted = this.host.getAdPlayer().getOriginalMutedState();\n const restoredVolume = this.host.getAdPlayer().getOriginalVolume();\n\n if (this.host.video.muted !== restoredMuted) {\n this.host.video.muted = restoredMuted;\n }\n if (Math.abs(this.host.video.volume - restoredVolume) > 0.01) {\n this.host.video.volume = restoredVolume;\n }\n\n if (this.host.shouldContinueLiveStreamDuringAds()) {\n if (this.host.video.paused) {\n if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n this.host.video.play()?.catch(() => {});\n } else {\n if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n } else if (this.host.video.paused) {\n this.host.video.play()?.catch(() => {});\n }\n }\n\n handleAdFailure(): void {\n this.timing.consecutiveFailures++;\n this.timing.recordGamNoFill();\n const remaining = this.timing.getRemainingAdMs();\n\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.timing.consecutiveFailures}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(`[CONTINUOUS-FETCH] Max consecutive failures reached (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n this.handleAdPodComplete();\n return;\n }\n\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n if (this.debug) console.log(\"[AD-ERROR] Ad failed and not enough time remaining for another ad. Failed URLs:\", this.timing.failedVastUrls.size);\n this.handleAdPodComplete();\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/ui/StormcloudVideoPlayer.cjs","../../src/ui/StormcloudVideoPlayer.tsx","../../src/sdk/hlsAdPlayer.ts","../../src/sdk/pal.ts","../../src/utils/mqttConfig.ts","../../src/utils/mqttClient.ts","../../src/utils/tracking.ts","../../src/utils/polyfills.ts","../../src/utils/vastEnvironmentSignals.ts","../../src/utils/vastMacros.ts","../../src/utils/browserCompat.ts","../../src/player/Scte35Parser.ts","../../src/player/Scte35CueManager.ts","../../src/player/AdConfigManager.ts","../../src/player/AdTimingService.ts","../../src/player/AdPreloadPool.ts","../../src/player/PlaceholderLayer.ts","../../src/player/HlsEngine.ts","../../src/player/PlayerControls.ts","../../src/player/AdBreakOrchestrator.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","StormcloudVideoPlayer_exports","StormcloudVideoPlayerComponent","module","exports","import_react","require","import_hls","MAX_VAST_WRAPPER_DEPTH","createHlsAdPlayer","contentVideo","options","adPlaying","originalMutedState","originalVolume","Math","max","min","volume","listeners","Map","licenseKey","mainHlsInstance","adVideoElement","adHls","adContainerEl","currentAd","sessionId","preloadedAds","preloadingAds","destroyed","pendingTimeouts","trackingFired","impression","start","firstQuartile","midpoint","thirdQuartile","complete","emit","event","payload","set","Array","fn","error","console","warn","generateSessionId","Date","now","random","toString","substr","fireTrackingPixels","urls","length","forEach","url","trackingUrl","includes","img","Image","src","log","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","width","height","bitrate","selectBestMediaFile","mediaFiles","Error","firstFile","mainQuality","scoredFiles","widthDiff","map","abs","file","resolutionDiff","heightDiff","fileBitrate","score","bitrateDiff","bestMatch","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","el","isProgressiveMediaFile","createEmptyTrackingUrls","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","extractTrackingUrls","trackingUrls","xmlDoc","textContent","trim","push","querySelectorAll","getAttribute","eventKey","mergeTrackingUrls","source","keys","concat","parseVastXml","xmlString","parser","DOMParser","parseFromString","parserError","querySelector","adElement","adId","title","clickThrough","wrapperUri","vastAdTagUri","isNoAdAvailable","durationText","durationParts","split","duration","parseInt","mediaFileElements","mf","index","bitrateAttr","bitrateValue","ad","id","fetchVastXml","vastTagUrl","response","fetch","mode","credentials","headers","referrerPolicy","ok","statusText","text","fetchAndParseVastAd","depth","accumulatedTracking","vastXml","parsed","substring","createAdVideoElement","video","document","createElement","style","position","left","top","objectFit","backgroundColor","playsInline","muted","setupAdEventListeners","addEventListener","progress","currentTime","handleAdComplete","e","handleAdError","ended","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","continueLiveStreamDuringAds","paused","play","catch","initialize","right","bottom","container","alignItems","justifyContent","zIndex","parentElement","appendChild","requestAds","has","delete","Promise","reject","resolve","contentVolume","isHlsAd","Hls","isSupported","destroy","enableWorker","lowLatencyMode","loadSource","attachMedia","on","Events","MANIFEST_PARSED","ERROR","data","fatal","load","stop","previousMutedState","visibility","opacity","timeoutId","clearTimeout","remove","removeChild","clear","getOriginalMutedState","setAdVolume","isAdPlaying","listener","Set","add","off","updateOriginalMutedState","nextVolume","getOriginalVolume","clamped","getAdVolume","showPlaceholder","hidePlaceholder","getLoadedAdDuration","getLoadedAdId","window","PAL_SDK_URL","_nonceLoader","_palLoadPromise","loadPalSdk","goog","pal","existing","timeout","setTimeout","script","onload","head","consentSettings","ConsentSettings","allowStorage","NonceLoader","createPalNonceManager","currentNonce","currentNonceManager","generateNonce","loader","request","manager","getOrCreateNonceLoader","NonceRequest","adWillAutoPlay","adWillPlayMuted","playerVolume","continuousPlayback","descriptionUrl","location","href","iconsSupported","playerType","playerVersion","supportedApiFrameworks","videoWidth","videoHeight","ppid","loadNonceManager","getNonce","injectNonce","URL","searchParams","base","replace","sep","encodeURIComponent","sendPlaybackStart","sendPlaybackEnd","sendAdClick","sendAdTouch","reset","DEFAULT_MQTT_CONFIG","enabled","brokerAddress","brokerPort","wsPort","username","password","topicPrefix","qos","mqttConfig","isMQTTEnabled","buildMQTTBrokerUrl","brokerUrl","buildPlayerTopic","channel","import_mqtt","LOG","client","status","initMQTTClient","clientId","slice","mqtt","connect","keepalive","clean","reconnectPeriod","connectTimeout","queueQoSZero","err","info","message","ensureMQTTClient","publishMQTT","topic","publish","JSON","stringify","cachedBrowserId","getClientInfo","screen","navigator","ua","userAgent","platform","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isSmartTV","isAndroid","isWebView","isWebApp","webosMatch","match","tizenMatch","tvMatch","test","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","hostname","origin","path","pathname","language","languages","join","cookieEnabled","doNotTrack","referrer","visibilityState","getBrowserID","clientInfo","crypto","fingerprintString","encodedData","utf8","buffer","i","hashBuffer","hashHex","hash","char","fallbackHash","timestamp","subtle","digest","Uint8Array","TextEncoder","encode","unescape","charCodeAt","b","padStart","padEnd","canPublish","Boolean","buildPlayerMetricEvent","context","flags","playerId","captureAt","toISOString","player_id","device_type","ad_loaded","adLoaded","ad_detect","adDetect","capture_at","inputStreamType","input_stream_type","publishTracking","body","sendInitialTracking","metricEvent","events","sendAdDetectTracking","adDetectInfo","sendHeartbeat","sendAdLoadedTracking","adLoadedInfo","sendAdImpressionTracking","adImpressionInfo","ad_played_count","ad_url","adUrl","heartbeatData","polyfillURLSearchParams","URLSearchParams","URLSearchParamsPolyfill","init","params","append","parseQueryString","query","cleanQuery","startsWith","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","values","String","getAll","callback","parts","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","finally","constructor","then","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","result","len","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","endsWith","polyfillStringIncludes","indexOf","initializePolyfills","AIRY_ANDROID_APP_ID","AIRY_WEBOS_APP_ID","AIRY_TIZEN_APP_ID","AIRY_ROKU_APP_ID","AIRY_APP_NAME","AIRY_DEFAULT_CONTENT_URL","CTV_SESSION_STORAGE_KEY","LG_TEST_APP_ID","LG_TEST_APP_NAME","LG_TEST_CONTENT_URL","_lgTestDeviceId","getLgTestDeviceId","createUuid","isLgWebOS","getDefaultAppId","DEVICE_ID_STORAGE_KEYS","ANDROID_ID_TYPES","resolveVastEnvironmentSignals","isCtv","bridgeSignals","readNativeBridgeSignals","lg","deviceId","readStoredDeviceId","deviceIdType","readStoredString","inferDeviceIdType","contentUrl","appId","appName","getOrCreateCtvSessionId","limitAdTracking","deviceTypeHint","isEquivalentDeviceIdType","tagType","runtimeType","tag","runtime","localStorage","setItem","randomUUID","floor","nibble","candidates","__STORMCLOUD_CTV_AD_INFO__","__STORMCLOUD_CTV__","stormcloudCtv","AiryTV","Android","webOS","tizen","amazon","filter","readBridgeValue","readBridgeBoolean","normalized","normalizeBoolean","getItem","readStoredLimitAdTracking","UNEXPANDED_MACRO_PATTERN","INVALID_VAST_PARAM_KEY","EXAMPLE_COM_URL","CTV_UNSUPPORTED_PARAMS","INLINE_DEVICE_MACRO_REPLACEMENTS","pattern","getValue","ctx","correlator","trimmed","generateCorrelator","getRandomValues","buf","Uint32Array","Number","MAX_SAFE_INTEGER","expandInlineMacroPlaceholders","baseUrl","applyDeviceIdentityParams","runtimeId","tagRdid","tagLat","latValue","isMacroPlaceholder","tagRdidValid","tagTypeValid","removeBrokenAppNameOrphans","toDelete","_value","suffix","trimStart","normalizeVastTagUrl","raw","anValue","orphanFragments","reconstructed","trimEnd","_match","prefix","val","replaceCorrelatorFallback","expandedUrl","streamCorrelator","pod","adPosition","requestUrl","pageUrl","existingUrl","consent","gdpr","gdprConsent","usPrivacy","adTest","staleKeys","timeoutMs","correlatorRegex","fetchConsentSignals","signals","tasks","tcfApi","__tcfapi","settled","tcData","success","eventStatus","gdprApplies","tcString","listenerId","uspApi","__uspapi","uspString","getChromeVersion","getWebKitVersion","getPlatform","detectBrowser","version","chromeVersion","majorVersion","webOSVersion","isLegacyTV","supportsModernJS","tizenVersion","webkitVersion","chromeVersionNum","getBrowserConfigOverrides","debug","browser","overrides","allowNativeHls","logBrowserInfo","parseCueOutDuration","num","parseFloat","isNaN","dStr","d","parseCueOutCont","res","elapsedMatch","durationMatch","elapsed","slashMatch","parseAttributeList","attrs","regex","exec","rawVal","toNumber","n","isManifestBasedMarker","marker","id3","splice_command_type","decodeId3ValueToText","decoder","TextDecoder","decode","out","fromCharCode","getFragmentStartSeconds","frag","startPTS","candidate","isFinite","parseScte35FromId3","cueOutMatch","arg","dur","ptsSeconds","durationSeconds","cueOutContMatch","cont","cueInMatch","daterangeMatch","hasScteOut","hasScteIn","klass","bin","parseScte35Binary","normalizeFragmentPayload","ArrayBuffer","isView","view","byteOffset","byteLength","detectTsPacketFormat","packetSizes","packetSize","tsPayloadOffset","offset","matchedPackets","packetStart","getPsiSectionStart","payloadUnitStart","pointerField","sectionStart","getPsiSectionLength","parsePatSection","pmtPids","sectionLength","sectionEnd","programNumber","pid","descriptorsIdentifyScte35","end","descriptorStart","descriptorEnd","registration","parsePmtSection","tsScte35Pids","programInfoLength","streamType","elementaryPid","esInfoLength","hasProcessedTsScte35Section","section","processedSections","checksum","firstKey","size","next","addScte35SectionMarker","markers","appendScte35Bytes","bytes","assemblers","assembler","expectedLength","collectScte35SectionsFromPayload","previousAssembler","subarray","tableId","totalLength","parseScte35FromTsPackets","packetInfo","sectionAssemblers","tsStart","secondByte","thirdByte","fourthByte","adaptationFieldControl","hasPayload","payloadStart","adaptationLength","payloadEnd","BitReader","bytePos","readBits","numBits","remainingInByte","bitPos","toRead","currentByte","shift","mask","bits","skipBits","bytePosition","readSpliceTime","r","ptsAdjustmentTicks","timeSpecifiedFlag","high","low","ptsTicks","markerTypeFromSegmentationTypeId","segmentationTypeId","parseScte35SegmentationDescriptor","descriptor","identifier","segmentationEventId","cancelIndicator","programSegmentationFlag","segmentationDurationFlag","componentCount","durationTicks","segmentationUpidLength","markerType","parseScte35SegmentationDescriptors","descriptorLoopLength","descriptorOffset","descriptorTag","descriptorLength","descriptorDataStart","descriptorDataEnd","descriptorMarker","ptsAdjLow","spliceEventId","Scte35CueManager","callbacks","ptsAdjHigh","spliceCommandLength","spliceCommandType","commandBodyStart","cancel","outOfNetwork","programSpliceFlag","durationFlag","spliceImmediateFlag","componentPtsSeconds","expectedDescriptorOffset","splice_event_id","segmentation_event_id","pendingScte35Cues","recentScte35CueKeys","recentScte35CueLimit","processedTsScte35Sections","pendingScte35CueKeyValue","activeScte35BreakKey","activeScte35BreakKeyValue","scheduledScte35BreakKey","scheduledScte35BreakKeyValue","createScte35CueContext","readiness","sn","fragmentSn","fragmentStartSec","fragmentStartSeconds","onScte35Cue","cue","createScte35Cue","trimRecentScte35CueMaps","onEarlyStartCue","shouldAcceptScte35EndCue","inAdBreak","isInAdBreak","hasRecentlyHandledScte35Cue","pendingKey","markScte35CueHandled","onPlaybackCue","activatePendingScte35CuesForFragment","matchingCues","getScte35CueKey","getScte35MarkerRaw","toIdentityString","daterangeId","ID","scteValue","round","getPendingScte35CueKey","isStrongScte35CueKey","recentKey","AdConfigManager","config","vmapBreaks","consumedVmapBreakIds","consentSignals","podCounter","podAssignedByPrefetch","adRequestPositionInBreak","lastHeartbeatTime","debugAdTiming","isVmapEnabled","isVmap","vmapUrl","fetchAdConfiguration","vastMode","vastEndpoint","apiUrl","imaPayload","decodedPayload","numberAds","fetchAndParseVmap","apiVastTagUrl","json","ima","vast","cue_tones","number_ads","apiNumberAds","vmapXml","parseVmapToBreaks","doc","VMAP_NS","adBreakNodes","getElementsByTagNameNS","getElementsByTagName","localName","node","timeOffsetRaw","startTimeMs","parseVmapTimeOffsetToMs","adTagNode","adTagUrl","breakId","sort","a","aStart","bStart","timeOffset","hms","hh","mm","ss","ms","hours","minutes","seconds","millis","percent","ratio","durationSec","getAdBreakKey","adBreak","resolveBreakStartMs","findCurrentOrNextBreak","schedule","tol","driftToleranceMs","breakStartMs","nowMs","findBreakForTime","durationMs","selectVastTagsForBreak","s","beginNewAdPod","generateVastUrlsWithCorrelators","count","adPlayer","palNonce","envSignals","ctvAdRequest","urlWithMacros","applyVastMacros","autoplay","finalUrl","initializeTracking","heartbeatInterval","setInterval","sendHeartbeatIfNeeded","destroyTracking","clearInterval","AdTimingService","adRequestWatchdogToken","adFailsafeToken","ptsDriftEmaMs","adBreakPlayedDurationMs","adBreakEpoch","adRequestTokenCounter","activeAdRequestToken","currentAdIndex","totalAdsInBreak","totalAdRequestsInBreak","maxTotalAdRequestsPerBreak","lastAdRequestTime","consecutiveFailures","maxConsecutiveFailures","backoffBaseMs","maxBackoffMs","defaultMinRemainingMsToStartAd","failedVastUrls","temporaryFailureUrls","temporaryFailureCooldownMs","globalConsecutiveNoFills","globalNoFillThreshold","globalNoFillCooldownUntil","globalNoFillBackoffBaseMs","globalNoFillBackoffMaxMs","globalLastGamRequestTime","globalMinGamIntervalMs","scheduleAdStopCountdown","remainingMs","clearAdStopTimer","ensureAdStoppedByTimer","adStopTimerId","onAdStopTimerFired","scheduleAdStartIn","nowWallClockMs","deltaMs","getDurationBudgetRemainingMs","logAdDurationDecision","budgetRemaining","delayMs","cueKey","clearAdStartTimer","onAdStartTimerFired","adStartTimerId","updatePtsDrift","ptsSecondsSample","sampleMs","alpha","resolveScteBreakStartWallClockMs","estimatedCurrentPtsMs","setAdBreakDurationBoundary","expectedAdBreakDurationMs","currentAdBreakStartWallClockMs","scteAdBreakEndWallClockMs","scheduleAdStopAtBreakBoundary","getWallClockRemainingAdMs","endWallClockMs","getAdBreakEndWallClockMs","getLoadedAdDurationMs","adController","adFitsRemainingBudget","accepted","remainingBudget","recordPlayedAdDuration","ensureLoadedAdFitsBudget","fits","rejectLoadedAdForDuration","markAdStarted","getRemainingAdMs","wallClockRemaining","configured","minRemainingMsToStartAd","hasTimeToStartAnotherAd","minRemaining","getMinRemainingMsToStartAd","isTemporaryAdError","isUrlInCooldown","failureTime","recordGamNoFill","cleanupTemporaryFailures","isGamInCooldown","backoff","pow","exponent","resetGamNoFillCounter","enforceGlobalRateLimit","waitMs","startAdRequestWatchdog","token","startAdFailsafeTimer","adFailsafeTimerId","clearAdRequestWatchdog","adFailsafeTimeoutMs","adRequestWatchdogId","logAdState","onWatchdogTimeout","clearAdFailsafeTimer","failsafeMs","videoPaused","onFailsafeTimeout","showAds","extra","resetForBreakEnd","preloadPoolLoop","AdPreloadPool","deps","pool","maxPoolSize","poolActive","loopRunning","active","isLoopRunning","startPreloadPool","startLoopImmediately","initialUrls","baseVastUrl","preloadAdIntoPool","vastUrl","timing","epoch","loadPromise","some","entry","hasAdError","adErrorPayload","errorListenerCleanup","preloadAd","errorListener","isNoFill","poolEntry","loadedDuration","lateErrorListener","shouldContinueLiveStreamDuringAds","createAdPlayer","code","vastErrorCode","loadedAt","isReady","findIndex","splice","newUrls","newUrl","getPendingAdBreak","getPreloadedAd","PlaceholderLayer","ensureContainer","show","transition","wasHidden","offsetHeight","requestAnimationFrame","hide","HlsEngine","cueManager","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","shouldUseNativeHls","getStreamType","canNative","canPlayType","setupNativeHls","isLive","setupHls","hls","import_hls2","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","_","_data","minSegments","details","live","onManifestParsed","minSegmentsBeforePlay","LEVEL_LOADED","_evt","hasPendingAdBreak","fragmentsToScan","fragments","tagList","isArray","idx","earlyDetection","FRAG_BUFFERED","FRAG_PARSING_METADATA","id3Tags","samples","pts","onId3Tag","FRAG_LOADED","processFragmentScte35Payload","FRAG_DECRYPTED","FRAG_CHANGED","activatePendingCuesForFragment","prog","ErrorTypes","NETWORK_ERROR","startLoad","recoverMediaError","onFatalDestroy","payloadData","getAdAudioVolume","toggleMute","newMutedState","restoreVolume","toggleFullscreen","fullscreenElement","requestFullscreen","isMuted","setMuted","setVolume","clampedVolume","getVolume","isFullscreen","resizePlayer","clientWidth","AdBreakOrchestrator","host","preloadPool","adConfig","placeholder","isShowingPlaceholder","continuousFetchingActive","continuousFetchLoopRunning","adRequestQueue","adPodQueue","maxPlaceholderDurationMs","pendingAdBreak","attachImaEventListeners","getAdPlayer","adIndex","remaining","queuedUrls","tryNextAvailableAdWithRateLimit","handleAdPodComplete","errorPayload","errorMessage","errorCode","cause","innerError","causeMessage","handleAdFailure","recreateAdController","shouldShowPlaceholder","preservedMutedState","preservedVolumeState","newAdPlayer","setAdPlayer","adBreakDurationMs","usePreloadedAd","preloaded","firstAdUrl","preloadedController","vastUrls","clearPendingAdBreak","firstAdUrlArray","generateVastUrls","startContinuousFetching","preservedMuted","preservedVolume","adVolume","currentMuted","currentVolume","fallbackPreloaded","swapToPreloadedAdPlayer","ap","fallbackError","continuousFetchLoop","maxQueueSize","newAdUrl","queuedUrlsPreview","generationDelay","stopContinuousFetching","backoffMultiplier","backoffDelay","effectiveMinInterval","timeSinceLastRequest","waitTime","minAdRequestIntervalMs","tryNextAvailableAd","nextAdUrl","playSingleAd","maxRetries","retryCount","showPlaceholderAndWaitForAds","requestToken","playError","preloadedFallback","fbAp"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/ui/StormcloudVideoPlayer.tsx\nvar StormcloudVideoPlayer_exports = {};\n__export(StormcloudVideoPlayer_exports, {\n StormcloudVideoPlayerComponent: () => StormcloudVideoPlayerComponent\n});\nmodule.exports = __toCommonJS(StormcloudVideoPlayer_exports);\nvar import_react = __toESM(require(\"react\"), 1);\n\n// src/sdk/hlsAdPlayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar MAX_VAST_WRAPPER_DEPTH = 5;\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 isHlsMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type === \"application/x-mpegurl\" || type === \"application/vnd.apple.mpegurl\" || type.includes(\"mpegurl\") || url.includes(\".m3u8\");\n }\n function isProgressiveMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type.startsWith(\"video/\") || url.endsWith(\".mp4\") || url.includes(\".mp4?\");\n }\n function createEmptyTrackingUrls() {\n return {\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 function extractTrackingUrls(xmlDoc) {\n const trackingUrls = createEmptyTrackingUrls();\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 xmlDoc.querySelectorAll(\"Error\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.error.push(url);\n });\n return trackingUrls;\n }\n function mergeTrackingUrls(target, source) {\n Object.keys(target).forEach((key) => {\n if (source[key] && source[key].length > 0) {\n target[key] = target[key].concat(source[key]);\n }\n });\n return target;\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 { type: \"empty\" };\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return { type: \"empty\" };\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n const wrapperUri = xmlDoc.querySelector(\"VASTAdTagURI\")?.textContent?.trim();\n if (wrapperUri) {\n console.log(\n `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n );\n return {\n type: \"wrapper\",\n vastAdTagUri: wrapperUri,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough\n };\n }\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 const mediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: void 0\n };\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\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 supported media files found in VAST XML\");\n }\n return { type: \"empty\" };\n }\n return {\n type: \"inline\",\n ad: {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough\n }\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return { type: \"empty\" };\n }\n }\n async function fetchVastXml(vastTagUrl) {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\"\n },\n referrerPolicy: \"no-referrer-when-downgrade\"\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n return response.text();\n }\n async function fetchAndParseVastAd(vastTagUrl, depth = 0, accumulatedTracking = createEmptyTrackingUrls()) {\n const vastXml = await fetchVastXml(vastTagUrl);\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 const parsed = parseVastXml(vastXml);\n if (parsed.type === \"empty\") {\n return null;\n }\n if (parsed.type === \"wrapper\") {\n if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n console.warn(\n `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n );\n return null;\n }\n mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n return fetchAndParseVastAd(\n parsed.vastAdTagUri,\n depth + 1,\n accumulatedTracking\n );\n }\n mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n return parsed.ad;\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 if (!adPlaying) return;\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 contentVideo.muted = true;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {\n });\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n emit(\"content_resume\");\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\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 = \"30\";\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.reject(new Error(\"No ads available from VAST response\"));\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 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 adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n adVideoElement.volume = Math.max(0, Math.min(1, originalVolume));\n adVideoElement.muted = originalMutedState;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n if (isHlsAd && import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n adHls = new import_hls.default({\n enableWorker: true,\n lowLatencyMode: false\n });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.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(import_hls.default.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && 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 if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\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 pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {\n });\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}, volume: ${contentVideo.volume}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {\n });\n }\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 = Math.max(0, Math.min(1, 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 const clamped = Math.max(0, Math.min(1, volume));\n adVideoElement.volume = clamped;\n adVideoElement.muted = clamped === 0;\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 getLoadedAdDuration() {\n return currentAd?.duration;\n },\n getLoadedAdId() {\n return currentAd?.id;\n }\n };\n}\n\n// src/sdk/pal.ts\nvar PAL_SDK_URL = \"https://imasdk.googleapis.com/pal/sdkloader/pal.js\";\nvar _nonceLoader;\nvar _palLoadPromise;\nfunction loadPalSdk() {\n if (typeof window !== \"undefined\" && window.goog?.pal) {\n return Promise.resolve();\n }\n if (_palLoadPromise) return _palLoadPromise;\n _palLoadPromise = new Promise((resolve, reject) => {\n const existing = document.querySelector(\n 'script[data-pal=\"true\"]'\n );\n if (existing) {\n if (window.goog?.pal) {\n resolve();\n return;\n }\n const timeout = setTimeout(\n () => reject(new Error(\"PAL SDK load timeout\")),\n 1e4\n );\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"PAL SDK load failed\"));\n });\n return;\n }\n const script = document.createElement(\"script\");\n script.src = PAL_SDK_URL;\n script.async = true;\n script.setAttribute(\"data-pal\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"PAL SDK load failed\"));\n document.head.appendChild(script);\n });\n return _palLoadPromise;\n}\nfunction getOrCreateNonceLoader() {\n if (_nonceLoader) return _nonceLoader;\n const goog = window.goog;\n const consentSettings = new goog.pal.ConsentSettings();\n consentSettings.allowStorage = true;\n _nonceLoader = new goog.pal.NonceLoader(consentSettings);\n return _nonceLoader;\n}\nfunction createPalNonceManager() {\n let currentNonce = \"\";\n let currentNonceManager;\n return {\n async generateNonce(options = {}) {\n try {\n await loadPalSdk();\n const loader = getOrCreateNonceLoader();\n const goog = window.goog;\n const request = new goog.pal.NonceRequest();\n request.adWillAutoPlay = options.adWillAutoPlay ?? true;\n request.adWillPlayMuted = options.adWillPlayMuted ?? false;\n request.playerVolume = options.playerVolume ?? (request.adWillPlayMuted ? 0 : 1);\n request.continuousPlayback = options.continuousPlayback ?? true;\n request.descriptionUrl = options.descriptionUrl || (typeof window !== \"undefined\" ? window.location.href : \"\");\n request.iconsSupported = true;\n request.playerType = \"StormcloudVideoPlayer\";\n request.playerVersion = \"1.0\";\n request.supportedApiFrameworks = \"2,7,9\";\n request.url = options.descriptionUrl || (typeof window !== \"undefined\" ? window.location.href : \"\");\n request.videoWidth = options.videoWidth || 640;\n request.videoHeight = options.videoHeight || 480;\n if (options.ppid) request.ppid = options.ppid;\n if (options.sessionId) request.sessionId = options.sessionId;\n const manager = await loader.loadNonceManager(request);\n currentNonceManager = manager;\n currentNonce = manager.getNonce();\n console.log(\"[PAL] Nonce generated successfully\");\n return currentNonce;\n } catch (error) {\n console.warn(\"[PAL] Failed to generate nonce:\", error);\n currentNonce = \"\";\n currentNonceManager = void 0;\n return \"\";\n }\n },\n getCurrentNonce() {\n return currentNonce;\n },\n injectNonce(vastTagUrl) {\n if (!currentNonce || !vastTagUrl) return vastTagUrl;\n try {\n const url = new URL(vastTagUrl);\n url.searchParams.delete(\"paln\");\n url.searchParams.set(\"givn\", currentNonce);\n return url.toString();\n } catch {\n let base = vastTagUrl.replace(/([?&])paln=[^&]*/g, \"\").replace(/[?&]$/, \"\");\n const sep = base.includes(\"?\") ? \"&\" : \"?\";\n return `${base}${sep}givn=${encodeURIComponent(currentNonce)}`;\n }\n },\n sendPlaybackStart() {\n try {\n currentNonceManager?.sendPlaybackStart();\n } catch {\n }\n },\n sendPlaybackEnd() {\n try {\n currentNonceManager?.sendPlaybackEnd();\n } catch {\n }\n },\n sendAdClick() {\n try {\n currentNonceManager?.sendAdClick();\n } catch {\n }\n },\n sendAdTouch(event) {\n try {\n currentNonceManager?.sendAdTouch(event);\n } catch {\n }\n },\n reset() {\n currentNonce = \"\";\n currentNonceManager = void 0;\n }\n };\n}\n\n// src/utils/mqttConfig.ts\nvar DEFAULT_MQTT_CONFIG = {\n enabled: true,\n brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n brokerPort: 8883,\n wsPort: 8084,\n username: \"for-sonifi\",\n password: \"sonifi-mqtt\",\n topicPrefix: \"adstorm/players\",\n qos: 1\n};\nvar mqttConfig = { ...DEFAULT_MQTT_CONFIG };\nfunction isMQTTEnabled() {\n return mqttConfig.enabled;\n}\nfunction buildMQTTBrokerUrl() {\n if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\nfunction buildPlayerTopic(licenseKey, channel) {\n return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n\n// src/utils/mqttClient.ts\nvar import_mqtt = __toESM(require(\"mqtt\"), 1);\nvar LOG = \"[StormcloudVideoPlayer][MQTT]\";\nvar client = null;\nvar status = \"disconnected\";\nfunction initMQTTClient() {\n if (client || !isMQTTEnabled()) return;\n const url = buildMQTTBrokerUrl();\n status = \"connecting\";\n const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n try {\n client = import_mqtt.default.connect(url, {\n clientId,\n username: mqttConfig.username,\n password: mqttConfig.password,\n keepalive: 60,\n clean: true,\n reconnectPeriod: 5e3,\n connectTimeout: 1e4,\n queueQoSZero: false\n });\n } catch (err) {\n status = \"error\";\n console.warn(`${LOG} connect() threw:`, err);\n return;\n }\n client.on(\"connect\", () => {\n status = \"connected\";\n console.info(`${LOG} connected to ${url}`);\n });\n client.on(\"reconnect\", () => {\n status = \"connecting\";\n console.info(`${LOG} reconnecting\\u2026`);\n });\n client.on(\"offline\", () => {\n status = \"disconnected\";\n console.warn(`${LOG} offline`);\n });\n client.on(\"error\", (err) => {\n status = \"error\";\n console.warn(`${LOG} error:`, err.message);\n });\n client.on(\"close\", () => {\n if (status === \"connected\") {\n status = \"disconnected\";\n }\n });\n}\nfunction ensureMQTTClient() {\n if (isMQTTEnabled() && !client) {\n initMQTTClient();\n }\n}\nfunction publishMQTT(topic, payload) {\n if (!isMQTTEnabled()) {\n return false;\n }\n ensureMQTTClient();\n if (!client) {\n return false;\n }\n try {\n client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n return true;\n } catch (err) {\n console.warn(`${LOG} publish failed on ${topic}:`, err);\n return false;\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?.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 hashHex = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle 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}\nfunction canPublish(licenseKey) {\n return Boolean(isMQTTEnabled() && licenseKey);\n}\nasync function buildPlayerMetricEvent(context = {}, flags = {}) {\n const clientInfo = getClientInfo();\n const playerId = await getBrowserID(clientInfo);\n const captureAt = flags.captureAt ?? (/* @__PURE__ */ new Date()).toISOString();\n return {\n player_id: playerId,\n device_type: clientInfo.deviceType,\n os: clientInfo.os.toLowerCase(),\n ad_loaded: flags.adLoaded ?? false,\n ad_detect: flags.adDetect ?? false,\n capture_at: captureAt,\n ...context.inputStreamType ? { input_stream_type: context.inputStreamType } : {}\n };\n}\nfunction publishTracking(licenseKey, channel, body) {\n ensureMQTTClient();\n publishMQTT(buildPlayerTopic(licenseKey, channel), body);\n}\nasync function sendInitialTracking(licenseKey, context = {}) {\n if (!canPublish(licenseKey)) return;\n try {\n const metricEvent = await buildPlayerMetricEvent(context, {\n adLoaded: false,\n adDetect: false\n });\n publishTracking(licenseKey, \"metrics\", {\n events: [metricEvent]\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\nasync function sendAdDetectTracking(licenseKey, adDetectInfo, context = {}) {\n try {\n await sendHeartbeat(licenseKey, context, {\n adDetect: true,\n captureAt: adDetectInfo.timestamp\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n error\n );\n }\n}\nasync function sendAdLoadedTracking(licenseKey, adLoadedInfo, context = {}) {\n try {\n await sendHeartbeat(licenseKey, context, {\n adLoaded: true,\n captureAt: adLoadedInfo.timestamp\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n error\n );\n }\n}\nasync function sendAdImpressionTracking(licenseKey, adImpressionInfo, context = {}) {\n if (!canPublish(licenseKey)) return;\n try {\n const metricEvent = await buildPlayerMetricEvent(context, {\n captureAt: adImpressionInfo.timestamp\n });\n publishTracking(licenseKey, \"heartbeat\", metricEvent);\n publishTracking(licenseKey, \"impressions\", {\n events: [\n {\n player_id: metricEvent.player_id,\n ad_played_count: 1,\n ad_url: adImpressionInfo.adUrl,\n capture_at: adImpressionInfo.timestamp\n }\n ]\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\nasync function sendHeartbeat(licenseKey, context = {}, flags = {}) {\n if (!canPublish(licenseKey)) return;\n try {\n const heartbeatData = await buildPlayerMetricEvent(context, flags);\n publishTracking(licenseKey, \"heartbeat\", heartbeatData);\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/utils/vastEnvironmentSignals.ts\nvar AIRY_ANDROID_APP_ID = \"com.freeairytv.android\";\nvar AIRY_WEBOS_APP_ID = \"com.freeairytv.webos\";\nvar AIRY_TIZEN_APP_ID = \"com.freeairytv.samsung\";\nvar AIRY_ROKU_APP_ID = \"com.freeairytv.roku\";\nvar AIRY_APP_NAME = \"AiryTV Movies & TV\";\nvar AIRY_DEFAULT_CONTENT_URL = \"https://live.airy.tv\";\nvar CTV_SESSION_STORAGE_KEY = \"stormcloud.ctv.sid\";\nvar LG_TEST_APP_ID = \"com.hulu.plus\";\nvar LG_TEST_APP_NAME = \"Hulu\";\nvar LG_TEST_CONTENT_URL = \"https://www.hulu.com/live-tv\";\nvar _lgTestDeviceId;\nfunction getLgTestDeviceId() {\n if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();\n return _lgTestDeviceId;\n}\nfunction isLgWebOS() {\n if (typeof navigator === \"undefined\") return false;\n return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);\n}\nfunction getDefaultAppId() {\n if (typeof navigator === \"undefined\") return AIRY_ANDROID_APP_ID;\n const ua = navigator.userAgent;\n if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;\n if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;\n if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;\n return AIRY_ANDROID_APP_ID;\n}\nvar DEVICE_ID_STORAGE_KEYS = [\n \"rdid\",\n \"ifa\",\n \"advertisingId\",\n \"advertising_id\",\n \"deviceAdvertisingId\",\n \"aaid\",\n \"adid\",\n \"rida\",\n \"tifa\",\n \"lgudid\"\n];\nvar ANDROID_ID_TYPES = /* @__PURE__ */ new Set([\"aaid\", \"adid\"]);\nfunction resolveVastEnvironmentSignals(isCtv) {\n const bridgeSignals = readNativeBridgeSignals();\n const lg = isCtv && isLgWebOS();\n const deviceId = bridgeSignals.deviceId || readStoredDeviceId() || (lg ? getLgTestDeviceId() : void 0);\n const deviceIdType = bridgeSignals.deviceIdType || readStoredString(\"deviceIdType\") || readStoredString(\"idtype\") || inferDeviceIdType() || (lg ? \"lgudid\" : void 0);\n const limitAdTracking = deviceId != null ? bridgeSignals.limitAdTracking ?? readStoredLimitAdTracking() ?? false : void 0;\n if (isCtv) {\n return {\n isCtv: true,\n contentUrl: bridgeSignals.contentUrl || readStoredString(\"contentUrl\") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),\n appId: bridgeSignals.appId || readStoredString(\"appId\") || readStoredString(\"msid\") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),\n appName: bridgeSignals.appName || readStoredString(\"appName\") || readStoredString(\"an\") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),\n sessionId: getOrCreateCtvSessionId(),\n ...deviceId ? { deviceId } : {},\n ...deviceIdType ? { deviceIdType } : {},\n ...limitAdTracking != null ? { limitAdTracking } : {},\n deviceTypeHint: 5\n };\n }\n return {\n isCtv: false,\n ...deviceId ? { deviceId } : {},\n ...deviceIdType ? { deviceIdType } : {},\n ...limitAdTracking != null ? { limitAdTracking } : {}\n };\n}\nfunction inferDeviceIdType() {\n if (typeof navigator === \"undefined\") {\n return void 0;\n }\n const ua = navigator.userAgent;\n if (/Roku/i.test(ua)) return \"rida\";\n if (/Tizen|Samsung/i.test(ua)) return \"tifa\";\n if (/AppleTV|Apple TV/i.test(ua)) return \"tvOS\";\n if (/AFT|Fire TV|Amazon/i.test(ua)) return \"afai\";\n if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return \"lgudid\";\n if (/Android|Google TV/i.test(ua)) return \"aaid\";\n if (/iPhone|iPad|iPod/i.test(ua)) return \"idfa\";\n return void 0;\n}\nfunction isEquivalentDeviceIdType(tagType, runtimeType) {\n if (!tagType || !runtimeType) return false;\n const tag = tagType.toLowerCase();\n const runtime = runtimeType.toLowerCase();\n if (tag === runtime) return true;\n return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);\n}\nfunction getOrCreateCtvSessionId() {\n const existing = readStoredString(CTV_SESSION_STORAGE_KEY);\n if (existing) {\n return existing;\n }\n const sessionId = createUuid();\n try {\n window.localStorage?.setItem(CTV_SESSION_STORAGE_KEY, sessionId);\n } catch {\n }\n return sessionId;\n}\nfunction createUuid() {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const value = Math.floor(Math.random() * 16);\n const nibble = char === \"x\" ? value : value & 3 | 8;\n return nibble.toString(16);\n });\n}\nfunction readNativeBridgeSignals() {\n if (typeof window === \"undefined\") {\n return {};\n }\n const candidates = [\n window.__STORMCLOUD_CTV_AD_INFO__,\n window.__STORMCLOUD_CTV__,\n window.stormcloudCtv,\n window.AiryTV,\n window.Android,\n window.webOS,\n window.tizen,\n window.amazon\n ].filter(Boolean);\n for (const source of candidates) {\n const contentUrl = readBridgeValue(source, [\"contentUrl\", \"url\", \"videoUrl\", \"canonicalUrl\"]) || void 0;\n const appId = readBridgeValue(source, [\"appId\", \"msid\", \"applicationId\", \"packageName\"]) || void 0;\n const appName = readBridgeValue(source, [\"appName\", \"an\", \"applicationName\"]) || void 0;\n const deviceId = readBridgeValue(source, [\n \"rdid\",\n \"ifa\",\n \"advertisingId\",\n \"adId\",\n \"deviceId\",\n \"lgudid\",\n \"LGUDID\",\n \"tifa\",\n \"rida\",\n \"afai\",\n \"aaid\"\n ]) || void 0;\n if (!contentUrl && !deviceId && !appId && !appName) continue;\n const deviceIdType = readBridgeValue(source, [\n \"idtype\",\n \"deviceIdType\",\n \"advertisingIdType\",\n \"idType\"\n ]) || inferDeviceIdType();\n const limitAdTracking = readBridgeBoolean(source, [\n \"is_lat\",\n \"limitAdTracking\",\n \"limitedAdTracking\",\n \"lat\"\n ]);\n return {\n ...contentUrl ? { contentUrl } : {},\n ...appId ? { appId } : {},\n ...appName ? { appName } : {},\n ...deviceId ? { deviceId } : {},\n ...deviceId && deviceIdType ? { deviceIdType } : {},\n ...deviceId && limitAdTracking != null ? { limitAdTracking } : {}\n };\n }\n return {};\n}\nfunction readBridgeValue(source, keys) {\n for (const key of keys) {\n const value = source?.[key];\n if (typeof value === \"string\" && value) {\n return value;\n }\n if (typeof value === \"function\") {\n try {\n const result = value.call(source);\n if (typeof result === \"string\" && result) {\n return result;\n }\n } catch {\n }\n }\n }\n return void 0;\n}\nfunction readBridgeBoolean(source, keys) {\n for (const key of keys) {\n const value = source?.[key];\n const normalized = normalizeBoolean(value);\n if (normalized != null) {\n return normalized;\n }\n if (typeof value === \"function\") {\n try {\n const result = normalizeBoolean(value.call(source));\n if (result != null) {\n return result;\n }\n } catch {\n }\n }\n }\n return void 0;\n}\nfunction readStoredDeviceId() {\n for (const key of DEVICE_ID_STORAGE_KEYS) {\n const value = readStoredString(key);\n if (value) {\n return value;\n }\n }\n return void 0;\n}\nfunction readStoredString(key) {\n if (typeof window === \"undefined\") {\n return void 0;\n }\n try {\n const value = window.localStorage?.getItem(key);\n return value || void 0;\n } catch {\n return void 0;\n }\n}\nfunction readStoredLimitAdTracking() {\n return normalizeBoolean(\n readStoredString(\"limitAdTracking\") || readStoredString(\"limitedAdTracking\") || readStoredString(\"is_lat\")\n );\n}\nfunction normalizeBoolean(value) {\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"number\") {\n return value === 1;\n }\n if (typeof value === \"string\") {\n const normalized = value.toLowerCase();\n if (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\") {\n return true;\n }\n if (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n return false;\n }\n }\n return void 0;\n}\n\n// src/utils/vastMacros.ts\nvar UNEXPANDED_MACRO_PATTERN = /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/;\nvar INVALID_VAST_PARAM_KEY = /^\\s|\\s$/;\nvar EXAMPLE_COM_URL = /example\\.com/i;\nvar CTV_UNSUPPORTED_PARAMS = [\n \"description_url\",\n \"tfcd\",\n \"npa\",\n \"min_ad_duration\",\n \"max_ad_duration\",\n \"unviewed_position_start\",\n \"impl\",\n \"vad_type\",\n \"gdpr\",\n \"gdpr_consent\",\n \"us_privacy\"\n];\nvar INLINE_DEVICE_MACRO_REPLACEMENTS = [\n { pattern: /\\[RDID\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[IFA\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[ADVERTISING[_-]?ID(?:ENTIFIER)?\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[DEVICE[_-]?ID\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[IDTYPE\\]/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /\\{rdid\\}/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\{device[_-]?id\\}/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\{idtype\\}/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi, getValue: (ctx) => ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0 },\n { pattern: /%%ADVERTISING_ID_TYPE%%/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /%%ADVERTISING_ID%%/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /%%LIMIT_AD_TRACKING%%/gi, getValue: (ctx) => ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0 },\n { pattern: /%%MSID%%/gi, getValue: (ctx) => ctx.appId },\n { pattern: /%%APP_NAME%%/gi, getValue: (ctx) => ctx.appName },\n { pattern: /%%SESSION_ID%%/gi, getValue: (ctx) => ctx.sessionId },\n { pattern: /%%CORRELATOR%%/gi, getValue: (ctx) => ctx.correlator }\n];\nfunction isMacroPlaceholder(value) {\n if (value == null) return true;\n const trimmed = value.trim();\n if (!trimmed) return true;\n if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;\n return /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(trimmed);\n}\nfunction generateCorrelator() {\n if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n try {\n const buf = new Uint32Array(2);\n crypto.getRandomValues(buf);\n const value = (buf[0] ?? 0) * 2097152 + ((buf[1] ?? 0) & 2097151);\n if (value > 0) {\n return String(value);\n }\n } catch {\n }\n }\n return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);\n}\nfunction expandInlineMacroPlaceholders(baseUrl, ctx) {\n let url = baseUrl;\n for (const { pattern, getValue } of INLINE_DEVICE_MACRO_REPLACEMENTS) {\n const value = getValue(ctx);\n if (value != null && value !== \"\") {\n url = url.replace(pattern, encodeURIComponent(value));\n }\n }\n return url;\n}\nfunction applyDeviceIdentityParams(params, ctx) {\n const runtimeId = ctx.deviceId?.trim();\n const runtimeType = ctx.deviceIdType?.trim() || inferDeviceIdType();\n const tagRdid = params.get(\"rdid\");\n const tagType = params.get(\"idtype\");\n const tagLat = params.get(\"is_lat\");\n const latValue = ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0;\n if (runtimeId) {\n params.set(\"rdid\", runtimeId);\n params.set(\"idtype\", runtimeType || tagType || \"aaid\");\n params.set(\"is_lat\", latValue ?? (isMacroPlaceholder(tagLat) ? \"0\" : tagLat));\n return;\n }\n const tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));\n const tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));\n if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {\n params.delete(\"rdid\");\n params.delete(\"idtype\");\n params.delete(\"is_lat\");\n return;\n }\n if (tagRdidValid) {\n if (isMacroPlaceholder(tagType) && runtimeType) {\n params.set(\"idtype\", runtimeType);\n }\n if (isMacroPlaceholder(tagLat)) {\n params.set(\"is_lat\", latValue ?? \"0\");\n }\n return;\n }\n params.delete(\"rdid\");\n params.delete(\"idtype\");\n params.delete(\"is_lat\");\n}\nfunction removeBrokenAppNameOrphans(params, appName) {\n const toDelete = [];\n params.forEach((_value, key) => {\n if (!key || INVALID_VAST_PARAM_KEY.test(key)) {\n toDelete.push(key);\n }\n });\n if (appName && appName.includes(\"&\")) {\n for (const suffix of appName.split(\"&\").slice(1)) {\n const trimmed = suffix.trimStart();\n if (!trimmed) continue;\n toDelete.push(suffix, ` ${trimmed}`, trimmed);\n }\n }\n for (const key of new Set(toDelete)) {\n if (key) params.delete(key);\n }\n}\nfunction normalizeVastTagUrl(raw) {\n if (!raw) return raw;\n try {\n const url = new URL(raw);\n const anValue = url.searchParams.get(\"an\");\n if (anValue !== null) {\n const orphanFragments = [];\n url.searchParams.forEach((_value, key) => {\n if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n orphanFragments.push(key.trim());\n }\n });\n if (orphanFragments.length > 0) {\n const reconstructed = [anValue.trimEnd(), ...orphanFragments].filter(Boolean).join(\" & \");\n url.searchParams.forEach((_value, key) => {\n if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n url.searchParams.delete(key);\n }\n });\n url.searchParams.set(\"an\", reconstructed);\n return url.toString().replace(\n /([?&]an=)([^&]*)/,\n (_match, prefix, val) => prefix + val.replace(/\\+/g, \"%20\")\n );\n }\n }\n removeBrokenAppNameOrphans(url.searchParams);\n return url.toString();\n } catch {\n return raw;\n }\n}\nfunction applyVastMacros(baseUrl, ctx) {\n const expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);\n let url;\n try {\n url = new URL(normalizeVastTagUrl(expandedUrl));\n } catch {\n return replaceCorrelatorFallback(expandedUrl, ctx.correlator);\n }\n const params = url.searchParams;\n removeBrokenAppNameOrphans(params, ctx.appName);\n params.set(\"correlator\", ctx.correlator);\n params.set(\"scor\", ctx.streamCorrelator);\n if (ctx.isCtv) {\n for (const key of CTV_UNSUPPORTED_PARAMS) {\n params.delete(key);\n }\n }\n if (ctx.pod != null) {\n params.set(\"pod\", String(ctx.pod));\n }\n if (ctx.adPosition != null) {\n params.set(\"ppos\", String(ctx.adPosition));\n }\n const requestUrl = ctx.contentUrl || ctx.pageUrl;\n if (requestUrl) {\n params.set(\"url\", requestUrl);\n if (!ctx.isCtv) {\n params.set(\"description_url\", requestUrl);\n }\n } else {\n const existingUrl = params.get(\"url\") || \"\";\n if (EXAMPLE_COM_URL.test(existingUrl)) {\n params.delete(\"url\");\n params.delete(\"description_url\");\n }\n }\n if (ctx.adWillPlayMuted != null) {\n params.set(\"vpmute\", ctx.adWillPlayMuted ? \"1\" : \"0\");\n }\n if (ctx.adWillAutoPlay != null) {\n params.set(\"vpa\", ctx.adWillAutoPlay ? \"auto\" : \"click\");\n }\n if (ctx.appId) {\n params.set(\"msid\", ctx.appId);\n }\n if (ctx.appName) {\n removeBrokenAppNameOrphans(params, ctx.appName);\n params.set(\"an\", ctx.appName);\n }\n if (ctx.sessionId) {\n params.set(\"sid\", ctx.sessionId);\n }\n if (ctx.deviceTypeHint != null) {\n params.set(\"dth\", String(ctx.deviceTypeHint));\n } else if (ctx.isCtv) {\n params.set(\"dth\", \"5\");\n }\n applyDeviceIdentityParams(params, ctx);\n if (!ctx.isCtv) {\n const consent = ctx.consent;\n if (consent?.gdpr != null) {\n params.set(\"gdpr\", consent.gdpr);\n }\n if (consent?.gdprConsent != null) {\n params.set(\"gdpr_consent\", consent.gdprConsent);\n }\n if (consent?.usPrivacy != null) {\n params.set(\"us_privacy\", consent.usPrivacy);\n }\n }\n if (ctx.adTest) {\n params.set(\"adtest\", \"on\");\n }\n const staleKeys = [];\n params.forEach((value, key) => {\n if (isMacroPlaceholder(value)) {\n staleKeys.push(key);\n }\n });\n for (const key of staleKeys) {\n params.delete(key);\n }\n removeBrokenAppNameOrphans(params, ctx.appName);\n return url.toString();\n}\nfunction replaceCorrelatorFallback(baseUrl, correlator) {\n const correlatorRegex = /([?&])correlator=([^&]*)/;\n if (correlatorRegex.test(baseUrl)) {\n return baseUrl.replace(correlatorRegex, `$1correlator=${correlator}`);\n }\n const sep = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${sep}correlator=${correlator}`;\n}\nfunction fetchConsentSignals(timeoutMs = 1500) {\n const signals = {};\n if (typeof window === \"undefined\") {\n return Promise.resolve(signals);\n }\n const tasks = [];\n const tcfApi = window.__tcfapi;\n if (typeof tcfApi === \"function\") {\n tasks.push(\n new Promise((resolve) => {\n let settled = false;\n try {\n tcfApi(\"addEventListener\", 2, (tcData, success) => {\n if (settled) return;\n if (success && tcData && (tcData.eventStatus === \"tcloaded\" || tcData.eventStatus === \"useractioncomplete\")) {\n settled = true;\n signals.gdpr = tcData.gdprApplies ? \"1\" : \"0\";\n if (typeof tcData.tcString === \"string\" && tcData.tcString) {\n signals.gdprConsent = tcData.tcString;\n }\n try {\n tcfApi(\"removeEventListener\", 2, () => {\n }, tcData.listenerId);\n } catch {\n }\n resolve();\n }\n });\n } catch {\n resolve();\n }\n setTimeout(() => {\n if (!settled) {\n settled = true;\n resolve();\n }\n }, timeoutMs);\n })\n );\n }\n const uspApi = window.__uspapi;\n if (typeof uspApi === \"function\") {\n tasks.push(\n new Promise((resolve) => {\n try {\n uspApi(\"getUSPData\", 1, (data, success) => {\n if (success && typeof data?.uspString === \"string\" && data.uspString) {\n signals.usPrivacy = data.uspString;\n }\n resolve();\n });\n } catch {\n resolve();\n }\n setTimeout(resolve, timeoutMs);\n })\n );\n }\n if (tasks.length === 0) {\n return Promise.resolve(signals);\n }\n return Promise.all(tasks).then(() => signals);\n}\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 supportsModernJS = true;\n let webOSVersion;\n let tizenVersion;\n let chromeVersionNum;\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n chromeVersionNum = chromeVersion > 0 ? chromeVersion : void 0;\n if (/Web0S|webOS|LG Browser|LGSTB/i.test(ua)) {\n name = \"LG WebOS\";\n isSmartTV = true;\n let match = ua.match(/Web0S[/\\s]*([\\d.]+)/i) || ua.match(/webOS[/\\s]*([\\d.]+)/i);\n if (!match || !match[1]) {\n match = ua.match(/webOSTV[/\\s-]*([\\d.]+)/i) || ua.match(/webOS\\.TV[/\\s-]*([\\d.]+)/i);\n }\n if (match && match[1]) {\n version = match[1];\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n webOSVersion = majorVersion;\n } else if (chromeVersion > 0) {\n if (chromeVersion >= 79) {\n webOSVersion = 6;\n version = \"6.0\";\n majorVersion = 6;\n } else if (chromeVersion >= 68) {\n webOSVersion = 5;\n version = \"5.0\";\n majorVersion = 5;\n } else if (chromeVersion >= 53) {\n webOSVersion = 4;\n version = \"4.0\";\n majorVersion = 4;\n } else if (chromeVersion >= 38) {\n webOSVersion = 3;\n version = \"3.0\";\n majorVersion = 3;\n } else {\n webOSVersion = 2;\n version = \"2.0\";\n majorVersion = 2;\n }\n } else {\n version = \"Unknown\";\n webOSVersion = void 0;\n }\n isLegacyTV = webOSVersion !== void 0 && webOSVersion < 3;\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 tizenVersion = majorVersion;\n }\n isLegacyTV = tizenVersion !== void 0 && tizenVersion < 3;\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\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 isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\n } else {\n if (chromeVersion > 0) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n if (chromeVersion < 50) {\n supportsModernJS = false;\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n }\n if (typeof URLSearchParams === \"undefined\") {\n supportsModernJS = false;\n }\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsModernJS,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum\n };\n}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\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 supportsModernJS: browser.supportsModernJS,\n ...browser.webOSVersion !== void 0 ? { webOSVersion: browser.webOSVersion } : {},\n ...browser.tizenVersion !== void 0 ? { tizenVersion: browser.tizenVersion } : {},\n ...browser.chromeVersion !== void 0 ? { chromeVersion: browser.chromeVersion } : {},\n userAgent: navigator.userAgent\n });\n}\n\n// src/player/Scte35Parser.ts\nfunction 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}\nfunction parseCueOutCont(value) {\n const res = {};\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\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)) {\n const slashMatch = value.match(/([0-9.]+)\\s*\\/\\s*([0-9.]+)/);\n if (slashMatch && slashMatch[1] && slashMatch[2]) {\n const elapsed = parseFloat(slashMatch[1]);\n const duration = parseFloat(slashMatch[2]);\n if (!Number.isNaN(elapsed) && !(\"elapsed\" in res)) res.elapsed = elapsed;\n if (!Number.isNaN(duration) && !(\"duration\" in res)) res.duration = duration;\n }\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return void 0;\n}\nfunction 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}\nfunction 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}\nfunction 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}\nfunction 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}\nfunction getFragmentStartSeconds(frag) {\n const candidates = [frag?.start, frag?.startPTS];\n for (const candidate of candidates) {\n if (typeof candidate === \"number\" && Number.isFinite(candidate)) {\n return candidate;\n }\n }\n return void 0;\n}\nfunction parseScte35FromId3(tag) {\n const text = 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 = 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 = 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 = 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 = 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 = parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n}\nfunction normalizeFragmentPayload(payload) {\n if (payload instanceof Uint8Array) {\n return payload;\n }\n if (payload instanceof ArrayBuffer) {\n return new Uint8Array(payload);\n }\n if (ArrayBuffer.isView(payload)) {\n const view = payload;\n return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n }\n return void 0;\n}\nfunction detectTsPacketFormat(data) {\n const packetSizes = [188, 192, 204];\n for (const packetSize of packetSizes) {\n const tsPayloadOffset = packetSize === 192 ? 4 : 0;\n for (let offset = 0; offset < packetSize; offset++) {\n let matchedPackets = 0;\n for (let packetStart = offset; packetStart + tsPayloadOffset < data.length && matchedPackets < 5; packetStart += packetSize) {\n if (data[packetStart + tsPayloadOffset] !== 71) {\n break;\n }\n matchedPackets++;\n }\n if (matchedPackets >= 2) {\n return { offset, packetSize, tsPayloadOffset };\n }\n }\n }\n return void 0;\n}\nfunction getPsiSectionStart(payload, payloadUnitStart) {\n if (!payloadUnitStart) {\n return void 0;\n }\n const pointerField = payload[0];\n if (pointerField == null) {\n return void 0;\n }\n const sectionStart = 1 + pointerField;\n return sectionStart < payload.length ? sectionStart : void 0;\n}\nfunction getPsiSectionLength(data, offset) {\n return ((data[offset + 1] ?? 0) & 15) << 8 | (data[offset + 2] ?? 0);\n}\nfunction parsePatSection(payload, payloadUnitStart, pmtPids) {\n const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n if (sectionStart == null || sectionStart + 8 >= payload.length) {\n return;\n }\n if (payload[sectionStart] !== 0) {\n return;\n }\n const sectionLength = getPsiSectionLength(payload, sectionStart);\n const sectionEnd = Math.min(\n payload.length,\n sectionStart + 3 + sectionLength\n );\n for (let offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4) {\n const programNumber = (payload[offset] ?? 0) << 8 | (payload[offset + 1] ?? 0);\n const pid = ((payload[offset + 2] ?? 0) & 31) << 8 | (payload[offset + 3] ?? 0);\n if (programNumber !== 0) {\n pmtPids.add(pid);\n }\n }\n}\nfunction descriptorsIdentifyScte35(data, start, end) {\n let offset = start;\n while (offset + 2 <= end) {\n const tag = data[offset] ?? 0;\n const length = data[offset + 1] ?? 0;\n const descriptorStart = offset + 2;\n const descriptorEnd = descriptorStart + length;\n if (descriptorEnd > end) {\n return false;\n }\n const registration = length >= 4 ? String.fromCharCode(\n data[descriptorStart] ?? 0,\n data[descriptorStart + 1] ?? 0,\n data[descriptorStart + 2] ?? 0,\n data[descriptorStart + 3] ?? 0\n ) : \"\";\n if (tag === 138 || registration === \"CUEI\" || registration === \"SCTE\") {\n return true;\n }\n offset = descriptorEnd;\n }\n return false;\n}\nfunction parsePmtSection(payload, payloadUnitStart, tsScte35Pids) {\n const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n if (sectionStart == null || sectionStart + 12 >= payload.length) {\n return;\n }\n if (payload[sectionStart] !== 2) {\n return;\n }\n const sectionLength = getPsiSectionLength(payload, sectionStart);\n const sectionEnd = Math.min(\n payload.length,\n sectionStart + 3 + sectionLength\n );\n const programInfoLength = ((payload[sectionStart + 10] ?? 0) & 15) << 8 | (payload[sectionStart + 11] ?? 0);\n let offset = sectionStart + 12 + programInfoLength;\n while (offset + 5 <= sectionEnd - 4) {\n const streamType = payload[offset] ?? 0;\n const elementaryPid = ((payload[offset + 1] ?? 0) & 31) << 8 | (payload[offset + 2] ?? 0);\n const esInfoLength = ((payload[offset + 3] ?? 0) & 15) << 8 | (payload[offset + 4] ?? 0);\n const descriptorStart = offset + 5;\n const descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);\n if (streamType === 134 || streamType === 6 && descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd)) {\n tsScte35Pids.add(elementaryPid);\n }\n offset = descriptorStart + esInfoLength;\n }\n}\nfunction hasProcessedTsScte35Section(section, processedSections) {\n let checksum = 0;\n for (let i = 0; i < section.length; i++) {\n checksum = checksum * 31 + (section[i] ?? 0) >>> 0;\n }\n const key = `${section.length}:${checksum}`;\n if (processedSections.has(key)) {\n return true;\n }\n processedSections.add(key);\n if (processedSections.size > 200) {\n const firstKey = processedSections.values().next().value;\n if (firstKey) {\n processedSections.delete(firstKey);\n }\n }\n return false;\n}\nfunction addScte35SectionMarker(section, markers, processedSections) {\n if (section[0] !== 252 || hasProcessedTsScte35Section(section, processedSections)) {\n return;\n }\n const marker = parseScte35Binary(section);\n if (!marker) {\n return;\n }\n marker.raw = {\n ...typeof marker.raw === \"object\" && marker.raw ? marker.raw : {},\n source: \"ts-packet\"\n };\n markers.push(marker);\n}\nfunction appendScte35Bytes(pid, bytes, assemblers, markers, processedSections) {\n const assembler = assemblers.get(pid);\n if (!assembler) {\n return;\n }\n for (let i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++) {\n assembler.bytes.push(bytes[i] ?? 0);\n }\n if (assembler.bytes.length >= assembler.expectedLength) {\n assemblers.delete(pid);\n addScte35SectionMarker(new Uint8Array(assembler.bytes), markers, processedSections);\n }\n}\nfunction collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, assemblers, markers, processedSections) {\n if (payload.length === 0) {\n return;\n }\n let offset = 0;\n if (payloadUnitStart) {\n const pointerField = payload[0] ?? 0;\n const previousAssembler = assemblers.get(pid);\n if (previousAssembler && pointerField > 0) {\n appendScte35Bytes(\n pid,\n payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n assemblers,\n markers,\n processedSections\n );\n }\n assemblers.delete(pid);\n offset = 1 + pointerField;\n } else {\n appendScte35Bytes(pid, payload, assemblers, markers, processedSections);\n return;\n }\n while (offset + 3 <= payload.length) {\n const tableId = payload[offset];\n if (tableId == null || tableId === 255) {\n return;\n }\n const sectionLength = getPsiSectionLength(payload, offset);\n const totalLength = 3 + sectionLength;\n if (sectionLength <= 0 || totalLength <= 3) {\n return;\n }\n if (offset + totalLength <= payload.length) {\n addScte35SectionMarker(\n payload.subarray(offset, offset + totalLength),\n markers,\n processedSections\n );\n offset += totalLength;\n } else {\n assemblers.set(pid, {\n bytes: Array.from(payload.subarray(offset)),\n expectedLength: totalLength\n });\n return;\n }\n }\n}\nfunction parseScte35FromTsPackets(data, tsScte35Pids, pmtPids, processedSections) {\n const packetInfo = detectTsPacketFormat(data);\n if (!packetInfo) {\n return [];\n }\n const markers = [];\n const sectionAssemblers = /* @__PURE__ */ new Map();\n for (let packetStart = packetInfo.offset; packetStart + packetInfo.packetSize <= data.length; packetStart += packetInfo.packetSize) {\n const tsStart = packetStart + packetInfo.tsPayloadOffset;\n if (data[tsStart] !== 71) {\n continue;\n }\n const secondByte = data[tsStart + 1];\n const thirdByte = data[tsStart + 2];\n const fourthByte = data[tsStart + 3];\n if (secondByte == null || thirdByte == null || fourthByte == null || (secondByte & 128) !== 0) {\n continue;\n }\n const payloadUnitStart = (secondByte & 64) !== 0;\n const pid = (secondByte & 31) << 8 | thirdByte;\n const adaptationFieldControl = fourthByte >> 4 & 3;\n const hasPayload = adaptationFieldControl === 1 || adaptationFieldControl === 3;\n if (!hasPayload) {\n continue;\n }\n let payloadStart = tsStart + 4;\n if (adaptationFieldControl === 3) {\n const adaptationLength = data[payloadStart];\n if (adaptationLength == null) {\n continue;\n }\n payloadStart += 1 + adaptationLength;\n }\n const payloadEnd = Math.min(tsStart + 188, data.length);\n if (payloadStart >= payloadEnd || payloadStart >= data.length) {\n continue;\n }\n const payload = data.subarray(payloadStart, payloadEnd);\n if (pid === 0) {\n parsePatSection(payload, payloadUnitStart, pmtPids);\n } else if (pmtPids.has(pid)) {\n parsePmtSection(payload, payloadUnitStart, tsScte35Pids);\n } else if (tsScte35Pids.has(pid)) {\n collectScte35SectionsFromPayload(\n pid,\n payload,\n payloadUnitStart,\n sectionAssemblers,\n markers,\n processedSections\n );\n }\n }\n return markers;\n}\nvar BitReader = class {\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 get bytePosition() {\n return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n }\n};\nfunction readSpliceTime(r, ptsAdjustmentTicks) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (!timeSpecifiedFlag) {\n r.readBits(7);\n return void 0;\n }\n r.readBits(6);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const ptsTicks = (high * 4294967296 + low + ptsAdjustmentTicks) % 8589934592;\n return ptsTicks / 9e4;\n}\nfunction markerTypeFromSegmentationTypeId(segmentationTypeId) {\n switch (segmentationTypeId) {\n case 16:\n case 34:\n case 48:\n case 50:\n case 52:\n case 54:\n return \"start\";\n case 17:\n case 35:\n case 49:\n case 51:\n case 53:\n case 55:\n return \"end\";\n default:\n return void 0;\n }\n}\nfunction parseScte35SegmentationDescriptor(descriptor) {\n if (descriptor.length < 11) {\n return void 0;\n }\n const identifier = String.fromCharCode(\n descriptor[0] ?? 0,\n descriptor[1] ?? 0,\n descriptor[2] ?? 0,\n descriptor[3] ?? 0\n );\n if (identifier !== \"CUEI\") {\n return void 0;\n }\n const segmentationEventId = (descriptor[4] ?? 0) * 16777216 + ((descriptor[5] ?? 0) << 16) + ((descriptor[6] ?? 0) << 8) + (descriptor[7] ?? 0);\n const cancelIndicator = ((descriptor[8] ?? 0) & 128) !== 0;\n if (cancelIndicator) {\n return void 0;\n }\n const flags = descriptor[9] ?? 0;\n const programSegmentationFlag = (flags & 128) !== 0;\n const segmentationDurationFlag = (flags & 64) !== 0;\n let offset = 10;\n if (!programSegmentationFlag) {\n const componentCount = descriptor[offset] ?? 0;\n offset += 1 + componentCount * 6;\n if (offset > descriptor.length) {\n return void 0;\n }\n }\n let durationSeconds = void 0;\n if (segmentationDurationFlag) {\n if (offset + 5 > descriptor.length) {\n return void 0;\n }\n const durationTicks = (descriptor[offset] ?? 0) * 4294967296 + (descriptor[offset + 1] ?? 0) * 16777216 + ((descriptor[offset + 2] ?? 0) << 16) + ((descriptor[offset + 3] ?? 0) << 8) + (descriptor[offset + 4] ?? 0);\n durationSeconds = durationTicks / 9e4;\n offset += 5;\n }\n if (offset + 2 > descriptor.length) {\n return void 0;\n }\n offset += 1;\n const segmentationUpidLength = descriptor[offset] ?? 0;\n offset += 1 + segmentationUpidLength;\n if (offset >= descriptor.length) {\n return void 0;\n }\n const segmentationTypeId = descriptor[offset] ?? 0;\n const markerType = markerTypeFromSegmentationTypeId(segmentationTypeId);\n if (!markerType) {\n return void 0;\n }\n return {\n type: markerType,\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n segmentationEventId\n };\n}\nfunction parseScte35SegmentationDescriptors(data, offset) {\n if (offset + 2 > data.length) {\n return void 0;\n }\n const descriptorLoopLength = (data[offset] ?? 0) << 8 | (data[offset + 1] ?? 0);\n let descriptorOffset = offset + 2;\n const descriptorEnd = Math.min(\n data.length,\n descriptorOffset + descriptorLoopLength\n );\n while (descriptorOffset + 2 <= descriptorEnd) {\n const descriptorTag = data[descriptorOffset] ?? 0;\n const descriptorLength = data[descriptorOffset + 1] ?? 0;\n const descriptorDataStart = descriptorOffset + 2;\n const descriptorDataEnd = descriptorDataStart + descriptorLength;\n if (descriptorDataEnd > descriptorEnd) {\n return void 0;\n }\n if (descriptorTag === 2) {\n const descriptorMarker = parseScte35SegmentationDescriptor(\n data.subarray(descriptorDataStart, descriptorDataEnd)\n );\n if (descriptorMarker) {\n return descriptorMarker;\n }\n }\n descriptorOffset = descriptorDataEnd;\n }\n return void 0;\n}\nfunction parseScte35Binary(data) {\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 if (sectionLength <= 0 || data.length < 3 + sectionLength) {\n return void 0;\n }\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 const ptsAdjustmentTicks = ptsAdjHigh * 4294967296 + ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n let markerType;\n let durationSeconds = void 0;\n let ptsSeconds = void 0;\n let spliceEventId = void 0;\n const commandBodyStart = r.bytePosition;\n if (spliceCommandType === 5) {\n spliceEventId = 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 markerType = outOfNetwork ? \"start\" : \"end\";\n if (programSpliceFlag && !spliceImmediateFlag) {\n ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\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 componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n if (ptsSeconds === void 0) {\n ptsSeconds = componentPtsSeconds;\n }\n }\n }\n }\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 } else if (spliceCommandType === 6) {\n ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n } else {\n return void 0;\n }\n const expectedDescriptorOffset = spliceCommandLength === 4095 ? r.bytePosition : commandBodyStart + spliceCommandLength;\n const descriptorMarker = parseScte35SegmentationDescriptors(\n data,\n expectedDescriptorOffset\n );\n if (descriptorMarker) {\n markerType = descriptorMarker.type;\n if (durationSeconds === void 0) {\n durationSeconds = descriptorMarker.durationSeconds;\n }\n }\n if (!markerType) {\n return void 0;\n }\n const marker = {\n type: markerType,\n ...ptsSeconds !== void 0 ? { ptsSeconds } : {},\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: {\n splice_command_type: spliceCommandType,\n ...spliceEventId !== void 0 ? { splice_event_id: spliceEventId } : {},\n ...descriptorMarker?.segmentationEventId !== void 0 ? { segmentation_event_id: descriptorMarker.segmentationEventId } : {}\n }\n };\n return marker;\n}\n\n// src/player/Scte35CueManager.ts\nvar Scte35CueManager = class {\n constructor(debug, callbacks) {\n this.pendingScte35Cues = /* @__PURE__ */ new Map();\n this.recentScte35CueKeys = /* @__PURE__ */ new Map();\n this.recentScte35CueLimit = 200;\n this.tsScte35Pids = /* @__PURE__ */ new Set();\n this.pmtPids = /* @__PURE__ */ new Set();\n this.processedTsScte35Sections = /* @__PURE__ */ new Set();\n this.debug = debug;\n this.callbacks = callbacks;\n }\n get pendingScte35CueKey() {\n return this.pendingScte35CueKeyValue;\n }\n set pendingScte35CueKey(value) {\n this.pendingScte35CueKeyValue = value;\n }\n get activeScte35BreakKey() {\n return this.activeScte35BreakKeyValue;\n }\n set activeScte35BreakKey(value) {\n this.activeScte35BreakKeyValue = value;\n }\n get scheduledScte35BreakKey() {\n return this.scheduledScte35BreakKeyValue;\n }\n set scheduledScte35BreakKey(value) {\n this.scheduledScte35BreakKeyValue = value;\n }\n createScte35CueContext(source, readiness, frag) {\n const context = { source, readiness };\n if (typeof frag?.sn === \"number\") {\n context.fragmentSn = frag.sn;\n }\n const fragmentStartSec = getFragmentStartSeconds(frag);\n if (fragmentStartSec !== void 0) {\n context.fragmentStartSeconds = fragmentStartSec;\n }\n return context;\n }\n onScte35Cue(marker, context) {\n const cue = this.createScte35Cue(marker, context);\n const pendingKey = this.getPendingScte35CueKey(cue);\n if (context.readiness === \"early\") {\n this.pendingScte35Cues.set(pendingKey, cue);\n this.trimRecentScte35CueMaps();\n if (marker.type === \"start\") {\n this.callbacks.onEarlyStartCue(marker, context.fragmentSn, cue.key);\n }\n return;\n }\n if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n key: cue.key,\n activeScte35BreakKey: this.activeScte35BreakKeyValue,\n inAdBreak: this.callbacks.isInAdBreak(),\n source: cue.source\n });\n }\n return;\n }\n if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue\", {\n key: cue.key,\n source: cue.source\n });\n }\n return;\n }\n this.pendingScte35Cues.delete(pendingKey);\n this.markScte35CueHandled(cue);\n this.callbacks.onPlaybackCue(marker, cue.key);\n }\n activatePendingScte35CuesForFragment(frag) {\n const fragmentSn = typeof frag?.sn === \"number\" ? frag.sn : void 0;\n if (fragmentSn === void 0) {\n return;\n }\n const matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(\n ([, cue]) => cue.fragmentSn === fragmentSn\n );\n matchingCues.forEach(([pendingKey, cue]) => {\n this.pendingScte35Cues.delete(pendingKey);\n const context = {\n source: cue.source,\n readiness: \"playback\"\n };\n context.fragmentSn = fragmentSn;\n const fragmentStartSec = cue.fragmentStartSeconds ?? getFragmentStartSeconds(frag);\n if (fragmentStartSec !== void 0) {\n context.fragmentStartSeconds = fragmentStartSec;\n }\n this.onScte35Cue(cue.marker, context);\n });\n }\n createScte35Cue(marker, context) {\n const cue = {\n marker,\n source: context.source,\n readiness: context.readiness,\n key: this.getScte35CueKey(marker, context)\n };\n if (context.fragmentSn !== void 0) {\n cue.fragmentSn = context.fragmentSn;\n }\n if (context.fragmentStartSeconds !== void 0) {\n cue.fragmentStartSeconds = context.fragmentStartSeconds;\n }\n return cue;\n }\n getScte35CueKey(marker, context) {\n const raw = this.getScte35MarkerRaw(marker);\n const spliceEventId = this.toIdentityString(raw?.splice_event_id);\n if (spliceEventId) {\n return `splice:${spliceEventId}`;\n }\n const segmentationEventId = this.toIdentityString(raw?.segmentation_event_id);\n if (segmentationEventId) {\n return `segmentation:${segmentationEventId}`;\n }\n const daterangeId = this.toIdentityString(raw?.attrs?.ID);\n if (daterangeId) {\n return `daterange:${daterangeId}`;\n }\n const scteValue = this.toIdentityString(raw?.attrs?.[\"SCTE35-OUT\"]) || this.toIdentityString(raw?.attrs?.[\"SCTE35-IN\"]);\n if (scteValue) {\n return `daterange-scte:${scteValue}`;\n }\n if (typeof marker.ptsSeconds === \"number\" && Number.isFinite(marker.ptsSeconds)) {\n return `pts:${Math.round(marker.ptsSeconds * 2) / 2}`;\n }\n if (context.fragmentSn !== void 0) {\n return `fragment:${context.fragmentSn}`;\n }\n return `${context.source}:wallclock:${Math.floor(Date.now() / 1e3)}`;\n }\n getPendingScte35CueKey(cue) {\n return `${cue.marker.type}:${cue.key}:${cue.fragmentSn !== void 0 ? cue.fragmentSn : \"unknown\"}`;\n }\n getScte35MarkerRaw(marker) {\n return typeof marker.raw === \"object\" && marker.raw !== null ? marker.raw : {};\n }\n toIdentityString(value) {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value);\n }\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n return void 0;\n }\n isStrongScte35CueKey(key) {\n return !!(key && (key.startsWith(\"splice:\") || key.startsWith(\"segmentation:\") || key.startsWith(\"daterange:\") || key.startsWith(\"daterange-scte:\")));\n }\n hasRecentlyHandledScte35Cue(cue) {\n if (this.activeScte35BreakKeyValue === cue.key || this.scheduledScte35BreakKeyValue === cue.key) {\n return true;\n }\n const recentKey = `${cue.marker.type}:${cue.key}`;\n return this.recentScte35CueKeys.has(recentKey);\n }\n markScte35CueHandled(cue) {\n this.recentScte35CueKeys.set(`${cue.marker.type}:${cue.key}`, Date.now());\n this.trimRecentScte35CueMaps();\n }\n trimRecentScte35CueMaps() {\n while (this.recentScte35CueKeys.size > this.recentScte35CueLimit) {\n const firstKey = this.recentScte35CueKeys.keys().next().value;\n if (!firstKey) {\n break;\n }\n this.recentScte35CueKeys.delete(firstKey);\n }\n while (this.pendingScte35Cues.size > this.recentScte35CueLimit) {\n const firstKey = this.pendingScte35Cues.keys().next().value;\n if (!firstKey) {\n break;\n }\n this.pendingScte35Cues.delete(firstKey);\n }\n }\n shouldAcceptScte35EndCue(cue) {\n if (!this.callbacks.isInAdBreak()) {\n return false;\n }\n if (this.isStrongScte35CueKey(this.activeScte35BreakKeyValue) && this.isStrongScte35CueKey(cue.key) && this.activeScte35BreakKeyValue !== cue.key) {\n return false;\n }\n return true;\n }\n};\n\n// src/player/AdConfigManager.ts\nvar AdConfigManager = class {\n constructor(config, video) {\n this.vmapBreaks = [];\n this.consumedVmapBreakIds = /* @__PURE__ */ new Set();\n this.streamCorrelator = generateCorrelator();\n this.consentSignals = {};\n this.podCounter = 0;\n this.podAssignedByPrefetch = false;\n this.adRequestPositionInBreak = 0;\n this.lastHeartbeatTime = 0;\n this.config = config;\n this.video = video;\n }\n get debug() {\n return !!this.config.debugAdTiming;\n }\n isVmapEnabled() {\n return !!(this.config.isVmap && this.config.vmapUrl?.trim());\n }\n async fetchAdConfiguration() {\n if (this.isVmapEnabled()) {\n await this.fetchAndParseVmap(this.config.vmapUrl);\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] VMAP mode enabled\");\n }\n return;\n }\n const vastMode = this.config.vastMode || \"default\";\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.debug) {\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.debug) {\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 = normalizeVastTagUrl(this.config.vastTagUrl);\n if (this.debug) {\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.debug) {\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.debug) {\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 let decodedPayload = imaPayload;\n try {\n decodedPayload = decodeURIComponent(imaPayload);\n } catch {\n console.warn(\"[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:\", imaPayload);\n }\n console.log(\"[StormcloudVideoPlayer] Raw VAST tag URL (from API):\", decodedPayload);\n this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);\n if (this.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Normalized VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.debug) {\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.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n async fetchAndParseVmap(vmapUrl) {\n if (!vmapUrl.trim()) {\n return;\n }\n try {\n const response = await fetch(vmapUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VMAP (${response.status})`);\n }\n const vmapXml = await response.text();\n this.vmapBreaks = this.parseVmapToBreaks(vmapXml);\n this.consumedVmapBreakIds.clear();\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Loaded ${this.vmapBreaks.length} VMAP ad break(s) from:`,\n vmapUrl\n );\n }\n } catch (error) {\n this.vmapBreaks = [];\n this.consumedVmapBreakIds.clear();\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Failed to load VMAP:\", error);\n }\n }\n }\n parseVmapToBreaks(vmapXml) {\n if (typeof DOMParser === \"undefined\") {\n return [];\n }\n const doc = new DOMParser().parseFromString(vmapXml, \"application/xml\");\n if (doc.querySelector(\"parsererror\")) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n }\n return [];\n }\n const VMAP_NS = \"http://www.iab.net/videosuite/vmap\";\n let adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, \"AdBreak\"));\n if (adBreakNodes.length === 0) {\n adBreakNodes = Array.from(\n doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\n );\n }\n if (adBreakNodes.length === 0) {\n adBreakNodes = Array.from(doc.getElementsByTagName(\"*\")).filter(\n (el) => el.localName === \"AdBreak\"\n );\n }\n const parsed = [];\n adBreakNodes.forEach((node, index) => {\n const timeOffsetRaw = (node.getAttribute(\"timeOffset\") || \"\").trim();\n const startTimeMs = this.parseVmapTimeOffsetToMs(timeOffsetRaw);\n if (startTimeMs == null) {\n return;\n }\n let adTagNode = node.getElementsByTagNameNS(VMAP_NS, \"AdTagURI\")[0];\n if (!adTagNode) {\n adTagNode = node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\") ?? void 0;\n }\n const adTagUrl = (adTagNode?.textContent || \"\").trim();\n if (!adTagUrl) {\n return;\n }\n const breakId = node.getAttribute(\"breakId\") || `vmap-break-${index}-${timeOffsetRaw || \"unknown\"}`;\n parsed.push({\n id: breakId,\n startTimeMs,\n vastTagUrl: adTagUrl\n });\n });\n parsed.sort((a, b) => {\n const aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;\n const bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;\n return aStart - bStart;\n });\n return parsed;\n }\n parseVmapTimeOffsetToMs(timeOffset) {\n if (!timeOffset) {\n return void 0;\n }\n const normalized = timeOffset.trim().toLowerCase();\n if (normalized === \"start\") {\n return 0;\n }\n if (normalized === \"end\") {\n return -1;\n }\n const hms = timeOffset.match(\n /^(\\d{1,2}):(\\d{2}):(\\d{2})(?:\\.(\\d{1,3}))?$/\n );\n if (hms) {\n const [, hh, mm, ss, ms = \"0\"] = hms;\n const hours = Number(hh);\n const minutes = Number(mm);\n const seconds = Number(ss);\n const millis = Number(ms.padEnd(3, \"0\").slice(0, 3));\n return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;\n }\n const percent = timeOffset.match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (percent) {\n const ratio = Number(percent[1]) / 100;\n const durationSec = this.video.duration;\n if (Number.isFinite(durationSec) && durationSec > 0) {\n return Math.floor(durationSec * 1e3 * ratio);\n }\n return void 0;\n }\n return void 0;\n }\n getAdBreakKey(adBreak) {\n if (adBreak.id) {\n return adBreak.id;\n }\n return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n }\n resolveBreakStartMs(adBreak) {\n if (adBreak.startTimeMs >= 0) {\n return adBreak.startTimeMs;\n }\n if (adBreak.startTimeMs === -1) {\n const durationSec = this.video.duration;\n if (Number.isFinite(durationSec) && durationSec > 0) {\n return Math.floor(durationSec * 1e3);\n }\n }\n return void 0;\n }\n findCurrentOrNextBreak(nowMs) {\n const schedule = this.vmapBreaks;\n let candidate;\n const tol = this.config.driftToleranceMs ?? 1e3;\n for (const b of schedule) {\n if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n continue;\n }\n const breakStartMs = this.resolveBreakStartMs(b);\n if (breakStartMs == null) {\n continue;\n }\n if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))) {\n candidate = b;\n }\n }\n return candidate;\n }\n findBreakForTime(nowMs) {\n const schedule = this.vmapBreaks;\n for (const b of schedule) {\n if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n continue;\n }\n const breakStartMs = this.resolveBreakStartMs(b);\n if (breakStartMs == null) {\n continue;\n }\n if (b.durationMs) {\n const end = breakStartMs + b.durationMs;\n if (nowMs >= breakStartMs && nowMs < end) {\n return b;\n }\n continue;\n }\n if (nowMs >= breakStartMs) {\n return b;\n }\n }\n return void 0;\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 beginNewAdPod() {\n this.podCounter++;\n this.adRequestPositionInBreak = 0;\n }\n generateVastUrlsWithCorrelators(baseUrl, count, adPlayer, palNonce, inAdBreak) {\n const urls = [];\n for (let i = 0; i < count; i++) {\n this.adRequestPositionInBreak++;\n const adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;\n const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n const urlWithMacros = applyVastMacros(baseUrl, {\n correlator: generateCorrelator(),\n streamCorrelator: this.streamCorrelator,\n pod: this.podCounter > 0 ? this.podCounter : void 0,\n adPosition: this.adRequestPositionInBreak,\n isCtv: envSignals.isCtv,\n contentUrl: envSignals.contentUrl,\n pageUrl: !envSignals.isCtv && typeof window !== \"undefined\" ? window.location.href : void 0,\n adWillPlayMuted,\n adWillAutoPlay: !!this.config.autoplay,\n appId: envSignals.appId,\n appName: envSignals.appName,\n sessionId: envSignals.sessionId,\n deviceId: envSignals.deviceId,\n deviceIdType: envSignals.deviceIdType,\n limitAdTracking: envSignals.limitAdTracking,\n deviceTypeHint: envSignals.deviceTypeHint,\n adTest: this.config.adTest,\n consent: this.consentSignals\n });\n const finalUrl = palNonce.injectNonce(urlWithMacros);\n console.log(\n `[StormcloudVideoPlayer] Resolved ad request URL (pod=${this.podCounter}, pos=${this.adRequestPositionInBreak}):`,\n finalUrl\n );\n urls.push(finalUrl);\n }\n return urls;\n }\n // --- Tracking ---\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.debug) {\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.debug) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n destroyTracking() {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = void 0;\n }\n }\n};\n\n// src/player/AdTimingService.ts\nvar AdTimingService = class {\n constructor(config, video, callbacks) {\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.ptsDriftEmaMs = 0;\n this.adBreakPlayedDurationMs = 0;\n this.adBreakEpoch = 0;\n this.adRequestTokenCounter = 0;\n this.activeAdRequestToken = null;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.totalAdRequestsInBreak = 0;\n this.maxTotalAdRequestsPerBreak = 10;\n this.lastAdRequestTime = 0;\n this.consecutiveFailures = 0;\n this.maxConsecutiveFailures = 5;\n this.minAdRequestIntervalMs = 3e3;\n this.backoffBaseMs = 1e3;\n this.maxBackoffMs = 15e3;\n this.defaultMinRemainingMsToStartAd = 4e3;\n this.failedVastUrls = /* @__PURE__ */ new Set();\n this.temporaryFailureUrls = /* @__PURE__ */ new Map();\n this.temporaryFailureCooldownMs = 3e4;\n this.globalConsecutiveNoFills = 0;\n this.globalNoFillThreshold = 3;\n this.globalNoFillCooldownUntil = 0;\n this.globalNoFillBackoffBaseMs = 5e3;\n this.globalNoFillBackoffMaxMs = 6e4;\n this.globalLastGamRequestTime = 0;\n this.globalMinGamIntervalMs = 3e3;\n this.config = config;\n this.video = video;\n this.callbacks = callbacks;\n }\n get debug() {\n return !!this.config.debugAdTiming;\n }\n // --- Ad stop timer ---\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 this.adStopTimerId = void 0;\n this.callbacks.onAdStopTimerFired();\n }\n // --- Ad start timer ---\n scheduleAdStartIn(delayMs, marker = { type: \"start\" }, cueKey) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.callbacks.onAdStartTimerFired(marker, cueKey);\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.callbacks.onAdStartTimerFired(marker, cueKey);\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\n // --- PTS drift ---\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 resolveScteBreakStartWallClockMs(marker) {\n const nowWallClockMs = Date.now();\n if (typeof marker.ptsSeconds !== \"number\") {\n return nowWallClockMs;\n }\n const nowMs = this.video.currentTime * 1e3;\n const estimatedCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = marker.ptsSeconds * 1e3 - estimatedCurrentPtsMs;\n if (!Number.isFinite(deltaMs)) {\n return nowWallClockMs;\n }\n return nowWallClockMs + Math.floor(deltaMs);\n }\n // --- Duration boundary ---\n setAdBreakDurationBoundary(durationMs) {\n this.expectedAdBreakDurationMs = durationMs;\n if (durationMs != null && this.currentAdBreakStartWallClockMs != null) {\n this.scteAdBreakEndWallClockMs = this.currentAdBreakStartWallClockMs + durationMs;\n } else {\n this.scteAdBreakEndWallClockMs = void 0;\n }\n }\n scheduleAdStopAtBreakBoundary() {\n if (this.expectedAdBreakDurationMs == null) {\n return;\n }\n this.scheduleAdStopCountdown(this.getWallClockRemainingAdMs());\n }\n // --- Duration budget ---\n getWallClockRemainingAdMs() {\n const endWallClockMs = this.getAdBreakEndWallClockMs();\n if (endWallClockMs != null) {\n return Math.max(0, endWallClockMs - Date.now());\n }\n return 0;\n }\n getAdBreakEndWallClockMs() {\n if (this.scteAdBreakEndWallClockMs != null) {\n return this.scteAdBreakEndWallClockMs;\n }\n if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null) {\n return void 0;\n }\n return this.currentAdBreakStartWallClockMs + this.expectedAdBreakDurationMs;\n }\n getDurationBudgetRemainingMs() {\n if (this.expectedAdBreakDurationMs == null) {\n return 0;\n }\n return Math.max(0, this.expectedAdBreakDurationMs - this.adBreakPlayedDurationMs);\n }\n getLoadedAdDurationMs(adController) {\n const durationSec = adController.getLoadedAdDuration?.();\n if (durationSec == null || durationSec <= 0) {\n return 0;\n }\n return Math.round(durationSec * 1e3);\n }\n adFitsRemainingBudget(durationMs) {\n if (durationMs <= 0) {\n return true;\n }\n return durationMs <= this.getDurationBudgetRemainingMs();\n }\n logAdDurationDecision(accepted, durationMs, adController) {\n if (!this.debug) {\n return;\n }\n const remainingBudget = this.getDurationBudgetRemainingMs();\n const adId = adController.getLoadedAdId?.() ?? \"unknown\";\n if (accepted) {\n console.log(\n `[AD-DURATION] Accepted ad id=${adId}, duration=${durationMs}ms, budget remaining after play=${Math.max(0, remainingBudget - durationMs)}ms`\n );\n } else {\n console.log(\n `[AD-DURATION] Rejected ad id=${adId}, duration=${durationMs}ms exceeds remaining budget=${remainingBudget}ms \\u2014 requesting another ad`\n );\n }\n }\n recordPlayedAdDuration(adController) {\n const durationMs = this.getLoadedAdDurationMs(adController);\n if (durationMs <= 0) {\n return;\n }\n this.adBreakPlayedDurationMs += durationMs;\n if (this.debug) {\n console.log(\n `[AD-DURATION] Played ${durationMs}ms \\u2014 total played=${this.adBreakPlayedDurationMs}ms / ${this.expectedAdBreakDurationMs ?? \"?\"}ms`\n );\n }\n }\n ensureLoadedAdFitsBudget(adController) {\n const durationMs = this.getLoadedAdDurationMs(adController);\n const fits = this.adFitsRemainingBudget(durationMs);\n this.logAdDurationDecision(fits, durationMs, adController);\n return fits;\n }\n rejectLoadedAdForDuration(adController) {\n try {\n adController.destroy();\n } catch {\n }\n }\n markAdStarted() {\n this.currentAdIndex++;\n this.totalAdsInBreak = this.currentAdIndex;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n }\n getRemainingAdMs() {\n const wallClockRemaining = this.getWallClockRemainingAdMs();\n const budgetRemaining = this.getDurationBudgetRemainingMs();\n if (this.expectedAdBreakDurationMs == null) {\n return wallClockRemaining;\n }\n return Math.min(wallClockRemaining, budgetRemaining);\n }\n getMinRemainingMsToStartAd() {\n const configured = this.config.minRemainingMsToStartAd;\n if (typeof configured === \"number\" && configured >= 0) {\n return configured;\n }\n return this.defaultMinRemainingMsToStartAd;\n }\n hasTimeToStartAnotherAd() {\n const minRemaining = this.getMinRemainingMsToStartAd();\n return this.getWallClockRemainingAdMs() > minRemaining && this.getDurationBudgetRemainingMs() > minRemaining;\n }\n // --- Circuit breaker ---\n isTemporaryAdError(error) {\n const message = error?.message?.toLowerCase() || \"\";\n if (message.includes(\"no ads available\") || message.includes(\"no fill\") || message.includes(\"nofill\")) {\n return true;\n }\n if (message.includes(\"timeout\")) {\n return true;\n }\n if (message.includes(\"rate limit\") || message.includes(\"too many requests\")) {\n return true;\n }\n if (message.includes(\"ad playback error\")) {\n return true;\n }\n return false;\n }\n isUrlInCooldown(vastTagUrl) {\n const failureTime = this.temporaryFailureUrls.get(vastTagUrl);\n if (failureTime == null) {\n return false;\n }\n const elapsed = Date.now() - failureTime;\n if (elapsed >= this.temporaryFailureCooldownMs) {\n this.temporaryFailureUrls.delete(vastTagUrl);\n return false;\n }\n return true;\n }\n cleanupTemporaryFailures() {\n const now = Date.now();\n for (const [url, timestamp] of this.temporaryFailureUrls) {\n if (now - timestamp >= this.temporaryFailureCooldownMs) {\n this.temporaryFailureUrls.delete(url);\n }\n }\n }\n isGamInCooldown() {\n return Date.now() < this.globalNoFillCooldownUntil;\n }\n recordGamNoFill() {\n this.globalConsecutiveNoFills++;\n if (this.globalConsecutiveNoFills >= this.globalNoFillThreshold) {\n const exponent = this.globalConsecutiveNoFills - this.globalNoFillThreshold;\n const backoff = Math.min(\n this.globalNoFillBackoffBaseMs * Math.pow(2, exponent),\n this.globalNoFillBackoffMaxMs\n );\n this.globalNoFillCooldownUntil = Date.now() + backoff;\n if (this.debug) {\n console.log(\n `[CIRCUIT-BREAKER] GAM cooldown activated: ${backoff}ms (${this.globalConsecutiveNoFills} consecutive no-fills)`\n );\n }\n }\n }\n resetGamNoFillCounter() {\n if (this.globalConsecutiveNoFills > 0 && this.debug) {\n console.log(\n `[CIRCUIT-BREAKER] Resetting no-fill counter (was ${this.globalConsecutiveNoFills})`\n );\n }\n this.globalConsecutiveNoFills = 0;\n this.globalNoFillCooldownUntil = 0;\n }\n async enforceGlobalRateLimit() {\n const now = Date.now();\n const elapsed = now - this.globalLastGamRequestTime;\n if (elapsed < this.globalMinGamIntervalMs) {\n const waitMs = this.globalMinGamIntervalMs - elapsed;\n if (this.debug) {\n console.log(`[RATE-LIMIT] Waiting ${waitMs}ms before next GAM request`);\n }\n await new Promise((resolve) => setTimeout(resolve, waitMs));\n }\n this.globalLastGamRequestTime = Date.now();\n }\n // --- Watchdog ---\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.callbacks.onWatchdogTimeout();\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 // --- Failsafe ---\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 });\n this.callbacks.onFailsafeTimeout();\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 logAdState(event, extra = {}, adPlayer, inAdBreak, showAds) {\n if (!this.debug) {\n return;\n }\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n showAds: showAds ?? false,\n adPlaying: adPlayer?.isAdPlaying() ?? false,\n inAdBreak: inAdBreak ?? false,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n // --- Reset for ad break end ---\n resetForBreakEnd() {\n this.clearAdStopTimer();\n this.clearAdStartTimer();\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.scteAdBreakEndWallClockMs = void 0;\n this.adBreakPlayedDurationMs = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.consecutiveFailures = 0;\n this.globalConsecutiveNoFills = 0;\n this.adBreakEpoch++;\n }\n destroy() {\n this.clearAdStopTimer();\n this.clearAdStartTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n }\n};\n\n// src/player/AdPreloadPool.ts\nvar AdPreloadPool = class {\n constructor(deps) {\n this.pool = [];\n this.maxPoolSize = 2;\n this.poolActive = false;\n this.loopRunning = false;\n this.deps = deps;\n }\n get active() {\n return this.poolActive;\n }\n set active(value) {\n this.poolActive = value;\n }\n get isLoopRunning() {\n return this.loopRunning;\n }\n startPreloadPool(baseVastUrl, initialUrls, startLoopImmediately = true) {\n if (this.poolActive) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n }\n return;\n }\n this.poolActive = true;\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Starting preload pool EARLY (target size: ${this.maxPoolSize})`);\n console.log(`[PRELOAD-POOL] Ad break hasn't started yet, but preloading ads in advance`);\n }\n for (const url of initialUrls) {\n if (this.pool.length < this.maxPoolSize) {\n this.preloadAdIntoPool(url);\n }\n }\n if (startLoopImmediately) {\n this.preloadPoolLoop(baseVastUrl);\n } else if (this.deps.debug) {\n console.log(\n \"[PRELOAD-POOL] Pre-break mode: preloaded once, waiting for SCTE start to continue fetching\"\n );\n }\n }\n async preloadAdIntoPool(vastUrl) {\n const timing = this.deps.timing;\n if (timing.isGamInCooldown()) {\n if (this.deps.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n }\n return;\n }\n if (this.pool.some((entry) => entry.vastUrl === vastUrl) || timing.failedVastUrls.has(vastUrl) || timing.isUrlInCooldown(vastUrl)) {\n return;\n }\n if (this.pool.length >= this.maxPoolSize) {\n return;\n }\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Preloading ad into pool: ${vastUrl}`);\n }\n const epoch = timing.adBreakEpoch;\n const loadPromise = (async () => {\n let hasAdError = false;\n let adErrorPayload = null;\n let errorListenerCleanup = null;\n try {\n const continueLiveStreamDuringAds = this.deps.shouldContinueLiveStreamDuringAds();\n const preloadAd = this.deps.createAdPlayer(continueLiveStreamDuringAds);\n preloadAd.initialize();\n const errorListener = (payload) => {\n hasAdError = true;\n adErrorPayload = payload;\n };\n preloadAd.on(\"ad_error\", errorListener);\n errorListenerCleanup = () => preloadAd.off(\"ad_error\", errorListener);\n await timing.enforceGlobalRateLimit();\n await preloadAd.requestAds(vastUrl);\n preloadAd.pause();\n await new Promise((resolve) => setTimeout(resolve, 1500));\n preloadAd.pause();\n if (hasAdError) {\n const isNoFill = adErrorPayload?.isNoFill || adErrorPayload?.code === 303 || adErrorPayload?.vastErrorCode === 303;\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n preloadAd.destroy();\n timing.recordGamNoFill();\n if (isNoFill) {\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preload returned no-fill: ${vastUrl}`);\n }\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n } else {\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n }\n if (adErrorPayload && !timing.isTemporaryAdError(adErrorPayload)) {\n timing.failedVastUrls.add(vastUrl);\n } else {\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n return;\n }\n if (!this.poolActive || epoch !== timing.adBreakEpoch) {\n if (this.deps.debug) {\n console.log(\n \"[PRELOAD-POOL] Discarding preloaded ad - break ended during fetch\"\n );\n }\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n try {\n preloadAd.destroy();\n } catch {\n }\n return;\n }\n const poolEntry = {\n vastUrl,\n adController: preloadAd,\n loadedAt: Date.now(),\n isReady: true,\n loadPromise: Promise.resolve()\n };\n const loadedDuration = preloadAd.getLoadedAdDuration?.();\n if (loadedDuration != null && loadedDuration > 0) {\n poolEntry.durationSeconds = loadedDuration;\n }\n const lateErrorListener = (payload) => {\n const index = this.pool.findIndex((entry) => entry.vastUrl === vastUrl);\n if (index >= 0) {\n this.pool.splice(index, 1);\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Late error detected, removed from pool: ${vastUrl}`, payload);\n }\n try {\n preloadAd.destroy();\n } catch {\n }\n }\n };\n preloadAd.on(\"ad_error\", lateErrorListener);\n this.pool.push(poolEntry);\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preloaded (no errors detected within timeout) (pool size: ${this.pool.length}/${this.maxPoolSize}, duration=${poolEntry.durationSeconds ?? \"?\"}s)`);\n }\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n } catch (error) {\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n timing.recordGamNoFill();\n if (this.deps.debug) {\n console.warn(`[PRELOAD-POOL] Failed to preload ad: ${vastUrl}`, error);\n }\n if (error instanceof Error && !timing.isTemporaryAdError(error)) {\n timing.failedVastUrls.add(vastUrl);\n } else if (error instanceof Error && timing.isTemporaryAdError(error)) {\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n })();\n loadPromise.catch(() => {\n });\n }\n async preloadPoolLoop(baseVastUrl) {\n if (this.loopRunning) {\n return;\n }\n this.loopRunning = true;\n const epoch = this.deps.timing.adBreakEpoch;\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Starting continuous preload loop\");\n }\n while (this.poolActive && epoch === this.deps.timing.adBreakEpoch) {\n if (this.deps.timing.isGamInCooldown()) {\n if (this.deps.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n }\n break;\n }\n if (!this.deps.isInAdBreak() && this.pool.length >= this.maxPoolSize) {\n await new Promise((resolve) => setTimeout(resolve, 2e3));\n continue;\n }\n if (!this.deps.isInAdBreak() && this.deps.getPendingAdBreak() === null) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n }\n break;\n }\n while (this.pool.length < this.maxPoolSize) {\n if (!this.poolActive || epoch !== this.deps.timing.adBreakEpoch || this.deps.timing.isGamInCooldown()) {\n break;\n }\n if (this.deps.isInAdBreak() && !this.deps.timing.hasTimeToStartAnotherAd()) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Not enough ad break time left, stopping preload\");\n }\n break;\n }\n const newUrls = this.deps.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const newUrl = newUrls[0];\n if (newUrl && !this.deps.timing.failedVastUrls.has(newUrl) && !this.deps.timing.isUrlInCooldown(newUrl)) {\n await this.preloadAdIntoPool(newUrl);\n }\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n }\n await new Promise((resolve) => setTimeout(resolve, 2e3));\n }\n this.loopRunning = false;\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Preload loop ended\");\n }\n }\n getPreloadedAd() {\n if (this.pool.length === 0) {\n return null;\n }\n const entry = this.pool.shift();\n if (!entry || !entry.isReady) {\n return null;\n }\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Using preloaded ad from pool (${this.pool.length} remaining)`);\n }\n return {\n vastUrl: entry.vastUrl,\n adController: entry.adController\n };\n }\n stop() {\n this.poolActive = false;\n this.loopRunning = false;\n for (const entry of this.pool) {\n try {\n entry.adController.destroy();\n } catch (error) {\n if (this.deps.debug) {\n console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n }\n }\n }\n this.pool = [];\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Preload pool stopped and cleaned up\");\n }\n }\n};\n\n// src/player/PlaceholderLayer.ts\nvar PlaceholderLayer = class {\n constructor(video, debug) {\n this.video = video;\n this.debug = debug;\n }\n ensureContainer() {\n if (this.container) {\n return;\n }\n const el = document.createElement(\"div\");\n el.style.position = \"absolute\";\n el.style.left = \"0\";\n el.style.top = \"0\";\n el.style.right = \"0\";\n el.style.bottom = \"0\";\n el.style.display = \"none\";\n el.style.alignItems = \"center\";\n el.style.justifyContent = \"center\";\n el.style.pointerEvents = \"none\";\n el.style.zIndex = \"5\";\n el.style.backgroundColor = \"#000\";\n el.style.transition = \"opacity 0.3s ease-in-out\";\n el.style.opacity = \"0\";\n if (!this.video.parentElement) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n this.video.parentElement.appendChild(el);\n this.container = el;\n }\n show() {\n this.ensureContainer();\n if (!this.container) {\n return;\n }\n if (!this.video.muted) {\n this.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n const wasHidden = this.container.style.display === \"none\" || this.container.style.opacity === \"0\";\n if (wasHidden) {\n this.container.style.transition = \"none\";\n } else {\n this.container.style.transition = \"opacity 0.3s ease-in-out\";\n }\n this.container.style.backgroundColor = \"#000\";\n this.container.style.display = \"flex\";\n this.container.offsetHeight;\n this.container.style.opacity = \"1\";\n this.container.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.container) {\n this.container.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and ad layer)\");\n }\n }\n hide() {\n if (!this.container) {\n return;\n }\n this.container.style.opacity = \"0\";\n setTimeout(() => {\n if (this.container) {\n this.container.style.display = \"none\";\n this.container.style.pointerEvents = \"none\";\n this.container.style.backgroundColor = \"#000\";\n }\n }, 300);\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n destroy() {\n if (this.container) {\n if (this.container.parentElement) {\n this.container.parentElement.removeChild(this.container);\n }\n this.container = void 0;\n }\n }\n};\n\n// src/player/HlsEngine.ts\nvar import_hls2 = __toESM(require(\"hls.js\"), 1);\nvar HlsEngine = class {\n constructor(config, video, cueManager, timing, callbacks) {\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.config = config;\n this.video = video;\n this.cueManager = cueManager;\n this.timing = timing;\n this.callbacks = callbacks;\n }\n get debug() {\n return !!this.config.debugAdTiming;\n }\n shouldUseNativeHls(getStreamType) {\n const streamType = 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 async setupNativeHls() {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.isLiveStream ?? (this.config.lowLatencyMode ?? false);\n if (this.debug) {\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 if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n }\n setupHls() {\n this.hls = new import_hls2.default({\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(import_hls2.default.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, _data) => {\n this.isLiveStream = this.config.isLiveStream ?? (this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false);\n await this.callbacks.onManifestParsed(this.isLiveStream);\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.debug) {\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(import_hls2.default.Events.LEVEL_LOADED, (_evt, data) => {\n if (this.callbacks.isInAdBreak() || this.callbacks.hasPendingAdBreak()) {\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\") ? parseAttributeList(value) : {};\n const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") || \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n if (hasScteOut) {\n const durationSeconds = parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value, earlyDetection: true }\n };\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n }\n this.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"early\", frag)\n });\n return;\n }\n }\n }\n }\n });\n this.hls.on(import_hls2.default.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.debug) {\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.debug) {\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.debug) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n this.hls.on(import_hls2.default.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(import_hls2.default.Events.FRAG_LOADED, (_evt, data) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : void 0,\n getFragmentStartSeconds(data?.frag)\n );\n });\n this.hls.on(import_hls2.default.Events.FRAG_DECRYPTED, (_evt, data) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : void 0,\n getFragmentStartSeconds(data?.frag)\n );\n });\n this.hls.on(import_hls2.default.Events.FRAG_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) {\n this.callbacks.activatePendingCuesForFragment(frag);\n 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 if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = 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.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.callbacks.onScte35Cue(\n { type: \"end\", raw: { tag, value } },\n {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n }\n );\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = 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 = 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.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n }\n if (hasScteIn) {\n this.callbacks.onScte35Cue(\n { type: \"end\", raw: { tag, value, attrs } },\n {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n }\n );\n }\n }\n }\n this.callbacks.activatePendingCuesForFragment(frag);\n });\n this.hls.on(import_hls2.default.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case import_hls2.default.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case import_hls2.default.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.callbacks.onFatalDestroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.timing.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = parseScte35FromId3(tag);\n if (marker) {\n this.callbacks.onScte35Cue(marker, {\n source: \"id3\",\n readiness: \"playback\"\n });\n }\n }\n processFragmentScte35Payload(payloadData, fragmentSn, fragmentStartSeconds) {\n const payload = normalizeFragmentPayload(payloadData);\n if (!payload) {\n return;\n }\n const markers = parseScte35FromTsPackets(\n payload,\n this.cueManager.tsScte35Pids,\n this.cueManager.pmtPids,\n this.cueManager.processedTsScte35Sections\n );\n markers.forEach((marker) => {\n const context = {\n source: \"ts\",\n readiness: \"early\"\n };\n if (fragmentSn !== void 0) {\n context.fragmentSn = fragmentSn;\n }\n if (fragmentStartSeconds !== void 0) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n this.callbacks.onScte35Cue(marker, context);\n });\n }\n destroy() {\n this.hls?.destroy();\n this.hls = void 0;\n }\n};\n\n// src/player/PlayerControls.ts\nfunction getAdAudioVolume(adPlayer) {\n return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();\n}\nfunction toggleMute(video, adPlayer, debug) {\n if (adPlayer.isAdPlaying()) {\n const newMutedState = !adPlayer.getOriginalMutedState();\n const restoreVolume = adPlayer.getOriginalVolume() || 1;\n adPlayer.updateOriginalMutedState(newMutedState, video.volume);\n adPlayer.setAdVolume(newMutedState ? 0 : restoreVolume);\n if (debug) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n video.muted = !video.muted;\n adPlayer.updateOriginalMutedState(video.muted, video.volume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", video.muted);\n }\n }\n}\nfunction toggleFullscreen(video, debug) {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (debug) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document.exitFullscreen().then(() => {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (debug) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n}\nfunction isMuted(video, adPlayer) {\n if (adPlayer.isAdPlaying()) {\n return adPlayer.getOriginalMutedState();\n }\n return video.muted;\n}\nfunction setMuted(video, adPlayer, muted, debug) {\n const adPlaying = adPlayer.isAdPlaying();\n if (adPlaying && muted === video.muted) {\n if (debug) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n video.muted = muted;\n if (adPlaying) {\n adPlayer.updateOriginalMutedState(muted, video.volume);\n adPlayer.setAdVolume(muted ? 0 : 1);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted\n });\n }\n return;\n }\n adPlayer.updateOriginalMutedState(muted, video.volume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n}\nfunction setVolume(video, adPlayer, volume, debug) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = adPlayer.isAdPlaying();\n if (adPlaying) {\n adPlayer.setAdVolume(clampedVolume);\n adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume\n });\n }\n } else {\n video.volume = clampedVolume;\n video.muted = clampedVolume === 0;\n adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n}\nfunction getVolume(video, adPlayer) {\n const adPlaying = adPlayer.isAdPlaying();\n if (adPlaying) {\n return adPlayer.getAdVolume();\n }\n return video.volume;\n}\nfunction isFullscreen() {\n return !!document.fullscreenElement;\n}\nfunction resizePlayer(video, adPlayer, debug) {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n if (adPlayer && adPlayer.isAdPlaying()) {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 480;\n if (debug) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n adPlayer.resize(width, height);\n }\n}\n\n// src/player/AdBreakOrchestrator.ts\nvar AdBreakOrchestrator = class {\n constructor(host, timing, preloadPool, adConfig, cueManager, placeholder) {\n this.inAdBreak = false;\n this.showAds = false;\n this.isShowingPlaceholder = false;\n this.adDetectSentForCurrentBreak = false;\n this.continuousFetchingActive = false;\n this.continuousFetchLoopRunning = false;\n this.adRequestQueue = [];\n this.adPodQueue = [];\n this.maxPlaceholderDurationMs = 5e3;\n this.pendingAdBreak = null;\n this.host = host;\n this.timing = timing;\n this.preloadPool = preloadPool;\n this.adConfig = adConfig;\n this.cueManager = cueManager;\n this.placeholder = placeholder;\n }\n get debug() {\n return !!this.host.config.debugAdTiming;\n }\n // ───────────────────────────────────────────────────────────────\n // IMA event listeners\n // ───────────────────────────────────────────────────────────────\n attachImaEventListeners() {\n const adPlayer = this.host.getAdPlayer();\n adPlayer.on(\"all_ads_completed\", () => {\n sendAdImpressionTracking(\n this.host.config.licenseKey,\n { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n const remaining = this.timing.getRemainingAdMs();\n this.timing.consecutiveFailures = 0;\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.inAdBreak) {\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n adPlayer.on(\"ad_error\", (errorPayload) => {\n let errorMessage = \"Ad playback failed\";\n if (errorPayload) {\n const errorCode = errorPayload.code || errorPayload.errorCode || \"unknown\";\n const vastErrorCode = errorPayload.vastErrorCode;\n const message = errorPayload.message || errorPayload.errorMessage || \"Unknown error\";\n const cause = errorPayload.cause || errorPayload.innerError || errorPayload.error;\n errorMessage = `Ad error: AdError ${errorCode}: ${message}`;\n if (vastErrorCode && vastErrorCode !== \"N/A\" && vastErrorCode !== errorCode) {\n errorMessage += ` (VAST Error Code: ${vastErrorCode})`;\n }\n if (cause) {\n const causeMessage = typeof cause === \"string\" ? cause : cause.message || String(cause);\n errorMessage += `. Caused by: ${causeMessage}`;\n }\n }\n console.error(\"[AD-ERROR]\", errorMessage, errorPayload || \"\");\n this.handleAdFailure();\n });\n adPlayer.on(\"content_pause\", () => {\n this.timing.clearAdFailsafeTimer();\n this.timing.clearAdRequestWatchdog();\n this.timing.activeAdRequestToken = null;\n this.showAds = true;\n this.timing.resetGamNoFillCounter();\n if (this.inAdBreak && this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n this.host.getAdPlayer().setAdVolume(getAdAudioVolume(this.host.getAdPlayer()));\n if (this.isShowingPlaceholder) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.host.getAdPlayer().hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n adPlayer.on(\"content_resume\", () => {\n sendAdImpressionTracking(\n this.host.config.licenseKey,\n { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n if (!this.host.video.muted) {\n this.host.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n }\n }\n this.timing.clearAdFailsafeTimer();\n this.timing.clearAdRequestWatchdog();\n this.timing.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n return;\n }\n this.timing.consecutiveFailures = 0;\n this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n const remaining = this.timing.getRemainingAdMs();\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n });\n }\n recreateAdController() {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Recreating AdController for new ad\");\n }\n const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n const adPlayer = this.host.getAdPlayer();\n if (shouldShowPlaceholder && adPlayer) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old AdController\");\n }\n this.placeholder.show();\n adPlayer.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n const preservedMutedState = adPlayer.getOriginalMutedState();\n const preservedVolumeState = adPlayer.getOriginalVolume();\n if (adPlayer) {\n try {\n adPlayer.destroy();\n this.host.video.muted = true;\n } catch (error) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Error destroying old AdController:\", error);\n }\n }\n }\n const continueLiveStreamDuringAds = this.host.shouldContinueLiveStreamDuringAds();\n const newAdPlayer = this.host.createAdPlayer(continueLiveStreamDuringAds);\n this.host.setAdPlayer(newAdPlayer);\n newAdPlayer.initialize();\n newAdPlayer.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n this.attachImaEventListeners();\n if (shouldShowPlaceholder) {\n this.placeholder.show();\n newAdPlayer.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n }\n clearPendingAdBreak() {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = void 0;\n }\n this.pendingAdBreak = null;\n this.cueManager.pendingScte35CueKey = void 0;\n this.adConfig.podAssignedByPrefetch = false;\n }\n // ───────────────────────────────────────────────────────────────\n // Ad break start\n // ───────────────────────────────────────────────────────────────\n async handleAdStart(_marker) {\n const scheduled = this.adConfig.findCurrentOrNextBreak(\n this.host.video.currentTime * 1e3\n );\n if (scheduled) {\n this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));\n }\n const tags = this.adConfig.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.adConfig.apiVastTagUrl) {\n baseVastUrl = this.adConfig.apiVastTagUrl;\n } else {\n this.clearPendingAdBreak();\n return;\n }\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled?.durationMs;\n if (this.debug) {\n const mode = this.host.config.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n this.timing.failedVastUrls.clear();\n this.timing.temporaryFailureUrls.clear();\n this.timing.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.timing.totalAdRequestsInBreak = 0;\n if (this.adConfig.podAssignedByPrefetch) {\n this.adConfig.podAssignedByPrefetch = false;\n } else {\n this.adConfig.beginNewAdPod();\n }\n const currentMuted = this.host.video.muted;\n const currentVolume = this.host.video.volume;\n this.host.getAdPlayer().updateOriginalMutedState(currentMuted, currentVolume);\n this.inAdBreak = true;\n this.timing.adBreakPlayedDurationMs = 0;\n this.timing.currentAdIndex = 0;\n this.timing.totalAdsInBreak = 0;\n this.adPodQueue = [];\n this.showAds = false;\n if (this.timing.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.timing.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n let firstAdUrl;\n let usePreloadedAd = false;\n let preloadedController;\n const preloaded = this.preloadPool.getPreloadedAd();\n if (preloaded) {\n firstAdUrl = preloaded.vastUrl;\n preloadedController = preloaded.adController;\n usePreloadedAd = true;\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: firstAdUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n }\n } else if (this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0) {\n this.adRequestQueue = [...this.pendingAdBreak.vastUrls];\n firstAdUrl = this.adRequestQueue.shift();\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Pool empty, using prefetched URLs (${this.adRequestQueue.length + 1} available)`);\n }\n this.clearPendingAdBreak();\n } else {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Generating new ad URLs...\");\n }\n const firstAdUrlArray = this.host.generateVastUrls(baseVastUrl, 1);\n firstAdUrl = firstAdUrlArray[0];\n this.adRequestQueue = [];\n }\n if (!firstAdUrl) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Failed to get first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First VAST URL:\", firstAdUrl);\n }\n try {\n if (usePreloadedAd && preloadedController) {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedController)) {\n this.timing.rejectLoadedAdForDuration(preloadedController);\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n const adPlayer = this.host.getAdPlayer();\n const preservedMuted = adPlayer.getOriginalMutedState();\n const preservedVolume = adPlayer.getOriginalVolume();\n adPlayer.destroy();\n this.host.video.muted = true;\n this.host.setAdPlayer(preloadedController);\n preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n this.attachImaEventListeners();\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n }\n preloadedController.resume();\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPool.active) {\n this.preloadPool.active = true;\n }\n if (!this.preloadPool.isLoopRunning) {\n this.preloadPool.preloadPoolLoop(baseVastUrl);\n }\n await preloadedController.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n preloadedController.setAdVolume(adVolume);\n } else {\n const adPlayer = this.host.getAdPlayer();\n await this.timing.enforceGlobalRateLimit();\n this.timing.lastAdRequestTime = Date.now();\n await adPlayer.requestAds(firstAdUrl);\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: firstAdUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad request successful, starting playback\");\n }\n if (!this.timing.ensureLoadedAdFitsBudget(adPlayer)) {\n this.timing.rejectLoadedAdForDuration(adPlayer);\n this.recreateAdController();\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPool.active) {\n this.preloadPool.startPreloadPool(baseVastUrl, []);\n }\n await adPlayer.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n adPlayer.setAdVolume(adVolume);\n }\n } catch (error) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] First ad request failed:\", error);\n }\n if (!usePreloadedAd) {\n const fallbackPreloaded = this.preloadPool.getPreloadedAd();\n if (fallbackPreloaded) {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad failed, using preloaded fallback\");\n }\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(fallbackPreloaded.adController)) {\n this.timing.rejectLoadedAdForDuration(fallbackPreloaded.adController);\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n this.swapToPreloadedAdPlayer(fallbackPreloaded.adController);\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPool.active) {\n this.preloadPool.active = true;\n this.preloadPool.preloadPoolLoop(baseVastUrl);\n }\n const ap = this.host.getAdPlayer();\n await ap.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n ap.setAdVolume(adVolume);\n return;\n } catch (fallbackError) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n }\n if (this.timing.isTemporaryAdError(error)) {\n this.timing.temporaryFailureUrls.set(firstAdUrl, Date.now());\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n }\n } else {\n this.timing.failedVastUrls.add(firstAdUrl);\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n }\n }\n this.timing.consecutiveFailures++;\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n }\n }\n swapToPreloadedAdPlayer(preloadedController) {\n const adPlayer = this.host.getAdPlayer();\n const preservedMuted = adPlayer.getOriginalMutedState();\n const preservedVolume = adPlayer.getOriginalVolume();\n adPlayer.destroy();\n this.host.video.muted = true;\n this.host.setAdPlayer(preloadedController);\n this.attachImaEventListeners();\n preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n preloadedController.resume();\n }\n // ───────────────────────────────────────────────────────────────\n // Continuous fetching\n // ───────────────────────────────────────────────────────────────\n startContinuousFetching(baseVastUrl) {\n if (!this.continuousFetchingActive) {\n return;\n }\n if (this.continuousFetchLoopRunning) {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Fetch loop already running, skipping duplicate start\");\n }\n return;\n }\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Starting continuous ad fetching loop\");\n }\n this.continuousFetchLoopRunning = true;\n this.continuousFetchLoop(baseVastUrl);\n }\n async continuousFetchLoop(baseVastUrl) {\n const epoch = this.timing.adBreakEpoch;\n while (this.continuousFetchingActive && this.inAdBreak && epoch === this.timing.adBreakEpoch) {\n const remaining = Math.min(\n this.timing.getWallClockRemainingAdMs(),\n this.timing.getDurationBudgetRemainingMs()\n );\n if (remaining <= this.timing.getMinRemainingMsToStartAd()) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Not enough ad break time left (wall=${this.timing.getWallClockRemainingAdMs()}ms, budget=${this.timing.getDurationBudgetRemainingMs()}ms), stopping URL generation`);\n }\n break;\n }\n if (this.timing.isGamInCooldown()) {\n if (this.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n }\n break;\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), stopping URL generation`);\n }\n break;\n }\n if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Maximum ad requests reached (${this.timing.maxTotalAdRequestsPerBreak}), stopping`);\n }\n break;\n }\n const maxQueueSize = 5;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] URL queue full (${this.adRequestQueue.length}), waiting...`);\n }\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n continue;\n }\n const newAdUrl = this.host.generateVastUrls(baseVastUrl, 1)[0];\n if (!newAdUrl || this.timing.failedVastUrls.has(newAdUrl) || this.timing.isUrlInCooldown(newAdUrl)) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n continue;\n }\n if (this.debug) {\n const queuedUrlsPreview = [...this.adRequestQueue, newAdUrl];\n console.log(\n `[CONTINUOUS-FETCH] Queued VAST URL (queue size: ${queuedUrlsPreview.length})`,\n { queuedUrls: queuedUrlsPreview }\n );\n }\n this.adRequestQueue.push(newAdUrl);\n const generationDelay = this.timing.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, this.timing.consecutiveFailures), 5e3) : 500;\n await new Promise((resolve) => setTimeout(resolve, generationDelay));\n }\n this.continuousFetchLoopRunning = false;\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] URL generation loop ended (queued: ${this.adRequestQueue.length})`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n }\n stopContinuousFetching() {\n this.continuousFetchingActive = false;\n this.continuousFetchLoopRunning = false;\n this.placeholder.hide();\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Stopping continuous ad fetching\");\n }\n }\n // ───────────────────────────────────────────────────────────────\n // Ad iteration\n // ───────────────────────────────────────────────────────────────\n async tryNextAvailableAdWithRateLimit() {\n if (!this.inAdBreak) {\n return;\n }\n const epoch = this.timing.adBreakEpoch;\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n const backoffMultiplier = Math.pow(2, this.timing.consecutiveFailures);\n const backoffDelay = Math.min(this.timing.backoffBaseMs * backoffMultiplier, this.timing.maxBackoffMs);\n const effectiveMinInterval = this.timing.minAdRequestIntervalMs + (this.timing.consecutiveFailures > 0 ? backoffDelay : 0);\n const timeSinceLastRequest = Date.now() - this.timing.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.timing.consecutiveFailures} failures)`);\n }\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) {\n return;\n }\n return this.tryNextAvailableAd(0);\n }\n async tryNextAvailableAd(retryCount = 0) {\n if (!this.inAdBreak) {\n return;\n }\n const remaining = this.timing.getRemainingAdMs();\n if (!this.timing.hasTimeToStartAnotherAd()) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Not enough time remaining (${remaining}ms) to start another ad, ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.timing.isGamInCooldown()) {\n if (this.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n this.timing.cleanupTemporaryFailures();\n const preloaded = this.preloadPool.getPreloadedAd();\n if (preloaded) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Using preloaded ad from pool`);\n }\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: preloaded.vastUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloaded.adController)) {\n this.timing.rejectLoadedAdForDuration(preloaded.adController);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n this.swapToPreloadedAdPlayer(preloaded.adController);\n const ap = this.host.getAdPlayer();\n await ap.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n ap.setAdVolume(getAdAudioVolume(ap));\n this.timing.consecutiveFailures = 0;\n return;\n } catch (error) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Preloaded ad failed to play:\", error);\n }\n }\n }\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) continue;\n if (this.timing.failedVastUrls.has(nextAdUrl)) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping permanently-failed URL, trying next...\");\n continue;\n }\n if (this.timing.isUrlInCooldown(nextAdUrl)) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping URL in cooldown (recent no-fill), trying next...\");\n continue;\n }\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Requesting next ad via HLS ad player (${this.timing.currentAdIndex + 1}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n try {\n await this.playSingleAd(nextAdUrl);\n this.timing.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = error.message;\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad request failed:\", errorMessage);\n if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.timing.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n const maxRetries = 3;\n if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2e3) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Queue empty, waiting for URLs... (${retryCount + 1}/${maxRetries})`);\n }\n await new Promise((resolve) => setTimeout(resolve, 500));\n await this.tryNextAvailableAd(retryCount + 1);\n return;\n }\n if (!this.isShowingPlaceholder && remaining > 1e3) {\n this.showPlaceholderAndWaitForAds();\n } else {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] No more ads available, ending ad break\");\n this.handleAdPodComplete();\n }\n }\n // ───────────────────────────────────────────────────────────────\n // Single ad playback\n // ───────────────────────────────────────────────────────────────\n async playSingleAd(vastTagUrl) {\n const adPlayer = this.host.getAdPlayer();\n if (adPlayer.isAdPlaying()) return;\n if (this.timing.failedVastUrls.has(vastTagUrl)) {\n if (this.debug) console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n throw new Error(\"VAST URL permanently failed\");\n }\n if (this.timing.isUrlInCooldown(vastTagUrl)) {\n if (this.debug) console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n throw new Error(\"VAST URL in cooldown after no-fill\");\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n throw new Error(\"Too many consecutive failures\");\n }\n if (this.timing.isGamInCooldown()) {\n if (this.debug) console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n throw new Error(\"GAM in cooldown\");\n }\n this.recreateAdController();\n const requestToken = ++this.timing.adRequestTokenCounter;\n this.timing.activeAdRequestToken = requestToken;\n this.timing.startAdRequestWatchdog(requestToken);\n try {\n await this.timing.enforceGlobalRateLimit();\n this.timing.lastAdRequestTime = Date.now();\n const ap = this.host.getAdPlayer();\n await ap.requestAds(vastTagUrl);\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: vastTagUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n this.timing.clearAdRequestWatchdog();\n if (this.timing.activeAdRequestToken !== requestToken) return;\n if (!this.timing.ensureLoadedAdFitsBudget(ap)) {\n this.timing.rejectLoadedAdForDuration(ap);\n this.recreateAdController();\n throw new Error(\"ad_duration_exceeds_budget\");\n }\n try {\n this.timing.startAdFailsafeTimer(requestToken);\n await ap.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n ap.setAdVolume(getAdAudioVolume(ap));\n this.timing.consecutiveFailures = 0;\n this.timing.temporaryFailureUrls.delete(vastTagUrl);\n } catch (playError) {\n if (this.debug) console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n const preloadedFallback = this.preloadPool.getPreloadedAd();\n if (preloadedFallback) {\n if (this.debug) console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n throw playError;\n }\n this.timing.clearAdFailsafeTimer();\n this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n this.timing.consecutiveFailures = 0;\n const fbAp = this.host.getAdPlayer();\n await fbAp.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n fbAp.setAdVolume(getAdAudioVolume(fbAp));\n return;\n } catch (fallbackError) {\n if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n if (this.timing.isTemporaryAdError(playError)) {\n this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.debug) console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n } else {\n this.timing.failedVastUrls.add(vastTagUrl);\n if (this.debug) console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n }\n this.timing.clearAdFailsafeTimer();\n if (this.timing.activeAdRequestToken === requestToken) {\n this.timing.activeAdRequestToken = null;\n }\n throw playError;\n }\n } catch (error) {\n const errorMessage = error?.message || \"\";\n if (this.debug) console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n const preloadedFallback = this.preloadPool.getPreloadedAd();\n if (preloadedFallback) {\n if (this.debug) console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n throw error;\n }\n this.timing.clearAdRequestWatchdog();\n this.timing.clearAdFailsafeTimer();\n this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n this.timing.consecutiveFailures = 0;\n const fbAp = this.host.getAdPlayer();\n await fbAp.play();\n this.timing.markAdStarted();\n fbAp.setAdVolume(getAdAudioVolume(fbAp));\n return;\n } catch (fallbackError) {\n if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n if (this.timing.isTemporaryAdError(error)) {\n this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.debug) console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n } else {\n this.timing.failedVastUrls.add(vastTagUrl);\n if (this.debug) console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n }\n this.timing.clearAdRequestWatchdog();\n this.timing.clearAdFailsafeTimer();\n if (this.timing.activeAdRequestToken === requestToken) {\n this.timing.activeAdRequestToken = null;\n }\n throw error;\n }\n }\n // ───────────────────────────────────────────────────────────────\n // Placeholder wait\n // ───────────────────────────────────────────────────────────────\n async showPlaceholderAndWaitForAds() {\n const remaining = this.timing.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n if (this.timing.isGamInCooldown()) {\n if (this.debug) console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n this.handleAdPodComplete();\n return;\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping placeholder - too many consecutive failures\");\n this.handleAdPodComplete();\n return;\n }\n if (waitTime < 1e3) {\n this.handleAdPodComplete();\n return;\n }\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n }\n this.isShowingPlaceholder = true;\n this.host.getAdPlayer().showPlaceholder();\n const checkInterval = 300;\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) return;\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Too many failures during placeholder wait\");\n break;\n }\n if (!this.timing.hasTimeToStartAnotherAd()) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Not enough time remaining during placeholder wait, ending ad break\");\n break;\n }\n while (this.adRequestQueue.length > 0) {\n if (!this.timing.hasTimeToStartAnotherAd()) break;\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) continue;\n if (this.timing.failedVastUrls.has(nextAdUrl)) continue;\n if (this.timing.isUrlInCooldown(nextAdUrl)) continue;\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad URL available, requesting via HLS ad player\");\n this.isShowingPlaceholder = false;\n this.host.getAdPlayer().hidePlaceholder();\n try {\n await this.playSingleAd(nextAdUrl);\n this.timing.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = error.message;\n if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.timing.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n }\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Placeholder timeout, ending ad break\");\n this.isShowingPlaceholder = false;\n this.host.getAdPlayer().hidePlaceholder();\n this.handleAdPodComplete();\n }\n // ───────────────────────────────────────────────────────────────\n // Ad break completion\n // ───────────────────────────────────────────────────────────────\n handleAdPodComplete() {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ad pod complete - cleaning up\");\n }\n this.timing.resetForBreakEnd();\n this.stopContinuousFetching();\n this.preloadPool.stop();\n this.clearPendingAdBreak();\n if (this.isShowingPlaceholder) {\n this.host.getAdPlayer().hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n this.adRequestQueue = [];\n this.inAdBreak = false;\n this.adDetectSentForCurrentBreak = false;\n this.cueManager.activeScte35BreakKey = void 0;\n this.cueManager.scheduledScte35BreakKey = void 0;\n this.adPodQueue = [];\n this.showAds = false;\n this.host.getAdPlayer().stop().catch(() => {\n });\n const restoredMuted = this.host.getAdPlayer().getOriginalMutedState();\n const restoredVolume = this.host.getAdPlayer().getOriginalVolume();\n if (this.host.video.muted !== restoredMuted) {\n this.host.video.muted = restoredMuted;\n }\n if (Math.abs(this.host.video.volume - restoredVolume) > 0.01) {\n this.host.video.volume = restoredVolume;\n }\n if (this.host.shouldContinueLiveStreamDuringAds()) {\n if (this.host.video.paused) {\n if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n this.host.video.play()?.catch(() => {\n });\n } else {\n if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n } else if (this.host.video.paused) {\n this.host.video.play()?.catch(() => {\n });\n }\n }\n handleAdFailure() {\n this.timing.consecutiveFailures++;\n this.timing.recordGamNoFill();\n const remaining = this.timing.getRemainingAdMs();\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.timing.consecutiveFailures}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(`[CONTINUOUS-FETCH] Max consecutive failures reached (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n this.handleAdPodComplete();\n return;\n }\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n if (this.debug) console.log(\"[AD-ERROR] Ad failed and not enough time remaining for another ad. Failed URLs:\", this.timing.failedVastUrls.size);\n this.handleAdPodComplete();\n }\n }\n};\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.attached = false;\n this.palPlaybackStarted = false;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.adPlayer = this.createAdPlayer(false);\n this.palNonce = createPalNonceManager();\n this.cueManager = new Scte35CueManager(!!this.config.debugAdTiming, {\n onEarlyStartCue: (marker, fragmentSn, cueKey) => {\n this.startAdPrefetch(marker, fragmentSn, cueKey);\n },\n onPlaybackCue: (marker, cueKey) => {\n this.onScte35Marker(marker, cueKey);\n },\n isInAdBreak: () => this.adBreak.inAdBreak\n });\n this.adConfig = new AdConfigManager(this.config, this.video);\n this.timing = new AdTimingService(this.config, this.video, {\n onAdStopTimerFired: () => this.onAdStopTimerFired(),\n onAdStartTimerFired: (marker, cueKey) => {\n this.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.timing.expectedAdBreakDurationMs\n );\n },\n onWatchdogTimeout: () => this.adBreak.handleAdFailure(),\n onFailsafeTimeout: () => this.adBreak.handleAdFailure()\n });\n this.preloadPool = new AdPreloadPool({\n debug: !!this.config.debugAdTiming,\n createAdPlayer: (c) => this.createAdPlayer(c),\n shouldContinueLiveStreamDuringAds: () => this.shouldContinueLiveStreamDuringAds(),\n timing: this.timing,\n generateVastUrlsWithCorrelators: (base, count) => this.generateVastUrls(base, count),\n isInAdBreak: () => this.adBreak.inAdBreak,\n getPendingAdBreak: () => this.adBreak.pendingAdBreak\n });\n this.placeholder = new PlaceholderLayer(this.video, !!this.config.debugAdTiming);\n this.hlsEngine = new HlsEngine(this.config, this.video, this.cueManager, this.timing, {\n onManifestParsed: async (isLive) => this.onManifestParsed(isLive),\n onScte35Cue: (marker, context) => this.cueManager.onScte35Cue(marker, context),\n activatePendingCuesForFragment: (frag) => this.cueManager.activatePendingScte35CuesForFragment(frag),\n onFatalDestroy: () => this.destroy(),\n isInAdBreak: () => this.adBreak.inAdBreak,\n hasPendingAdBreak: () => this.adBreak.pendingAdBreak !== null\n });\n this.adBreak = new AdBreakOrchestrator(\n {\n config: this.config,\n video: this.video,\n getAdPlayer: () => this.adPlayer,\n setAdPlayer: (p) => {\n this.adPlayer = p;\n },\n createAdPlayer: (c) => this.createAdPlayer(c),\n shouldContinueLiveStreamDuringAds: () => this.shouldContinueLiveStreamDuringAds(),\n generateVastUrls: (base, count) => this.generateVastUrls(base, count)\n },\n this.timing,\n this.preloadPool,\n this.adConfig,\n this.cueManager,\n this.placeholder\n );\n }\n get debug() {\n return !!this.config.debugAdTiming;\n }\n createAdPlayer(continueLiveStreamDuringAds) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Creating HLS ad player\");\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},\n ...this.hlsEngine?.hls ? { mainHlsInstance: this.hlsEngine.hls } : {}\n });\n }\n generateVastUrls(baseUrl, count) {\n return this.adConfig.generateVastUrlsWithCorrelators(\n baseUrl,\n count,\n this.adPlayer,\n this.palNonce,\n this.adBreak.inAdBreak\n );\n }\n // ───────────────────────────────────────────────────────────────\n // Lifecycle\n // ───────────────────────────────────────────────────────────────\n async load() {\n if (!this.attached) {\n this.attach();\n }\n try {\n await this.adConfig.fetchAdConfiguration();\n } catch (error) {\n if (this.debug) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n this.palNonce.generateNonce({\n videoWidth: this.video.offsetWidth || this.video.clientWidth || 640,\n videoHeight: this.video.offsetHeight || this.video.clientHeight || 480,\n adWillAutoPlay: !!this.config.autoplay,\n adWillPlayMuted: true,\n playerVolume: 0,\n continuousPlayback: this.config.lowLatencyMode ?? false\n }).catch(() => {\n });\n fetchConsentSignals().then((signals) => {\n this.adConfig.consentSignals = signals;\n }).catch(() => {\n });\n this.adConfig.initializeTracking();\n if (this.hlsEngine.shouldUseNativeHls(() => this.getStreamType())) {\n this.adPlayer.destroy();\n this.adPlayer = this.createAdPlayer(false);\n this.adPlayer.initialize();\n await this.hlsEngine.setupNativeHls();\n return;\n }\n this.hlsEngine.setupHls();\n }\n async onManifestParsed(isLive) {\n if (!this.adConfig.isVmapEnabled() && !isLive && this.adConfig.vmapBreaks.length === 0 && this.adConfig.apiVastTagUrl) {\n const prerollKey = \"synthetic-vod-preroll\";\n if (!this.adConfig.consumedVmapBreakIds.has(prerollKey)) {\n this.adConfig.vmapBreaks = [\n { id: prerollKey, startTimeMs: 0, vastTagUrl: this.adConfig.apiVastTagUrl }\n ];\n if (this.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Injected synthetic VOD preroll from apiVastTagUrl\"\n );\n }\n }\n }\n if (this.debug) {\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,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior\n });\n }\n this.adPlayer.destroy();\n this.adPlayer = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.adPlayer.initialize();\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.adPlayer.initialize();\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.adBreak.attachImaEventListeners();\n this.video.addEventListener(\"play\", () => {\n if (!this.palPlaybackStarted && !this.adPlayer.isAdPlaying()) {\n this.palPlaybackStarted = true;\n this.palNonce.sendPlaybackStart();\n }\n });\n this.endedHandler = () => {\n if (this.palPlaybackStarted) {\n this.palPlaybackStarted = false;\n this.palNonce.sendPlaybackEnd();\n }\n this.onVideoEnded();\n };\n this.video.addEventListener(\"ended\", this.endedHandler);\n this.video.addEventListener(\"mousedown\", (e) => {\n this.palNonce.sendAdTouch(e);\n });\n this.video.addEventListener(\"touchstart\", (e) => {\n this.palNonce.sendAdTouch(e);\n });\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.hlsEngine.nativeHlsMode && this.hlsEngine.videoSrcProtection && !this.adPlayer.isAdPlaying()) {\n if (this.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.hlsEngine.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.hlsEngine.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 shouldContinueLiveStreamDuringAds() {\n if (this.config.allowNativeHls) return false;\n if (!this.hlsEngine.isLiveStream) return false;\n return true;\n }\n // ───────────────────────────────────────────────────────────────\n // SCTE-35 marker orchestration\n // ───────────────────────────────────────────────────────────────\n onScte35Marker(marker, cueKey) {\n if (this.debug) {\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 hasPendingAdBreak: !!this.adBreak.pendingAdBreak\n });\n }\n if (marker.type === \"start\") {\n if (this.adBreak.inAdBreak) {\n if (marker.durationSeconds != null) {\n const newDurationMs = marker.durationSeconds * 1e3;\n if (this.timing.expectedAdBreakDurationMs == null || newDurationMs > this.timing.expectedAdBreakDurationMs) {\n this.timing.setAdBreakDurationBoundary(newDurationMs);\n this.timing.scheduleAdStopAtBreakBoundary();\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${newDurationMs}ms, remaining: ${this.timing.getWallClockRemainingAdMs()}ms`\n );\n }\n }\n }\n return;\n }\n if (!this.adBreak.adDetectSentForCurrentBreak) {\n this.adBreak.adDetectSentForCurrentBreak = true;\n const detectPayload = {};\n if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;\n if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;\n sendAdDetectTracking(this.config.licenseKey, { source: \"scte35\", timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...detectPayload }).catch(() => {\n });\n }\n const hasPrefetchedAds = this.adBreak.pendingAdBreak && this.adBreak.pendingAdBreak.vastUrls.length > 0;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.adBreak.pendingAdBreak?.marker.durationSeconds != null ? this.adBreak.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;\n const isManifest = isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker: isManifest,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n hasPrefetchedAds\n });\n }\n if (isManifest && forceImmediate) {\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Starting ad immediately (manifest-based)${hasPrefetchedAds ? \" with prefetched ads\" : \"\"}`\n );\n }\n this.timing.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\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.timing.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.debug) {\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.debug) {\n console.log(`[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`);\n }\n this.timing.expectedAdBreakDurationMs = durationMs;\n this.cueManager.scheduledScte35BreakKey = cueKey;\n this.timing.scheduleAdStartIn(deltaMs, marker, cueKey);\n } else {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\");\n }\n this.timing.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n } else {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Starting ad immediately (fallback)\");\n }\n this.timing.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.adBreak.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.timing.setAdBreakDurationBoundary(marker.durationSeconds * 1e3);\n }\n this.timing.scheduleAdStopAtBreakBoundary();\n if (!this.adPlayer.isAdPlaying() && this.timing.activeAdRequestToken === null && this.adBreak.adRequestQueue.length > 0 && this.timing.hasTimeToStartAnotherAd()) {\n this.adBreak.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n const remaining = this.timing.getRemainingAdMs();\n const adPlaying = this.adPlayer.isAdPlaying();\n const hasQueuedAds = this.adBreak.adRequestQueue.length > 0;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.timing.activeAdRequestToken !== null\n });\n }\n this.timing.scteAdBreakEndWallClockMs = Date.now();\n this.timing.clearAdStartTimer();\n this.timing.clearAdStopTimer();\n if (adPlaying) {\n this.adPlayer.stop().catch(() => {\n });\n }\n this.adBreak.handleAdPodComplete();\n return;\n }\n }\n startScte35AdBreak(marker, cueKey, durationMs) {\n this.adBreak.inAdBreak = true;\n this.cueManager.activeScte35BreakKey = cueKey ?? this.cueManager.pendingScte35CueKey;\n this.cueManager.scheduledScte35BreakKey = void 0;\n this.timing.currentAdBreakStartWallClockMs = this.timing.resolveScteBreakStartWallClockMs(marker);\n this.timing.setAdBreakDurationBoundary(durationMs);\n this.adBreak.handleAdStart(marker);\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n onAdStopTimerFired() {\n if (!this.adBreak.inAdBreak) return;\n const adPlaying = this.adPlayer.isAdPlaying();\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 : 0;\n const endWallClockMs = this.timing.getAdBreakEndWallClockMs() ?? Date.now();\n const overrunMs = Math.max(0, Date.now() - endWallClockMs);\n const shouldExtendAdBreak = adPlaying && overrunMs < maxExtensionMs;\n if (shouldExtendAdBreak) {\n this.timing.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Ad break boundary reached (overrun=${overrunMs}ms) - hard-stopping ads and resuming stream`\n );\n }\n if (adPlaying) {\n this.adPlayer.stop().catch(() => {\n });\n }\n this.adBreak.handleAdPodComplete();\n }\n // ───────────────────────────────────────────────────────────────\n // Ad prefetch\n // ───────────────────────────────────────────────────────────────\n startAdPrefetch(marker, fragmentSn, cueKey) {\n if (this.adBreak.pendingAdBreak || this.adBreak.inAdBreak) return;\n const scheduled = this.adConfig.findCurrentOrNextBreak(this.video.currentTime * 1e3);\n const tags = this.adConfig.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.adConfig.apiVastTagUrl) {\n baseVastUrl = this.adConfig.apiVastTagUrl;\n } else {\n if (this.debug) console.warn(\"[StormcloudVideoPlayer] No VAST URL available for prefetch\");\n return;\n }\n this.adConfig.beginNewAdPod();\n this.adConfig.podAssignedByPrefetch = true;\n const generatedUrls = this.generateVastUrls(baseVastUrl, 1);\n this.adBreak.pendingAdBreak = {\n marker,\n ...fragmentSn !== void 0 ? { detectedAtFragmentSn: fragmentSn } : {},\n vastUrls: generatedUrls,\n isFetching: false,\n fetchStartTime: Date.now()\n };\n this.cueManager.pendingScte35CueKey = cueKey;\n this.adBreak.adDetectSentForCurrentBreak = true;\n const detectPayload = {};\n if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;\n if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;\n if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;\n sendAdDetectTracking(this.config.licenseKey, { source: \"scte35\", timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...detectPayload }).catch(() => {\n });\n if (this.debug) {\n console.log(\"[PREFETCH] Starting ad prefetch for upcoming ad break\");\n console.log(`[PREFETCH] Pre-generated ${generatedUrls.length} VAST URLs`);\n }\n this.preloadPool.startPreloadPool(baseVastUrl, generatedUrls.slice(0, 1), false);\n }\n // ───────────────────────────────────────────────────────────────\n // VMAP time-based ad breaks\n // ───────────────────────────────────────────────────────────────\n onTimeUpdate(currentTimeSec) {\n if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;\n if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;\n const nowMs = currentTimeSec * 1e3;\n const breakToPlay = this.adConfig.findBreakForTime(nowMs);\n if (breakToPlay) {\n void this.handleVmapAdBreak(breakToPlay, nowMs).catch((error) => {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] VMAP ad break failed gracefully:\", error);\n }\n });\n }\n }\n onVideoEnded() {\n if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;\n if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;\n const durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;\n const postroll = this.adConfig.vmapBreaks.find(\n (b) => b.startTimeMs === -1 && !this.adConfig.consumedVmapBreakIds.has(this.adConfig.getAdBreakKey(b))\n );\n if (postroll) {\n void this.handleVmapAdBreak(postroll, durationMs).catch((error) => {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] VMAP post-roll failed gracefully:\", error);\n }\n });\n }\n }\n async handleVmapAdBreak(adBreak, nowMs) {\n const key = this.adConfig.getAdBreakKey(adBreak);\n if (this.adConfig.consumedVmapBreakIds.has(key)) return;\n const breakStartMs = this.adConfig.resolveBreakStartMs(adBreak);\n if (breakStartMs == null) return;\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = breakStartMs + durationMs;\n const inWindow = durationMs > 0 ? nowMs >= breakStartMs && nowMs < endMs : nowMs >= breakStartMs;\n if (inWindow) {\n this.adConfig.consumedVmapBreakIds.add(key);\n const tags = this.adConfig.selectVastTagsForBreak(adBreak);\n if (!tags || tags.length === 0) return;\n const first = tags[0];\n const rest = tags.slice(1);\n this.adBreak.adPodQueue = rest;\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.adBreak.showAds = true;\n this.adBreak.inAdBreak = true;\n this.timing.currentAdBreakStartWallClockMs = Date.now();\n if (!this.video.paused) {\n this.video.pause();\n }\n try {\n await this.adBreak.playSingleAd(first);\n } catch (error) {\n this.adBreak.adPodQueue = [];\n this.adBreak.inAdBreak = false;\n this.adBreak.showAds = false;\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] VMAP ad request failed:\", error);\n }\n }\n }\n }\n // ───────────────────────────────────────────────────────────────\n // Public API\n // ───────────────────────────────────────────────────────────────\n getCurrentAdIndex() {\n return this.timing.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.timing.totalAdsInBreak;\n }\n getAdRemainingMs() {\n return this.timing.getRemainingAdMs();\n }\n isAdPlaying() {\n return this.adBreak.inAdBreak && this.adPlayer.isAdPlaying();\n }\n isShowingAds() {\n return this.adBreak.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 isLive() {\n return this.hlsEngine.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n toggleMute() {\n toggleMute(this.video, this.adPlayer, this.debug);\n }\n toggleFullscreen() {\n return toggleFullscreen(this.video, this.debug);\n }\n isMuted() {\n return isMuted(this.video, this.adPlayer);\n }\n setMuted(muted) {\n setMuted(this.video, this.adPlayer, muted, this.debug);\n }\n setVolume(volume) {\n setVolume(this.video, this.adPlayer, volume, this.debug);\n }\n getVolume() {\n return getVolume(this.video, this.adPlayer);\n }\n isFullscreen() {\n return isFullscreen();\n }\n resize() {\n resizePlayer(this.video, this.adPlayer, this.debug);\n }\n // ───────────────────────────────────────────────────────────────\n // Destroy\n // ───────────────────────────────────────────────────────────────\n destroy() {\n this.adBreak.stopContinuousFetching();\n this.preloadPool.stop();\n this.timing.destroy();\n this.adBreak.clearPendingAdBreak();\n this.placeholder.destroy();\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.endedHandler) {\n this.video.removeEventListener(\"ended\", this.endedHandler);\n delete this.endedHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n this.adConfig.destroyTracking();\n this.hlsEngine.destroy();\n this.adPlayer?.destroy();\n if (this.palPlaybackStarted) {\n this.palPlaybackStarted = false;\n this.palNonce.sendPlaybackEnd();\n }\n this.palNonce.reset();\n this.adBreak.adRequestQueue = [];\n this.timing.consecutiveFailures = 0;\n }\n};\n\n// src/ui/StormcloudVideoPlayer.tsx\nvar import_fa = require(\"react-icons/fa\");\nvar import_jsx_runtime = require(\"react/jsx-runtime\");\nvar CRITICAL_PROPS = [\n \"src\",\n \"allowNativeHls\",\n \"isLiveStream\",\n \"licenseKey\",\n \"isVmap\",\n \"vmapUrl\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"vastMode\",\n \"ctvAdRequest\"\n];\nvar CONTROLS_HIDE_DELAY = 3e3;\nvar DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;\nvar StormcloudVideoPlayerComponent = import_react.default.memo(\n (props) => {\n const {\n src,\n autoplay,\n muted,\n lowLatencyMode,\n allowNativeHls,\n isLiveStream,\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 isVmap,\n vmapUrl,\n minSegmentsBeforePlay,\n ctvAdRequest,\n ...restVideoAttrs\n } = props;\n const videoRef = (0, import_react.useRef)(null);\n const playerRef = (0, import_react.useRef)(null);\n const bufferingTimeoutRef = (0, import_react.useRef)(null);\n const controlsTimerRef = (0, import_react.useRef)(null);\n const wrapperRef = (0, import_react.useRef)(null);\n const [adStatus, setAdStatus] = import_react.default.useState({ showAds: false, currentIndex: 0, totalAds: 0, remainingSeconds: 0 });\n const [shouldShowNativeControls, setShouldShowNativeControls] = import_react.default.useState(true);\n const [isMuted2, setIsMuted] = import_react.default.useState(false);\n const [isFullscreen2, setIsFullscreen] = import_react.default.useState(false);\n const [isPlaying, setIsPlaying] = import_react.default.useState(false);\n const [currentTime, setCurrentTime] = import_react.default.useState(0);\n const [duration, setDuration] = import_react.default.useState(0);\n const [volume, setVolume2] = import_react.default.useState(1);\n const [playbackRate, setPlaybackRate] = import_react.default.useState(1);\n const [showVolumeSlider, setShowVolumeSlider] = import_react.default.useState(false);\n const [showSpeedMenu, setShowSpeedMenu] = import_react.default.useState(false);\n const [isLoading, setIsLoading] = import_react.default.useState(true);\n const [isBuffering, setIsBuffering] = import_react.default.useState(false);\n const [showCenterPlay, setShowCenterPlay] = import_react.default.useState(false);\n const [showLicenseWarning, setShowLicenseWarning] = import_react.default.useState(false);\n const [controlsVisible, setControlsVisible] = import_react.default.useState(true);\n const [viewportWidth, setViewportWidth] = import_react.default.useState(\n typeof window !== \"undefined\" ? window.innerWidth : 1920\n );\n const [isPortrait, setIsPortrait] = import_react.default.useState(\n typeof window !== \"undefined\" ? window.innerHeight > window.innerWidth : false\n );\n const [playerAspectRatio, setPlayerAspectRatio] = import_react.default.useState(\n DEFAULT_PLAYER_ASPECT_RATIO\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 resetControlsTimer = (0, import_react.useCallback)(() => {\n if (controlsTimerRef.current) {\n clearTimeout(controlsTimerRef.current);\n }\n setControlsVisible(true);\n controlsTimerRef.current = window.setTimeout(() => {\n if (!showVolumeSlider && !showSpeedMenu) {\n setControlsVisible(false);\n }\n }, CONTROLS_HIDE_DELAY);\n }, [showVolumeSlider, showSpeedMenu]);\n const handleWrapperMouseMove = (0, import_react.useCallback)(() => {\n resetControlsTimer();\n }, [resetControlsTimer]);\n const handleWrapperMouseLeave = (0, import_react.useCallback)(() => {\n if (!showVolumeSlider && !showSpeedMenu) {\n setControlsVisible(false);\n }\n }, [showVolumeSlider, showSpeedMenu]);\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 resetControlsTimer();\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 resetControlsTimer();\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 || isLiveStream === false : true);\n const criticalPropsKey = (0, import_react.useMemo)(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n isLiveStream,\n licenseKey,\n isVmap,\n vmapUrl,\n lowLatencyMode,\n driftToleranceMs,\n vastMode\n ]);\n (0, import_react.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 (isLiveStream !== void 0) cfg.isLiveStream = isLiveStream;\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 (isVmap !== void 0) cfg.isVmap = isVmap;\n if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;\n if (minSegmentsBeforePlay !== void 0)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n if (ctvAdRequest !== void 0) cfg.ctvAdRequest = ctvAdRequest;\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 (0, import_react.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 (0, import_react.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 const remainingMs = playerRef.current.getAdRemainingMs();\n const remainingSeconds = showAds ? Math.max(0, Math.ceil(remainingMs / 1e3)) : 0;\n setAdStatus((prev) => {\n if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds || prev.remainingSeconds !== remainingSeconds) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds, remainingSeconds };\n }\n return prev;\n });\n }\n };\n const interval = setInterval(checkAdStatus, 50);\n return () => clearInterval(interval);\n }, []);\n (0, import_react.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 (0, import_react.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 = playerRef.current.getVolume();\n setVolume2(\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 === wrapperRef.current\n );\n };\n const interval = setInterval(updateStates, 200);\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === wrapperRef.current\n );\n };\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n return () => {\n clearInterval(interval);\n document.removeEventListener(\n \"fullscreenchange\",\n handleFullscreenChange\n );\n };\n }, []);\n (0, import_react.useEffect)(() => {\n if (!videoRef.current) return;\n const handleLoadedMetadata = () => {\n const video2 = videoRef.current;\n if (video2) {\n if (video2.videoWidth > 0 && video2.videoHeight > 0) {\n setPlayerAspectRatio(video2.videoWidth / video2.videoHeight);\n }\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 (0, import_react.useEffect)(() => {\n setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);\n }, [src]);\n (0, import_react.useEffect)(() => {\n return () => {\n if (controlsTimerRef.current) {\n clearTimeout(controlsTimerRef.current);\n }\n };\n }, []);\n const progressPercent = duration > 0 ? currentTime / duration * 100 : 0;\n const VolumeIcon = isMuted2 || volume === 0 ? import_fa.FaVolumeMute : volume < 0.5 ? import_fa.FaVolumeDown : import_fa.FaVolumeUp;\n return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"style\", { children: `\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-loading-glow {\n 0%, 100% { opacity: 0.85; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.05); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-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 .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n ` }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n ref: wrapperRef,\n className: `sc-wrapper ${wrapperClassName || \"\"}`,\n onMouseMove: handleWrapperMouseMove,\n onMouseLeave: handleWrapperMouseLeave,\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n position: isFullscreen2 ? \"fixed\" : \"relative\",\n top: isFullscreen2 ? 0 : void 0,\n left: isFullscreen2 ? 0 : void 0,\n overflow: \"hidden\",\n width: isFullscreen2 ? \"100vw\" : \"100%\",\n height: isFullscreen2 ? \"100vh\" : \"auto\",\n minHeight: isFullscreen2 ? \"100vh\" : \"auto\",\n aspectRatio: isFullscreen2 ? void 0 : playerAspectRatio,\n maxWidth: isFullscreen2 ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen2 ? \"100vh\" : \"none\",\n zIndex: isFullscreen2 ? 999999 : void 0,\n backgroundColor: \"#000\",\n borderRadius: isFullscreen2 ? 0 : void 0,\n boxShadow: isFullscreen2 ? \"none\" : void 0,\n ...wrapperStyle\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"video\",\n {\n ref: videoRef,\n className,\n style: {\n display: \"block\",\n width: \"100%\",\n height: \"100%\",\n maxWidth: \"100%\",\n maxHeight: isFullscreen2 ? \"100%\" : \"none\",\n objectFit: isFullscreen2 ? \"cover\" : \"contain\",\n backgroundColor: \"#000\",\n aspectRatio: isFullscreen2 ? \"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__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: \"sc-loading-indicator\",\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 20,\n width: `${Math.max(34, 38 * responsiveScale)}px`,\n height: `${Math.max(34, 38 * responsiveScale)}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n animation: \"sc-loading-glow 1.4s ease-in-out infinite\",\n filter: \"drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n inset: 0,\n borderRadius: \"50%\",\n border: \"3px solid rgba(255, 255, 255, 0.25)\",\n borderTopColor: \"#ff0000\",\n borderRightColor: \"rgba(255, 255, 255, 0.85)\",\n animation: \"sc-spin 0.8s linear infinite\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: \"7px\",\n height: \"7px\",\n borderRadius: \"50%\",\n background: \"#ff0000\",\n boxShadow: \"0 0 10px rgba(255, 0, 0, 0.65)\"\n }\n }\n )\n ]\n }\n ),\n showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.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: \"rgba(220, 38, 38, 0.92)\",\n backdropFilter: \"blur(24px)\",\n color: \"white\",\n padding: \"28px 36px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n boxShadow: \"0 24px 64px rgba(0, 0, 0, 0.5)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"18px\", fontWeight: \"700\", marginBottom: \"10px\", letterSpacing: \"-0.02em\" }, children: \"License Key Required\" }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { fontSize: \"13px\", lineHeight: \"1.6\", color: \"rgba(255, 255, 255, 0.85)\" }, children: [\n \"Please provide a valid license key to use the Stormcloud Video Player.\",\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"br\", {}),\n \"Contact your administrator for licensing information.\"\n ] })\n ]\n }\n ),\n adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: `${12 * responsiveScale}px`,\n left: `${12 * responsiveScale}px`,\n zIndex: 50,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n pointerEvents: \"none\",\n animation: \"sc-fade-in 0.3s ease\"\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n background: \"rgba(234, 179, 8, 0.95)\",\n color: \"#111\",\n padding: `${4 * responsiveScale}px ${12 * responsiveScale}px`,\n borderRadius: \"6px\",\n fontSize: `${11 * responsiveScale}px`,\n fontWeight: 700,\n letterSpacing: \"0.08em\",\n textTransform: \"uppercase\",\n boxShadow: \"0 2px 12px rgba(234, 179, 8, 0.35)\"\n },\n children: `Ad ${Math.max(1, adStatus.currentIndex)}`\n }\n )\n }\n ),\n showCenterPlay && !isLoading && !isBuffering && !showLicenseWarning && !adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.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: \"rgba(0, 0, 0, 0.55)\",\n backdropFilter: \"blur(8px)\",\n borderRadius: \"50%\",\n width: `${92 * responsiveScale}px`,\n height: `${92 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"background 0.2s ease, transform 0.2s ease\",\n animation: \"sc-fade-in 0.2s ease\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.background = \"rgba(0, 0, 0, 0.72)\";\n e.currentTarget.style.transform = \"translate(-50%, -50%) scale(1.06)\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.background = \"rgba(0, 0, 0, 0.55)\";\n e.currentTarget.style.transform = \"translate(-50%, -50%) scale(1)\";\n },\n title: \"Play\",\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaPlay,\n {\n size: Math.max(24, 32 * responsiveScale),\n color: \"white\",\n style: { marginLeft: \"4px\" }\n }\n )\n }\n ),\n shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: \"sc-controls-bar\",\n style: {\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background: \"linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.35) 60%, transparent 100%)\",\n padding: `${20 * responsiveScale}px ${12 * responsiveScale}px ${8 * responsiveScale}px`,\n zIndex: 10,\n opacity: controlsVisible || adStatus.showAds ? 1 : 0,\n transform: controlsVisible || adStatus.showAds ? \"translateY(0)\" : \"translateY(6px)\",\n pointerEvents: controlsVisible || adStatus.showAds ? \"auto\" : \"none\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: \"sc-progress-track\",\n style: {\n width: \"100%\",\n height: \"3px\",\n background: \"rgba(255, 255, 255, 0.2)\",\n borderRadius: \"1.5px\",\n marginBottom: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n position: \"relative\",\n transition: \"height 0.1s ease\"\n },\n onClick: handleTimelineSeek,\n onMouseEnter: (e) => {\n e.currentTarget.style.height = \"5px\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.height = \"3px\";\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: 0,\n left: 0,\n bottom: 0,\n background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n borderRadius: \"1.5px\",\n width: `${progressPercent}%`,\n transition: \"width 0.15s linear\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n className: \"sc-progress-thumb\",\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: `${progressPercent}%`,\n transform: \"translate(-50%, -50%) scale(0)\",\n width: \"13px\",\n height: \"13px\",\n background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 4px rgba(0, 0, 0, 0.3)\",\n transition: \"transform 0.1s ease, left 0.15s linear\"\n }\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n gap: `${8 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: `${8 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: handlePlayPause,\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`\n },\n title: isPlaying ? \"Pause\" : \"Play\",\n children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPause, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPlay, { size: Math.max(14, 18 * responsiveScale), style: { marginLeft: \"2px\" } })\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n paddingRight: `${6 * responsiveScale}px`\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n if (playerRef.current) playerRef.current.toggleMute();\n onVolumeToggle?.();\n resetControlsTimer();\n },\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`\n },\n title: isMuted2 ? \"Unmute\" : \"Mute\",\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, { size: Math.max(14, 18 * responsiveScale) })\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n overflow: \"hidden\",\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n display: \"flex\",\n alignItems: \"center\",\n paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n paddingRight: showVolumeSlider ? `${8 * responsiveScale}px` : \"0\"\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: `${56 * responsiveScale}px`,\n height: \"3px\",\n cursor: \"pointer\",\n borderRadius: \"1.5px\"\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const el = e.currentTarget;\n const move = (ev) => {\n const r2 = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));\n };\n const up = () => {\n document.removeEventListener(\"mousemove\", move);\n document.removeEventListener(\"mouseup\", up);\n };\n document.addEventListener(\"mousemove\", move);\n document.addEventListener(\"mouseup\", up);\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n },\n onClick: (e) => {\n e.stopPropagation();\n const r = e.currentTarget.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: 0,\n left: 0,\n bottom: 0,\n width: `${(isMuted2 ? 0 : volume) * 100}%`,\n background: \"#fff\",\n borderRadius: \"1.5px\",\n transition: \"width 0.1s ease-out\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: `${(isMuted2 ? 0 : volume) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n width: \"12px\",\n height: \"12px\",\n background: \"#fff\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n transition: \"left 0.1s ease-out\"\n }\n }\n )\n ]\n }\n )\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: `${13 * responsiveScale}px`,\n fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\",\n fontVariantNumeric: \"tabular-nums\",\n userSelect: \"none\",\n marginLeft: `${4 * responsiveScale}px`\n },\n children: [\n formatTime(currentTime),\n \" \",\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { color: \"rgba(255,255,255,0.5)\" }, children: \"/\" }),\n \" \",\n formatTime(duration)\n ]\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n gap: `${8 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { position: \"relative\", display: viewportWidth < 600 ? \"none\" : \"block\" }, children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n setShowSpeedMenu(!showSpeedMenu);\n resetControlsTimer();\n },\n style: {\n padding: `${6 * responsiveScale}px ${10 * responsiveScale}px`,\n borderRadius: `${6 * responsiveScale}px`,\n fontSize: `${13 * responsiveScale}px`,\n fontFamily: \"'SF Mono', 'Cascadia Code', monospace\",\n fontWeight: \"600\",\n minHeight: `${32 * responsiveScale}px`\n },\n title: \"Playback Speed\",\n children: [\n playbackRate,\n \"x\"\n ]\n }\n ),\n showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n right: 0,\n marginBottom: \"8px\",\n background: \"rgba(0, 0, 0, 0.8)\",\n backdropFilter: \"blur(24px)\",\n WebkitBackdropFilter: \"blur(24px)\",\n borderRadius: \"10px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"80px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5)\",\n animation: \"sc-fade-in 0.15s ease\"\n },\n children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map((speed) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"button\",\n {\n onClick: () => handlePlaybackRateChange(speed),\n style: {\n display: \"block\",\n width: \"100%\",\n padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n background: playbackRate === speed ? \"rgba(255, 255, 255, 0.12)\" : \"transparent\",\n border: \"none\",\n color: playbackRate === speed ? \"#fff\" : \"rgba(255, 255, 255, 0.7)\",\n cursor: \"pointer\",\n fontSize: `${12 * responsiveScale}px`,\n fontFamily: \"'SF Mono', monospace\",\n fontWeight: playbackRate === speed ? \"700\" : \"500\",\n textAlign: \"center\",\n transition: \"background 0.15s ease, color 0.15s ease\"\n },\n onMouseEnter: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"rgba(255, 255, 255, 0.08)\";\n e.target.style.color = \"#fff\";\n }\n },\n onMouseLeave: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"transparent\";\n e.target.style.color = \"rgba(255, 255, 255, 0.7)\";\n }\n },\n children: [\n speed,\n \"x\"\n ]\n },\n speed\n ))\n }\n )\n ] }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (wrapperRef.current) {\n if (!document.fullscreenElement) {\n wrapperRef.current.requestFullscreen().catch(() => {\n });\n } else {\n document.exitFullscreen().catch(() => {\n });\n }\n }\n resetControlsTimer();\n },\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`\n },\n title: isFullscreen2 ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, { size: Math.max(14, 18 * responsiveScale) })\n }\n )\n ]\n }\n )\n ]\n }\n )\n ]\n }\n ) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: `${10 * responsiveScale}px`,\n left: `${10 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n zIndex: 10,\n opacity: controlsVisible ? 1 : 0,\n transition: \"opacity 0.35s ease\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n background: \"#ff3b30\",\n animation: \"sc-pulse 1.5s ease-in-out infinite\",\n flexShrink: 0\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"span\",\n {\n style: {\n fontSize: `${12 * responsiveScale}px`,\n fontFamily: \"'SF Pro Display', 'Segoe UI', Arial, sans-serif\",\n fontWeight: 700,\n letterSpacing: \"0.08em\",\n color: \"#fff\",\n textShadow: \"0 1px 3px rgba(0,0,0,0.6)\",\n userSelect: \"none\"\n },\n children: \"LIVE\"\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: \"sc-controls-bar\",\n style: {\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n alignItems: isPortrait ? \"flex-end\" : \"center\",\n gap: `${8 * responsiveScale}px`,\n zIndex: 10,\n opacity: controlsVisible ? 1 : 0,\n transform: controlsVisible ? \"translateY(0)\" : \"translateY(4px)\",\n pointerEvents: controlsVisible ? \"auto\" : \"none\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n display: \"flex\",\n alignItems: \"center\",\n background: \"rgba(0, 0, 0, 0.6)\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: \"2px\",\n paddingRight: `${8 * responsiveScale}px`\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n if (playerRef.current) playerRef.current.toggleMute();\n onVolumeToggle?.();\n resetControlsTimer();\n },\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`\n },\n title: isMuted2 ? \"Unmute\" : \"Mute\",\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, { size: Math.max(14, 18 * responsiveScale) })\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n overflow: \"hidden\",\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n display: \"flex\",\n alignItems: \"center\",\n paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n paddingRight: showVolumeSlider ? `${10 * responsiveScale}px` : \"0\"\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: `${56 * responsiveScale}px`,\n height: \"3px\",\n cursor: \"pointer\",\n borderRadius: \"1.5px\"\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const el = e.currentTarget;\n const move = (ev) => {\n const r2 = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));\n };\n const up = () => {\n document.removeEventListener(\"mousemove\", move);\n document.removeEventListener(\"mouseup\", up);\n };\n document.addEventListener(\"mousemove\", move);\n document.addEventListener(\"mouseup\", up);\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n },\n onClick: (e) => {\n e.stopPropagation();\n const r = e.currentTarget.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" } }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: 0,\n left: 0,\n bottom: 0,\n width: `${(isMuted2 ? 0 : volume) * 100}%`,\n background: \"#fff\",\n borderRadius: \"1.5px\",\n transition: \"width 0.1s ease-out\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"50%\",\n left: `${(isMuted2 ? 0 : volume) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n width: \"12px\",\n height: \"12px\",\n background: \"#fff\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n transition: \"left 0.1s ease-out\"\n }\n }\n )\n ]\n }\n )\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n className: \"sc-ctrl-btn\",\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (wrapperRef.current) {\n if (!document.fullscreenElement) {\n wrapperRef.current.requestFullscreen().catch(() => {\n });\n } else {\n document.exitFullscreen().catch(() => {\n });\n }\n }\n resetControlsTimer();\n },\n style: {\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n background: \"rgba(0, 0, 0, 0.6)\"\n },\n title: isFullscreen2 ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, { size: Math.max(14, 18 * responsiveScale) })\n }\n )\n ]\n }\n )\n ] }),\n onControlClick && /* @__PURE__ */ (0, import_jsx_runtime.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// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n StormcloudVideoPlayerComponent\n});\n","import React, { useEffect, useRef, useMemo, useCallback } 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} 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 \"isLiveStream\",\n \"licenseKey\",\n \"isVmap\",\n \"vmapUrl\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n \"vastMode\",\n \"ctvAdRequest\",\n] as const;\n\nconst CONTROLS_HIDE_DELAY = 3000;\nconst DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;\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 isLiveStream,\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 isVmap,\n vmapUrl,\n minSegmentsBeforePlay,\n ctvAdRequest,\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 controlsTimerRef = useRef<number | null>(null);\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n const [adStatus, setAdStatus] = React.useState<{\n showAds: boolean;\n currentIndex: number;\n totalAds: number;\n remainingSeconds: number;\n }>({ showAds: false, currentIndex: 0, totalAds: 0, remainingSeconds: 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 [controlsVisible, setControlsVisible] = React.useState(true);\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 const [playerAspectRatio, setPlayerAspectRatio] = React.useState(\n DEFAULT_PLAYER_ASPECT_RATIO\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 resetControlsTimer = useCallback(() => {\n if (controlsTimerRef.current) {\n clearTimeout(controlsTimerRef.current);\n }\n setControlsVisible(true);\n controlsTimerRef.current = window.setTimeout(() => {\n if (!showVolumeSlider && !showSpeedMenu) {\n setControlsVisible(false);\n }\n }, CONTROLS_HIDE_DELAY);\n }, [showVolumeSlider, showSpeedMenu]);\n\n const handleWrapperMouseMove = useCallback(() => {\n resetControlsTimer();\n }, [resetControlsTimer]);\n\n const handleWrapperMouseLeave = useCallback(() => {\n if (!showVolumeSlider && !showSpeedMenu) {\n setControlsVisible(false);\n }\n }, [showVolumeSlider, showSpeedMenu]);\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 resetControlsTimer();\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 resetControlsTimer();\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 &&\n (isHlsStream ? (allowNativeHls || isLiveStream === false) : true);\n\n const criticalPropsKey = useMemo(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n isLiveStream,\n licenseKey,\n isVmap,\n vmapUrl,\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 (isLiveStream !== undefined) cfg.isLiveStream = isLiveStream;\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 (isVmap !== undefined) cfg.isVmap = isVmap;\n if (vmapUrl !== undefined) cfg.vmapUrl = vmapUrl;\n if (minSegmentsBeforePlay !== undefined)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n if (ctvAdRequest !== undefined) cfg.ctvAdRequest = ctvAdRequest;\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 const remainingMs = playerRef.current.getAdRemainingMs();\n const remainingSeconds = showAds\n ? Math.max(0, Math.ceil(remainingMs / 1000))\n : 0;\n\n setAdStatus((prev) => {\n if (\n prev.showAds !== showAds ||\n prev.currentIndex !== currentIndex ||\n prev.totalAds !== totalAds ||\n prev.remainingSeconds !== remainingSeconds\n ) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds, remainingSeconds };\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 = playerRef.current.getVolume();\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 === wrapperRef.current\n );\n };\n\n const interval = setInterval(updateStates, 200);\n\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === wrapperRef.current\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 const video = videoRef.current;\n if (video) {\n if (video.videoWidth > 0 && video.videoHeight > 0) {\n setPlayerAspectRatio(video.videoWidth / video.videoHeight);\n }\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 useEffect(() => {\n setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);\n }, [src]);\n\n useEffect(() => {\n return () => {\n if (controlsTimerRef.current) {\n clearTimeout(controlsTimerRef.current);\n }\n };\n }, []);\n\n const progressPercent = duration > 0 ? (currentTime / duration) * 100 : 0;\n\n const VolumeIcon = isMuted || volume === 0\n ? FaVolumeMute\n : volume < 0.5\n ? FaVolumeDown\n : FaVolumeUp;\n\n return (\n <>\n <style>\n {`\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-loading-glow {\n 0%, 100% { opacity: 0.85; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.05); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-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 .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n `}\n </style>\n <div\n ref={wrapperRef}\n className={`sc-wrapper ${wrapperClassName || \"\"}`}\n onMouseMove={handleWrapperMouseMove}\n onMouseLeave={handleWrapperMouseLeave}\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 aspectRatio: isFullscreen ? undefined : playerAspectRatio,\n maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : undefined,\n backgroundColor: \"#000\",\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: \"100%\",\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 <div\n className=\"sc-loading-indicator\"\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n zIndex: 20,\n width: `${Math.max(34, 38 * responsiveScale)}px`,\n height: `${Math.max(34, 38 * responsiveScale)}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n animation: \"sc-loading-glow 1.4s ease-in-out infinite\",\n filter: \"drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))\",\n }}\n >\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n borderRadius: \"50%\",\n border: \"3px solid rgba(255, 255, 255, 0.25)\",\n borderTopColor: \"#ff0000\",\n borderRightColor: \"rgba(255, 255, 255, 0.85)\",\n animation: \"sc-spin 0.8s linear infinite\",\n }}\n />\n <div\n style={{\n width: \"7px\",\n height: \"7px\",\n borderRadius: \"50%\",\n background: \"#ff0000\",\n boxShadow: \"0 0 10px rgba(255, 0, 0, 0.65)\",\n }}\n />\n </div>\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: \"rgba(220, 38, 38, 0.92)\",\n backdropFilter: \"blur(24px)\",\n color: \"white\",\n padding: \"28px 36px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n boxShadow: \"0 24px 64px rgba(0, 0, 0, 0.5)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\",\n }}\n >\n <div style={{ fontSize: \"18px\", fontWeight: \"700\", marginBottom: \"10px\", letterSpacing: \"-0.02em\" }}>\n License Key Required\n </div>\n <div style={{ fontSize: \"13px\", lineHeight: \"1.6\", color: \"rgba(255, 255, 255, 0.85)\" }}>\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 {adStatus.showAds && (\n <div\n style={{\n position: \"absolute\",\n top: `${12 * responsiveScale}px`,\n left: `${12 * responsiveScale}px`,\n zIndex: 50,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n pointerEvents: \"none\",\n animation: \"sc-fade-in 0.3s ease\",\n }}\n >\n <div\n style={{\n background: \"rgba(234, 179, 8, 0.95)\",\n color: \"#111\",\n padding: `${4 * responsiveScale}px ${12 * responsiveScale}px`,\n borderRadius: \"6px\",\n fontSize: `${11 * responsiveScale}px`,\n fontWeight: 700,\n letterSpacing: \"0.08em\",\n textTransform: \"uppercase\" as const,\n boxShadow: \"0 2px 12px rgba(234, 179, 8, 0.35)\",\n }}\n >\n {`Ad ${Math.max(1, adStatus.currentIndex)}`}\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: \"rgba(0, 0, 0, 0.55)\",\n backdropFilter: \"blur(8px)\",\n borderRadius: \"50%\",\n width: `${92 * responsiveScale}px`,\n height: `${92 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"background 0.2s ease, transform 0.2s ease\",\n animation: \"sc-fade-in 0.2s ease\",\n }}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLElement).style.background = \"rgba(0, 0, 0, 0.72)\";\n (e.currentTarget as HTMLElement).style.transform = \"translate(-50%, -50%) scale(1.06)\";\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLElement).style.background = \"rgba(0, 0, 0, 0.55)\";\n (e.currentTarget as HTMLElement).style.transform = \"translate(-50%, -50%) scale(1)\";\n }}\n title=\"Play\"\n >\n <FaPlay\n size={Math.max(24, 32 * responsiveScale)}\n color=\"white\"\n style={{ marginLeft: \"4px\" }}\n />\n </div>\n )}\n\n {shouldShowEnhancedControls && !showLicenseWarning ? (\n <div\n className=\"sc-controls-bar\"\n style={{\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background: \"linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.35) 60%, transparent 100%)\",\n padding: `${20 * responsiveScale}px ${12 * responsiveScale}px ${8 * responsiveScale}px`,\n zIndex: 10,\n opacity: controlsVisible || adStatus.showAds ? 1 : 0,\n transform: controlsVisible || adStatus.showAds ? \"translateY(0)\" : \"translateY(6px)\",\n pointerEvents: controlsVisible || adStatus.showAds ? \"auto\" : \"none\",\n }}\n >\n {/* Progress Bar */}\n <div\n className=\"sc-progress-track\"\n style={{\n width: \"100%\",\n height: \"3px\",\n background: \"rgba(255, 255, 255, 0.2)\",\n borderRadius: \"1.5px\",\n marginBottom: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n position: \"relative\",\n transition: \"height 0.1s ease\",\n }}\n onClick={handleTimelineSeek}\n onMouseEnter={(e) => { e.currentTarget.style.height = \"5px\"; }}\n onMouseLeave={(e) => { e.currentTarget.style.height = \"3px\"; }}\n >\n <div\n style={{\n position: \"absolute\",\n top: 0, left: 0, bottom: 0,\n background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n borderRadius: \"1.5px\",\n width: `${progressPercent}%`,\n transition: \"width 0.15s linear\",\n }}\n />\n <div\n className=\"sc-progress-thumb\"\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: `${progressPercent}%`,\n transform: \"translate(-50%, -50%) scale(0)\",\n width: \"13px\",\n height: \"13px\",\n background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 4px rgba(0, 0, 0, 0.3)\",\n transition: \"transform 0.1s ease, left 0.15s linear\",\n }}\n />\n </div>\n\n {/* Controls Row */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n {/* Left Group */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n {/* Play/Pause */}\n <button\n className=\"sc-ctrl-btn\"\n onClick={handlePlayPause}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n }}\n title={isPlaying ? \"Pause\" : \"Play\"}\n >\n {isPlaying ? (\n <FaPause size={Math.max(14, 18 * responsiveScale)} />\n ) : (\n <FaPlay size={Math.max(14, 18 * responsiveScale)} style={{ marginLeft: \"2px\" }} />\n )}\n </button>\n\n {/* Volume Group - YouTube Style */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n paddingRight: `${6 * responsiveScale}px`,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => {\n if (playerRef.current) playerRef.current.toggleMute();\n onVolumeToggle?.();\n resetControlsTimer();\n }}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n <VolumeIcon size={Math.max(14, 18 * responsiveScale)} />\n </button>\n <div\n style={{\n width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n overflow: \"hidden\",\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n display: \"flex\",\n alignItems: \"center\",\n paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n paddingRight: showVolumeSlider ? `${8 * responsiveScale}px` : \"0\",\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: `${56 * responsiveScale}px`,\n height: \"3px\",\n cursor: \"pointer\",\n borderRadius: \"1.5px\",\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const el = e.currentTarget;\n const move = (ev: MouseEvent) => {\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r.left) / r.width)));\n };\n const up = () => { document.removeEventListener(\"mousemove\", move); document.removeEventListener(\"mouseup\", up); };\n document.addEventListener(\"mousemove\", move);\n document.addEventListener(\"mouseup\", up);\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n }}\n onClick={(e) => {\n e.stopPropagation();\n const r = e.currentTarget.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n }}\n >\n <div style={{ position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" }} />\n <div\n style={{\n position: \"absolute\",\n top: 0, left: 0, bottom: 0,\n width: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"#fff\",\n borderRadius: \"1.5px\",\n transition: \"width 0.1s ease-out\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: `${(isMuted ? 0 : volume) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n width: \"12px\",\n height: \"12px\",\n background: \"#fff\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n transition: \"left 0.1s ease-out\",\n }}\n />\n </div>\n </div>\n </div>\n\n {/* Time Display */}\n <div\n style={{\n fontSize: `${13 * responsiveScale}px`,\n fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\",\n fontVariantNumeric: \"tabular-nums\",\n userSelect: \"none\",\n marginLeft: `${4 * responsiveScale}px`,\n }}\n >\n {formatTime(currentTime)}{\" \"}\n <span style={{ color: \"rgba(255,255,255,0.5)\" }}>/</span>{\" \"}\n {formatTime(duration)}\n </div>\n </div>\n\n {/* Right Group */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n {/* Speed Selector */}\n <div style={{ position: \"relative\", display: viewportWidth < 600 ? \"none\" : \"block\" }}>\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => { setShowSpeedMenu(!showSpeedMenu); resetControlsTimer(); }}\n style={{\n padding: `${6 * responsiveScale}px ${10 * responsiveScale}px`,\n borderRadius: `${6 * responsiveScale}px`,\n fontSize: `${13 * responsiveScale}px`,\n fontFamily: \"'SF Mono', 'Cascadia Code', monospace\",\n fontWeight: \"600\",\n minHeight: `${32 * responsiveScale}px`,\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: \"8px\",\n background: \"rgba(0, 0, 0, 0.8)\",\n backdropFilter: \"blur(24px)\",\n WebkitBackdropFilter: \"blur(24px)\",\n borderRadius: \"10px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"80px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5)\",\n animation: \"sc-fade-in 0.15s ease\",\n }}\n >\n {[0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map((speed) => (\n <button\n key={speed}\n onClick={() => handlePlaybackRateChange(speed)}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n background: playbackRate === speed\n ? \"rgba(255, 255, 255, 0.12)\"\n : \"transparent\",\n border: \"none\",\n color: playbackRate === speed ? \"#fff\" : \"rgba(255, 255, 255, 0.7)\",\n cursor: \"pointer\",\n fontSize: `${12 * responsiveScale}px`,\n fontFamily: \"'SF Mono', monospace\",\n fontWeight: playbackRate === speed ? \"700\" : \"500\",\n textAlign: \"center\",\n transition: \"background 0.15s ease, color 0.15s ease\",\n }}\n onMouseEnter={(e) => {\n if (playbackRate !== speed) {\n (e.target as HTMLElement).style.background = \"rgba(255, 255, 255, 0.08)\";\n (e.target as HTMLElement).style.color = \"#fff\";\n }\n }}\n onMouseLeave={(e) => {\n if (playbackRate !== speed) {\n (e.target as HTMLElement).style.background = \"transparent\";\n (e.target as HTMLElement).style.color = \"rgba(255, 255, 255, 0.7)\";\n }\n }}\n >\n {speed}x\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Fullscreen */}\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (wrapperRef.current) {\n if (!document.fullscreenElement) {\n wrapperRef.current.requestFullscreen().catch(() => {});\n } else {\n document.exitFullscreen().catch(() => {});\n }\n }\n resetControlsTimer();\n }}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n }}\n title={isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"}\n >\n {isFullscreen ? (\n <FaCompress size={Math.max(14, 18 * responsiveScale)} />\n ) : (\n <FaExpand size={Math.max(14, 18 * responsiveScale)} />\n )}\n </button>\n </div>\n </div>\n </div>\n ) : (\n showCustomControls && !showLicenseWarning && (\n <>\n <div\n style={{\n position: \"absolute\",\n top: `${10 * responsiveScale}px`,\n left: `${10 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n zIndex: 10,\n opacity: controlsVisible ? 1 : 0,\n transition: \"opacity 0.35s ease\",\n }}\n >\n <div\n style={{\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n background: \"#ff3b30\",\n animation: \"sc-pulse 1.5s ease-in-out infinite\",\n flexShrink: 0,\n }}\n />\n <span\n style={{\n fontSize: `${12 * responsiveScale}px`,\n fontFamily: \"'SF Pro Display', 'Segoe UI', Arial, sans-serif\",\n fontWeight: 700,\n letterSpacing: \"0.08em\",\n color: \"#fff\",\n textShadow: \"0 1px 3px rgba(0,0,0,0.6)\",\n userSelect: \"none\",\n }}\n >\n LIVE\n </span>\n </div>\n\n <div\n className=\"sc-controls-bar\"\n style={{\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n alignItems: isPortrait ? \"flex-end\" : \"center\",\n gap: `${8 * responsiveScale}px`,\n zIndex: 10,\n opacity: controlsVisible ? 1 : 0,\n transform: controlsVisible ? \"translateY(0)\" : \"translateY(4px)\",\n pointerEvents: controlsVisible ? \"auto\" : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n background: \"rgba(0, 0, 0, 0.6)\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: \"2px\",\n paddingRight: `${8 * responsiveScale}px`,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => {\n if (playerRef.current) playerRef.current.toggleMute();\n onVolumeToggle?.();\n resetControlsTimer();\n }}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n <VolumeIcon size={Math.max(14, 18 * responsiveScale)} />\n </button>\n <div\n style={{\n width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n overflow: \"hidden\",\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n display: \"flex\",\n alignItems: \"center\",\n paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n paddingRight: showVolumeSlider ? `${10 * responsiveScale}px` : \"0\",\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: `${56 * responsiveScale}px`,\n height: \"3px\",\n cursor: \"pointer\",\n borderRadius: \"1.5px\",\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const el = e.currentTarget;\n const move = (ev: MouseEvent) => {\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r.left) / r.width)));\n };\n const up = () => { document.removeEventListener(\"mousemove\", move); document.removeEventListener(\"mouseup\", up); };\n document.addEventListener(\"mousemove\", move);\n document.addEventListener(\"mouseup\", up);\n const r = el.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n }}\n onClick={(e) => {\n e.stopPropagation();\n const r = e.currentTarget.getBoundingClientRect();\n handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n }}\n >\n <div style={{ position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" }} />\n <div\n style={{\n position: \"absolute\",\n top: 0, left: 0, bottom: 0,\n width: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"#fff\",\n borderRadius: \"1.5px\",\n transition: \"width 0.1s ease-out\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: `${(isMuted ? 0 : volume) * 100}%`,\n transform: \"translate(-50%, -50%)\",\n width: \"12px\",\n height: \"12px\",\n background: \"#fff\",\n borderRadius: \"50%\",\n boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n transition: \"left 0.1s ease-out\",\n }}\n />\n </div>\n </div>\n </div>\n\n <button\n className=\"sc-ctrl-btn\"\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (wrapperRef.current) {\n if (!document.fullscreenElement) {\n wrapperRef.current.requestFullscreen().catch(() => {});\n } else {\n document.exitFullscreen().catch(() => {});\n }\n }\n resetControlsTimer();\n }}\n style={{\n padding: `${8 * responsiveScale}px`,\n borderRadius: \"50%\",\n minWidth: `${36 * responsiveScale}px`,\n minHeight: `${36 * responsiveScale}px`,\n background: \"rgba(0, 0, 0, 0.6)\",\n }}\n title={isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"}\n >\n {isFullscreen ? (\n <FaCompress size={Math.max(14, 18 * responsiveScale)} />\n ) : (\n <FaExpand size={Math.max(14, 18 * responsiveScale)} />\n )}\n </button>\n </div>\n </>\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 type { AdController } 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\ntype VastParseResult =\n | { type: \"inline\"; ad: VastAd }\n | {\n type: \"wrapper\";\n vastAdTagUri: string;\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n }\n | { type: \"empty\" };\n\nconst MAX_VAST_WRAPPER_DEPTH = 5;\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): AdController {\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 isHlsMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type === \"application/x-mpegurl\" ||\n type === \"application/vnd.apple.mpegurl\" ||\n type.includes(\"mpegurl\") ||\n url.includes(\".m3u8\")\n );\n }\n\n function isProgressiveMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type.startsWith(\"video/\") ||\n url.endsWith(\".mp4\") ||\n url.includes(\".mp4?\")\n );\n }\n\n function createEmptyTrackingUrls(): VastTrackingUrls {\n return {\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\n function extractTrackingUrls(xmlDoc: Document): VastTrackingUrls {\n const trackingUrls = createEmptyTrackingUrls();\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 xmlDoc.querySelectorAll(\"Error\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.error.push(url);\n });\n\n return trackingUrls;\n }\n\n function mergeTrackingUrls(\n target: VastTrackingUrls,\n source: VastTrackingUrls\n ): VastTrackingUrls {\n (Object.keys(target) as Array<keyof VastTrackingUrls>).forEach((key) => {\n if (source[key] && source[key].length > 0) {\n target[key] = target[key].concat(source[key]);\n }\n });\n return target;\n }\n\n function parseVastXml(xmlString: string): VastParseResult {\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 { type: \"empty\" };\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return { type: \"empty\" };\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n const wrapperUri = xmlDoc\n .querySelector(\"VASTAdTagURI\")\n ?.textContent?.trim();\n if (wrapperUri) {\n console.log(\n `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n );\n return {\n type: \"wrapper\",\n vastAdTagUri: wrapperUri,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough,\n };\n }\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 const mediaFile: VastMediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: undefined,\n };\n\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n mediaFile.bitrate =\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined;\n\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\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 supported media files found in VAST XML\");\n }\n return { type: \"empty\" };\n }\n\n return {\n type: \"inline\",\n ad: {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough,\n },\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return { type: \"empty\" };\n }\n }\n\n async function fetchVastXml(vastTagUrl: string): Promise<string> {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\",\n },\n referrerPolicy: \"no-referrer-when-downgrade\",\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n return response.text();\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string,\n depth = 0,\n accumulatedTracking: VastTrackingUrls = createEmptyTrackingUrls()\n ): Promise<VastAd | null> {\n const vastXml = await fetchVastXml(vastTagUrl);\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 const parsed = parseVastXml(vastXml);\n\n if (parsed.type === \"empty\") {\n return null;\n }\n\n if (parsed.type === \"wrapper\") {\n if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n console.warn(\n `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n );\n return null;\n }\n\n mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n return fetchAndParseVastAd(\n parsed.vastAdTagUri,\n depth + 1,\n accumulatedTracking\n );\n }\n\n mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n return parsed.ad;\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 if (!adPlaying) return;\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 contentVideo.muted = true;\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 console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {});\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\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 = \"30\";\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.reject(new Error(\"No ads available from VAST response\"));\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 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 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 adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n adVideoElement.volume = Math.max(0, Math.min(1, originalVolume));\n adVideoElement.muted = originalMutedState;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n\n if (isHlsAd && 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 (isHlsAd && (\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 if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\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 pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {});\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}, volume: ${contentVideo.volume}`\n );\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {});\n }\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 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 = Math.max(0, Math.min(1, 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 const clamped = Math.max(0, Math.min(1, volume));\n adVideoElement.volume = clamped;\n adVideoElement.muted = clamped === 0;\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 getLoadedAdDuration() {\n return currentAd?.duration;\n },\n getLoadedAdId() {\n return currentAd?.id;\n },\n };\n}\n","declare global {\n interface Window {\n goog?: any;\n }\n}\n\nconst PAL_SDK_URL =\n \"https://imasdk.googleapis.com/pal/sdkloader/pal.js\";\n\nlet _nonceLoader: any | undefined;\nlet _palLoadPromise: Promise<void> | undefined;\n\nfunction loadPalSdk(): Promise<void> {\n if (typeof window !== \"undefined\" && window.goog?.pal) {\n return Promise.resolve();\n }\n\n if (_palLoadPromise) return _palLoadPromise;\n\n _palLoadPromise = new Promise<void>((resolve, reject) => {\n const existing = document.querySelector(\n 'script[data-pal=\"true\"]'\n ) as HTMLScriptElement | null;\n\n if (existing) {\n if (window.goog?.pal) {\n resolve();\n return;\n }\n const timeout = setTimeout(\n () => reject(new Error(\"PAL SDK load timeout\")),\n 10000\n );\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"PAL SDK load failed\"));\n });\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = PAL_SDK_URL;\n script.async = true;\n script.setAttribute(\"data-pal\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"PAL SDK load failed\"));\n document.head.appendChild(script);\n });\n\n return _palLoadPromise;\n}\n\nfunction getOrCreateNonceLoader(): any {\n if (_nonceLoader) return _nonceLoader;\n const goog = window.goog;\n const consentSettings = new goog.pal.ConsentSettings();\n consentSettings.allowStorage = true;\n _nonceLoader = new goog.pal.NonceLoader(consentSettings);\n return _nonceLoader;\n}\n\nexport interface PalNonceOptions {\n videoWidth?: number;\n videoHeight?: number;\n descriptionUrl?: string;\n ppid?: string;\n sessionId?: string;\n adWillAutoPlay?: boolean;\n adWillPlayMuted?: boolean;\n playerVolume?: number;\n continuousPlayback?: boolean;\n}\n\nexport interface PalNonceManager {\n generateNonce(options?: PalNonceOptions): Promise<string>;\n\n getCurrentNonce(): string;\n\n injectNonce(vastTagUrl: string): string;\n\n sendPlaybackStart(): void;\n\n sendPlaybackEnd(): void;\n\n sendAdClick(): void;\n\n sendAdTouch(event: MouseEvent | TouchEvent): void;\n\n reset(): void;\n}\n\nexport function createPalNonceManager(): PalNonceManager {\n let currentNonce = \"\";\n let currentNonceManager: any | undefined;\n\n return {\n async generateNonce(options: PalNonceOptions = {}): Promise<string> {\n try {\n await loadPalSdk();\n\n const loader = getOrCreateNonceLoader();\n const goog = window.goog;\n\n const request = new goog.pal.NonceRequest();\n request.adWillAutoPlay = options.adWillAutoPlay ?? true;\n request.adWillPlayMuted = options.adWillPlayMuted ?? false;\n request.playerVolume =\n options.playerVolume ?? (request.adWillPlayMuted ? 0 : 1);\n request.continuousPlayback = options.continuousPlayback ?? true;\n request.descriptionUrl =\n options.descriptionUrl ||\n (typeof window !== \"undefined\" ? window.location.href : \"\");\n request.iconsSupported = true;\n request.playerType = \"StormcloudVideoPlayer\";\n request.playerVersion = \"1.0\";\n request.supportedApiFrameworks = \"2,7,9\";\n request.url =\n options.descriptionUrl ||\n (typeof window !== \"undefined\" ? window.location.href : \"\");\n request.videoWidth = options.videoWidth || 640;\n request.videoHeight = options.videoHeight || 480;\n\n if (options.ppid) request.ppid = options.ppid;\n if (options.sessionId) request.sessionId = options.sessionId;\n\n const manager = await loader.loadNonceManager(request);\n currentNonceManager = manager;\n currentNonce = manager.getNonce() as string;\n\n console.log(\"[PAL] Nonce generated successfully\");\n return currentNonce;\n } catch (error) {\n console.warn(\"[PAL] Failed to generate nonce:\", error);\n currentNonce = \"\";\n currentNonceManager = undefined;\n return \"\";\n }\n },\n\n getCurrentNonce(): string {\n return currentNonce;\n },\n\n injectNonce(vastTagUrl: string): string {\n if (!currentNonce || !vastTagUrl) return vastTagUrl;\n\n try {\n const url = new URL(vastTagUrl);\n url.searchParams.delete(\"paln\");\n url.searchParams.set(\"givn\", currentNonce);\n return url.toString();\n } catch {\n let base = vastTagUrl\n .replace(/([?&])paln=[^&]*/g, \"\")\n .replace(/[?&]$/, \"\");\n const sep = base.includes(\"?\") ? \"&\" : \"?\";\n return `${base}${sep}givn=${encodeURIComponent(currentNonce)}`;\n }\n },\n\n sendPlaybackStart(): void {\n try {\n currentNonceManager?.sendPlaybackStart();\n } catch {}\n },\n\n sendPlaybackEnd(): void {\n try {\n currentNonceManager?.sendPlaybackEnd();\n } catch {}\n },\n\n sendAdClick(): void {\n try {\n currentNonceManager?.sendAdClick();\n } catch {}\n },\n\n sendAdTouch(event: MouseEvent | TouchEvent): void {\n try {\n currentNonceManager?.sendAdTouch(event);\n } catch {}\n },\n\n reset(): void {\n currentNonce = \"\";\n currentNonceManager = undefined;\n },\n };\n}\n","export const MQTT_CA_CERT_FILE = \"src/certs/emqxsl-ca.crt\";\n\nexport type MQTTConfig = {\n enabled: boolean;\n brokerAddress: string;\n brokerPort: number;\n wsPort: number;\n username: string;\n password: string;\n topicPrefix: string;\n qos: 0 | 1 | 2;\n brokerUrl?: string;\n};\n\nexport const DEFAULT_MQTT_CONFIG: MQTTConfig = {\n enabled: true,\n brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n brokerPort: 8883,\n wsPort: 8084,\n username: \"for-sonifi\",\n password: \"sonifi-mqtt\",\n topicPrefix: \"adstorm/players\",\n qos: 1,\n};\n\nexport const mqttConfig: MQTTConfig = { ...DEFAULT_MQTT_CONFIG };\n\nexport function applyMQTTConfig(overrides: Partial<MQTTConfig>): void {\n Object.assign(mqttConfig, overrides);\n}\n\nexport function isMQTTEnabled(): boolean {\n return mqttConfig.enabled;\n}\n\nexport function buildMQTTBrokerUrl(): string {\n if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\n\nexport function buildPlayerTopic(\n licenseKey: string,\n channel: \"metrics\" | \"impressions\" | \"heartbeat\"\n): string {\n return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n","import mqtt from \"mqtt\";\nimport type { MqttClient } from \"mqtt\";\nimport {\n applyMQTTConfig,\n buildMQTTBrokerUrl,\n isMQTTEnabled,\n mqttConfig,\n} from \"./mqttConfig\";\nimport type { MQTTConfig } from \"./mqttConfig\";\n\nconst LOG = \"[StormcloudVideoPlayer][MQTT]\";\n\nexport type MQTTStatus = \"disconnected\" | \"connecting\" | \"connected\" | \"error\";\n\nlet client: MqttClient | null = null;\nlet status: MQTTStatus = \"disconnected\";\n\nexport function getMQTTStatus(): MQTTStatus {\n return status;\n}\n\nexport function isMQTTConnected(): boolean {\n return status === \"connected\" && client !== null && client.connected;\n}\n\nexport function isMQTTConfigured(): boolean {\n return isMQTTEnabled();\n}\n\nexport function configureMQTT(overrides: Partial<MQTTConfig>): void {\n applyMQTTConfig(overrides);\n disconnectMQTT();\n}\n\nexport function initMQTTClient(): void {\n if (client || !isMQTTEnabled()) return;\n\n const url = buildMQTTBrokerUrl();\n status = \"connecting\";\n\n const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n\n try {\n client = mqtt.connect(url, {\n clientId,\n username: mqttConfig.username,\n password: mqttConfig.password,\n keepalive: 60,\n clean: true,\n reconnectPeriod: 5000,\n connectTimeout: 10_000,\n queueQoSZero: false,\n });\n } catch (err) {\n status = \"error\";\n console.warn(`${LOG} connect() threw:`, err);\n return;\n }\n\n client.on(\"connect\", () => {\n status = \"connected\";\n console.info(`${LOG} connected to ${url}`);\n });\n\n client.on(\"reconnect\", () => {\n status = \"connecting\";\n console.info(`${LOG} reconnecting…`);\n });\n\n client.on(\"offline\", () => {\n status = \"disconnected\";\n console.warn(`${LOG} offline`);\n });\n\n client.on(\"error\", (err) => {\n status = \"error\";\n console.warn(`${LOG} error:`, err.message);\n });\n\n client.on(\"close\", () => {\n if (status === \"connected\") {\n status = \"disconnected\";\n }\n });\n}\n\nexport function ensureMQTTClient(): void {\n if (isMQTTEnabled() && !client) {\n initMQTTClient();\n }\n}\n\nexport function publishMQTT(\n topic: string,\n payload: Record<string, unknown>\n): boolean {\n if (!isMQTTEnabled()) {\n return false;\n }\n\n ensureMQTTClient();\n\n if (!client) {\n return false;\n }\n\n try {\n client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n return true;\n } catch (err) {\n console.warn(`${LOG} publish failed on ${topic}:`, err);\n return false;\n }\n}\n\nexport function disconnectMQTT(): void {\n if (client) {\n client.end(true);\n client = null;\n status = \"disconnected\";\n }\n}\n","import type {\n ClientInfo,\n AdDetectInfo,\n AdLoadedInfo,\n AdImpressionInfo,\n PlayerAnalyticsContext,\n} from \"../types\";\nimport { buildPlayerTopic, isMQTTEnabled } from \"./mqttConfig\";\nimport { ensureMQTTClient, publishMQTT } from \"./mqttClient\";\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?.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 hashHex = Array.from(new Uint8Array(hashBuffer))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle 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\ntype PlayerMetricFlags = {\n adLoaded?: boolean;\n adDetect?: boolean;\n captureAt?: string;\n};\n\nfunction canPublish(licenseKey: string | undefined): licenseKey is string {\n return Boolean(isMQTTEnabled() && licenseKey);\n}\n\nasync function buildPlayerMetricEvent(\n context: PlayerAnalyticsContext = {},\n flags: PlayerMetricFlags = {}\n): Promise<Record<string, unknown>> {\n const clientInfo = getClientInfo();\n const playerId = await getBrowserID(clientInfo);\n const captureAt = flags.captureAt ?? new Date().toISOString();\n\n return {\n player_id: playerId,\n device_type: clientInfo.deviceType,\n os: clientInfo.os.toLowerCase(),\n ad_loaded: flags.adLoaded ?? false,\n ad_detect: flags.adDetect ?? false,\n capture_at: captureAt,\n ...(context.inputStreamType\n ? { input_stream_type: context.inputStreamType }\n : {}),\n };\n}\n\nfunction publishTracking(\n licenseKey: string,\n channel: \"metrics\" | \"impressions\" | \"heartbeat\",\n body: Record<string, unknown>\n): void {\n ensureMQTTClient();\n publishMQTT(buildPlayerTopic(licenseKey, channel), body);\n}\n\nexport async function sendInitialTracking(\n licenseKey?: string,\n context: PlayerAnalyticsContext = {}\n): Promise<void> {\n if (!canPublish(licenseKey)) return;\n\n try {\n const metricEvent = await buildPlayerMetricEvent(context, {\n adLoaded: false,\n adDetect: false,\n });\n\n publishTracking(licenseKey, \"metrics\", {\n events: [metricEvent],\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\n\nexport async function sendAdDetectTracking(\n licenseKey: string | undefined,\n adDetectInfo: AdDetectInfo,\n context: PlayerAnalyticsContext = {}\n): Promise<void> {\n try {\n await sendHeartbeat(licenseKey, context, {\n adDetect: true,\n captureAt: adDetectInfo.timestamp,\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n error\n );\n }\n}\n\nexport async function sendAdLoadedTracking(\n licenseKey: string | undefined,\n adLoadedInfo: AdLoadedInfo,\n context: PlayerAnalyticsContext = {}\n): Promise<void> {\n try {\n await sendHeartbeat(licenseKey, context, {\n adLoaded: true,\n captureAt: adLoadedInfo.timestamp,\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n error\n );\n }\n}\n\nexport async function sendAdImpressionTracking(\n licenseKey: string | undefined,\n adImpressionInfo: AdImpressionInfo,\n context: PlayerAnalyticsContext = {}\n): Promise<void> {\n if (!canPublish(licenseKey)) return;\n\n try {\n const metricEvent = await buildPlayerMetricEvent(context, {\n captureAt: adImpressionInfo.timestamp,\n });\n\n publishTracking(licenseKey, \"heartbeat\", metricEvent);\n publishTracking(licenseKey, \"impressions\", {\n events: [\n {\n player_id: metricEvent.player_id,\n ad_played_count: 1,\n ad_url: adImpressionInfo.adUrl,\n capture_at: adImpressionInfo.timestamp,\n },\n ],\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\n\nexport async function sendHeartbeat(\n licenseKey?: string,\n context: PlayerAnalyticsContext = {},\n flags: PlayerMetricFlags = {}\n): Promise<void> {\n if (!canPublish(licenseKey)) return;\n\n try {\n const heartbeatData = await buildPlayerMetricEvent(context, flags);\n publishTracking(licenseKey, \"heartbeat\", heartbeatData);\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","export interface VastEnvironmentSignals {\n isCtv: boolean;\n contentUrl?: string;\n appId?: string;\n appName?: string;\n sessionId?: string;\n deviceId?: string;\n deviceIdType?: string;\n limitAdTracking?: boolean;\n deviceTypeHint?: number;\n}\n\nconst AIRY_ANDROID_APP_ID = \"com.freeairytv.android\";\nconst AIRY_WEBOS_APP_ID = \"com.freeairytv.webos\";\nconst AIRY_TIZEN_APP_ID = \"com.freeairytv.samsung\";\nconst AIRY_ROKU_APP_ID = \"com.freeairytv.roku\";\nconst AIRY_APP_NAME = \"AiryTV Movies & TV\";\nconst AIRY_DEFAULT_CONTENT_URL = \"https://live.airy.tv\";\nconst CTV_SESSION_STORAGE_KEY = \"stormcloud.ctv.sid\";\n\nconst LG_TEST_APP_ID = \"com.hulu.plus\";\nconst LG_TEST_APP_NAME = \"Hulu\";\nconst LG_TEST_CONTENT_URL = \"https://www.hulu.com/live-tv\";\n\nlet _lgTestDeviceId: string | undefined;\nfunction getLgTestDeviceId(): string {\n if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();\n return _lgTestDeviceId;\n}\n\nfunction isLgWebOS(): boolean {\n if (typeof navigator === \"undefined\") return false;\n return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);\n}\n\nfunction getDefaultAppId(): string {\n if (typeof navigator === \"undefined\") return AIRY_ANDROID_APP_ID;\n const ua = navigator.userAgent;\n if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;\n if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;\n if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;\n return AIRY_ANDROID_APP_ID;\n}\n\nconst DEVICE_ID_STORAGE_KEYS = [\n \"rdid\",\n \"ifa\",\n \"advertisingId\",\n \"advertising_id\",\n \"deviceAdvertisingId\",\n \"aaid\",\n \"adid\",\n \"rida\",\n \"tifa\",\n \"lgudid\",\n];\n\nconst ANDROID_ID_TYPES = new Set([\"aaid\", \"adid\"]);\n\nexport function resolveVastEnvironmentSignals(isCtv: boolean): VastEnvironmentSignals {\n const bridgeSignals = readNativeBridgeSignals();\n const lg = isCtv && isLgWebOS();\n\n const deviceId =\n bridgeSignals.deviceId ||\n readStoredDeviceId() ||\n (lg ? getLgTestDeviceId() : undefined);\n const deviceIdType =\n bridgeSignals.deviceIdType ||\n readStoredString(\"deviceIdType\") ||\n readStoredString(\"idtype\") ||\n inferDeviceIdType() ||\n (lg ? \"lgudid\" : undefined);\n const limitAdTracking =\n deviceId != null\n ? bridgeSignals.limitAdTracking ?? readStoredLimitAdTracking() ?? false\n : undefined;\n\n if (isCtv) {\n return {\n isCtv: true,\n contentUrl:\n bridgeSignals.contentUrl ||\n readStoredString(\"contentUrl\") ||\n (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),\n appId:\n bridgeSignals.appId ||\n readStoredString(\"appId\") ||\n readStoredString(\"msid\") ||\n (lg ? LG_TEST_APP_ID : getDefaultAppId()),\n appName:\n bridgeSignals.appName ||\n readStoredString(\"appName\") ||\n readStoredString(\"an\") ||\n (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),\n sessionId: getOrCreateCtvSessionId(),\n ...(deviceId ? { deviceId } : {}),\n ...(deviceIdType ? { deviceIdType } : {}),\n ...(limitAdTracking != null ? { limitAdTracking } : {}),\n deviceTypeHint: 5,\n };\n }\n\n return {\n isCtv: false,\n ...(deviceId ? { deviceId } : {}),\n ...(deviceIdType ? { deviceIdType } : {}),\n ...(limitAdTracking != null ? { limitAdTracking } : {}),\n };\n}\n\nexport function inferDeviceIdType(): string | undefined {\n if (typeof navigator === \"undefined\") {\n return undefined;\n }\n\n const ua = navigator.userAgent;\n if (/Roku/i.test(ua)) return \"rida\";\n if (/Tizen|Samsung/i.test(ua)) return \"tifa\";\n if (/AppleTV|Apple TV/i.test(ua)) return \"tvOS\";\n if (/AFT|Fire TV|Amazon/i.test(ua)) return \"afai\";\n if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return \"lgudid\";\n if (/Android|Google TV/i.test(ua)) return \"aaid\";\n if (/iPhone|iPad|iPod/i.test(ua)) return \"idfa\";\n return undefined;\n}\n\nexport function isEquivalentDeviceIdType(\n tagType: string | undefined,\n runtimeType: string | undefined\n): boolean {\n if (!tagType || !runtimeType) return false;\n const tag = tagType.toLowerCase();\n const runtime = runtimeType.toLowerCase();\n if (tag === runtime) return true;\n return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);\n}\n\nfunction getOrCreateCtvSessionId(): string {\n const existing = readStoredString(CTV_SESSION_STORAGE_KEY);\n if (existing) {\n return existing;\n }\n\n const sessionId = createUuid();\n try {\n window.localStorage?.setItem(CTV_SESSION_STORAGE_KEY, sessionId);\n } catch {}\n return sessionId;\n}\n\nfunction createUuid(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n const value = Math.floor(Math.random() * 16);\n const nibble = char === \"x\" ? value : (value & 0x3) | 0x8;\n return nibble.toString(16);\n });\n}\n\nfunction readNativeBridgeSignals(): {\n contentUrl?: string;\n appId?: string;\n appName?: string;\n deviceId?: string;\n deviceIdType?: string;\n limitAdTracking?: boolean;\n} {\n if (typeof window === \"undefined\") {\n return {};\n }\n\n const candidates = [\n (window as any).__STORMCLOUD_CTV_AD_INFO__,\n (window as any).__STORMCLOUD_CTV__,\n (window as any).stormcloudCtv,\n (window as any).AiryTV,\n (window as any).Android,\n (window as any).webOS,\n (window as any).tizen,\n (window as any).amazon,\n ].filter(Boolean);\n\n for (const source of candidates) {\n const contentUrl =\n readBridgeValue(source, [\"contentUrl\", \"url\", \"videoUrl\", \"canonicalUrl\"]) ||\n undefined;\n const appId =\n readBridgeValue(source, [\"appId\", \"msid\", \"applicationId\", \"packageName\"]) ||\n undefined;\n const appName =\n readBridgeValue(source, [\"appName\", \"an\", \"applicationName\"]) || undefined;\n const deviceId =\n readBridgeValue(source, [\n \"rdid\",\n \"ifa\",\n \"advertisingId\",\n \"adId\",\n \"deviceId\",\n \"lgudid\",\n \"LGUDID\",\n \"tifa\",\n \"rida\",\n \"afai\",\n \"aaid\",\n ]) || undefined;\n\n if (!contentUrl && !deviceId && !appId && !appName) continue;\n\n const deviceIdType =\n readBridgeValue(source, [\n \"idtype\",\n \"deviceIdType\",\n \"advertisingIdType\",\n \"idType\",\n ]) || inferDeviceIdType();\n const limitAdTracking = readBridgeBoolean(source, [\n \"is_lat\",\n \"limitAdTracking\",\n \"limitedAdTracking\",\n \"lat\",\n ]);\n\n return {\n ...(contentUrl ? { contentUrl } : {}),\n ...(appId ? { appId } : {}),\n ...(appName ? { appName } : {}),\n ...(deviceId ? { deviceId } : {}),\n ...(deviceId && deviceIdType ? { deviceIdType } : {}),\n ...(deviceId && limitAdTracking != null ? { limitAdTracking } : {}),\n };\n }\n\n return {};\n}\n\nfunction readBridgeValue(source: any, keys: string[]): string | undefined {\n for (const key of keys) {\n const value = source?.[key];\n if (typeof value === \"string\" && value) {\n return value;\n }\n if (typeof value === \"function\") {\n try {\n const result = value.call(source);\n if (typeof result === \"string\" && result) {\n return result;\n }\n } catch {}\n }\n }\n return undefined;\n}\n\nfunction readBridgeBoolean(source: any, keys: string[]): boolean | undefined {\n for (const key of keys) {\n const value = source?.[key];\n const normalized = normalizeBoolean(value);\n if (normalized != null) {\n return normalized;\n }\n if (typeof value === \"function\") {\n try {\n const result = normalizeBoolean(value.call(source));\n if (result != null) {\n return result;\n }\n } catch {}\n }\n }\n return undefined;\n}\n\nfunction readStoredDeviceId(): string | undefined {\n for (const key of DEVICE_ID_STORAGE_KEYS) {\n const value = readStoredString(key);\n if (value) {\n return value;\n }\n }\n return undefined;\n}\n\nfunction readStoredString(key: string): string | undefined {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n\n try {\n const value = window.localStorage?.getItem(key);\n return value || undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction readStoredLimitAdTracking(): boolean | undefined {\n return normalizeBoolean(\n readStoredString(\"limitAdTracking\") ||\n readStoredString(\"limitedAdTracking\") ||\n readStoredString(\"is_lat\")\n );\n}\n\nfunction normalizeBoolean(value: unknown): boolean | undefined {\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"number\") {\n return value === 1;\n }\n if (typeof value === \"string\") {\n const normalized = value.toLowerCase();\n if (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\") {\n return true;\n }\n if (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n return false;\n }\n }\n return undefined;\n}\n","import {\n inferDeviceIdType,\n isEquivalentDeviceIdType,\n} from \"./vastEnvironmentSignals\";\n\nexport interface VastConsentSignals {\n gdpr?: string | undefined;\n gdprConsent?: string | undefined;\n usPrivacy?: string | undefined;\n}\n\nexport interface VastMacroContext {\n correlator: string;\n streamCorrelator: string;\n pod?: number | undefined;\n adPosition?: number | undefined;\n isCtv?: boolean | undefined;\n contentUrl?: string | undefined;\n pageUrl?: string | undefined;\n adWillPlayMuted?: boolean | undefined;\n adWillAutoPlay?: boolean | undefined;\n appId?: string | undefined;\n appName?: string | undefined;\n sessionId?: string | undefined;\n deviceId?: string | undefined;\n deviceIdType?: string | undefined;\n limitAdTracking?: boolean | undefined;\n deviceTypeHint?: number | undefined;\n adTest?: boolean | undefined;\n consent?: VastConsentSignals | undefined;\n}\n\nconst UNEXPANDED_MACRO_PATTERN = /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/;\nconst INVALID_VAST_PARAM_KEY = /^\\s|\\s$/;\nconst EXAMPLE_COM_URL = /example\\.com/i;\nconst CTV_UNSUPPORTED_PARAMS = [\n \"description_url\",\n \"tfcd\",\n \"npa\",\n \"min_ad_duration\",\n \"max_ad_duration\",\n \"unviewed_position_start\",\n \"impl\",\n \"vad_type\",\n \"gdpr\",\n \"gdpr_consent\",\n \"us_privacy\",\n];\n\nconst INLINE_DEVICE_MACRO_REPLACEMENTS: Array<{\n pattern: RegExp;\n getValue: (ctx: VastMacroContext) => string | undefined;\n}> = [\n { pattern: /\\[RDID\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[IFA\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[ADVERTISING[_-]?ID(?:ENTIFIER)?\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[DEVICE[_-]?ID\\]/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\[IDTYPE\\]/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /\\{rdid\\}/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\{device[_-]?id\\}/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /\\{idtype\\}/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi, getValue: (ctx) =>\n ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined },\n { pattern: /%%ADVERTISING_ID_TYPE%%/gi, getValue: (ctx) => ctx.deviceIdType },\n { pattern: /%%ADVERTISING_ID%%/gi, getValue: (ctx) => ctx.deviceId },\n { pattern: /%%LIMIT_AD_TRACKING%%/gi, getValue: (ctx) =>\n ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined },\n { pattern: /%%MSID%%/gi, getValue: (ctx) => ctx.appId },\n { pattern: /%%APP_NAME%%/gi, getValue: (ctx) => ctx.appName },\n { pattern: /%%SESSION_ID%%/gi, getValue: (ctx) => ctx.sessionId },\n { pattern: /%%CORRELATOR%%/gi, getValue: (ctx) => ctx.correlator },\n];\n\nexport function isMacroPlaceholder(value: string | null | undefined): boolean {\n if (value == null) return true;\n const trimmed = value.trim();\n if (!trimmed) return true;\n if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;\n return /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(trimmed);\n}\n\nexport function generateCorrelator(): string {\n if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n try {\n const buf = new Uint32Array(2);\n crypto.getRandomValues(buf);\n const value = (buf[0] ?? 0) * 0x200000 + ((buf[1] ?? 0) & 0x1fffff);\n if (value > 0) {\n return String(value);\n }\n } catch {\n }\n }\n return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);\n}\n\nfunction expandInlineMacroPlaceholders(baseUrl: string, ctx: VastMacroContext): string {\n let url = baseUrl;\n for (const { pattern, getValue } of INLINE_DEVICE_MACRO_REPLACEMENTS) {\n const value = getValue(ctx);\n if (value != null && value !== \"\") {\n url = url.replace(pattern, encodeURIComponent(value));\n }\n }\n return url;\n}\n\nfunction applyDeviceIdentityParams(\n params: URLSearchParams,\n ctx: VastMacroContext\n): void {\n const runtimeId = ctx.deviceId?.trim();\n const runtimeType = ctx.deviceIdType?.trim() || inferDeviceIdType();\n const tagRdid = params.get(\"rdid\");\n const tagType = params.get(\"idtype\");\n const tagLat = params.get(\"is_lat\");\n const latValue =\n ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined;\n\n if (runtimeId) {\n params.set(\"rdid\", runtimeId);\n params.set(\"idtype\", runtimeType || tagType || \"aaid\");\n params.set(\"is_lat\", latValue ?? (isMacroPlaceholder(tagLat) ? \"0\" : tagLat!));\n return;\n }\n\n const tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));\n const tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));\n\n if (\n tagRdidValid &&\n tagTypeValid &&\n runtimeType &&\n !isEquivalentDeviceIdType(tagType!, runtimeType)\n ) {\n params.delete(\"rdid\");\n params.delete(\"idtype\");\n params.delete(\"is_lat\");\n return;\n }\n\n if (tagRdidValid) {\n if (isMacroPlaceholder(tagType) && runtimeType) {\n params.set(\"idtype\", runtimeType);\n }\n if (isMacroPlaceholder(tagLat)) {\n params.set(\"is_lat\", latValue ?? \"0\");\n }\n return;\n }\n\n params.delete(\"rdid\");\n params.delete(\"idtype\");\n params.delete(\"is_lat\");\n}\n\nfunction removeBrokenAppNameOrphans(\n params: URLSearchParams,\n appName?: string\n): void {\n const toDelete: string[] = [];\n\n params.forEach((_value, key) => {\n if (!key || INVALID_VAST_PARAM_KEY.test(key)) {\n toDelete.push(key);\n }\n });\n\n if (appName && appName.includes(\"&\")) {\n for (const suffix of appName.split(\"&\").slice(1)) {\n const trimmed = suffix.trimStart();\n if (!trimmed) continue;\n toDelete.push(suffix, ` ${trimmed}`, trimmed);\n }\n }\n\n for (const key of new Set(toDelete)) {\n if (key) params.delete(key);\n }\n}\n\nexport function normalizeVastTagUrl(raw: string): string {\n if (!raw) return raw;\n\n try {\n const url = new URL(raw);\n\n const anValue = url.searchParams.get(\"an\");\n if (anValue !== null) {\n const orphanFragments: string[] = [];\n url.searchParams.forEach((_value, key) => {\n if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n orphanFragments.push(key.trim());\n }\n });\n if (orphanFragments.length > 0) {\n const reconstructed = [anValue.trimEnd(), ...orphanFragments]\n .filter(Boolean)\n .join(\" & \");\n\n url.searchParams.forEach((_value, key) => {\n if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n url.searchParams.delete(key);\n }\n });\n url.searchParams.set(\"an\", reconstructed);\n\n return url.toString().replace(\n /([?&]an=)([^&]*)/,\n (_match, prefix, val) => prefix + val.replace(/\\+/g, \"%20\")\n );\n }\n }\n\n removeBrokenAppNameOrphans(url.searchParams);\n return url.toString();\n } catch {\n return raw;\n }\n}\n\nexport function applyVastMacros(\n baseUrl: string,\n ctx: VastMacroContext\n): string {\n const expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);\n let url: URL;\n try {\n url = new URL(normalizeVastTagUrl(expandedUrl));\n } catch {\n return replaceCorrelatorFallback(expandedUrl, ctx.correlator);\n }\n\n const params = url.searchParams;\n\n removeBrokenAppNameOrphans(params, ctx.appName);\n\n params.set(\"correlator\", ctx.correlator);\n params.set(\"scor\", ctx.streamCorrelator);\n if (ctx.isCtv) {\n for (const key of CTV_UNSUPPORTED_PARAMS) {\n params.delete(key);\n }\n }\n\n if (ctx.pod != null) {\n params.set(\"pod\", String(ctx.pod));\n }\n if (ctx.adPosition != null) {\n params.set(\"ppos\", String(ctx.adPosition));\n }\n\n const requestUrl = ctx.contentUrl || ctx.pageUrl;\n if (requestUrl) {\n params.set(\"url\", requestUrl);\n if (!ctx.isCtv) {\n params.set(\"description_url\", requestUrl);\n }\n } else {\n const existingUrl = params.get(\"url\") || \"\";\n if (EXAMPLE_COM_URL.test(existingUrl)) {\n params.delete(\"url\");\n params.delete(\"description_url\");\n }\n }\n\n if (ctx.adWillPlayMuted != null) {\n params.set(\"vpmute\", ctx.adWillPlayMuted ? \"1\" : \"0\");\n }\n if (ctx.adWillAutoPlay != null) {\n params.set(\"vpa\", ctx.adWillAutoPlay ? \"auto\" : \"click\");\n }\n\n if (ctx.appId) {\n params.set(\"msid\", ctx.appId);\n }\n if (ctx.appName) {\n removeBrokenAppNameOrphans(params, ctx.appName);\n params.set(\"an\", ctx.appName);\n }\n if (ctx.sessionId) {\n params.set(\"sid\", ctx.sessionId);\n }\n if (ctx.deviceTypeHint != null) {\n params.set(\"dth\", String(ctx.deviceTypeHint));\n } else if (ctx.isCtv) {\n params.set(\"dth\", \"5\");\n }\n\n applyDeviceIdentityParams(params, ctx);\n\n if (!ctx.isCtv) {\n const consent = ctx.consent;\n if (consent?.gdpr != null) {\n params.set(\"gdpr\", consent.gdpr);\n }\n if (consent?.gdprConsent != null) {\n params.set(\"gdpr_consent\", consent.gdprConsent);\n }\n if (consent?.usPrivacy != null) {\n params.set(\"us_privacy\", consent.usPrivacy);\n }\n }\n\n if (ctx.adTest) {\n params.set(\"adtest\", \"on\");\n }\n\n const staleKeys: string[] = [];\n params.forEach((value, key) => {\n if (isMacroPlaceholder(value)) {\n staleKeys.push(key);\n }\n });\n for (const key of staleKeys) {\n params.delete(key);\n }\n\n removeBrokenAppNameOrphans(params, ctx.appName);\n\n return url.toString();\n}\n\nfunction replaceCorrelatorFallback(baseUrl: string, correlator: string): string {\n const correlatorRegex = /([?&])correlator=([^&]*)/;\n if (correlatorRegex.test(baseUrl)) {\n return baseUrl.replace(correlatorRegex, `$1correlator=${correlator}`);\n }\n const sep = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${sep}correlator=${correlator}`;\n}\n\nexport function fetchConsentSignals(\n timeoutMs: number = 1500\n): Promise<VastConsentSignals> {\n const signals: VastConsentSignals = {};\n if (typeof window === \"undefined\") {\n return Promise.resolve(signals);\n }\n\n const tasks: Promise<void>[] = [];\n\n const tcfApi = (window as any).__tcfapi;\n if (typeof tcfApi === \"function\") {\n tasks.push(\n new Promise<void>((resolve) => {\n let settled = false;\n try {\n tcfApi(\"addEventListener\", 2, (tcData: any, success: boolean) => {\n if (settled) return;\n if (\n success &&\n tcData &&\n (tcData.eventStatus === \"tcloaded\" ||\n tcData.eventStatus === \"useractioncomplete\")\n ) {\n settled = true;\n signals.gdpr = tcData.gdprApplies ? \"1\" : \"0\";\n if (typeof tcData.tcString === \"string\" && tcData.tcString) {\n signals.gdprConsent = tcData.tcString;\n }\n try {\n tcfApi(\"removeEventListener\", 2, () => {}, tcData.listenerId);\n } catch {}\n resolve();\n }\n });\n } catch {\n resolve();\n }\n setTimeout(() => {\n if (!settled) {\n settled = true;\n resolve();\n }\n }, timeoutMs);\n })\n );\n }\n\n const uspApi = (window as any).__uspapi;\n if (typeof uspApi === \"function\") {\n tasks.push(\n new Promise<void>((resolve) => {\n try {\n uspApi(\"getUSPData\", 1, (data: any, success: boolean) => {\n if (success && typeof data?.uspString === \"string\" && data.uspString) {\n signals.usPrivacy = data.uspString;\n }\n resolve();\n });\n } catch {\n resolve();\n }\n setTimeout(resolve, timeoutMs);\n })\n );\n }\n\n if (tasks.length === 0) {\n return Promise.resolve(signals);\n }\n\n return Promise.all(tasks).then(() => signals);\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 supportsModernJS: boolean;\n webOSVersion?: number | undefined;\n tizenVersion?: number | undefined;\n chromeVersion?: number | undefined;\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 supportsModernJS = true;\n let webOSVersion: number | undefined;\n let tizenVersion: number | undefined;\n let chromeVersionNum: number | undefined;\n\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n chromeVersionNum = chromeVersion > 0 ? chromeVersion : undefined;\n\n if (/Web0S|webOS|LG Browser|LGSTB/i.test(ua)) {\n name = 'LG WebOS';\n isSmartTV = true;\n\n let match = ua.match(/Web0S[/\\s]*([\\d.]+)/i) || ua.match(/webOS[/\\s]*([\\d.]+)/i);\n\n if (!match || !match[1]) {\n match = ua.match(/webOSTV[/\\s-]*([\\d.]+)/i) || ua.match(/webOS\\.TV[/\\s-]*([\\d.]+)/i);\n }\n\n if (match && match[1]) {\n version = match[1];\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n webOSVersion = majorVersion;\n } else if (chromeVersion > 0) {\n if (chromeVersion >= 79) {\n webOSVersion = 6;\n version = '6.0';\n majorVersion = 6;\n } else if (chromeVersion >= 68) {\n webOSVersion = 5;\n version = '5.0';\n majorVersion = 5;\n } else if (chromeVersion >= 53) {\n webOSVersion = 4;\n version = '4.0';\n majorVersion = 4;\n } else if (chromeVersion >= 38) {\n webOSVersion = 3;\n version = '3.0';\n majorVersion = 3;\n } else {\n webOSVersion = 2;\n version = '2.0';\n majorVersion = 2;\n }\n } else {\n version = 'Unknown';\n webOSVersion = undefined;\n }\n\n isLegacyTV = webOSVersion !== undefined && webOSVersion < 3;\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 tizenVersion = majorVersion;\n }\n\n isLegacyTV = tizenVersion !== undefined && tizenVersion < 3;\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\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 isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\n } else {\n if (chromeVersion > 0) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n\n if (chromeVersion < 50) {\n supportsModernJS = false;\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\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 supportsModernJS,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum,\n };\n}\n\nexport function getBrowserConfigOverrides(): {\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: { allowNativeHls?: boolean } = {};\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\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\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 supportsModernJS: browser.supportsModernJS,\n ...(browser.webOSVersion !== undefined ? { webOSVersion: browser.webOSVersion } : {}),\n ...(browser.tizenVersion !== undefined ? { tizenVersion: browser.tizenVersion } : {}),\n ...(browser.chromeVersion !== undefined ? { chromeVersion: browser.chromeVersion } : {}),\n userAgent: navigator.userAgent,\n });\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\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","import type { Scte35Marker, Id3TagInfo } from \"../types\";\n\nexport function 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\nexport function parseCueOutCont(\n value: string\n): { elapsed?: number; duration?: number } | undefined {\n const res: { elapsed?: number; duration?: number } = {};\n\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\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\n if (!(\"elapsed\" in res) || !(\"duration\" in res)) {\n const slashMatch = value.match(/([0-9.]+)\\s*\\/\\s*([0-9.]+)/);\n if (slashMatch && slashMatch[1] && slashMatch[2]) {\n const elapsed = parseFloat(slashMatch[1]);\n const duration = parseFloat(slashMatch[2]);\n if (!Number.isNaN(elapsed) && !(\"elapsed\" in res)) res.elapsed = elapsed;\n if (!Number.isNaN(duration) && !(\"duration\" in res)) res.duration = duration;\n }\n }\n\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return undefined;\n}\n\nexport function 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\nexport function 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\nexport function 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\nexport function 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\nexport function getFragmentStartSeconds(frag: any): number | undefined {\n const candidates = [frag?.start, frag?.startPTS];\n for (const candidate of candidates) {\n if (typeof candidate === \"number\" && Number.isFinite(candidate)) {\n return candidate;\n }\n }\n return undefined;\n}\n\nexport function parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = 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 = 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 = 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 = 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 = 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 = parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n}\n\nexport function normalizeFragmentPayload(payload: unknown): Uint8Array | undefined {\n if (payload instanceof Uint8Array) {\n return payload;\n }\n if (payload instanceof ArrayBuffer) {\n return new Uint8Array(payload);\n }\n if (ArrayBuffer.isView(payload)) {\n const view = payload as ArrayBufferView;\n return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n }\n return undefined;\n}\n\n// --- Transport Stream SCTE-35 parsing ---\n\nexport function detectTsPacketFormat(\n data: Uint8Array\n): { offset: number; packetSize: number; tsPayloadOffset: number } | undefined {\n const packetSizes = [188, 192, 204];\n for (const packetSize of packetSizes) {\n const tsPayloadOffset = packetSize === 192 ? 4 : 0;\n for (let offset = 0; offset < packetSize; offset++) {\n let matchedPackets = 0;\n for (\n let packetStart = offset;\n packetStart + tsPayloadOffset < data.length &&\n matchedPackets < 5;\n packetStart += packetSize\n ) {\n if (data[packetStart + tsPayloadOffset] !== 0x47) {\n break;\n }\n matchedPackets++;\n }\n if (matchedPackets >= 2) {\n return { offset, packetSize, tsPayloadOffset };\n }\n }\n }\n return undefined;\n}\n\nfunction getPsiSectionStart(\n payload: Uint8Array,\n payloadUnitStart: boolean\n): number | undefined {\n if (!payloadUnitStart) {\n return undefined;\n }\n const pointerField = payload[0];\n if (pointerField == null) {\n return undefined;\n }\n const sectionStart = 1 + pointerField;\n return sectionStart < payload.length ? sectionStart : undefined;\n}\n\nfunction getPsiSectionLength(data: Uint8Array, offset: number): number {\n return (((data[offset + 1] ?? 0) & 0x0f) << 8) | (data[offset + 2] ?? 0);\n}\n\nfunction parsePatSection(\n payload: Uint8Array,\n payloadUnitStart: boolean,\n pmtPids: Set<number>\n): void {\n const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n if (sectionStart == null || sectionStart + 8 >= payload.length) {\n return;\n }\n if (payload[sectionStart] !== 0x00) {\n return;\n }\n\n const sectionLength = getPsiSectionLength(payload, sectionStart);\n const sectionEnd = Math.min(\n payload.length,\n sectionStart + 3 + sectionLength\n );\n\n for (let offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4) {\n const programNumber =\n ((payload[offset] ?? 0) << 8) | (payload[offset + 1] ?? 0);\n const pid =\n (((payload[offset + 2] ?? 0) & 0x1f) << 8) |\n (payload[offset + 3] ?? 0);\n if (programNumber !== 0) {\n pmtPids.add(pid);\n }\n }\n}\n\nfunction descriptorsIdentifyScte35(\n data: Uint8Array,\n start: number,\n end: number\n): boolean {\n let offset = start;\n while (offset + 2 <= end) {\n const tag = data[offset] ?? 0;\n const length = data[offset + 1] ?? 0;\n const descriptorStart = offset + 2;\n const descriptorEnd = descriptorStart + length;\n if (descriptorEnd > end) {\n return false;\n }\n\n const registration =\n length >= 4\n ? String.fromCharCode(\n data[descriptorStart] ?? 0,\n data[descriptorStart + 1] ?? 0,\n data[descriptorStart + 2] ?? 0,\n data[descriptorStart + 3] ?? 0\n )\n : \"\";\n if (tag === 0x8a || registration === \"CUEI\" || registration === \"SCTE\") {\n return true;\n }\n\n offset = descriptorEnd;\n }\n return false;\n}\n\nfunction parsePmtSection(\n payload: Uint8Array,\n payloadUnitStart: boolean,\n tsScte35Pids: Set<number>\n): void {\n const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n if (sectionStart == null || sectionStart + 12 >= payload.length) {\n return;\n }\n if (payload[sectionStart] !== 0x02) {\n return;\n }\n\n const sectionLength = getPsiSectionLength(payload, sectionStart);\n const sectionEnd = Math.min(\n payload.length,\n sectionStart + 3 + sectionLength\n );\n const programInfoLength =\n (((payload[sectionStart + 10] ?? 0) & 0x0f) << 8) |\n (payload[sectionStart + 11] ?? 0);\n\n let offset = sectionStart + 12 + programInfoLength;\n while (offset + 5 <= sectionEnd - 4) {\n const streamType = payload[offset] ?? 0;\n const elementaryPid =\n (((payload[offset + 1] ?? 0) & 0x1f) << 8) |\n (payload[offset + 2] ?? 0);\n const esInfoLength =\n (((payload[offset + 3] ?? 0) & 0x0f) << 8) |\n (payload[offset + 4] ?? 0);\n const descriptorStart = offset + 5;\n const descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);\n\n if (\n streamType === 0x86 ||\n (streamType === 0x06 &&\n descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd))\n ) {\n tsScte35Pids.add(elementaryPid);\n }\n\n offset = descriptorStart + esInfoLength;\n }\n}\n\nfunction hasProcessedTsScte35Section(\n section: Uint8Array,\n processedSections: Set<string>\n): boolean {\n let checksum = 0;\n for (let i = 0; i < section.length; i++) {\n checksum = (checksum * 31 + (section[i] ?? 0)) >>> 0;\n }\n\n const key = `${section.length}:${checksum}`;\n if (processedSections.has(key)) {\n return true;\n }\n\n processedSections.add(key);\n if (processedSections.size > 200) {\n const firstKey = processedSections.values().next().value;\n if (firstKey) {\n processedSections.delete(firstKey);\n }\n }\n return false;\n}\n\nfunction addScte35SectionMarker(\n section: Uint8Array,\n markers: Scte35Marker[],\n processedSections: Set<string>\n): void {\n if (section[0] !== 0xfc || hasProcessedTsScte35Section(section, processedSections)) {\n return;\n }\n\n const marker = parseScte35Binary(section);\n if (!marker) {\n return;\n }\n\n marker.raw = {\n ...(typeof marker.raw === \"object\" && marker.raw ? marker.raw : {}),\n source: \"ts-packet\",\n };\n markers.push(marker);\n}\n\nfunction appendScte35Bytes(\n pid: number,\n bytes: Uint8Array,\n assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n markers: Scte35Marker[],\n processedSections: Set<string>\n): void {\n const assembler = assemblers.get(pid);\n if (!assembler) {\n return;\n }\n\n for (let i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++) {\n assembler.bytes.push(bytes[i] ?? 0);\n }\n\n if (assembler.bytes.length >= assembler.expectedLength) {\n assemblers.delete(pid);\n addScte35SectionMarker(new Uint8Array(assembler.bytes), markers, processedSections);\n }\n}\n\nfunction collectScte35SectionsFromPayload(\n pid: number,\n payload: Uint8Array,\n payloadUnitStart: boolean,\n assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n markers: Scte35Marker[],\n processedSections: Set<string>\n): void {\n if (payload.length === 0) {\n return;\n }\n\n let offset = 0;\n if (payloadUnitStart) {\n const pointerField = payload[0] ?? 0;\n const previousAssembler = assemblers.get(pid);\n if (previousAssembler && pointerField > 0) {\n appendScte35Bytes(\n pid,\n payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n assemblers,\n markers,\n processedSections\n );\n }\n assemblers.delete(pid);\n offset = 1 + pointerField;\n } else {\n appendScte35Bytes(pid, payload, assemblers, markers, processedSections);\n return;\n }\n\n while (offset + 3 <= payload.length) {\n const tableId = payload[offset];\n if (tableId == null || tableId === 0xff) {\n return;\n }\n\n const sectionLength = getPsiSectionLength(payload, offset);\n const totalLength = 3 + sectionLength;\n if (sectionLength <= 0 || totalLength <= 3) {\n return;\n }\n\n if (offset + totalLength <= payload.length) {\n addScte35SectionMarker(\n payload.subarray(offset, offset + totalLength),\n markers,\n processedSections\n );\n offset += totalLength;\n } else {\n assemblers.set(pid, {\n bytes: Array.from(payload.subarray(offset)),\n expectedLength: totalLength,\n });\n return;\n }\n }\n}\n\nexport function parseScte35FromTsPackets(\n data: Uint8Array,\n tsScte35Pids: Set<number>,\n pmtPids: Set<number>,\n processedSections: Set<string>\n): Scte35Marker[] {\n const packetInfo = detectTsPacketFormat(data);\n if (!packetInfo) {\n return [];\n }\n\n const markers: Scte35Marker[] = [];\n const sectionAssemblers = new Map<\n number,\n { bytes: number[]; expectedLength: number }\n >();\n\n for (\n let packetStart = packetInfo.offset;\n packetStart + packetInfo.packetSize <= data.length;\n packetStart += packetInfo.packetSize\n ) {\n const tsStart = packetStart + packetInfo.tsPayloadOffset;\n if (data[tsStart] !== 0x47) {\n continue;\n }\n\n const secondByte = data[tsStart + 1];\n const thirdByte = data[tsStart + 2];\n const fourthByte = data[tsStart + 3];\n if (\n secondByte == null ||\n thirdByte == null ||\n fourthByte == null ||\n (secondByte & 0x80) !== 0\n ) {\n continue;\n }\n\n const payloadUnitStart = (secondByte & 0x40) !== 0;\n const pid = ((secondByte & 0x1f) << 8) | thirdByte;\n const adaptationFieldControl = (fourthByte >> 4) & 0x03;\n const hasPayload =\n adaptationFieldControl === 1 || adaptationFieldControl === 3;\n if (!hasPayload) {\n continue;\n }\n\n let payloadStart = tsStart + 4;\n if (adaptationFieldControl === 3) {\n const adaptationLength = data[payloadStart];\n if (adaptationLength == null) {\n continue;\n }\n payloadStart += 1 + adaptationLength;\n }\n\n const payloadEnd = Math.min(tsStart + 188, data.length);\n if (payloadStart >= payloadEnd || payloadStart >= data.length) {\n continue;\n }\n\n const payload = data.subarray(payloadStart, payloadEnd);\n if (pid === 0) {\n parsePatSection(payload, payloadUnitStart, pmtPids);\n } else if (pmtPids.has(pid)) {\n parsePmtSection(payload, payloadUnitStart, tsScte35Pids);\n } else if (tsScte35Pids.has(pid)) {\n collectScte35SectionsFromPayload(\n pid,\n payload,\n payloadUnitStart,\n sectionAssemblers,\n markers,\n processedSections\n );\n }\n }\n\n return markers;\n}\n\n// --- Binary SCTE-35 parsing ---\n\nclass 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 get bytePosition(): number {\n return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n }\n}\n\nfunction readSpliceTime(\n r: BitReader,\n ptsAdjustmentTicks: number\n): number | undefined {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (!timeSpecifiedFlag) {\n r.readBits(7);\n return undefined;\n }\n r.readBits(6);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const ptsTicks =\n (high * 0x100000000 + low + ptsAdjustmentTicks) % 0x200000000;\n return ptsTicks / 90000;\n}\n\nfunction markerTypeFromSegmentationTypeId(\n segmentationTypeId: number\n): Scte35Marker[\"type\"] | undefined {\n switch (segmentationTypeId) {\n case 0x10:\n case 0x22:\n case 0x30:\n case 0x32:\n case 0x34:\n case 0x36:\n return \"start\";\n case 0x11:\n case 0x23:\n case 0x31:\n case 0x33:\n case 0x35:\n case 0x37:\n return \"end\";\n default:\n return undefined;\n }\n}\n\nfunction parseScte35SegmentationDescriptor(\n descriptor: Uint8Array\n):\n | {\n type: Scte35Marker[\"type\"];\n durationSeconds?: number;\n segmentationEventId?: number;\n }\n | undefined {\n if (descriptor.length < 11) {\n return undefined;\n }\n\n const identifier = String.fromCharCode(\n descriptor[0] ?? 0,\n descriptor[1] ?? 0,\n descriptor[2] ?? 0,\n descriptor[3] ?? 0\n );\n if (identifier !== \"CUEI\") {\n return undefined;\n }\n\n const segmentationEventId =\n ((descriptor[4] ?? 0) * 0x1000000) +\n ((descriptor[5] ?? 0) << 16) +\n ((descriptor[6] ?? 0) << 8) +\n (descriptor[7] ?? 0);\n const cancelIndicator = ((descriptor[8] ?? 0) & 0x80) !== 0;\n if (cancelIndicator) {\n return undefined;\n }\n\n const flags = descriptor[9] ?? 0;\n const programSegmentationFlag = (flags & 0x80) !== 0;\n const segmentationDurationFlag = (flags & 0x40) !== 0;\n let offset = 10;\n\n if (!programSegmentationFlag) {\n const componentCount = descriptor[offset] ?? 0;\n offset += 1 + componentCount * 6;\n if (offset > descriptor.length) {\n return undefined;\n }\n }\n\n let durationSeconds: number | undefined = undefined;\n if (segmentationDurationFlag) {\n if (offset + 5 > descriptor.length) {\n return undefined;\n }\n const durationTicks =\n ((descriptor[offset] ?? 0) * 0x100000000) +\n ((descriptor[offset + 1] ?? 0) * 0x1000000) +\n ((descriptor[offset + 2] ?? 0) << 16) +\n ((descriptor[offset + 3] ?? 0) << 8) +\n (descriptor[offset + 4] ?? 0);\n durationSeconds = durationTicks / 90000;\n offset += 5;\n }\n\n if (offset + 2 > descriptor.length) {\n return undefined;\n }\n offset += 1;\n const segmentationUpidLength = descriptor[offset] ?? 0;\n offset += 1 + segmentationUpidLength;\n if (offset >= descriptor.length) {\n return undefined;\n }\n\n const segmentationTypeId = descriptor[offset] ?? 0;\n const markerType = markerTypeFromSegmentationTypeId(segmentationTypeId);\n if (!markerType) {\n return undefined;\n }\n\n return {\n type: markerType,\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n segmentationEventId,\n };\n}\n\nfunction parseScte35SegmentationDescriptors(\n data: Uint8Array,\n offset: number\n):\n | {\n type: Scte35Marker[\"type\"];\n durationSeconds?: number;\n segmentationEventId?: number;\n }\n | undefined {\n if (offset + 2 > data.length) {\n return undefined;\n }\n\n const descriptorLoopLength =\n ((data[offset] ?? 0) << 8) | (data[offset + 1] ?? 0);\n let descriptorOffset = offset + 2;\n const descriptorEnd = Math.min(\n data.length,\n descriptorOffset + descriptorLoopLength\n );\n\n while (descriptorOffset + 2 <= descriptorEnd) {\n const descriptorTag = data[descriptorOffset] ?? 0;\n const descriptorLength = data[descriptorOffset + 1] ?? 0;\n const descriptorDataStart = descriptorOffset + 2;\n const descriptorDataEnd = descriptorDataStart + descriptorLength;\n if (descriptorDataEnd > descriptorEnd) {\n return undefined;\n }\n\n if (descriptorTag === 0x02) {\n const descriptorMarker = parseScte35SegmentationDescriptor(\n data.subarray(descriptorDataStart, descriptorDataEnd)\n );\n if (descriptorMarker) {\n return descriptorMarker;\n }\n }\n\n descriptorOffset = descriptorDataEnd;\n }\n\n return undefined;\n}\n\nexport function parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\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 if (sectionLength <= 0 || data.length < 3 + sectionLength) {\n return undefined;\n }\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 const ptsAdjustmentTicks = ptsAdjHigh * 0x100000000 + ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n\n let markerType: Scte35Marker[\"type\"] | undefined;\n let durationSeconds: number | undefined = undefined;\n let ptsSeconds: number | undefined = undefined;\n let spliceEventId: number | undefined = undefined;\n const commandBodyStart = r.bytePosition;\n\n if (spliceCommandType === 5) {\n spliceEventId = 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 markerType = outOfNetwork ? \"start\" : \"end\";\n\n if (programSpliceFlag && !spliceImmediateFlag) {\n ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\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 componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n if (ptsSeconds === undefined) {\n ptsSeconds = componentPtsSeconds;\n }\n }\n }\n }\n\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 } else if (spliceCommandType === 6) {\n ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n } else {\n return undefined;\n }\n\n const expectedDescriptorOffset =\n spliceCommandLength === 0x0fff\n ? r.bytePosition\n : commandBodyStart + spliceCommandLength;\n const descriptorMarker = parseScte35SegmentationDescriptors(\n data,\n expectedDescriptorOffset\n );\n\n if (descriptorMarker) {\n markerType = descriptorMarker.type;\n if (durationSeconds === undefined) {\n durationSeconds = descriptorMarker.durationSeconds;\n }\n }\n\n if (!markerType) {\n return undefined;\n }\n\n const marker: Scte35Marker = {\n type: markerType,\n ...(ptsSeconds !== undefined ? { ptsSeconds } : {}),\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: {\n splice_command_type: spliceCommandType,\n ...(spliceEventId !== undefined ? { splice_event_id: spliceEventId } : {}),\n ...(descriptorMarker?.segmentationEventId !== undefined\n ? { segmentation_event_id: descriptorMarker.segmentationEventId }\n : {}),\n },\n } as Scte35Marker;\n return marker;\n}\n","import type { Scte35Marker } from \"../types\";\nimport type {\n NormalizedScte35Cue,\n Scte35CueContext,\n Scte35CueSource,\n Scte35CueReadiness,\n} from \"./playerTypes\";\nimport { getFragmentStartSeconds } from \"./Scte35Parser\";\n\nexport interface Scte35CueManagerCallbacks {\n onEarlyStartCue(marker: Scte35Marker, fragmentSn: number | undefined, cueKey: string): void;\n onPlaybackCue(marker: Scte35Marker, cueKey?: string): void;\n isInAdBreak(): boolean;\n}\n\nexport class Scte35CueManager {\n private readonly pendingScte35Cues: Map<string, NormalizedScte35Cue> = new Map();\n private readonly recentScte35CueKeys: Map<string, number> = new Map();\n private readonly recentScte35CueLimit: number = 200;\n private pendingScte35CueKeyValue: string | undefined;\n private activeScte35BreakKeyValue: string | undefined;\n private scheduledScte35BreakKeyValue: string | undefined;\n\n readonly tsScte35Pids: Set<number> = new Set();\n readonly pmtPids: Set<number> = new Set();\n readonly processedTsScte35Sections: Set<string> = new Set();\n\n private debug: boolean;\n private callbacks: Scte35CueManagerCallbacks;\n\n constructor(debug: boolean, callbacks: Scte35CueManagerCallbacks) {\n this.debug = debug;\n this.callbacks = callbacks;\n }\n\n get pendingScte35CueKey(): string | undefined {\n return this.pendingScte35CueKeyValue;\n }\n set pendingScte35CueKey(value: string | undefined) {\n this.pendingScte35CueKeyValue = value;\n }\n\n get activeScte35BreakKey(): string | undefined {\n return this.activeScte35BreakKeyValue;\n }\n set activeScte35BreakKey(value: string | undefined) {\n this.activeScte35BreakKeyValue = value;\n }\n\n get scheduledScte35BreakKey(): string | undefined {\n return this.scheduledScte35BreakKeyValue;\n }\n set scheduledScte35BreakKey(value: string | undefined) {\n this.scheduledScte35BreakKeyValue = value;\n }\n\n createScte35CueContext(\n source: Scte35CueSource,\n readiness: Scte35CueReadiness,\n frag?: any\n ): Scte35CueContext {\n const context: Scte35CueContext = { source, readiness };\n if (typeof frag?.sn === \"number\") {\n context.fragmentSn = frag.sn;\n }\n const fragmentStartSec = getFragmentStartSeconds(frag);\n if (fragmentStartSec !== undefined) {\n context.fragmentStartSeconds = fragmentStartSec;\n }\n return context;\n }\n\n onScte35Cue(marker: Scte35Marker, context: Scte35CueContext): void {\n const cue = this.createScte35Cue(marker, context);\n const pendingKey = this.getPendingScte35CueKey(cue);\n\n if (context.readiness === \"early\") {\n this.pendingScte35Cues.set(pendingKey, cue);\n this.trimRecentScte35CueMaps();\n\n if (marker.type === \"start\") {\n this.callbacks.onEarlyStartCue(marker, context.fragmentSn, cue.key);\n }\n return;\n }\n\n if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n key: cue.key,\n activeScte35BreakKey: this.activeScte35BreakKeyValue,\n inAdBreak: this.callbacks.isInAdBreak(),\n source: cue.source,\n });\n }\n return;\n }\n\n if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue\", {\n key: cue.key,\n source: cue.source,\n });\n }\n return;\n }\n\n this.pendingScte35Cues.delete(pendingKey);\n this.markScte35CueHandled(cue);\n this.callbacks.onPlaybackCue(marker, cue.key);\n }\n\n activatePendingScte35CuesForFragment(frag: any): void {\n const fragmentSn = typeof frag?.sn === \"number\" ? frag.sn : undefined;\n if (fragmentSn === undefined) {\n return;\n }\n\n const matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(\n ([, cue]) => cue.fragmentSn === fragmentSn\n );\n\n matchingCues.forEach(([pendingKey, cue]) => {\n this.pendingScte35Cues.delete(pendingKey);\n const context: Scte35CueContext = {\n source: cue.source,\n readiness: \"playback\",\n };\n context.fragmentSn = fragmentSn;\n const fragmentStartSec =\n cue.fragmentStartSeconds ?? getFragmentStartSeconds(frag);\n if (fragmentStartSec !== undefined) {\n context.fragmentStartSeconds = fragmentStartSec;\n }\n this.onScte35Cue(cue.marker, context);\n });\n }\n\n private createScte35Cue(\n marker: Scte35Marker,\n context: Scte35CueContext\n ): NormalizedScte35Cue {\n const cue: NormalizedScte35Cue = {\n marker,\n source: context.source,\n readiness: context.readiness,\n key: this.getScte35CueKey(marker, context),\n };\n if (context.fragmentSn !== undefined) {\n cue.fragmentSn = context.fragmentSn;\n }\n if (context.fragmentStartSeconds !== undefined) {\n cue.fragmentStartSeconds = context.fragmentStartSeconds;\n }\n return cue;\n }\n\n private getScte35CueKey(\n marker: Scte35Marker,\n context: Scte35CueContext\n ): string {\n const raw = this.getScte35MarkerRaw(marker);\n const spliceEventId = this.toIdentityString(raw?.splice_event_id);\n if (spliceEventId) {\n return `splice:${spliceEventId}`;\n }\n\n const segmentationEventId = this.toIdentityString(raw?.segmentation_event_id);\n if (segmentationEventId) {\n return `segmentation:${segmentationEventId}`;\n }\n\n const daterangeId = this.toIdentityString(raw?.attrs?.ID);\n if (daterangeId) {\n return `daterange:${daterangeId}`;\n }\n\n const scteValue =\n this.toIdentityString(raw?.attrs?.[\"SCTE35-OUT\"]) ||\n this.toIdentityString(raw?.attrs?.[\"SCTE35-IN\"]);\n if (scteValue) {\n return `daterange-scte:${scteValue}`;\n }\n\n if (typeof marker.ptsSeconds === \"number\" && Number.isFinite(marker.ptsSeconds)) {\n return `pts:${Math.round(marker.ptsSeconds * 2) / 2}`;\n }\n\n if (context.fragmentSn !== undefined) {\n return `fragment:${context.fragmentSn}`;\n }\n\n return `${context.source}:wallclock:${Math.floor(Date.now() / 1000)}`;\n }\n\n private getPendingScte35CueKey(cue: NormalizedScte35Cue): string {\n return `${cue.marker.type}:${cue.key}:${\n cue.fragmentSn !== undefined ? cue.fragmentSn : \"unknown\"\n }`;\n }\n\n private getScte35MarkerRaw(marker: Scte35Marker): any {\n return typeof marker.raw === \"object\" && marker.raw !== null\n ? (marker.raw as any)\n : {};\n }\n\n private toIdentityString(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value);\n }\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n return undefined;\n }\n\n isStrongScte35CueKey(key: string | undefined): boolean {\n return !!(\n key &&\n (key.startsWith(\"splice:\") ||\n key.startsWith(\"segmentation:\") ||\n key.startsWith(\"daterange:\") ||\n key.startsWith(\"daterange-scte:\"))\n );\n }\n\n private hasRecentlyHandledScte35Cue(cue: NormalizedScte35Cue): boolean {\n if (\n this.activeScte35BreakKeyValue === cue.key ||\n this.scheduledScte35BreakKeyValue === cue.key\n ) {\n return true;\n }\n\n const recentKey = `${cue.marker.type}:${cue.key}`;\n return this.recentScte35CueKeys.has(recentKey);\n }\n\n private markScte35CueHandled(cue: NormalizedScte35Cue): void {\n this.recentScte35CueKeys.set(`${cue.marker.type}:${cue.key}`, Date.now());\n this.trimRecentScte35CueMaps();\n }\n\n private trimRecentScte35CueMaps(): void {\n while (this.recentScte35CueKeys.size > this.recentScte35CueLimit) {\n const firstKey = this.recentScte35CueKeys.keys().next().value;\n if (!firstKey) {\n break;\n }\n this.recentScte35CueKeys.delete(firstKey);\n }\n\n while (this.pendingScte35Cues.size > this.recentScte35CueLimit) {\n const firstKey = this.pendingScte35Cues.keys().next().value;\n if (!firstKey) {\n break;\n }\n this.pendingScte35Cues.delete(firstKey);\n }\n }\n\n private shouldAcceptScte35EndCue(cue: NormalizedScte35Cue): boolean {\n if (!this.callbacks.isInAdBreak()) {\n return false;\n }\n\n if (\n this.isStrongScte35CueKey(this.activeScte35BreakKeyValue) &&\n this.isStrongScte35CueKey(cue.key) &&\n this.activeScte35BreakKeyValue !== cue.key\n ) {\n return false;\n }\n\n return true;\n }\n}\n","import type {\n StormcloudVideoPlayerConfig,\n AdBreak,\n StormcloudApiResponse,\n AdController,\n} from \"../types\";\nimport type { PalNonceManager } from \"../sdk/pal\";\nimport { applyVastMacros, generateCorrelator, normalizeVastTagUrl } from \"../utils/vastMacros\";\nimport type { VastConsentSignals } from \"../utils/vastMacros\";\nimport { resolveVastEnvironmentSignals } from \"../utils/vastEnvironmentSignals\";\nimport { sendHeartbeat, sendInitialTracking } from \"../utils/tracking\";\n\nexport class AdConfigManager {\n vmapBreaks: AdBreak[] = [];\n consumedVmapBreakIds: Set<string> = new Set();\n apiVastTagUrl: string | undefined;\n apiNumberAds: number | undefined;\n readonly streamCorrelator: string = generateCorrelator();\n consentSignals: VastConsentSignals = {};\n podCounter: number = 0;\n podAssignedByPrefetch: boolean = false;\n adRequestPositionInBreak: number = 0;\n\n private lastHeartbeatTime: number = 0;\n private heartbeatInterval: number | undefined;\n\n private config: StormcloudVideoPlayerConfig;\n private video: HTMLVideoElement;\n\n constructor(config: StormcloudVideoPlayerConfig, video: HTMLVideoElement) {\n this.config = config;\n this.video = video;\n }\n\n get debug(): boolean {\n return !!this.config.debugAdTiming;\n }\n\n isVmapEnabled(): boolean {\n return !!(this.config.isVmap && this.config.vmapUrl?.trim());\n }\n\n async fetchAdConfiguration(): Promise<void> {\n if (this.isVmapEnabled()) {\n await this.fetchAndParseVmap(this.config.vmapUrl!);\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] VMAP mode enabled\");\n }\n return;\n }\n\n const vastMode = this.config.vastMode || \"default\";\n\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.debug) {\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.debug) {\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 = normalizeVastTagUrl(this.config.vastTagUrl);\n if (this.debug) {\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.debug) {\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.debug) {\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 let decodedPayload = imaPayload;\n try {\n decodedPayload = decodeURIComponent(imaPayload);\n } catch {\n console.warn(\"[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:\", imaPayload);\n }\n console.log(\"[StormcloudVideoPlayer] Raw VAST tag URL (from API):\", decodedPayload);\n this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);\n if (this.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Normalized VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.debug) {\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.debug) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n\n private async fetchAndParseVmap(vmapUrl: string): Promise<void> {\n if (!vmapUrl.trim()) {\n return;\n }\n\n try {\n const response = await fetch(vmapUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VMAP (${response.status})`);\n }\n\n const vmapXml = await response.text();\n this.vmapBreaks = this.parseVmapToBreaks(vmapXml);\n this.consumedVmapBreakIds.clear();\n\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] Loaded ${this.vmapBreaks.length} VMAP ad break(s) from:`,\n vmapUrl\n );\n }\n } catch (error) {\n this.vmapBreaks = [];\n this.consumedVmapBreakIds.clear();\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Failed to load VMAP:\", error);\n }\n }\n }\n\n private parseVmapToBreaks(vmapXml: string): AdBreak[] {\n if (typeof DOMParser === \"undefined\") {\n return [];\n }\n\n const doc = new DOMParser().parseFromString(vmapXml, \"application/xml\");\n if (doc.querySelector(\"parsererror\")) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n }\n return [];\n }\n\n const VMAP_NS = \"http://www.iab.net/videosuite/vmap\";\n let adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, \"AdBreak\"));\n if (adBreakNodes.length === 0) {\n adBreakNodes = Array.from(\n doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\n );\n }\n if (adBreakNodes.length === 0) {\n adBreakNodes = Array.from(doc.getElementsByTagName(\"*\")).filter(\n (el) => el.localName === \"AdBreak\"\n );\n }\n const parsed: AdBreak[] = [];\n\n adBreakNodes.forEach((node, index) => {\n const timeOffsetRaw = (node.getAttribute(\"timeOffset\") || \"\").trim();\n const startTimeMs = this.parseVmapTimeOffsetToMs(timeOffsetRaw);\n if (startTimeMs == null) {\n return;\n }\n\n let adTagNode = node.getElementsByTagNameNS(VMAP_NS, \"AdTagURI\")[0];\n if (!adTagNode) {\n adTagNode =\n (node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\") as Element | null) ??\n undefined;\n }\n const adTagUrl = (adTagNode?.textContent || \"\").trim();\n if (!adTagUrl) {\n return;\n }\n\n const breakId =\n node.getAttribute(\"breakId\") ||\n `vmap-break-${index}-${timeOffsetRaw || \"unknown\"}`;\n parsed.push({\n id: breakId,\n startTimeMs,\n vastTagUrl: adTagUrl,\n });\n });\n\n parsed.sort((a, b) => {\n const aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;\n const bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;\n return aStart - bStart;\n });\n\n return parsed;\n }\n\n private parseVmapTimeOffsetToMs(timeOffset: string): number | undefined {\n if (!timeOffset) {\n return undefined;\n }\n\n const normalized = timeOffset.trim().toLowerCase();\n if (normalized === \"start\") {\n return 0;\n }\n\n if (normalized === \"end\") {\n return -1;\n }\n\n const hms = timeOffset.match(\n /^(\\d{1,2}):(\\d{2}):(\\d{2})(?:\\.(\\d{1,3}))?$/\n );\n if (hms) {\n const [, hh, mm, ss, ms = \"0\"] = hms;\n const hours = Number(hh);\n const minutes = Number(mm);\n const seconds = Number(ss);\n const millis = Number(ms.padEnd(3, \"0\").slice(0, 3));\n return ((hours * 3600 + minutes * 60 + seconds) * 1000) + millis;\n }\n\n const percent = timeOffset.match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (percent) {\n const ratio = Number(percent[1]) / 100;\n const durationSec = this.video.duration;\n if (Number.isFinite(durationSec) && durationSec > 0) {\n return Math.floor(durationSec * 1000 * ratio);\n }\n return undefined;\n }\n\n return undefined;\n }\n\n getAdBreakKey(adBreak: AdBreak): string {\n if (adBreak.id) {\n return adBreak.id;\n }\n return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n }\n\n resolveBreakStartMs(adBreak: AdBreak): number | undefined {\n if (adBreak.startTimeMs >= 0) {\n return adBreak.startTimeMs;\n }\n\n if (adBreak.startTimeMs === -1) {\n const durationSec = this.video.duration;\n if (Number.isFinite(durationSec) && durationSec > 0) {\n return Math.floor(durationSec * 1000);\n }\n }\n\n return undefined;\n }\n\n findCurrentOrNextBreak(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = this.vmapBreaks;\n let candidate: AdBreak | undefined;\n const tol = this.config.driftToleranceMs ?? 1000;\n for (const b of schedule) {\n if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n continue;\n }\n const breakStartMs = this.resolveBreakStartMs(b);\n if (breakStartMs == null) {\n continue;\n }\n if (\n breakStartMs <= nowMs + tol &&\n (candidate == null ||\n breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))\n ) {\n candidate = b;\n }\n }\n return candidate;\n }\n\n findBreakForTime(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = this.vmapBreaks;\n for (const b of schedule) {\n if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n continue;\n }\n const breakStartMs = this.resolveBreakStartMs(b);\n if (breakStartMs == null) {\n continue;\n }\n\n if (b.durationMs) {\n const end = breakStartMs + b.durationMs;\n if (nowMs >= breakStartMs && nowMs < end) {\n return b;\n }\n continue;\n }\n\n if (nowMs >= breakStartMs) {\n return b;\n }\n }\n return undefined;\n }\n\n 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 beginNewAdPod(): void {\n this.podCounter++;\n this.adRequestPositionInBreak = 0;\n }\n\n generateVastUrlsWithCorrelators(\n baseUrl: string,\n count: number,\n adPlayer: AdController,\n palNonce: PalNonceManager,\n inAdBreak: boolean\n ): string[] {\n const urls: string[] = [];\n\n for (let i = 0; i < count; i++) {\n this.adRequestPositionInBreak++;\n\n const adWillPlayMuted = inAdBreak\n ? adPlayer.getOriginalMutedState()\n : this.video.muted;\n const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n\n const urlWithMacros = applyVastMacros(baseUrl, {\n correlator: generateCorrelator(),\n streamCorrelator: this.streamCorrelator,\n pod: this.podCounter > 0 ? this.podCounter : undefined,\n adPosition: this.adRequestPositionInBreak,\n isCtv: envSignals.isCtv,\n contentUrl: envSignals.contentUrl,\n pageUrl:\n !envSignals.isCtv && typeof window !== \"undefined\"\n ? window.location.href\n : undefined,\n adWillPlayMuted,\n adWillAutoPlay: !!this.config.autoplay,\n appId: envSignals.appId,\n appName: envSignals.appName,\n sessionId: envSignals.sessionId,\n deviceId: envSignals.deviceId,\n deviceIdType: envSignals.deviceIdType,\n limitAdTracking: envSignals.limitAdTracking,\n deviceTypeHint: envSignals.deviceTypeHint,\n adTest: this.config.adTest,\n consent: this.consentSignals,\n });\n\n const finalUrl = palNonce.injectNonce(urlWithMacros);\n console.log(\n `[StormcloudVideoPlayer] Resolved ad request URL (pod=${this.podCounter}, pos=${this.adRequestPositionInBreak}):`,\n finalUrl\n );\n urls.push(finalUrl);\n }\n\n return urls;\n }\n\n // --- Tracking ---\n\n 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.debug) {\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.debug) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n destroyTracking(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n }\n}\n","import type { AdController, StormcloudVideoPlayerConfig, Scte35Marker } from \"../types\";\n\nexport interface AdTimingCallbacks {\n onAdStopTimerFired(): void;\n onAdStartTimerFired(marker: Scte35Marker, cueKey: string | undefined): void;\n onWatchdogTimeout(): void;\n onFailsafeTimeout(): void;\n}\n\nexport class AdTimingService {\n private adStopTimerId: number | undefined;\n private adStartTimerId: number | undefined;\n private adFailsafeTimerId: number | undefined;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n\n ptsDriftEmaMs = 0;\n expectedAdBreakDurationMs: number | undefined;\n currentAdBreakStartWallClockMs: number | undefined;\n scteAdBreakEndWallClockMs: number | undefined;\n adBreakPlayedDurationMs: number = 0;\n adBreakEpoch: number = 0;\n\n adRequestTokenCounter = 0;\n activeAdRequestToken: number | null = null;\n currentAdIndex: number = 0;\n totalAdsInBreak: number = 0;\n totalAdRequestsInBreak: number = 0;\n readonly maxTotalAdRequestsPerBreak: number = 10;\n lastAdRequestTime: number = 0;\n consecutiveFailures: number = 0;\n readonly maxConsecutiveFailures: number = 5;\n readonly minAdRequestIntervalMs: number = 3000;\n readonly backoffBaseMs: number = 1000;\n readonly maxBackoffMs: number = 15000;\n private readonly defaultMinRemainingMsToStartAd: number = 4000;\n\n failedVastUrls: Set<string> = new Set();\n temporaryFailureUrls: Map<string, number> = new Map();\n private readonly temporaryFailureCooldownMs: number = 30000;\n\n private globalConsecutiveNoFills: number = 0;\n private readonly globalNoFillThreshold: number = 3;\n private globalNoFillCooldownUntil: number = 0;\n private readonly globalNoFillBackoffBaseMs: number = 5000;\n private readonly globalNoFillBackoffMaxMs: number = 60000;\n private globalLastGamRequestTime: number = 0;\n private readonly globalMinGamIntervalMs: number = 3000;\n\n private config: StormcloudVideoPlayerConfig;\n private video: HTMLVideoElement;\n private callbacks: AdTimingCallbacks;\n\n constructor(\n config: StormcloudVideoPlayerConfig,\n video: HTMLVideoElement,\n callbacks: AdTimingCallbacks\n ) {\n this.config = config;\n this.video = video;\n this.callbacks = callbacks;\n }\n\n get debug(): boolean {\n return !!this.config.debugAdTiming;\n }\n\n // --- Ad stop timer ---\n\n 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 clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private ensureAdStoppedByTimer(): void {\n this.adStopTimerId = undefined;\n this.callbacks.onAdStopTimerFired();\n }\n\n // --- Ad start timer ---\n\n scheduleAdStartIn(\n delayMs: number,\n marker: Scte35Marker = { type: \"start\" } as Scte35Marker,\n cueKey?: string\n ): void {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.callbacks.onAdStartTimerFired(marker, cueKey);\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.callbacks.onAdStartTimerFired(marker, cueKey);\n }, ms) as unknown as number;\n }\n\n clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n // --- PTS drift ---\n\n 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 resolveScteBreakStartWallClockMs(marker: Scte35Marker): number {\n const nowWallClockMs = Date.now();\n if (typeof marker.ptsSeconds !== \"number\") {\n return nowWallClockMs;\n }\n\n const nowMs = this.video.currentTime * 1000;\n const estimatedCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = marker.ptsSeconds * 1000 - estimatedCurrentPtsMs;\n if (!Number.isFinite(deltaMs)) {\n return nowWallClockMs;\n }\n\n return nowWallClockMs + Math.floor(deltaMs);\n }\n\n // --- Duration boundary ---\n\n setAdBreakDurationBoundary(durationMs: number | undefined): void {\n this.expectedAdBreakDurationMs = durationMs;\n if (\n durationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n this.scteAdBreakEndWallClockMs =\n this.currentAdBreakStartWallClockMs + durationMs;\n } else {\n this.scteAdBreakEndWallClockMs = undefined;\n }\n }\n\n scheduleAdStopAtBreakBoundary(): void {\n if (this.expectedAdBreakDurationMs == null) {\n return;\n }\n this.scheduleAdStopCountdown(this.getWallClockRemainingAdMs());\n }\n\n // --- Duration budget ---\n\n getWallClockRemainingAdMs(): number {\n const endWallClockMs = this.getAdBreakEndWallClockMs();\n if (endWallClockMs != null) {\n return Math.max(0, endWallClockMs - Date.now());\n }\n return 0;\n }\n\n getAdBreakEndWallClockMs(): number | undefined {\n if (this.scteAdBreakEndWallClockMs != null) {\n return this.scteAdBreakEndWallClockMs;\n }\n if (\n this.expectedAdBreakDurationMs == null ||\n this.currentAdBreakStartWallClockMs == null\n ) {\n return undefined;\n }\n return this.currentAdBreakStartWallClockMs + this.expectedAdBreakDurationMs;\n }\n\n getDurationBudgetRemainingMs(): number {\n if (this.expectedAdBreakDurationMs == null) {\n return 0;\n }\n return Math.max(0, this.expectedAdBreakDurationMs - this.adBreakPlayedDurationMs);\n }\n\n getLoadedAdDurationMs(adController: AdController): number {\n const durationSec = adController.getLoadedAdDuration?.();\n if (durationSec == null || durationSec <= 0) {\n return 0;\n }\n return Math.round(durationSec * 1000);\n }\n\n adFitsRemainingBudget(durationMs: number): boolean {\n if (durationMs <= 0) {\n return true;\n }\n return durationMs <= this.getDurationBudgetRemainingMs();\n }\n\n logAdDurationDecision(\n accepted: boolean,\n durationMs: number,\n adController: AdController\n ): void {\n if (!this.debug) {\n return;\n }\n const remainingBudget = this.getDurationBudgetRemainingMs();\n const adId = adController.getLoadedAdId?.() ?? \"unknown\";\n if (accepted) {\n console.log(\n `[AD-DURATION] Accepted ad id=${adId}, duration=${durationMs}ms, budget remaining after play=${Math.max(0, remainingBudget - durationMs)}ms`\n );\n } else {\n console.log(\n `[AD-DURATION] Rejected ad id=${adId}, duration=${durationMs}ms exceeds remaining budget=${remainingBudget}ms — requesting another ad`\n );\n }\n }\n\n recordPlayedAdDuration(adController: AdController): void {\n const durationMs = this.getLoadedAdDurationMs(adController);\n if (durationMs <= 0) {\n return;\n }\n this.adBreakPlayedDurationMs += durationMs;\n if (this.debug) {\n console.log(\n `[AD-DURATION] Played ${durationMs}ms — total played=${this.adBreakPlayedDurationMs}ms / ${this.expectedAdBreakDurationMs ?? \"?\"}ms`\n );\n }\n }\n\n ensureLoadedAdFitsBudget(adController: AdController): boolean {\n const durationMs = this.getLoadedAdDurationMs(adController);\n const fits = this.adFitsRemainingBudget(durationMs);\n this.logAdDurationDecision(fits, durationMs, adController);\n return fits;\n }\n\n rejectLoadedAdForDuration(adController: AdController): void {\n try {\n adController.destroy();\n } catch {}\n }\n\n markAdStarted(): void {\n this.currentAdIndex++;\n this.totalAdsInBreak = this.currentAdIndex;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n }\n\n getRemainingAdMs(): number {\n const wallClockRemaining = this.getWallClockRemainingAdMs();\n const budgetRemaining = this.getDurationBudgetRemainingMs();\n if (this.expectedAdBreakDurationMs == null) {\n return wallClockRemaining;\n }\n return Math.min(wallClockRemaining, budgetRemaining);\n }\n\n getMinRemainingMsToStartAd(): number {\n const configured = this.config.minRemainingMsToStartAd;\n if (typeof configured === \"number\" && configured >= 0) {\n return configured;\n }\n return this.defaultMinRemainingMsToStartAd;\n }\n\n hasTimeToStartAnotherAd(): boolean {\n const minRemaining = this.getMinRemainingMsToStartAd();\n return (\n this.getWallClockRemainingAdMs() > minRemaining &&\n this.getDurationBudgetRemainingMs() > minRemaining\n );\n }\n\n // --- Circuit breaker ---\n\n isTemporaryAdError(error: Error): boolean {\n const message = error?.message?.toLowerCase() || \"\";\n\n if (message.includes(\"no ads available\") || message.includes(\"no fill\") || message.includes(\"nofill\")) {\n return true;\n }\n if (message.includes(\"timeout\")) {\n return true;\n }\n if (message.includes(\"rate limit\") || message.includes(\"too many requests\")) {\n return true;\n }\n if (message.includes(\"ad playback error\")) {\n return true;\n }\n return false;\n }\n\n isUrlInCooldown(vastTagUrl: string): boolean {\n const failureTime = this.temporaryFailureUrls.get(vastTagUrl);\n if (failureTime == null) {\n return false;\n }\n\n const elapsed = Date.now() - failureTime;\n if (elapsed >= this.temporaryFailureCooldownMs) {\n this.temporaryFailureUrls.delete(vastTagUrl);\n return false;\n }\n\n return true;\n }\n\n cleanupTemporaryFailures(): void {\n const now = Date.now();\n for (const [url, timestamp] of this.temporaryFailureUrls) {\n if (now - timestamp >= this.temporaryFailureCooldownMs) {\n this.temporaryFailureUrls.delete(url);\n }\n }\n }\n\n isGamInCooldown(): boolean {\n return Date.now() < this.globalNoFillCooldownUntil;\n }\n\n recordGamNoFill(): void {\n this.globalConsecutiveNoFills++;\n\n if (this.globalConsecutiveNoFills >= this.globalNoFillThreshold) {\n const exponent = this.globalConsecutiveNoFills - this.globalNoFillThreshold;\n const backoff = Math.min(\n this.globalNoFillBackoffBaseMs * Math.pow(2, exponent),\n this.globalNoFillBackoffMaxMs\n );\n this.globalNoFillCooldownUntil = Date.now() + backoff;\n\n if (this.debug) {\n console.log(\n `[CIRCUIT-BREAKER] GAM cooldown activated: ${backoff}ms (${this.globalConsecutiveNoFills} consecutive no-fills)`\n );\n }\n }\n }\n\n resetGamNoFillCounter(): void {\n if (this.globalConsecutiveNoFills > 0 && this.debug) {\n console.log(\n `[CIRCUIT-BREAKER] Resetting no-fill counter (was ${this.globalConsecutiveNoFills})`\n );\n }\n this.globalConsecutiveNoFills = 0;\n this.globalNoFillCooldownUntil = 0;\n }\n\n async enforceGlobalRateLimit(): Promise<void> {\n const now = Date.now();\n const elapsed = now - this.globalLastGamRequestTime;\n if (elapsed < this.globalMinGamIntervalMs) {\n const waitMs = this.globalMinGamIntervalMs - elapsed;\n if (this.debug) {\n console.log(`[RATE-LIMIT] Waiting ${waitMs}ms before next GAM request`);\n }\n await new Promise(resolve => setTimeout(resolve, waitMs));\n }\n this.globalLastGamRequestTime = Date.now();\n }\n\n // --- Watchdog ---\n\n 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.callbacks.onWatchdogTimeout();\n }, timeoutMs) as unknown as number;\n\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n\n 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 // --- Failsafe ---\n\n 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 });\n\n this.callbacks.onFailsafeTimeout();\n }, failsafeMs) as unknown as number;\n\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n\n 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 logAdState(event: string, extra: Record<string, unknown> = {}, adPlayer?: AdController, inAdBreak?: boolean, showAds?: boolean): void {\n if (!this.debug) {\n return;\n }\n\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: new Date().toISOString(),\n showAds: showAds ?? false,\n adPlaying: adPlayer?.isAdPlaying() ?? false,\n inAdBreak: inAdBreak ?? false,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n // --- Reset for ad break end ---\n\n resetForBreakEnd(): void {\n this.clearAdStopTimer();\n this.clearAdStartTimer();\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.scteAdBreakEndWallClockMs = undefined;\n this.adBreakPlayedDurationMs = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.consecutiveFailures = 0;\n this.globalConsecutiveNoFills = 0;\n this.adBreakEpoch++;\n }\n\n destroy(): void {\n this.clearAdStopTimer();\n this.clearAdStartTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n }\n}\n","import type { AdController, Scte35Marker } from \"../types\";\nimport type { AdTimingService } from \"./AdTimingService\";\n\nexport interface AdPreloadPoolDeps {\n debug: boolean;\n createAdPlayer(continueLiveStreamDuringAds: boolean): AdController;\n shouldContinueLiveStreamDuringAds(): boolean;\n timing: AdTimingService;\n generateVastUrlsWithCorrelators(baseUrl: string, count: number): string[];\n isInAdBreak(): boolean;\n getPendingAdBreak(): { marker: Scte35Marker; vastUrls: string[]; isFetching: boolean } | null;\n}\n\nexport class AdPreloadPool {\n private pool: Array<{\n vastUrl: string;\n adController: AdController;\n loadedAt: number;\n isReady: boolean;\n loadPromise: Promise<void>;\n durationSeconds?: number;\n }> = [];\n private readonly maxPoolSize: number = 2;\n private poolActive: boolean = false;\n private loopRunning: boolean = false;\n\n private deps: AdPreloadPoolDeps;\n\n constructor(deps: AdPreloadPoolDeps) {\n this.deps = deps;\n }\n\n get active(): boolean {\n return this.poolActive;\n }\n\n set active(value: boolean) {\n this.poolActive = value;\n }\n\n get isLoopRunning(): boolean {\n return this.loopRunning;\n }\n\n startPreloadPool(\n baseVastUrl: string,\n initialUrls: string[],\n startLoopImmediately: boolean = true\n ): void {\n if (this.poolActive) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n }\n return;\n }\n\n this.poolActive = true;\n\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Starting preload pool EARLY (target size: ${this.maxPoolSize})`);\n console.log(`[PRELOAD-POOL] Ad break hasn't started yet, but preloading ads in advance`);\n }\n\n for (const url of initialUrls) {\n if (this.pool.length < this.maxPoolSize) {\n this.preloadAdIntoPool(url);\n }\n }\n\n if (startLoopImmediately) {\n this.preloadPoolLoop(baseVastUrl);\n } else if (this.deps.debug) {\n console.log(\n \"[PRELOAD-POOL] Pre-break mode: preloaded once, waiting for SCTE start to continue fetching\"\n );\n }\n }\n\n private async preloadAdIntoPool(vastUrl: string): Promise<void> {\n const timing = this.deps.timing;\n\n if (timing.isGamInCooldown()) {\n if (this.deps.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n }\n return;\n }\n\n if (\n this.pool.some(entry => entry.vastUrl === vastUrl) ||\n timing.failedVastUrls.has(vastUrl) ||\n timing.isUrlInCooldown(vastUrl)\n ) {\n return;\n }\n\n if (this.pool.length >= this.maxPoolSize) {\n return;\n }\n\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Preloading ad into pool: ${vastUrl}`);\n }\n\n const epoch = timing.adBreakEpoch;\n const loadPromise = (async () => {\n let hasAdError = false;\n let adErrorPayload: any = null;\n let errorListenerCleanup: (() => void) | null = null;\n\n try {\n const continueLiveStreamDuringAds = this.deps.shouldContinueLiveStreamDuringAds();\n const preloadAd = this.deps.createAdPlayer(continueLiveStreamDuringAds);\n preloadAd.initialize();\n\n const errorListener = (payload?: any) => {\n hasAdError = true;\n adErrorPayload = payload;\n };\n preloadAd.on(\"ad_error\", errorListener);\n errorListenerCleanup = () => preloadAd.off(\"ad_error\", errorListener);\n\n await timing.enforceGlobalRateLimit();\n await preloadAd.requestAds(vastUrl);\n\n preloadAd.pause();\n\n await new Promise(resolve => setTimeout(resolve, 1500));\n\n preloadAd.pause();\n\n if (hasAdError) {\n const isNoFill = adErrorPayload?.isNoFill ||\n adErrorPayload?.code === 303 ||\n adErrorPayload?.vastErrorCode === 303;\n\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n preloadAd.destroy();\n\n timing.recordGamNoFill();\n\n if (isNoFill) {\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preload returned no-fill: ${vastUrl}`);\n }\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n } else {\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n }\n if (adErrorPayload && !timing.isTemporaryAdError(adErrorPayload as Error)) {\n timing.failedVastUrls.add(vastUrl);\n } else {\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n return;\n }\n\n if (!this.poolActive || epoch !== timing.adBreakEpoch) {\n if (this.deps.debug) {\n console.log(\n \"[PRELOAD-POOL] Discarding preloaded ad - break ended during fetch\"\n );\n }\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n try {\n preloadAd.destroy();\n } catch {}\n return;\n }\n\n const poolEntry: {\n vastUrl: string;\n adController: AdController;\n loadedAt: number;\n isReady: boolean;\n loadPromise: Promise<void>;\n durationSeconds?: number;\n } = {\n vastUrl,\n adController: preloadAd,\n loadedAt: Date.now(),\n isReady: true,\n loadPromise: Promise.resolve(),\n };\n const loadedDuration = preloadAd.getLoadedAdDuration?.();\n if (loadedDuration != null && loadedDuration > 0) {\n poolEntry.durationSeconds = loadedDuration;\n }\n\n const lateErrorListener = (payload?: any) => {\n const index = this.pool.findIndex(entry => entry.vastUrl === vastUrl);\n if (index >= 0) {\n this.pool.splice(index, 1);\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Late error detected, removed from pool: ${vastUrl}`, payload);\n }\n try {\n preloadAd.destroy();\n } catch {}\n }\n };\n preloadAd.on(\"ad_error\", lateErrorListener);\n\n this.pool.push(poolEntry);\n\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Ad preloaded (no errors detected within timeout) (pool size: ${this.pool.length}/${this.maxPoolSize}, duration=${poolEntry.durationSeconds ?? \"?\"}s)`);\n }\n\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n } catch (error) {\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n\n timing.recordGamNoFill();\n\n if (this.deps.debug) {\n console.warn(`[PRELOAD-POOL] Failed to preload ad: ${vastUrl}`, error);\n }\n\n if (error instanceof Error && !timing.isTemporaryAdError(error)) {\n timing.failedVastUrls.add(vastUrl);\n } else if (error instanceof Error && timing.isTemporaryAdError(error)) {\n timing.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n })();\n\n loadPromise.catch(() => {});\n }\n\n async preloadPoolLoop(baseVastUrl: string): Promise<void> {\n if (this.loopRunning) {\n return;\n }\n\n this.loopRunning = true;\n const epoch = this.deps.timing.adBreakEpoch;\n\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Starting continuous preload loop\");\n }\n\n while (this.poolActive && epoch === this.deps.timing.adBreakEpoch) {\n if (this.deps.timing.isGamInCooldown()) {\n if (this.deps.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n }\n break;\n }\n\n if (!this.deps.isInAdBreak() && this.pool.length >= this.maxPoolSize) {\n await new Promise(resolve => setTimeout(resolve, 2000));\n continue;\n }\n\n if (!this.deps.isInAdBreak() && this.deps.getPendingAdBreak() === null) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n }\n break;\n }\n\n while (this.pool.length < this.maxPoolSize) {\n if (\n !this.poolActive ||\n epoch !== this.deps.timing.adBreakEpoch ||\n this.deps.timing.isGamInCooldown()\n ) {\n break;\n }\n\n if (this.deps.isInAdBreak() && !this.deps.timing.hasTimeToStartAnotherAd()) {\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Not enough ad break time left, stopping preload\");\n }\n break;\n }\n\n const newUrls = this.deps.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const newUrl = newUrls[0];\n\n if (newUrl && !this.deps.timing.failedVastUrls.has(newUrl) && !this.deps.timing.isUrlInCooldown(newUrl)) {\n await this.preloadAdIntoPool(newUrl);\n }\n\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n\n await new Promise(resolve => setTimeout(resolve, 2000));\n }\n\n this.loopRunning = false;\n\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Preload loop ended\");\n }\n }\n\n getPreloadedAd(): { vastUrl: string; adController: AdController } | null {\n if (this.pool.length === 0) {\n return null;\n }\n\n const entry = this.pool.shift();\n if (!entry || !entry.isReady) {\n return null;\n }\n\n if (this.deps.debug) {\n console.log(`[PRELOAD-POOL] Using preloaded ad from pool (${this.pool.length} remaining)`);\n }\n\n return {\n vastUrl: entry.vastUrl,\n adController: entry.adController,\n };\n }\n\n stop(): void {\n this.poolActive = false;\n this.loopRunning = false;\n\n for (const entry of this.pool) {\n try {\n entry.adController.destroy();\n } catch (error) {\n if (this.deps.debug) {\n console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n }\n }\n }\n\n this.pool = [];\n\n if (this.deps.debug) {\n console.log(\"[PRELOAD-POOL] Preload pool stopped and cleaned up\");\n }\n }\n}\n","export class PlaceholderLayer {\n private container: HTMLDivElement | undefined;\n private debug: boolean;\n private video: HTMLVideoElement;\n\n constructor(video: HTMLVideoElement, debug: boolean) {\n this.video = video;\n this.debug = debug;\n }\n\n private ensureContainer(): void {\n if (this.container) {\n return;\n }\n\n const el = document.createElement(\"div\");\n el.style.position = \"absolute\";\n el.style.left = \"0\";\n el.style.top = \"0\";\n el.style.right = \"0\";\n el.style.bottom = \"0\";\n el.style.display = \"none\";\n el.style.alignItems = \"center\";\n el.style.justifyContent = \"center\";\n el.style.pointerEvents = \"none\";\n el.style.zIndex = \"5\";\n el.style.backgroundColor = \"#000\";\n el.style.transition = \"opacity 0.3s ease-in-out\";\n el.style.opacity = \"0\";\n\n if (!this.video.parentElement) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n\n this.video.parentElement.appendChild(el);\n this.container = el;\n }\n\n show(): void {\n this.ensureContainer();\n\n if (!this.container) {\n return;\n }\n\n if (!this.video.muted) {\n this.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n\n const wasHidden = this.container.style.display === \"none\" || this.container.style.opacity === \"0\";\n if (wasHidden) {\n this.container.style.transition = \"none\";\n } else {\n this.container.style.transition = \"opacity 0.3s ease-in-out\";\n }\n\n this.container.style.backgroundColor = \"#000\";\n this.container.style.display = \"flex\";\n this.container.offsetHeight;\n this.container.style.opacity = \"1\";\n this.container.style.pointerEvents = \"auto\";\n\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.container) {\n this.container.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and ad layer)\");\n }\n }\n\n hide(): void {\n if (!this.container) {\n return;\n }\n\n this.container.style.opacity = \"0\";\n setTimeout(() => {\n if (this.container) {\n this.container.style.display = \"none\";\n this.container.style.pointerEvents = \"none\";\n this.container.style.backgroundColor = \"#000\";\n }\n }, 300);\n\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n\n destroy(): void {\n if (this.container) {\n if (this.container.parentElement) {\n this.container.parentElement.removeChild(this.container);\n }\n this.container = undefined;\n }\n }\n}\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n} from \"../types\";\nimport type { Scte35CueContext } from \"./playerTypes\";\nimport {\n parseScte35FromId3,\n parseScte35FromTsPackets,\n normalizeFragmentPayload,\n getFragmentStartSeconds,\n parseCueOutDuration,\n parseCueOutCont,\n parseAttributeList,\n toNumber,\n} from \"./Scte35Parser\";\nimport type { Scte35CueManager } from \"./Scte35CueManager\";\nimport type { AdTimingService } from \"./AdTimingService\";\n\nexport interface HlsEngineCallbacks {\n onManifestParsed(isLive: boolean): Promise<void>;\n onScte35Cue(marker: Scte35Marker, context: Scte35CueContext): void;\n activatePendingCuesForFragment(frag: any): void;\n onFatalDestroy(): void;\n isInAdBreak(): boolean;\n hasPendingAdBreak(): boolean;\n}\n\nexport class HlsEngine {\n hls: Hls | undefined;\n isLiveStream: boolean = false;\n nativeHlsMode: boolean = false;\n videoSrcProtection: string | null = null;\n\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n\n private readonly config: StormcloudVideoPlayerConfig;\n private readonly video: HTMLVideoElement;\n private readonly cueManager: Scte35CueManager;\n private readonly timing: AdTimingService;\n private readonly callbacks: HlsEngineCallbacks;\n\n constructor(\n config: StormcloudVideoPlayerConfig,\n video: HTMLVideoElement,\n cueManager: Scte35CueManager,\n timing: AdTimingService,\n callbacks: HlsEngineCallbacks\n ) {\n this.config = config;\n this.video = video;\n this.cueManager = cueManager;\n this.timing = timing;\n this.callbacks = callbacks;\n }\n\n private get debug(): boolean {\n return !!this.config.debugAdTiming;\n }\n\n shouldUseNativeHls(getStreamType: () => \"hls\" | \"other\"): boolean {\n const streamType = 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\n async setupNativeHls(): Promise<void> {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.isLiveStream ?? (this.config.lowLatencyMode ?? false);\n\n if (this.debug) {\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 if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n }\n\n setupHls(): void {\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.config.isLiveStream ??\n (this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false);\n\n await this.callbacks.onManifestParsed(this.isLiveStream);\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.debug) {\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.callbacks.isInAdBreak() || this.callbacks.hasPendingAdBreak()) {\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 ? 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 const durationSeconds = parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value, earlyDetection: true },\n } as Scte35Marker;\n\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n }\n\n this.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"early\", frag),\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.debug) {\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.debug) {\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.debug) {\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_LOADED, (_evt, data: any) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : undefined,\n getFragmentStartSeconds(data?.frag)\n );\n });\n\n this.hls.on(Hls.Events.FRAG_DECRYPTED, (_evt, data: any) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : undefined,\n getFragmentStartSeconds(data?.frag)\n );\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)) {\n this.callbacks.activatePendingCuesForFragment(frag);\n return;\n }\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-CONT\")) {\n const prog = 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.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.callbacks.onScte35Cue(\n { type: \"end\", raw: { tag, value } },\n {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n }\n );\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = 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 = 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.callbacks.onScte35Cue(marker, {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n }\n if (hasScteIn) {\n this.callbacks.onScte35Cue(\n { type: \"end\", raw: { tag, value, attrs } },\n {\n ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n }\n );\n }\n }\n }\n this.callbacks.activatePendingCuesForFragment(frag);\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.callbacks.onFatalDestroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.timing.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = parseScte35FromId3(tag);\n if (marker) {\n this.callbacks.onScte35Cue(marker, {\n source: \"id3\",\n readiness: \"playback\",\n });\n }\n }\n\n private processFragmentScte35Payload(\n payloadData: unknown,\n fragmentSn?: number,\n fragmentStartSeconds?: number\n ): void {\n const payload = normalizeFragmentPayload(payloadData);\n if (!payload) {\n return;\n }\n\n const markers = parseScte35FromTsPackets(\n payload,\n this.cueManager.tsScte35Pids,\n this.cueManager.pmtPids,\n this.cueManager.processedTsScte35Sections\n );\n markers.forEach((marker) => {\n const context: Scte35CueContext = {\n source: \"ts\",\n readiness: \"early\",\n };\n if (fragmentSn !== undefined) {\n context.fragmentSn = fragmentSn;\n }\n if (fragmentStartSeconds !== undefined) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n this.callbacks.onScte35Cue(marker, context);\n });\n }\n\n destroy(): void {\n this.hls?.destroy();\n this.hls = undefined;\n }\n}\n","import type { AdController } from \"../types\";\n\nexport function getAdAudioVolume(adPlayer: AdController): number {\n return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();\n}\n\nexport function toggleMute(\n video: HTMLVideoElement,\n adPlayer: AdController,\n debug: boolean\n): void {\n if (adPlayer.isAdPlaying()) {\n const newMutedState = !adPlayer.getOriginalMutedState();\n const restoreVolume = adPlayer.getOriginalVolume() || 1;\n\n adPlayer.updateOriginalMutedState(newMutedState, video.volume);\n adPlayer.setAdVolume(newMutedState ? 0 : restoreVolume);\n\n if (debug) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n video.muted = !video.muted;\n adPlayer.updateOriginalMutedState(video.muted, video.volume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", video.muted);\n }\n }\n}\n\nexport function toggleFullscreen(\n video: HTMLVideoElement,\n debug: boolean\n): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = 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 (debug) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (debug) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document\n .exitFullscreen()\n .then(() => {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (debug) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n}\n\nexport function isMuted(\n video: HTMLVideoElement,\n adPlayer: AdController\n): boolean {\n if (adPlayer.isAdPlaying()) {\n return adPlayer.getOriginalMutedState();\n }\n return video.muted;\n}\n\nexport function setMuted(\n video: HTMLVideoElement,\n adPlayer: AdController,\n muted: boolean,\n debug: boolean\n): void {\n const adPlaying = adPlayer.isAdPlaying();\n\n if (adPlaying && muted === video.muted) {\n if (debug) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n\n video.muted = muted;\n\n if (adPlaying) {\n adPlayer.updateOriginalMutedState(muted, video.volume);\n adPlayer.setAdVolume(muted ? 0 : 1);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted,\n });\n }\n return;\n }\n\n adPlayer.updateOriginalMutedState(muted, video.volume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n}\n\nexport function setVolume(\n video: HTMLVideoElement,\n adPlayer: AdController,\n volume: number,\n debug: boolean\n): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = adPlayer.isAdPlaying();\n\n if (adPlaying) {\n adPlayer.setAdVolume(clampedVolume);\n adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume,\n });\n }\n } else {\n video.volume = clampedVolume;\n video.muted = clampedVolume === 0;\n adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n}\n\nexport function getVolume(\n video: HTMLVideoElement,\n adPlayer: AdController\n): number {\n const adPlaying = adPlayer.isAdPlaying();\n if (adPlaying) {\n return adPlayer.getAdVolume();\n }\n return video.volume;\n}\n\nexport function isFullscreen(): boolean {\n return !!document.fullscreenElement;\n}\n\nexport function resizePlayer(\n video: HTMLVideoElement,\n adPlayer: AdController,\n debug: boolean\n): void {\n if (debug) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n\n if (adPlayer && adPlayer.isAdPlaying()) {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 480;\n\n if (debug) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n\n adPlayer.resize(width, height);\n }\n}\n","import type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n AdController,\n} from \"../types\";\nimport {\n sendAdLoadedTracking,\n sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport type { AdTimingService } from \"./AdTimingService\";\nimport type { AdPreloadPool } from \"./AdPreloadPool\";\nimport type { AdConfigManager } from \"./AdConfigManager\";\nimport type { Scte35CueManager } from \"./Scte35CueManager\";\nimport type { PlaceholderLayer } from \"./PlaceholderLayer\";\nimport { getAdAudioVolume } from \"./PlayerControls\";\n\nexport interface AdBreakOrchestratorHost {\n readonly config: StormcloudVideoPlayerConfig;\n readonly video: HTMLVideoElement;\n getAdPlayer(): AdController;\n setAdPlayer(player: AdController): void;\n createAdPlayer(continueLiveStreamDuringAds: boolean): AdController;\n shouldContinueLiveStreamDuringAds(): boolean;\n generateVastUrls(baseUrl: string, count: number): string[];\n}\n\nexport class AdBreakOrchestrator {\n inAdBreak = false;\n showAds: boolean = false;\n isShowingPlaceholder: boolean = false;\n adDetectSentForCurrentBreak: boolean = false;\n\n private continuousFetchingActive: boolean = false;\n private continuousFetchLoopRunning = false;\n adRequestQueue: string[] = [];\n adPodQueue: string[] = [];\n private readonly maxPlaceholderDurationMs: number = 5000;\n\n pendingAdBreak: {\n marker: Scte35Marker;\n detectedAtFragmentSn?: number;\n vastUrls: string[];\n isFetching: boolean;\n fetchStartTime?: number;\n } | null = null;\n prefetchTimerId: number | undefined;\n\n private readonly host: AdBreakOrchestratorHost;\n private readonly timing: AdTimingService;\n private readonly preloadPool: AdPreloadPool;\n private readonly adConfig: AdConfigManager;\n private readonly cueManager: Scte35CueManager;\n private readonly placeholder: PlaceholderLayer;\n\n constructor(\n host: AdBreakOrchestratorHost,\n timing: AdTimingService,\n preloadPool: AdPreloadPool,\n adConfig: AdConfigManager,\n cueManager: Scte35CueManager,\n placeholder: PlaceholderLayer\n ) {\n this.host = host;\n this.timing = timing;\n this.preloadPool = preloadPool;\n this.adConfig = adConfig;\n this.cueManager = cueManager;\n this.placeholder = placeholder;\n }\n\n private get debug(): boolean {\n return !!this.host.config.debugAdTiming;\n }\n\n // ───────────────────────────────────────────────────────────────\n // IMA event listeners\n // ───────────────────────────────────────────────────────────────\n\n attachImaEventListeners(): void {\n const adPlayer = this.host.getAdPlayer();\n adPlayer.on(\"all_ads_completed\", () => {\n sendAdImpressionTracking(\n this.host.config.licenseKey,\n { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n const remaining = this.timing.getRemainingAdMs();\n\n this.timing.consecutiveFailures = 0;\n\n if (this.debug) {\n console.log(\n `[StormcloudVideoPlayer] all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n\n if (this.inAdBreak) {\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n adPlayer.on(\"ad_error\", (errorPayload?: any) => {\n let errorMessage = \"Ad playback failed\";\n\n if (errorPayload) {\n const errorCode = errorPayload.code || errorPayload.errorCode || \"unknown\";\n const vastErrorCode = errorPayload.vastErrorCode;\n const message = errorPayload.message || errorPayload.errorMessage || \"Unknown error\";\n const cause = errorPayload.cause || errorPayload.innerError || errorPayload.error;\n\n errorMessage = `Ad error: AdError ${errorCode}: ${message}`;\n\n if (vastErrorCode && vastErrorCode !== \"N/A\" && vastErrorCode !== errorCode) {\n errorMessage += ` (VAST Error Code: ${vastErrorCode})`;\n }\n\n if (cause) {\n const causeMessage = typeof cause === \"string\" ? cause : (cause.message || String(cause));\n errorMessage += `. Caused by: ${causeMessage}`;\n }\n }\n\n console.error(\"[AD-ERROR]\", errorMessage, errorPayload || \"\");\n this.handleAdFailure();\n });\n adPlayer.on(\"content_pause\", () => {\n this.timing.clearAdFailsafeTimer();\n this.timing.clearAdRequestWatchdog();\n this.timing.activeAdRequestToken = null;\n this.showAds = true;\n this.timing.resetGamNoFillCounter();\n\n if (this.inAdBreak && this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n\n this.host.getAdPlayer().setAdVolume(getAdAudioVolume(this.host.getAdPlayer()));\n\n if (this.isShowingPlaceholder) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.host.getAdPlayer().hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n adPlayer.on(\"content_resume\", () => {\n sendAdImpressionTracking(\n this.host.config.licenseKey,\n { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n if (!this.host.video.muted) {\n this.host.video.muted = true;\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n }\n }\n\n this.timing.clearAdFailsafeTimer();\n this.timing.clearAdRequestWatchdog();\n this.timing.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n return;\n }\n\n this.timing.consecutiveFailures = 0;\n\n this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n const remaining = this.timing.getRemainingAdMs();\n\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n });\n }\n\n recreateAdController(): void {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Recreating AdController for new ad\");\n }\n\n const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n const adPlayer = this.host.getAdPlayer();\n if (shouldShowPlaceholder && adPlayer) {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old AdController\");\n }\n this.placeholder.show();\n adPlayer.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n\n const preservedMutedState = adPlayer.getOriginalMutedState();\n const preservedVolumeState = adPlayer.getOriginalVolume();\n\n if (adPlayer) {\n try {\n adPlayer.destroy();\n this.host.video.muted = true;\n } catch (error) {\n if (this.debug) {\n console.warn(\"[StormcloudVideoPlayer] Error destroying old AdController:\", error);\n }\n }\n }\n\n const continueLiveStreamDuringAds = this.host.shouldContinueLiveStreamDuringAds();\n const newAdPlayer = this.host.createAdPlayer(continueLiveStreamDuringAds);\n this.host.setAdPlayer(newAdPlayer);\n\n newAdPlayer.initialize();\n newAdPlayer.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n this.attachImaEventListeners();\n\n if (shouldShowPlaceholder) {\n this.placeholder.show();\n newAdPlayer.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n }\n\n clearPendingAdBreak(): void {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = undefined;\n }\n this.pendingAdBreak = null;\n this.cueManager.pendingScte35CueKey = undefined;\n this.adConfig.podAssignedByPrefetch = false;\n }\n\n // ───────────────────────────────────────────────────────────────\n // Ad break start\n // ───────────────────────────────────────────────────────────────\n\n async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const scheduled = this.adConfig.findCurrentOrNextBreak(\n this.host.video.currentTime * 1000\n );\n if (scheduled) {\n this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));\n }\n const tags = this.adConfig.selectVastTagsForBreak(scheduled);\n\n let baseVastUrl: string;\n\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.adConfig.apiVastTagUrl) {\n baseVastUrl = this.adConfig.apiVastTagUrl;\n } else {\n this.clearPendingAdBreak();\n return;\n }\n\n const adBreakDurationMs =\n _marker.durationSeconds != null\n ? _marker.durationSeconds * 1000\n : scheduled?.durationMs;\n\n if (this.debug) {\n const mode = this.host.config.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n\n this.timing.failedVastUrls.clear();\n this.timing.temporaryFailureUrls.clear();\n this.timing.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.timing.totalAdRequestsInBreak = 0;\n\n if (this.adConfig.podAssignedByPrefetch) {\n this.adConfig.podAssignedByPrefetch = false;\n } else {\n this.adConfig.beginNewAdPod();\n }\n\n const currentMuted = this.host.video.muted;\n const currentVolume = this.host.video.volume;\n this.host.getAdPlayer().updateOriginalMutedState(currentMuted, currentVolume);\n\n this.inAdBreak = true;\n this.timing.adBreakPlayedDurationMs = 0;\n this.timing.currentAdIndex = 0;\n this.timing.totalAdsInBreak = 0;\n this.adPodQueue = [];\n this.showAds = false;\n\n if (\n this.timing.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.timing.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n\n let firstAdUrl: string | undefined;\n let usePreloadedAd = false;\n let preloadedController: AdController | undefined;\n\n const preloaded = this.preloadPool.getPreloadedAd();\n if (preloaded) {\n firstAdUrl = preloaded.vastUrl;\n preloadedController = preloaded.adController;\n usePreloadedAd = true;\n\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: firstAdUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n }\n } else if (this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0) {\n this.adRequestQueue = [...this.pendingAdBreak.vastUrls];\n firstAdUrl = this.adRequestQueue.shift();\n\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Pool empty, using prefetched URLs (${this.adRequestQueue.length + 1} available)`);\n }\n\n this.clearPendingAdBreak();\n } else {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Generating new ad URLs...\");\n }\n\n const firstAdUrlArray = this.host.generateVastUrls(baseVastUrl, 1);\n firstAdUrl = firstAdUrlArray[0];\n this.adRequestQueue = [];\n }\n\n if (!firstAdUrl) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Failed to get first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First VAST URL:\", firstAdUrl);\n }\n\n try {\n if (usePreloadedAd && preloadedController) {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedController)) {\n this.timing.rejectLoadedAdForDuration(preloadedController);\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n const adPlayer = this.host.getAdPlayer();\n const preservedMuted = adPlayer.getOriginalMutedState();\n const preservedVolume = adPlayer.getOriginalVolume();\n adPlayer.destroy();\n this.host.video.muted = true;\n this.host.setAdPlayer(preloadedController);\n preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n\n this.attachImaEventListeners();\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n }\n\n preloadedController.resume();\n\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n\n if (!this.preloadPool.active) {\n this.preloadPool.active = true;\n }\n if (!this.preloadPool.isLoopRunning) {\n this.preloadPool.preloadPoolLoop(baseVastUrl);\n }\n\n await preloadedController.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n const adVolume = currentMuted ? 0 : currentVolume;\n preloadedController.setAdVolume(adVolume);\n } else {\n const adPlayer = this.host.getAdPlayer();\n await this.timing.enforceGlobalRateLimit();\n this.timing.lastAdRequestTime = Date.now();\n await adPlayer.requestAds(firstAdUrl);\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: firstAdUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad request successful, starting playback\");\n }\n\n if (!this.timing.ensureLoadedAdFitsBudget(adPlayer)) {\n this.timing.rejectLoadedAdForDuration(adPlayer);\n this.recreateAdController();\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n\n if (!this.preloadPool.active) {\n this.preloadPool.startPreloadPool(baseVastUrl, []);\n }\n\n await adPlayer.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n const adVolume = currentMuted ? 0 : currentVolume;\n adPlayer.setAdVolume(adVolume);\n }\n } catch (error) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] First ad request failed:\", error);\n }\n\n if (!usePreloadedAd) {\n const fallbackPreloaded = this.preloadPool.getPreloadedAd();\n if (fallbackPreloaded) {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad failed, using preloaded fallback\");\n }\n\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(fallbackPreloaded.adController)) {\n this.timing.rejectLoadedAdForDuration(fallbackPreloaded.adController);\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n this.swapToPreloadedAdPlayer(fallbackPreloaded.adController);\n\n this.timing.consecutiveFailures = 0;\n this.startContinuousFetching(baseVastUrl);\n\n if (!this.preloadPool.active) {\n this.preloadPool.active = true;\n this.preloadPool.preloadPoolLoop(baseVastUrl);\n }\n\n const ap = this.host.getAdPlayer();\n await ap.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n const adVolume = currentMuted ? 0 : currentVolume;\n ap.setAdVolume(adVolume);\n\n return;\n } catch (fallbackError) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n }\n\n if (this.timing.isTemporaryAdError(error as Error)) {\n this.timing.temporaryFailureUrls.set(firstAdUrl, Date.now());\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n }\n } else {\n this.timing.failedVastUrls.add(firstAdUrl);\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n }\n }\n this.timing.consecutiveFailures++;\n\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n }\n }\n\n private swapToPreloadedAdPlayer(preloadedController: AdController): void {\n const adPlayer = this.host.getAdPlayer();\n const preservedMuted = adPlayer.getOriginalMutedState();\n const preservedVolume = adPlayer.getOriginalVolume();\n adPlayer.destroy();\n this.host.video.muted = true;\n this.host.setAdPlayer(preloadedController);\n this.attachImaEventListeners();\n preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n preloadedController.resume();\n }\n\n // ───────────────────────────────────────────────────────────────\n // Continuous fetching\n // ───────────────────────────────────────────────────────────────\n\n private startContinuousFetching(baseVastUrl: string): void {\n if (!this.continuousFetchingActive) {\n return;\n }\n\n if (this.continuousFetchLoopRunning) {\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Fetch loop already running, skipping duplicate start\");\n }\n return;\n }\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Starting continuous ad fetching loop\");\n }\n\n this.continuousFetchLoopRunning = true;\n this.continuousFetchLoop(baseVastUrl);\n }\n\n private async continuousFetchLoop(baseVastUrl: string): Promise<void> {\n const epoch = this.timing.adBreakEpoch;\n while (\n this.continuousFetchingActive &&\n this.inAdBreak &&\n epoch === this.timing.adBreakEpoch\n ) {\n const remaining = Math.min(\n this.timing.getWallClockRemainingAdMs(),\n this.timing.getDurationBudgetRemainingMs()\n );\n\n if (remaining <= this.timing.getMinRemainingMsToStartAd()) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Not enough ad break time left (wall=${this.timing.getWallClockRemainingAdMs()}ms, budget=${this.timing.getDurationBudgetRemainingMs()}ms), stopping URL generation`);\n }\n break;\n }\n\n if (this.timing.isGamInCooldown()) {\n if (this.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n }\n break;\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), stopping URL generation`);\n }\n break;\n }\n\n if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Maximum ad requests reached (${this.timing.maxTotalAdRequestsPerBreak}), stopping`);\n }\n break;\n }\n\n const maxQueueSize = 5;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] URL queue full (${this.adRequestQueue.length}), waiting...`);\n }\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n const newAdUrl = this.host.generateVastUrls(baseVastUrl, 1)[0];\n\n if (!newAdUrl || this.timing.failedVastUrls.has(newAdUrl) || this.timing.isUrlInCooldown(newAdUrl)) {\n await new Promise(resolve => setTimeout(resolve, 500));\n continue;\n }\n\n if (this.debug) {\n const queuedUrlsPreview = [...this.adRequestQueue, newAdUrl];\n console.log(\n `[CONTINUOUS-FETCH] Queued VAST URL (queue size: ${queuedUrlsPreview.length})`,\n { queuedUrls: queuedUrlsPreview }\n );\n }\n\n this.adRequestQueue.push(newAdUrl);\n\n const generationDelay = this.timing.consecutiveFailures > 0\n ? Math.min(1000 * Math.pow(2, this.timing.consecutiveFailures), 5000)\n : 500;\n await new Promise(resolve => setTimeout(resolve, generationDelay));\n }\n\n this.continuousFetchLoopRunning = false;\n\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] URL generation loop ended (queued: ${this.adRequestQueue.length})`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n }\n\n stopContinuousFetching(): void {\n this.continuousFetchingActive = false;\n this.continuousFetchLoopRunning = false;\n\n this.placeholder.hide();\n\n if (this.debug) {\n console.log(\"[CONTINUOUS-FETCH] Stopping continuous ad fetching\");\n }\n }\n\n // ───────────────────────────────────────────────────────────────\n // Ad iteration\n // ───────────────────────────────────────────────────────────────\n\n async tryNextAvailableAdWithRateLimit(): Promise<void> {\n if (!this.inAdBreak) {\n return;\n }\n\n const epoch = this.timing.adBreakEpoch;\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n const backoffMultiplier = Math.pow(2, this.timing.consecutiveFailures);\n const backoffDelay = Math.min(this.timing.backoffBaseMs * backoffMultiplier, this.timing.maxBackoffMs);\n const effectiveMinInterval = this.timing.minAdRequestIntervalMs + (this.timing.consecutiveFailures > 0 ? backoffDelay : 0);\n\n const timeSinceLastRequest = Date.now() - this.timing.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.timing.consecutiveFailures} failures)`);\n }\n await new Promise(resolve => setTimeout(resolve, waitTime));\n }\n\n if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) {\n return;\n }\n\n return this.tryNextAvailableAd(0);\n }\n\n private async tryNextAvailableAd(retryCount: number = 0): Promise<void> {\n if (!this.inAdBreak) {\n return;\n }\n\n const remaining = this.timing.getRemainingAdMs();\n\n if (!this.timing.hasTimeToStartAnotherAd()) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Not enough time remaining (${remaining}ms) to start another ad, ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.timing.isGamInCooldown()) {\n if (this.debug) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n this.timing.cleanupTemporaryFailures();\n\n const preloaded = this.preloadPool.getPreloadedAd();\n if (preloaded) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Using preloaded ad from pool`);\n }\n\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: preloaded.vastUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloaded.adController)) {\n this.timing.rejectLoadedAdForDuration(preloaded.adController);\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n this.swapToPreloadedAdPlayer(preloaded.adController);\n\n const ap = this.host.getAdPlayer();\n await ap.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n ap.setAdVolume(getAdAudioVolume(ap));\n\n this.timing.consecutiveFailures = 0;\n return;\n } catch (error) {\n if (this.debug) {\n console.warn(\"[CONTINUOUS-FETCH] Preloaded ad failed to play:\", error);\n }\n }\n }\n\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n\n if (!nextAdUrl) continue;\n\n if (this.timing.failedVastUrls.has(nextAdUrl)) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping permanently-failed URL, trying next...\");\n continue;\n }\n\n if (this.timing.isUrlInCooldown(nextAdUrl)) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping URL in cooldown (recent no-fill), trying next...\");\n continue;\n }\n\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Requesting next ad via HLS ad player (${this.timing.currentAdIndex + 1}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n\n try {\n await this.playSingleAd(nextAdUrl);\n this.timing.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = (error as Error).message;\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad request failed:\", errorMessage);\n\n if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.timing.consecutiveFailures++;\n }\n\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n\n const maxRetries = 3;\n if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2000) {\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Queue empty, waiting for URLs... (${retryCount + 1}/${maxRetries})`);\n }\n await new Promise(resolve => setTimeout(resolve, 500));\n await this.tryNextAvailableAd(retryCount + 1);\n return;\n }\n\n if (!this.isShowingPlaceholder && remaining > 1000) {\n this.showPlaceholderAndWaitForAds();\n } else {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] No more ads available, ending ad break\");\n this.handleAdPodComplete();\n }\n }\n\n // ───────────────────────────────────────────────────────────────\n // Single ad playback\n // ───────────────────────────────────────────────────────────────\n\n async playSingleAd(vastTagUrl: string): Promise<void> {\n const adPlayer = this.host.getAdPlayer();\n if (adPlayer.isAdPlaying()) return;\n\n if (this.timing.failedVastUrls.has(vastTagUrl)) {\n if (this.debug) console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n throw new Error(\"VAST URL permanently failed\");\n }\n\n if (this.timing.isUrlInCooldown(vastTagUrl)) {\n if (this.debug) console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n throw new Error(\"VAST URL in cooldown after no-fill\");\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n throw new Error(\"Too many consecutive failures\");\n }\n\n if (this.timing.isGamInCooldown()) {\n if (this.debug) console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n throw new Error(\"GAM in cooldown\");\n }\n\n this.recreateAdController();\n\n const requestToken = ++this.timing.adRequestTokenCounter;\n this.timing.activeAdRequestToken = requestToken;\n this.timing.startAdRequestWatchdog(requestToken);\n\n try {\n await this.timing.enforceGlobalRateLimit();\n this.timing.lastAdRequestTime = Date.now();\n const ap = this.host.getAdPlayer();\n await ap.requestAds(vastTagUrl);\n sendAdLoadedTracking(\n this.host.config.licenseKey,\n { source: \"hls\", vastUrl: vastTagUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n this.timing.clearAdRequestWatchdog();\n\n if (this.timing.activeAdRequestToken !== requestToken) return;\n\n if (!this.timing.ensureLoadedAdFitsBudget(ap)) {\n this.timing.rejectLoadedAdForDuration(ap);\n this.recreateAdController();\n throw new Error(\"ad_duration_exceeds_budget\");\n }\n\n try {\n this.timing.startAdFailsafeTimer(requestToken);\n await ap.play();\n this.timing.markAdStarted();\n\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n\n ap.setAdVolume(getAdAudioVolume(ap));\n this.timing.consecutiveFailures = 0;\n this.timing.temporaryFailureUrls.delete(vastTagUrl);\n } catch (playError) {\n if (this.debug) console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n\n const preloadedFallback = this.preloadPool.getPreloadedAd();\n if (preloadedFallback) {\n if (this.debug) console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n throw playError;\n }\n this.timing.clearAdFailsafeTimer();\n this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n this.timing.consecutiveFailures = 0;\n const fbAp = this.host.getAdPlayer();\n await fbAp.play();\n this.timing.markAdStarted();\n if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n this.timing.scheduleAdStopAtBreakBoundary();\n }\n fbAp.setAdVolume(getAdAudioVolume(fbAp));\n return;\n } catch (fallbackError) {\n if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n\n if (this.timing.isTemporaryAdError(playError as Error)) {\n this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.debug) console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n } else {\n this.timing.failedVastUrls.add(vastTagUrl);\n if (this.debug) console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n }\n\n this.timing.clearAdFailsafeTimer();\n if (this.timing.activeAdRequestToken === requestToken) {\n this.timing.activeAdRequestToken = null;\n }\n throw playError;\n }\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"\";\n if (this.debug) console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n\n const preloadedFallback = this.preloadPool.getPreloadedAd();\n if (preloadedFallback) {\n if (this.debug) console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n try {\n if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n throw error;\n }\n this.timing.clearAdRequestWatchdog();\n this.timing.clearAdFailsafeTimer();\n this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n this.timing.consecutiveFailures = 0;\n const fbAp = this.host.getAdPlayer();\n await fbAp.play();\n this.timing.markAdStarted();\n fbAp.setAdVolume(getAdAudioVolume(fbAp));\n return;\n } catch (fallbackError) {\n if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n\n if (this.timing.isTemporaryAdError(error as Error)) {\n this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.debug) console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n } else {\n this.timing.failedVastUrls.add(vastTagUrl);\n if (this.debug) console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n }\n\n this.timing.clearAdRequestWatchdog();\n this.timing.clearAdFailsafeTimer();\n if (this.timing.activeAdRequestToken === requestToken) {\n this.timing.activeAdRequestToken = null;\n }\n throw error;\n }\n }\n\n // ───────────────────────────────────────────────────────────────\n // Placeholder wait\n // ───────────────────────────────────────────────────────────────\n\n private async showPlaceholderAndWaitForAds(): Promise<void> {\n const remaining = this.timing.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n\n if (this.timing.isGamInCooldown()) {\n if (this.debug) console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n this.handleAdPodComplete();\n return;\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping placeholder - too many consecutive failures\");\n this.handleAdPodComplete();\n return;\n }\n\n if (waitTime < 1000) {\n this.handleAdPodComplete();\n return;\n }\n\n if (this.debug) {\n console.log(`[CONTINUOUS-FETCH] Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n }\n\n this.isShowingPlaceholder = true;\n this.host.getAdPlayer().showPlaceholder();\n\n const checkInterval = 300;\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) return;\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Too many failures during placeholder wait\");\n break;\n }\n\n if (!this.timing.hasTimeToStartAnotherAd()) {\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Not enough time remaining during placeholder wait, ending ad break\");\n break;\n }\n\n while (this.adRequestQueue.length > 0) {\n if (!this.timing.hasTimeToStartAnotherAd()) break;\n\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) continue;\n if (this.timing.failedVastUrls.has(nextAdUrl)) continue;\n if (this.timing.isUrlInCooldown(nextAdUrl)) continue;\n\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad URL available, requesting via HLS ad player\");\n\n this.isShowingPlaceholder = false;\n this.host.getAdPlayer().hidePlaceholder();\n\n try {\n await this.playSingleAd(nextAdUrl);\n this.timing.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = (error as Error).message;\n if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n await this.tryNextAvailableAdWithRateLimit();\n return;\n }\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.timing.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n }\n\n if (this.debug) console.log(\"[CONTINUOUS-FETCH] Placeholder timeout, ending ad break\");\n\n this.isShowingPlaceholder = false;\n this.host.getAdPlayer().hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n // ───────────────────────────────────────────────────────────────\n // Ad break completion\n // ───────────────────────────────────────────────────────────────\n\n handleAdPodComplete(): void {\n if (this.debug) {\n console.log(\"[StormcloudVideoPlayer] Ad pod complete - cleaning up\");\n }\n\n this.timing.resetForBreakEnd();\n\n this.stopContinuousFetching();\n this.preloadPool.stop();\n this.clearPendingAdBreak();\n\n if (this.isShowingPlaceholder) {\n this.host.getAdPlayer().hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n\n this.adRequestQueue = [];\n\n this.inAdBreak = false;\n this.adDetectSentForCurrentBreak = false;\n this.cueManager.activeScte35BreakKey = undefined;\n this.cueManager.scheduledScte35BreakKey = undefined;\n this.adPodQueue = [];\n this.showAds = false;\n\n this.host.getAdPlayer().stop().catch(() => {});\n\n const restoredMuted = this.host.getAdPlayer().getOriginalMutedState();\n const restoredVolume = this.host.getAdPlayer().getOriginalVolume();\n\n if (this.host.video.muted !== restoredMuted) {\n this.host.video.muted = restoredMuted;\n }\n if (Math.abs(this.host.video.volume - restoredVolume) > 0.01) {\n this.host.video.volume = restoredVolume;\n }\n\n if (this.host.shouldContinueLiveStreamDuringAds()) {\n if (this.host.video.paused) {\n if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n this.host.video.play()?.catch(() => {});\n } else {\n if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n } else if (this.host.video.paused) {\n this.host.video.play()?.catch(() => {});\n }\n }\n\n handleAdFailure(): void {\n this.timing.consecutiveFailures++;\n this.timing.recordGamNoFill();\n const remaining = this.timing.getRemainingAdMs();\n\n if (this.debug) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.timing.consecutiveFailures}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n\n if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n if (this.debug) console.log(`[CONTINUOUS-FETCH] Max consecutive failures reached (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n this.handleAdPodComplete();\n return;\n }\n\n if (this.timing.hasTimeToStartAnotherAd()) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n if (this.debug) console.log(\"[AD-ERROR] Ad failed and not enough time remaining for another ad. Failed URLs:\", this.timing.failedVastUrls.size);\n this.handleAdPodComplete();\n }\n }\n}\n"]}
|