stormcloud-video-player 0.3.60 → 0.3.61
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 +242 -211
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +25 -16
- package/lib/index.d.ts +25 -16
- package/lib/index.js +242 -211
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +242 -211
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/players/HlsPlayer.cjs +242 -211
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +242 -211
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-Vj55FghO.d.cts → types-XKUJJhlG.d.cts} +13 -4
- package/lib/ui/StormcloudVideoPlayer.cjs +242 -211
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/utils/tracking.cjs +210 -217
- package/lib/utils/tracking.cjs.map +1 -1
- package/lib/utils/tracking.d.cts +11 -13
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/players/index.cjs","../../src/players/index.ts","../../src/utils.ts","../../src/patterns.ts","../../src/players/HlsPlayer.tsx","../../src/player/StormcloudVideoPlayer.ts","../../src/utils/browserCompat.ts","../../src/sdk/ima.ts","../../src/sdk/hlsAdPlayer.ts","../../src/utils/tracking.ts","../../src/utils/polyfills.ts"],"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","players_exports","default","players_default","module","exports","import_react","lazy","require","reactLazy","IS_BROWSER","window","document","IS_GLOBAL","globalThis","IS_IOS","test","navigator","userAgent","url","IS_SAFARI","HLS_EXTENSIONS","DASH_EXTENSIONS","VIDEO_EXTENSIONS","canPlay","hls","HLS_PATHS","dash","video","audio","AUDIO_EXTENSIONS","file","import_hls","getChromeVersion","ua","match","parseInt","getWebKitVersion","getPlatform","userAgentData","platform","detectBrowser","version","majorVersion","isSmartTV","isLegacyTV","supportsIMA","supportsModernJS","recommendedAdPlayer","webOSVersion","tizenVersion","chromeVersionNum","chromeVersion","webkitVersion","parts","split","toString","Promise","Map","Set","URLSearchParams","supportsGoogleIMA","browser","createElement","e","imaSupport","contentVideoHidden","style","transition","setTimeout","baseUrl","replace","RegExp","param","logBrowserInfo","debug","console","log","getBrowserConfigOverrides","overrides","adPlayerType","allowNativeHls","createImaController","options","adPlaying","originalMutedState","originalVolume","volume","Number","isNaN","Math","max","min","listeners","adVideoElement","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","hideContentVideo","opacity","visibility","muted","showContentVideo","offsetHeight","createAdVideoElement","adVideo","position","top","left","width","height","objectFit","backgroundColor","zIndex","playsInline","addEventListener","event","payload","Array","set","fn","ensureImaLoaded","warn","reject","Error","frameEl","frameElement","sandboxAttr","getAttribute","t","trim","filter","length","allowsScripts","tokens","has","error","google","ima","resolve","existing","querySelector","timeout","clearTimeout","script","async","defer","setAttribute","onload","onerror","head","appendChild","adsManager","adsLoader","adDisplayContainer","adContainerEl","lastAdTagUrl","adsLoadedPromise","adsLoadedReject","makeAdsRequest","vastTagUrl","adsRequest","AdsRequest","companionSizes","size","ciuSzsValue","map","join","currentLocation","location","topLocation","currentUrl","href","topUrl","currentDomain","hostname","modifiedVastTagUrl","URL","searchParams","paramsToRemove","forEach","includes","params","adTagUrl","linearAdSlotWidth","separator","videoWidth","offsetWidth","clientWidth","videoHeight","clientHeight","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","setCompanionSlots","companionSlots","slot","CompanionAdSlot","push","setAdWillAutoPlay","willAutoPlay","paused","autoplay","setAdWillPlayMuted","willPlayMuted","vastLoadTimeout","requestAds","ensurePlaceholderContainer","container","right","bottom","display","alignItems","justifyContent","pointerEvents","parentElement","destroyAdsManager","destroy","destroyAdsLoader","initialize","then","AdDisplayContainer","catch","currentReject","adsLoaderCls","adsLoadedResolve","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","evt","adsRenderingSettings","AdsRenderingSettings","enablePreloading","getAdsManager","AdEvent","AdErrorEvent","AD_ERROR","errorEvent","getError","errorCode","getErrorCode","vastErrorCode","getVastErrorCode","errorMessage","getMessage","innerError","getInnerError","inner","message","String","cause","isNoFill","emit","code","continueLiveStreamDuringAds","play","CONTENT_PAUSE_REQUESTED","pause","adVolume","setVolume","STARTED","CONTENT_RESUME_REQUESTED","ALL_ADS_COMPLETED","adErrorEvent","init","ViewMode","NORMAL","start","resume","stop","removeChild","isAdPlaying","resize","on","listener","add","off","delete","updateOriginalMutedState","nextVolume","getOriginalMutedState","getOriginalVolume","setAdVolume","clampedVolume","getAdVolume","getVolume","showPlaceholder","wasHidden","destroyed","requestAnimationFrame","hidePlaceholder","createHlsAdPlayer","contentVideo","licenseKey","mainHlsInstance","adHls","currentAd","sessionId","preloadedAds","preloadingAds","pendingTimeouts","trackingFired","impression","midpoint","thirdQuartile","complete","generateSessionId","Date","now","random","substr","fireTrackingPixels","urls","trackingUrl","img","Image","src","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","bitrate","selectBestMediaFile","mediaFiles","firstFile","mainQuality","scoredFiles","widthDiff","heightDiff","abs","fileBitrate","bitrateDiff","score","resolutionDiff","sort","a","b","bestMatch","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","isProgressiveMediaFile","startsWith","endsWith","parseVastXml","xmlString","xmlDoc","parser","DOMParser","parseFromString","parserError","textContent","adElement","adId","title","isNoAdAvailable","durationText","durationParts","duration","mediaFileElements","querySelectorAll","mf","index","bitrateAttr","bitrateValue","trackingUrls","firstQuartile","mute","unmute","fullscreen","exitFullscreen","skip","el","eventKey","clickThrough","id","response","fetchAndParseVastAd","vastXml","fetch","mode","credentials","headers","referrerPolicy","ok","statusText","text","substring","setupAdEventListeners","progress","currentTime","handleAdComplete","handleAdError","ended","ad","contentVolume","isHlsAd","Hls","isSupported","lowLatencyMode","attachMedia","Events","MANIFEST_PARSED","data","fatal","previousMutedState","load","timeoutId","remove","clear","cachedBrowserId","getClientInfo","screen","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isAndroid","isWebView","isWebApp","webosMatch","tizenMatch","tvMatch","androidModelMatch","matchMedia","matches","standalone","angle","domain","origin","path","pathname","language","languages","cookieEnabled","referrer","visibilityState","getBrowserID","clientInfo","fingerprintString","encodedData","utf8","buffer","i","hashBuffer","hashArray","hashHex","hash","char","fallbackHash","timestamp","JSON","stringify","crypto","subtle","digest","TextEncoder","encode","unescape","encodeURIComponent","Uint8Array","charCodeAt","padStart","padEnd","sendInitialTracking","browserId","trackingData","method","body","status","json","sendHeartbeat","heartbeatData","toISOString","TRACK_API_URL","mapToAdTrackingSource","source","postAdTracking","sendAdDetectTracking","adDetectInfo","durationSeconds","ptsSeconds","detectedAtFragmentSn","sendAdLoadedTracking","adLoadedInfo","vastUrl","sendAdImpressionTracking","adImpressionInfo","adIndex","polyfillURLSearchParams","URLSearchParamsPolyfill","parseQueryString","append","query","cleanQuery","slice","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","values","getAll","callback","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","finally","constructor","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","len","result","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","polyfillStringIncludes","indexOf","initializePolyfills","StormcloudVideoPlayer","config","attached","inAdBreak","ptsDriftEmaMs","adPodQueue","vmapBreaks","consumedVmapBreakIds","lastHeartbeatTime","currentAdIndex","totalAdsInBreak","showAds","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","adRequestTokenCounter","activeAdRequestToken","adRequestWatchdogToken","adFailsafeToken","failedVastUrls","temporaryFailureUrls","temporaryFailureCooldownMs","continuousFetchingActive","adRequestQueue","maxPlaceholderDurationMs","isShowingPlaceholder","tsScte35Pids","pmtPids","processedTsScte35Sections","pendingScte35Cues","recentScte35CueKeys","recentScte35CueLimit","totalAdRequestsInBreak","maxTotalAdRequestsPerBreak","pendingAdBreak","consecutiveFailures","maxConsecutiveFailures","lastAdRequestTime","minAdRequestIntervalMs","backoffBaseMs","maxBackoffMs","globalConsecutiveNoFills","globalNoFillThreshold","globalNoFillCooldownUntil","globalNoFillBackoffBaseMs","globalNoFillBackoffMaxMs","globalLastGamRequestTime","globalMinGamIntervalMs","preloadPool","maxPreloadPoolSize","preloadPoolActive","preloadPoolLoopRunning","adDetectSentForCurrentBreak","continuousFetchLoopRunning","browserOverrides","debugAdTiming","createAdPlayer","vastMode","attach","fetchAdConfiguration","initializeTracking","shouldUseNativeHls","isLive","import_hls2","enableWorker","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","maxBufferLength","maxMaxBufferLength","maxBufferSize","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","loadSource","_","adBehavior","minSegments","some","details","live","shouldContinueLiveStreamDuringAds","minSegmentsBeforePlay","LEVEL_LOADED","_evt","fragments","fragmentsToScan","frag","tagList","isArray","entry","tag","idx","attrs","parseAttributeList","hasScteOut","parseCueOutDuration","marker","raw","earlyDetection","onScte35Cue","createScte35CueContext","FRAG_BUFFERED","err","FRAG_PARSING_METADATA","id3Tags","samples","s","pts","onId3Tag","FRAG_LOADED","processFragmentScte35Payload","sn","getFragmentStartSeconds","FRAG_DECRYPTED","FRAG_CHANGED","prog","parseCueOutCont","elapsed","hasScteIn","klass","toNumber","activatePendingScte35CuesForFragment","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","attachImaEventListeners","remaining","getRemainingAdMs","queuedUrls","tryNextAvailableAdWithRateLimit","handleAdPodComplete","errorPayload","causeMessage","handleAdFailure","clearAdFailsafeTimer","clearAdRequestWatchdog","resetGamNoFillCounter","expectedAdBreakDurationMs","adStopTimerId","scheduleAdStopCountdown","currentMuted","currentVolume","recreateImaController","shouldShowPlaceholder","showPlaceholderLayer","preservedMutedState","preservedVolumeState","placeholderContainer","hidePlaceholderLayer","wasPaused","parseScte35FromId3","timeUpdateHandler","onTimeUpdate","emptiedHandler","streamType","getStreamType","canNative","canPlayType","updatePtsDrift","readiness","decodeId3ValueToText","cueOutMatch","arg","dur","id3","cueOutContMatch","cont","cueInMatch","daterangeMatch","bin","out","parseScte35Binary","decoder","TextDecoder","decode","fromCharCode","context","fragmentSn","fragmentStartSeconds","candidates","startPTS","candidate","isFinite","cue","createScte35Cue","pendingKey","getPendingScte35CueKey","trimRecentScte35CueMaps","startAdPrefetch","shouldAcceptScte35EndCue","activeScte35BreakKey","hasRecentlyHandledScte35Cue","markScte35CueHandled","onScte35Marker","getScte35CueKey","getScte35MarkerRaw","spliceEventId","toIdentityString","splice_event_id","segmentationEventId","segmentation_event_id","daterangeId","ID","scteValue","round","floor","isStrongScte35CueKey","scheduledScte35BreakKey","recentKey","firstKey","keys","next","matchingCues","entries","cueKey","hasPendingAdBreak","newDurationMs","durationMs","startScte35AdBreak","elapsedMs","currentAdBreakStartWallClockMs","remainingMs","detectPayload","hasPrefetchedAds","vastUrls","isManifestMarker","isManifestBasedMarker","forceImmediate","immediateManifestAds","hasPts","clearAdStartTimer","tol","driftToleranceMs","nowMs","estCurrentPtsMs","deltaMs","markerPtsMs","tolerance","scheduleAdStartIn","hasQueuedAds","activeAdRequest","clearAdStopTimer","pendingScte35CueKey","handleAdStart","num","parseFloat","dStr","d","res","elapsedMatch","durationMatch","slashMatch","fourthByte","pid","packetSize","regex","exec","rawVal","val","n","splice_command_type","normalizeFragmentPayload","ArrayBuffer","isView","view","byteOffset","byteLength","payloadData","markers","parseScte35FromTsPackets","packetInfo","detectTsPacketFormat","sectionAssemblers","packetStart","offset","tsStart","tsPayloadOffset","secondByte","thirdByte","payloadUnitStart","adaptationFieldControl","hasPayload","payloadStart","adaptationLength","payloadEnd","subarray","parsePatSection","collectScte35SectionsFromPayload","packetSizes","matchedPackets","sectionStart","getPsiSectionStart","sectionLength","getPsiSectionLength","sectionEnd","programNumber","descriptorEnd","parsePmtSection","programInfoLength","elementaryPid","esInfoLength","descriptorStart","descriptorsIdentifyScte35","end","registration","assemblers","pointerField","previousAssembler","tableId","appendScte35Bytes","totalLength","addScte35SectionMarker","section","checksum","BitReader","bytes","expectedLength","assembler","hasProcessedTsScte35Section","buf","bytePos","bitPos","readBits","numBits","remainingInByte","toRead","currentByte","shift","mask","bits","r","cancel","programSpliceFlag","spliceImmediateFlag","skipBits","bytePosition","readSpliceTime","ptsAdjustmentTicks","timeSpecifiedFlag","high","low","ptsTicks","ptsAdjHigh","ptsAdjLow","spliceCommandLength","spliceCommandType","markerType","commandBodyStart","outOfNetwork","durationFlag","componentCount","componentPtsSeconds","durationTicks","expectedDescriptorOffset","descriptorMarker","parseScte35SegmentationDescriptors","descriptorTag","descriptorLoopLength","descriptorOffset","descriptorDataStart","descriptorDataEnd","descriptorLength","parseScte35SegmentationDescriptor","descriptor","identifier","cancelIndicator","flags","programSegmentationFlag","segmentationDurationFlag","segmentationUpidLength","segmentationTypeId","markerTypeFromSegmentationTypeId","heartbeatInterval","setInterval","sendHeartbeatIfNeeded","vastEndpoint","apiUrl","imaPayload","numberAds","vmapUrl","fetchAndParseVmap","apiVastTagUrl","parseVmapToBreaks","vmapXml","vast","cue_tones","number_ads","apiNumberAds","doc","adBreakNodes","parsed","node","timeOffsetRaw","startTimeMs","parseVmapTimeOffsetToMs","adTagNode","breakId","aStart","MAX_SAFE_INTEGER","bStart","timeOffset","normalized","hms","hh","mm","ss","ms","hours","minutes","seconds","millis","percent","ratio","durationSec","getAdBreakKey","adBreak","resolveBreakStartMs","getCurrentAdIndex","getTotalAdsInBreak","getAdRemainingMs","generateVastUrlsWithCorrelators","count","baseTimestamp","uniqueCorrelator","urlWithCorrelator","correlatorRegex","isShowingAds","shouldShowNativeControls","showCustomControls","scheduled","findCurrentOrNextBreak","tags","selectVastTagsForBreak","baseVastUrl","urlsToPregenerate","generatedUrls","isFetching","fetchStartTime","startPreloadPool","clearPendingAdBreak","prefetchTimerId","initialUrls","preloadAdIntoPool","preloadPoolLoop","loadPromise","isGamInCooldown","isUrlInCooldown","hasAdError","adErrorPayload","errorListenerCleanup","preloadIma","errorListener","poolEntry","lateErrorListener","enforceGlobalRateLimit","recordGamNoFill","isTemporaryAdError","imaController","loadedAt","splice","newUrls","newUrl","getPreloadedAd","isReady","stopPreloadPool","_marker","adBreakDurationMs","firstAdUrl","usePreloadedAd","preloadedController","preloaded","firstAdUrlArray","fallbackPreloaded","fallbackError"],"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/players/index.ts\nvar players_exports = {};\n__export(players_exports, {\n default: () => players_default\n});\nmodule.exports = __toCommonJS(players_exports);\n\n// src/utils.ts\nvar import_react = require(\"react\");\nvar lazy = import_react.lazy;\nvar IS_BROWSER = typeof window !== \"undefined\" && window.document;\nvar IS_GLOBAL = typeof globalThis !== \"undefined\" && globalThis.window && globalThis.window.document;\nvar IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(navigator.userAgent);\nvar IS_SAFARI = IS_BROWSER && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n\n// src/patterns.ts\nvar HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nvar HLS_PATHS = /\\/hls\\//i;\nvar DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nvar VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nvar AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\nvar canPlay = {\n hls: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n dash: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n video: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n audio: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n file: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n }\n};\n\n// src/players/HlsPlayer.tsx\nvar import_react2 = require(\"react\");\n\n// src/player/StormcloudVideoPlayer.ts\nvar import_hls2 = __toESM(require(\"hls.js\"), 1);\n\n// src/utils/browserCompat.ts\nfunction getChromeVersion(ua) {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getWebKitVersion(ua) {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getPlatform() {\n if (\"userAgentData\" in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? \"iPhone\" : \"MacIntel\";\n }\n if (/Win/i.test(ua)) {\n return \"Win32\";\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? \"Linux armv8l\" : \"Linux x86_64\";\n }\n if (/CrOS/i.test(ua)) {\n return \"CrOS\";\n }\n return navigator.platform || \"Unknown\";\n}\nfunction detectBrowser() {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n let name = \"Unknown\";\n let version = \"0\";\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer = \"ima\";\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 if (webOSVersion !== void 0 && webOSVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (webOSVersion !== void 0 && webOSVersion >= 3) {\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/Tizen/i.test(ua)) {\n name = \"Samsung Tizen\";\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n tizenVersion = majorVersion;\n }\n if (tizenVersion !== void 0 && tizenVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (tizenVersion !== void 0 && tizenVersion >= 3 && chromeVersion >= 47) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else {\n if (chromeVersion > 0) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (chromeVersion < 50) {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\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 supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum\n };\n}\nfunction supportsGoogleIMA() {\n const browser = detectBrowser();\n if (browser.isLegacyTV) {\n return false;\n }\n if (typeof document === \"undefined\" || typeof document.createElement !== \"function\") {\n return false;\n }\n try {\n const video = document.createElement(\"video\");\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n if (typeof Promise === \"undefined\") {\n return false;\n }\n return browser.supportsIMA;\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n console.log(\"[StormcloudVideoPlayer] Browser Compatibility Info:\", {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n ...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}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = \"hls\";\n }\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\n\n// src/sdk/ima.ts\nfunction createImaController(video, options) {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume = typeof video.volume === \"number\" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;\n const listeners = /* @__PURE__ */ new Map();\n let adVideoElement;\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n function hideContentVideo() {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n function showContentVideo() {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n function createAdVideoElement() {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"2\";\n adVideo.playsInline = true;\n adVideo.volume = originalVolume;\n adVideo.muted = originalMutedState;\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n return adVideo;\n }\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {\n }\n }\n }\n function ensureImaLoaded() {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n try {\n const frameEl = window.frameElement;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr.split(/\\s+/).map((t) => t.trim()).filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {\n }\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n );\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 1e4);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n let adsManager;\n let adsLoader;\n let adDisplayContainer;\n let adContainerEl;\n let lastAdTagUrl;\n let adsLoadedPromise;\n let adsLoadedResolve;\n let adsLoadedReject;\n function makeAdsRequest(google, vastTagUrl) {\n const adsRequest = new google.ima.AdsRequest();\n const companionSizes = [\n { width: 728, height: 90 },\n { width: 300, height: 250 },\n { width: 180, height: 150 },\n { width: 120, height: 60 },\n { width: 88, height: 31 },\n { width: 300, height: 60 },\n { width: 300, height: 100 },\n { width: 320, height: 50 },\n { width: 468, height: 60 },\n { width: 300, height: 600 },\n { width: 160, height: 600 }\n ];\n const ciuSzsValue = companionSizes.map((size) => `fluid|${size.width}x${size.height}`).join(\",\");\n const currentLocation = typeof window !== \"undefined\" ? window.location : null;\n const topLocation = typeof window !== \"undefined\" && window.top ? window.top.location : currentLocation;\n const currentUrl = currentLocation?.href || \"\";\n const topUrl = topLocation?.href || currentUrl;\n const currentDomain = currentLocation?.hostname || \"\";\n let modifiedVastTagUrl = vastTagUrl;\n try {\n const url = new URL(vastTagUrl);\n url.searchParams.set(\"ciu_szs\", ciuSzsValue);\n if (!url.searchParams.has(\"mpt\")) {\n url.searchParams.set(\"mpt\", \"h5_vsi\");\n }\n if (!url.searchParams.has(\"ctv\")) {\n url.searchParams.set(\"ctv\", \"0\");\n }\n if (!url.searchParams.has(\"gdpr\")) {\n url.searchParams.set(\"gdpr\", \"0\");\n }\n if (!url.searchParams.has(\"top\") && topUrl) {\n url.searchParams.set(\"top\", topUrl);\n }\n if (!url.searchParams.has(\"loc\") && currentUrl) {\n url.searchParams.set(\"loc\", currentUrl);\n }\n if (!url.searchParams.has(\"cdm\") && currentDomain) {\n url.searchParams.set(\"cdm\", currentDomain);\n }\n if (!url.searchParams.has(\"eoidce\")) {\n url.searchParams.set(\"eoidce\", \"1\");\n }\n if (!url.searchParams.has(\"fbidx\")) {\n url.searchParams.set(\"fbidx\", \"0\");\n }\n modifiedVastTagUrl = url.toString();\n } catch (e) {\n let baseUrl = vastTagUrl;\n const paramsToRemove = [\"ciu_szs\", \"mpt\", \"ctv\", \"gdpr\", \"top\", \"loc\", \"cdm\", \"eoidce\", \"fbidx\"];\n paramsToRemove.forEach((param) => {\n if (baseUrl.includes(`${param}=`)) {\n baseUrl = baseUrl.replace(new RegExp(`[?&]${param}=[^&]*`, \"g\"), \"\");\n }\n });\n baseUrl = baseUrl.replace(/[?&]$/, \"\");\n const params = new URLSearchParams();\n params.set(\"ciu_szs\", ciuSzsValue);\n params.set(\"mpt\", \"h5_vsi\");\n params.set(\"ctv\", \"0\");\n params.set(\"gdpr\", \"0\");\n if (topUrl) params.set(\"top\", topUrl);\n if (currentUrl) params.set(\"loc\", currentUrl);\n if (currentDomain) params.set(\"cdm\", currentDomain);\n params.set(\"eoidce\", \"1\");\n params.set(\"fbidx\", \"0\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n modifiedVastTagUrl = `${baseUrl}${separator}${params.toString()}`;\n }\n adsRequest.adTagUrl = modifiedVastTagUrl;\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 480;\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n if (typeof adsRequest.setCompanionSlots === \"function\") {\n try {\n const companionSlots = [];\n for (const size of companionSizes) {\n const slot = new google.ima.CompanionAdSlot();\n slot.width = size.width;\n slot.height = size.height;\n companionSlots.push(slot);\n }\n adsRequest.setCompanionSlots(companionSlots);\n } catch (error) {\n console.warn(\"[IMA] Failed to set companion slots:\", error);\n }\n }\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n adsRequest.vastLoadTimeout = 1e4;\n adsLoader.requestAds(adsRequest);\n }\n function ensurePlaceholderContainer() {\n if (adContainerEl) {\n return;\n }\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {\n }\n adsManager = void 0;\n }\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n function destroyAdsLoader() {\n if (adsLoader) {\n try {\n adsLoader.destroy();\n } catch {\n }\n adsLoader = void 0;\n }\n }\n return {\n initialize() {\n ensureImaLoaded().then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {\n }\n }\n }).catch(() => {\n });\n },\n async requestAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n return Promise.reject(error);\n }\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n return Promise.reject(error);\n }\n if (adPlaying) {\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n destroyAdsManager();\n destroyAdsLoader();\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n let currentReject;\n adsLoadedPromise = new Promise((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n }, 1e4);\n });\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n video.parentElement.appendChild(container);\n adContainerEl = container;\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n }\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt) => {\n try {\n const adsRenderingSettings = new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent) => {\n const error = errorEvent.getError();\n const errorCode = error.getErrorCode?.() || \"unknown\";\n const vastErrorCode = error.getVastErrorCode?.() || \"N/A\";\n const errorMessage = error.getMessage?.() || \"Unknown error\";\n let innerError;\n try {\n if (typeof error.getInnerError === \"function\") {\n const inner = error.getInnerError();\n if (inner) {\n innerError = typeof inner === \"string\" ? inner : inner.message || String(inner);\n }\n }\n if (!innerError && error.cause) {\n innerError = typeof error.cause === \"string\" ? error.cause : error.cause.message || String(error.cause);\n }\n if (!innerError && error.innerError) {\n innerError = typeof error.innerError === \"string\" ? error.innerError : error.innerError.message || String(error.innerError);\n }\n } catch (e) {\n }\n const isNoFill = errorCode === 303 || vastErrorCode === 303;\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\", {\n code: errorCode,\n vastErrorCode,\n message: errorMessage,\n cause: innerError,\n isNoFill\n });\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {\n });\n }\n }\n }\n );\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adsManager) {\n try {\n adsManager.setVolume(adVolume);\n } catch {\n }\n }\n emit(\"content_pause\");\n }\n );\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n hideContentVideo();\n if (adVideoElement) {\n const adVolume = originalVolume;\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n if (adsManager) {\n try {\n adsManager.setVolume(originalMutedState ? 0 : adVolume);\n } catch {\n }\n }\n }\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n showContentVideo();\n emit(\"content_resume\");\n }\n );\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n emit(\"all_ads_completed\");\n });\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = void 0;\n adsLoadedReject = void 0;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent) => {\n const error = adErrorEvent.getError();\n const errorCode = error.getErrorCode?.() || \"unknown\";\n const vastErrorCode = error.getVastErrorCode?.() || \"N/A\";\n const errorMessage = error.getMessage?.() || \"Unknown error\";\n let innerError;\n try {\n if (typeof error.getInnerError === \"function\") {\n const inner = error.getInnerError();\n if (inner) {\n innerError = typeof inner === \"string\" ? inner : inner.message || String(inner);\n }\n }\n if (!innerError && error.cause) {\n innerError = typeof error.cause === \"string\" ? error.cause : error.cause.message || String(error.cause);\n }\n if (!innerError && error.innerError) {\n innerError = typeof error.innerError === \"string\" ? error.innerError : error.innerError.message || String(error.innerError);\n }\n } catch (e) {\n }\n const isNoFill = errorCode === 303 || vastErrorCode === 303;\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(isNoFill ? \"No ads available\" : \"Ads loader error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\", {\n code: errorCode,\n vastErrorCode,\n message: errorMessage,\n isNoFill,\n cause: innerError\n });\n },\n false\n );\n }\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 480;\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n adPlaying = true;\n const adVolume = originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n try {\n adsManager.setVolume(originalMutedState ? 0 : adVolume);\n } catch {\n }\n adsManager.start();\n return Promise.resolve();\n } catch (error) {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {\n });\n }\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adsManager || !adPlaying) {\n return;\n }\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n if (adsManager && typeof adsManager.pause === \"function\") {\n adsManager.pause();\n }\n } catch (error) {\n console.warn(\"[IMA] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adsManager || !adPlaying) {\n return;\n }\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {\n });\n }\n if (adsManager && typeof adsManager.resume === \"function\") {\n adsManager.resume();\n }\n } catch (error) {\n console.warn(\"[IMA] Error resuming ad:\", error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n console.log(\"[IMA] Content video paused in live mode on stop, resuming playback\");\n video.play().catch(() => {\n });\n }\n } else if (video.paused) {\n video.play().catch(() => {\n });\n }\n try {\n adsManager?.stop?.();\n } catch {\n }\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"none\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n adVideoElement = void 0;\n }\n }, 500);\n }\n showContentVideo();\n try {\n adsLoader?.destroy?.();\n } catch {\n }\n adDisplayContainer = void 0;\n adsLoader = void 0;\n contentVideoHidden = false;\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {\n }\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n hideContentVideo();\n if (adContainerEl) {\n const wasHidden = adContainerEl.style.display === \"none\" || adContainerEl.style.opacity === \"0\";\n if (wasHidden) {\n adContainerEl.style.transition = \"none\";\n } else {\n adContainerEl.style.transition = \"opacity 0.3s ease-in-out\";\n }\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (adContainerEl) {\n adContainerEl.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.backgroundColor = \"#000\";\n }\n }, 300);\n }\n }\n };\n}\n\n// src/sdk/hlsAdPlayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\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 parseVastXml(xmlString) {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n 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 null;\n }\n const trackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: []\n };\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n async function fetchAndParseVastAd(vastTagUrl) {\n const response = await fetch(vastTagUrl, {\n 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 const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml);\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n video.volume = 1;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n const progress = adVideoElement.currentTime / currentAd.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function handleAdComplete() {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\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 contentVideo.volume = 0;\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 contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n 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 = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\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 = originalMutedState ? 0 : originalVolume;\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n }\n };\n}\n\n// src/utils/tracking.ts\nvar cachedBrowserId = null;\nfunction getClientInfo() {\n const ua = navigator.userAgent;\n const platform = navigator.platform;\n const vendor = navigator.vendor || \"\";\n const maxTouchPoints = navigator.maxTouchPoints || 0;\n const memory = navigator.deviceMemory || null;\n const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n const screenInfo = {\n width: screen?.width,\n height: screen?.height,\n availWidth: screen?.availWidth,\n availHeight: screen?.availHeight,\n orientation: screen?.orientation?.type || \"\",\n pixelDepth: screen?.pixelDepth\n };\n let deviceType = \"desktop\";\n let brand = \"Unknown\";\n let os = \"Unknown\";\n let model = \"\";\n let isSmartTV = false;\n let isAndroid = false;\n let isWebView = false;\n let isWebApp = false;\n if (ua.includes(\"Web0S\")) {\n brand = \"LG\";\n os = \"webOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n } else if (ua.includes(\"Tizen\")) {\n brand = \"Samsung\";\n os = \"Tizen\";\n isSmartTV = true;\n deviceType = \"tv\";\n const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n model = tizenMatch ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim() : \"Tizen TV\";\n } else if (ua.includes(\"Philips\")) {\n brand = \"Philips\";\n os = \"Saphi\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n brand = \"Sharp\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Android\") && (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))) {\n brand = \"Sony\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Android\") && (ua.includes(\"NetCast\") || ua.includes(\"LG\"))) {\n brand = \"LG\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n brand = \"Roku\";\n os = \"Roku OS\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"AppleTV\")) {\n brand = \"Apple\";\n os = \"tvOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n }\n if (ua.includes(\"Android\")) {\n isAndroid = true;\n os = \"Android\";\n deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n if (ua.includes(\"Android\") && (maxTouchPoints === 0 || ua.includes(\"Google TV\") || ua.includes(\"XiaoMi\"))) {\n deviceType = \"tv\";\n isSmartTV = true;\n brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n }\n const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n if (androidModelMatch && androidModelMatch[1]) {\n model = androidModelMatch[1];\n }\n }\n if (/iPad|iPhone|iPod/.test(ua)) {\n os = \"iOS\";\n deviceType = \"mobile\";\n brand = \"Apple\";\n if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n deviceType = \"tablet\";\n }\n }\n if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n if (ua.includes(\"Windows\")) {\n os = \"Windows\";\n deviceType = \"desktop\";\n } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n os = \"macOS\";\n deviceType = \"desktop\";\n if (maxTouchPoints > 1) deviceType = \"tablet\";\n } else if (ua.includes(\"Linux\")) {\n os = \"Linux\";\n deviceType = \"desktop\";\n }\n }\n if (brand === \"Unknown\") {\n if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n if (vendor.includes(\"Apple\")) brand = \"Apple\";\n if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n }\n isWebView = /wv|WebView|Linux; U;/.test(ua);\n if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n isWebView = true;\n }\n isWebApp = window.matchMedia(\"(display-mode: standalone)\").matches || window.navigator.standalone === true || window.screen?.orientation?.angle !== void 0;\n return {\n brand,\n os,\n model: model || ua.substring(0, 50) + \"...\",\n deviceType,\n isSmartTV,\n isAndroid,\n isWebView,\n isWebApp,\n domain: window.location.hostname,\n origin: window.location.origin,\n path: window.location.pathname,\n userAgent: ua,\n vendor,\n platform,\n screen: screenInfo,\n hardwareConcurrency,\n deviceMemory: memory,\n maxTouchPoints,\n language: navigator.language,\n languages: navigator.languages?.join(\",\") || \"\",\n cookieEnabled: navigator.cookieEnabled,\n doNotTrack: navigator.doNotTrack || \"\",\n referrer: document.referrer,\n visibilityState: document.visibilityState\n };\n}\nasync function getBrowserID(clientInfo) {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n const fingerprintString = JSON.stringify(clientInfo);\n if (typeof crypto !== \"undefined\" && crypto.subtle && crypto.subtle.digest) {\n try {\n await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n let encodedData;\n if (typeof TextEncoder !== \"undefined\") {\n encodedData = new TextEncoder().encode(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\n const buffer = new Uint8Array(utf8.length);\n for (let i = 0; i < utf8.length; i++) {\n buffer[i] = utf8.charCodeAt(i);\n }\n encodedData = buffer;\n }\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n const timestamp = Date.now().toString(16).padStart(12, \"0\");\n const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\nasync function sendInitialTracking(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = {\n browserId,\n ...clientInfo\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\nasync function sendHeartbeat(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const heartbeatData = {\n browserId,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\nvar TRACK_API_URL = \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\nfunction mapToAdTrackingSource(source, adPlayerType) {\n if (source === \"prebid\" || source === \"ima\" || source === \"hls\") {\n return source;\n }\n if (source === \"preload\" || source === \"ssp\") {\n return source === \"ssp\" ? \"prebid\" : \"ima\";\n }\n return adPlayerType === \"hls\" ? \"hls\" : \"ima\";\n}\nasync function postAdTracking(licenseKey, body) {\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_API_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body)\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\nasync function sendAdDetectTracking(licenseKey, payload) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const adDetectInfo = {\n source: payload.source ?? \"scte35\",\n timestamp: payload.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),\n ...payload.durationSeconds != null && { durationSeconds: payload.durationSeconds },\n ...payload.ptsSeconds != null && { ptsSeconds: payload.ptsSeconds },\n ...payload.detectedAtFragmentSn != null && { detectedAtFragmentSn: payload.detectedAtFragmentSn }\n };\n const body = {\n browserId,\n ...clientInfo,\n ...licenseKey && { licenseKey },\n adDetectInfo\n };\n await postAdTracking(licenseKey, body);\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending ad-detect tracking:\", error);\n }\n}\nasync function sendAdLoadedTracking(licenseKey, payload, adPlayerType) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const source = mapToAdTrackingSource(payload.source, adPlayerType);\n const adLoadedInfo = {\n source,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n ...payload.vastUrl != null && { vastUrl: payload.vastUrl },\n ...payload.durationSeconds != null && { durationSeconds: payload.durationSeconds }\n };\n const body = {\n browserId,\n ...clientInfo,\n ...licenseKey && { licenseKey },\n adLoadedInfo\n };\n await postAdTracking(licenseKey, body);\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending ad-loaded tracking:\", error);\n }\n}\nasync function sendAdImpressionTracking(licenseKey, payload, adPlayerType) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const source = mapToAdTrackingSource(payload.source, adPlayerType);\n const adImpressionInfo = {\n source,\n adIndex: payload.adIndex,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n ...payload.durationSeconds != null && { durationSeconds: payload.durationSeconds }\n };\n const body = {\n browserId,\n ...clientInfo,\n ...licenseKey && { licenseKey },\n adImpressionInfo\n };\n await postAdTracking(licenseKey, body);\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending ad-impression tracking:\", error);\n }\n}\n\n// src/utils/polyfills.ts\nfunction polyfillURLSearchParams() {\n if (typeof URLSearchParams !== \"undefined\") {\n return;\n }\n class URLSearchParamsPolyfill {\n constructor(init) {\n this.params = /* @__PURE__ */ new Map();\n if (typeof init === \"string\") {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n parseQueryString(query) {\n const cleanQuery = query.startsWith(\"?\") ? query.slice(1) : query;\n if (!cleanQuery) return;\n cleanQuery.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : \"\";\n this.append(decodedKey, decodedValue);\n }\n });\n }\n safeDecodeURIComponent(str) {\n try {\n return decodeURIComponent(str.replace(/\\+/g, \" \"));\n } catch (e) {\n return str;\n }\n }\n append(name, value) {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n delete(name) {\n this.params.delete(name);\n }\n get(name) {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;\n }\n getAll(name) {\n return this.params.get(name) || [];\n }\n has(name) {\n return this.params.has(name);\n }\n set(name, value) {\n this.params.set(name, [String(value)]);\n }\n forEach(callback) {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n toString() {\n const parts = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join(\"&\");\n }\n }\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\nfunction polyfillTextEncoder() {\n if (typeof TextEncoder !== \"undefined\") {\n return;\n }\n class TextEncoderPolyfill {\n constructor() {\n this.encoding = \"utf-8\";\n }\n encode(str) {\n const utf8 = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 128) {\n utf8.push(charcode);\n } else if (charcode < 2048) {\n utf8.push(192 | charcode >> 6, 128 | charcode & 63);\n } else if (charcode < 55296 || charcode >= 57344) {\n utf8.push(\n 224 | charcode >> 12,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n } else {\n i++;\n charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);\n utf8.push(\n 240 | charcode >> 18,\n 128 | charcode >> 12 & 63,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n window.TextEncoder = TextEncoderPolyfill;\n}\nfunction polyfillPromiseFinally() {\n if (typeof Promise !== \"undefined\" && !Promise.prototype.finally) {\n Promise.prototype.finally = function(callback) {\n const constructor = this.constructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) => constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\nfunction polyfillObjectAssign() {\n if (typeof Object.assign !== \"function\") {\n Object.assign = function(target, ...sources) {\n if (target == null) {\n throw new TypeError(\"Cannot convert undefined or null to object\");\n }\n const to = Object(target);\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n }\n}\nfunction polyfillArrayFrom() {\n if (!Array.from) {\n Array.from = function(arrayLike, mapFn, thisArg) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError(\"Array.from requires an array-like object\");\n }\n const len = items.length >>> 0;\n const result = new Array(len);\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n return result;\n };\n }\n}\nfunction polyfillStringStartsWith() {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function(search, pos) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\nfunction polyfillStringEndsWith() {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function(search, length) {\n if (length === void 0 || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\nfunction polyfillStringIncludes() {\n if (!String.prototype.includes) {\n String.prototype.includes = function(search, start) {\n if (typeof start !== \"number\") {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\nfunction initializePolyfills() {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.adPodQueue = [];\n this.vmapBreaks = [];\n this.consumedVmapBreakIds = /* @__PURE__ */ new Set();\n this.lastHeartbeatTime = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.showAds = false;\n this.isLiveStream = false;\n this.nativeHlsMode = false;\n this.videoSrcProtection = null;\n this.bufferedSegmentsCount = 0;\n this.shouldAutoplayAfterBuffering = false;\n this.hasInitialBufferCompleted = false;\n this.adRequestTokenCounter = 0;\n this.activeAdRequestToken = null;\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.failedVastUrls = /* @__PURE__ */ new Set();\n this.temporaryFailureUrls = /* @__PURE__ */ new Map();\n this.temporaryFailureCooldownMs = 3e4;\n this.continuousFetchingActive = false;\n this.adRequestQueue = [];\n this.maxPlaceholderDurationMs = 5e3;\n this.isShowingPlaceholder = false;\n this.tsScte35Pids = /* @__PURE__ */ new Set();\n this.pmtPids = /* @__PURE__ */ new Set();\n this.processedTsScte35Sections = /* @__PURE__ */ new Set();\n this.pendingScte35Cues = /* @__PURE__ */ new Map();\n this.recentScte35CueKeys = /* @__PURE__ */ new Map();\n this.recentScte35CueLimit = 200;\n this.totalAdRequestsInBreak = 0;\n this.maxTotalAdRequestsPerBreak = 10;\n this.pendingAdBreak = null;\n this.consecutiveFailures = 0;\n this.maxConsecutiveFailures = 5;\n this.lastAdRequestTime = 0;\n this.minAdRequestIntervalMs = 3e3;\n this.backoffBaseMs = 1e3;\n this.maxBackoffMs = 15e3;\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.preloadPool = [];\n this.maxPreloadPoolSize = 2;\n this.preloadPoolActive = false;\n this.preloadPoolLoopRunning = false;\n this.adDetectSentForCurrentBreak = false;\n this.continuousFetchLoopRunning = false;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.ima = this.createAdPlayer(false);\n }\n createAdPlayer(continueLiveStreamDuringAds) {\n const vastMode = this.config.vastMode || \"default\";\n let adPlayerType = this.config.adPlayerType || (vastMode === \"adstorm\" ? \"hls\" : \"ima\");\n if (adPlayerType === \"ima\" && !supportsGoogleIMA()) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player\"\n );\n }\n adPlayerType = \"hls\";\n }\n if (adPlayerType === \"hls\") {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)\"\n );\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},\n ...this.hls ? { mainHlsInstance: this.hls } : {}\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating Google IMA ad player (IMA mode)\"\n );\n }\n return createImaController(this.video, {\n continueLiveStreamDuringAds\n });\n }\n }\n async load() {\n if (!this.attached) {\n this.attach();\n }\n try {\n await this.fetchAdConfiguration();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n this.initializeTracking();\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\"\n }\n );\n }\n this.ima.destroy();\n this.ima = this.createAdPlayer(false);\n this.ima.initialize();\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n return;\n }\n this.hls = new 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 if (this.config.allowNativeHls === false) {\n this.isLiveStream = true;\n } else {\n this.isLiveStream = this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n }\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds() ? \"live (main video continues muted during ads)\" : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior\n });\n }\n this.ima.destroy();\n this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.ima.initialize();\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n }\n });\n this.hls.on(import_hls2.default.Events.LEVEL_LOADED, (_evt, data) => {\n if (this.inAdBreak || this.pendingAdBreak) {\n return;\n }\n const details = data?.details;\n if (!details || !details.fragments || details.fragments.length === 0) {\n return;\n }\n const fragmentsToScan = Math.min(5, details.fragments.length);\n for (let i = 0; i < fragmentsToScan; i++) {\n const frag = details.fragments[i];\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) continue;\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n }\n }\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = tag.includes(\"EXT-X-DATERANGE\") ? this.parseAttributeList(value) : {};\n const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") || \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n if (hasScteOut) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value, earlyDetection: true }\n };\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] \\u{1F3AF} EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n }\n this.onScte35Cue(marker, {\n ...this.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.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n this.hls.on(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 this.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 this.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.activatePendingScte35CuesForFragment(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 = this.parseCueOutCont(value);\n const marker = {\n type: \"progress\",\n ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},\n ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},\n raw: { tag, value }\n };\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Cue(\n { type: \"end\", raw: { tag, value } },\n {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n }\n );\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { tag, value, attrs }\n };\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n }\n if (hasScteIn) {\n this.onScte35Cue(\n { type: \"end\", raw: { tag, value, attrs } },\n {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n }\n );\n }\n }\n }\n this.activatePendingScte35CuesForFragment(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.destroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n attachImaEventListeners() {\n this.ima.on(\"all_ads_completed\", () => {\n sendAdImpressionTracking(\n this.config.licenseKey,\n { adIndex: this.currentAdIndex },\n this.config.adPlayerType\n ).catch(() => {\n });\n const remaining = this.getRemainingAdMs();\n this.consecutiveFailures = 0;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.inAdBreak) {\n if (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n this.ima.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 this.ima.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n this.resetGamNoFillCounter();\n if (this.inAdBreak && this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.ima.on(\"content_resume\", () => {\n sendAdImpressionTracking(\n this.config.licenseKey,\n { adIndex: this.currentAdIndex },\n this.config.adPlayerType\n ).catch(() => {\n });\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n }\n }\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n return;\n }\n this.consecutiveFailures = 0;\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\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 (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n });\n }\n recreateImaController() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Recreating ImaController for new ad\");\n }\n const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n if (shouldShowPlaceholder && this.ima) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController\");\n }\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n const preservedMutedState = this.ima.getOriginalMutedState();\n const preservedVolumeState = this.ima.getOriginalVolume();\n if (this.ima) {\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Error destroying old ImaController:\", error);\n }\n }\n }\n const continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();\n this.ima = this.createAdPlayer(continueLiveStreamDuringAds);\n this.ima.initialize();\n this.ima.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n this.attachImaEventListeners();\n if (shouldShowPlaceholder) {\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n }\n ensurePlaceholderContainer() {\n if (this.placeholderContainer) {\n return;\n }\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"5\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!this.video.parentElement) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n this.video.parentElement.appendChild(container);\n this.placeholderContainer = container;\n }\n showPlaceholderLayer() {\n this.ensurePlaceholderContainer();\n if (!this.placeholderContainer) {\n return;\n }\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n const wasHidden = this.placeholderContainer.style.display === \"none\" || this.placeholderContainer.style.opacity === \"0\";\n if (wasHidden) {\n this.placeholderContainer.style.transition = \"none\";\n } else {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n this.placeholderContainer.style.backgroundColor = \"#000\";\n this.placeholderContainer.style.display = \"flex\";\n this.placeholderContainer.offsetHeight;\n this.placeholderContainer.style.opacity = \"1\";\n this.placeholderContainer.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)\");\n }\n }\n hidePlaceholderLayer() {\n if (!this.placeholderContainer) {\n return;\n }\n this.placeholderContainer.style.opacity = \"0\";\n setTimeout(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.display = \"none\";\n this.placeholderContainer.style.pointerEvents = \"none\";\n this.placeholderContainer.style.backgroundColor = \"#000\";\n }\n }, 300);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n attach() {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n this.ima.initialize();\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachImaEventListeners();\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {\n });\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n shouldUseNativeHls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Cue(marker, {\n source: \"id3\",\n readiness: \"playback\"\n });\n }\n }\n parseScte35FromId3(tag) {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return void 0;\n const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) || text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...dur !== void 0 ? { durationSeconds: dur } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker = {\n type: \"progress\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n if (hasScteIn) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n }\n if (/SCTE35-OUT/i.test(text)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n }\n decodeId3ValueToText(value) {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]);\n return out;\n } catch {\n return void 0;\n }\n }\n createScte35CueContext(source, readiness, frag) {\n const context = { source, readiness };\n if (typeof frag?.sn === \"number\") {\n context.fragmentSn = frag.sn;\n }\n const fragmentStartSeconds = this.getFragmentStartSeconds(frag);\n if (fragmentStartSeconds !== void 0) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n return context;\n }\n 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 }\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.startAdPrefetch(marker, context.fragmentSn, cue.key);\n }\n return;\n }\n if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n key: cue.key,\n activeScte35BreakKey: this.activeScte35BreakKey,\n inAdBreak: this.inAdBreak,\n source: cue.source\n });\n }\n return;\n }\n if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n if (this.config.debugAdTiming) {\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.onScte35Marker(marker, cue.key);\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.activeScte35BreakKey === cue.key || this.scheduledScte35BreakKey === 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.inAdBreak) {\n return false;\n }\n if (this.isStrongScte35CueKey(this.activeScte35BreakKey) && this.isStrongScte35CueKey(cue.key) && this.activeScte35BreakKey !== cue.key) {\n return false;\n }\n return true;\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 fragmentStartSeconds = cue.fragmentStartSeconds ?? this.getFragmentStartSeconds(frag);\n if (fragmentStartSeconds !== void 0) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n this.onScte35Cue(cue.marker, context);\n });\n }\n onScte35Marker(marker, cueKey) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n hasPendingAdBreak: !!this.pendingAdBreak\n });\n }\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n if (marker.durationSeconds != null) {\n const newDurationMs = marker.durationSeconds * 1e3;\n if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {\n this.expectedAdBreakDurationMs = newDurationMs;\n const elapsedMs = this.currentAdBreakStartWallClockMs != null ? Date.now() - this.currentAdBreakStartWallClockMs : 0;\n const remainingMs = Math.max(0, newDurationMs - elapsedMs);\n this.scheduleAdStopCountdown(remainingMs);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${newDurationMs}ms, remaining: ${remainingMs}ms`\n );\n }\n }\n }\n return;\n }\n if (!this.adDetectSentForCurrentBreak) {\n this.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, detectPayload).catch(() => {\n });\n }\n const hasPrefetchedAds = this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.pendingAdBreak?.marker.durationSeconds != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n hasPrefetchedAds\n });\n }\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Starting ad immediately (manifest-based)${hasPrefetchedAds ? \" with prefetched ads\" : \"\"}`\n );\n }\n this.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.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1e3,\n deltaMs,\n tolerance: tol\n });\n }\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.expectedAdBreakDurationMs = durationMs;\n this.scheduledScte35BreakKey = cueKey;\n this.scheduleAdStartIn(deltaMs, marker, cueKey);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0) {\n this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.ima.isAdPlaying();\n const hasQueuedAds = this.adRequestQueue.length > 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null\n });\n }\n if (adPlaying || remaining > 1e3 && hasQueuedAds) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active\");\n }\n return;\n }\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n if (adPlaying) {\n this.ima.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n return;\n }\n }\n startScte35AdBreak(marker, cueKey, durationMs) {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE start marker\");\n }\n }\n this.inAdBreak = true;\n this.activeScte35BreakKey = cueKey ?? this.pendingScte35CueKey;\n this.scheduledScte35BreakKey = void 0;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.handleAdStart(marker);\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n }\n parseCueOutDuration(value) {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match = value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) || value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? void 0 : d;\n }\n return void 0;\n }\n parseCueOutCont(value) {\n const 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 }\n parseAttributeList(value) {\n const attrs = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match;\n while ((match = regex.exec(value)) !== null) {\n const key = match[1] ?? \"\";\n let rawVal = match[3] ?? match[4] ?? \"\";\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n toNumber(val) {\n if (val == null) return void 0;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? void 0 : n;\n }\n isManifestBasedMarker(marker) {\n const raw = marker.raw;\n if (!raw) return false;\n if (raw.tag) {\n const tag = String(raw.tag);\n return tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-CUE-IN\") || tag.includes(\"EXT-X-DATERANGE\");\n }\n if (raw.id3) return false;\n if (raw.splice_command_type) return false;\n return false;\n }\n 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 }\n processFragmentScte35Payload(payloadData, fragmentSn, fragmentStartSeconds) {\n const payload = this.normalizeFragmentPayload(payloadData);\n if (!payload) {\n return;\n }\n const markers = this.parseScte35FromTsPackets(payload);\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.onScte35Cue(marker, context);\n });\n }\n parseScte35FromTsPackets(data) {\n const packetInfo = this.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 this.parsePatSection(payload, payloadUnitStart);\n } else if (this.pmtPids.has(pid)) {\n this.parsePmtSection(payload, payloadUnitStart);\n } else if (this.tsScte35Pids.has(pid)) {\n this.collectScte35SectionsFromPayload(\n pid,\n payload,\n payloadUnitStart,\n sectionAssemblers,\n markers\n );\n }\n }\n return markers;\n }\n 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 }\n parsePatSection(payload, payloadUnitStart) {\n const sectionStart = this.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 = this.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 this.pmtPids.add(pid);\n }\n }\n }\n parsePmtSection(payload, payloadUnitStart) {\n const sectionStart = this.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 = this.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 && this.descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd)) {\n this.tsScte35Pids.add(elementaryPid);\n }\n offset = descriptorStart + esInfoLength;\n }\n }\n 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 }\n collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, assemblers, markers) {\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 this.appendScte35Bytes(\n pid,\n payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n assemblers,\n markers\n );\n }\n assemblers.delete(pid);\n offset = 1 + pointerField;\n } else {\n this.appendScte35Bytes(pid, payload, assemblers, markers);\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 = this.getPsiSectionLength(payload, offset);\n const totalLength = 3 + sectionLength;\n if (sectionLength <= 0 || totalLength <= 3) {\n return;\n }\n if (offset + totalLength <= payload.length) {\n this.addScte35SectionMarker(\n payload.subarray(offset, offset + totalLength),\n markers\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 appendScte35Bytes(pid, bytes, assemblers, markers) {\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 this.addScte35SectionMarker(new Uint8Array(assembler.bytes), markers);\n }\n }\n addScte35SectionMarker(section, markers) {\n if (section[0] !== 252 || this.hasProcessedTsScte35Section(section)) {\n return;\n }\n const marker = this.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 }\n hasProcessedTsScte35Section(section) {\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 (this.processedTsScte35Sections.has(key)) {\n return true;\n }\n this.processedTsScte35Sections.add(key);\n if (this.processedTsScte35Sections.size > 200) {\n const firstKey = this.processedTsScte35Sections.values().next().value;\n if (firstKey) {\n this.processedTsScte35Sections.delete(firstKey);\n }\n }\n return false;\n }\n 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 }\n getPsiSectionLength(data, offset) {\n return ((data[offset + 1] ?? 0) & 15) << 8 | (data[offset + 2] ?? 0);\n }\n parseScte35Binary(data) {\n class BitReader {\n constructor(buf) {\n this.buf = buf;\n this.bytePos = 0;\n this.bitPos = 0;\n }\n readBits(numBits) {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos];\n const shift = remainingInByte - toRead;\n const mask = (1 << toRead) - 1 & 255;\n const bits = currentByte >> shift & mask;\n result = result << toRead | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n) {\n this.readBits(n);\n }\n get bytePosition() {\n return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n }\n }\n const readSpliceTime = (r2, ptsAdjustmentTicks2) => {\n const timeSpecifiedFlag = r2.readBits(1) === 1;\n if (!timeSpecifiedFlag) {\n r2.readBits(7);\n return void 0;\n }\n r2.readBits(6);\n const high = r2.readBits(1);\n const low = r2.readBits(32);\n const ptsTicks = (high * 4294967296 + low + ptsAdjustmentTicks2) % 8589934592;\n return ptsTicks / 9e4;\n };\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 252) return void 0;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n 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 = this.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 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 = this.parseScte35SegmentationDescriptor(\n data.subarray(descriptorDataStart, descriptorDataEnd)\n );\n if (descriptorMarker) {\n return descriptorMarker;\n }\n }\n descriptorOffset = descriptorDataEnd;\n }\n return void 0;\n }\n 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 = this.markerTypeFromSegmentationTypeId(segmentationTypeId);\n if (!markerType) {\n return void 0;\n }\n return {\n type: markerType,\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n segmentationEventId\n };\n }\n 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 }\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n });\n }\n sendHeartbeatIfNeeded() {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n async fetchAdConfiguration() {\n if (this.config.vmapUrl) {\n await this.fetchAndParseVmap(this.config.vmapUrl);\n }\n const vastMode = this.config.vastMode || \"default\";\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n );\n }\n return;\n }\n const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n this.apiVastTagUrl = vastEndpoint;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n vastEndpoint\n );\n }\n return;\n }\n if (this.config.vastTagUrl) {\n this.apiVastTagUrl = this.config.vastTagUrl;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n return;\n }\n const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n apiUrl\n );\n }\n const headers = {};\n if (this.config.licenseKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n }\n const response = await fetch(apiUrl, { headers });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n );\n }\n return;\n }\n const data = await response.json();\n const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n if (imaPayload) {\n this.apiVastTagUrl = decodeURIComponent(imaPayload);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n );\n }\n }\n const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n if (numberAds != null && numberAds > 0) {\n this.apiNumberAds = numberAds;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n 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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n }\n return [];\n }\n const adBreakNodes = Array.from(\n doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\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 const adTagNode = node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\");\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 getCurrentAdIndex() {\n return this.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.totalAdsInBreak;\n }\n getAdRemainingMs() {\n return this.getRemainingAdMs();\n }\n generateVastUrlsWithCorrelators(baseUrl, count) {\n const urls = [];\n const baseTimestamp = Date.now();\n for (let i = 0; i < count; i++) {\n const timestamp = baseTimestamp + i;\n const random = Math.floor(Math.random() * 1e12);\n const uniqueCorrelator = `${timestamp}_${random}_${i}`;\n let urlWithCorrelator;\n const correlatorRegex = /([?&])correlator=([^&]*)/;\n if (correlatorRegex.test(baseUrl)) {\n urlWithCorrelator = baseUrl.replace(correlatorRegex, `$1correlator=${uniqueCorrelator}`);\n } else if (baseUrl.includes(\"?\")) {\n urlWithCorrelator = `${baseUrl}&correlator=${uniqueCorrelator}`;\n } else {\n urlWithCorrelator = `${baseUrl}?correlator=${uniqueCorrelator}`;\n }\n urls.push(urlWithCorrelator);\n }\n return urls;\n }\n isAdPlaying() {\n return this.inAdBreak && this.ima.isAdPlaying();\n }\n isShowingAds() {\n return this.showAds;\n }\n getStreamType() {\n const url = this.config.src.toLowerCase();\n if (url.includes(\".m3u8\") || url.includes(\"/hls/\") || url.includes(\"application/vnd.apple.mpegurl\")) {\n return \"hls\";\n }\n return \"other\";\n }\n shouldShowNativeControls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));\n }\n shouldContinueLiveStreamDuringAds() {\n if (this.config.allowNativeHls) {\n return false;\n }\n if (!this.isLiveStream) {\n return false;\n }\n return true;\n }\n startAdPrefetch(marker, fragmentSn, cueKey) {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n const scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);\n const tags = this.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] No VAST URL available for prefetch\");\n }\n return;\n }\n const urlsToPregenerate = 5;\n const generatedUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, urlsToPregenerate);\n this.pendingAdBreak = {\n marker,\n ...fragmentSn !== void 0 ? { detectedAtFragmentSn: fragmentSn } : {},\n vastUrls: generatedUrls,\n isFetching: false,\n fetchStartTime: Date.now()\n };\n this.pendingScte35CueKey = cueKey;\n this.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, detectPayload).catch(() => {\n });\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] \\u{1F504} Starting ad prefetch for upcoming ad break\");\n console.log(`[PREFETCH] \\u{1F4CB} Pre-generated ${generatedUrls.length} VAST URLs`);\n }\n this.startPreloadPool(baseVastUrl, generatedUrls.slice(0, this.maxPreloadPoolSize));\n }\n clearPendingAdBreak() {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = void 0;\n }\n this.pendingAdBreak = null;\n this.pendingScte35CueKey = void 0;\n }\n startPreloadPool(baseVastUrl, initialUrls) {\n if (this.preloadPoolActive) {\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n }\n return;\n }\n this.preloadPoolActive = true;\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u{1F3CA} Starting preload pool EARLY (target size: ${this.maxPreloadPoolSize})`);\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.preloadPool.length < this.maxPreloadPoolSize) {\n this.preloadAdIntoPool(url);\n }\n }\n this.preloadPoolLoop(baseVastUrl);\n }\n async preloadAdIntoPool(vastUrl) {\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n }\n return;\n }\n if (this.preloadPool.some((entry) => entry.vastUrl === vastUrl) || this.failedVastUrls.has(vastUrl) || this.isUrlInCooldown(vastUrl)) {\n return;\n }\n if (this.preloadPool.length >= this.maxPreloadPoolSize) {\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u{1F4E5} Preloading ad into pool: ${vastUrl}`);\n }\n const loadPromise = (async () => {\n let hasAdError = false;\n let adErrorPayload = null;\n let errorListenerCleanup = null;\n try {\n const continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();\n const preloadIma = this.createAdPlayer(continueLiveStreamDuringAds);\n preloadIma.initialize();\n const errorListener = (payload) => {\n hasAdError = true;\n adErrorPayload = payload;\n };\n preloadIma.on(\"ad_error\", errorListener);\n errorListenerCleanup = () => preloadIma.off(\"ad_error\", errorListener);\n await this.enforceGlobalRateLimit();\n await preloadIma.requestAds(vastUrl);\n preloadIma.pause();\n await new Promise((resolve) => setTimeout(resolve, 1500));\n preloadIma.pause();\n if (hasAdError) {\n const isNoFill = adErrorPayload?.isNoFill || adErrorPayload?.code === 303 || adErrorPayload?.vastErrorCode === 303;\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n preloadIma.destroy();\n this.recordGamNoFill();\n if (isNoFill) {\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u26A0\\uFE0F Ad preload returned no-fill: ${vastUrl}`);\n }\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n } else {\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u26A0\\uFE0F Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n }\n if (adErrorPayload && !this.isTemporaryAdError(adErrorPayload)) {\n this.failedVastUrls.add(vastUrl);\n } else {\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n return;\n }\n const poolEntry = {\n vastUrl,\n imaController: preloadIma,\n loadedAt: Date.now(),\n isReady: true,\n loadPromise: Promise.resolve()\n };\n const lateErrorListener = (payload) => {\n const index = this.preloadPool.findIndex((entry) => entry.vastUrl === vastUrl);\n if (index >= 0) {\n this.preloadPool.splice(index, 1);\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u26A0\\uFE0F Late error detected, removed from pool: ${vastUrl}`, payload);\n }\n try {\n preloadIma.destroy();\n } catch {\n }\n }\n };\n preloadIma.on(\"ad_error\", lateErrorListener);\n this.preloadPool.push(poolEntry);\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u2705 Ad preloaded (no errors detected within timeout) (pool size: ${this.preloadPool.length}/${this.maxPreloadPoolSize})`);\n }\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n } catch (error) {\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n this.recordGamNoFill();\n if (this.config.debugAdTiming) {\n console.warn(`[PRELOAD-POOL] \\u26A0\\uFE0F Failed to preload ad: ${vastUrl}`, error);\n }\n if (error instanceof Error && !this.isTemporaryAdError(error)) {\n this.failedVastUrls.add(vastUrl);\n } else if (error instanceof Error && this.isTemporaryAdError(error)) {\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n })();\n loadPromise.catch(() => {\n });\n }\n async preloadPoolLoop(baseVastUrl) {\n if (this.preloadPoolLoopRunning) {\n return;\n }\n this.preloadPoolLoopRunning = true;\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] \\u{1F504} Starting continuous preload loop\");\n }\n while (this.preloadPoolActive) {\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n }\n break;\n }\n if (!this.inAdBreak && this.preloadPool.length >= this.maxPreloadPoolSize) {\n await new Promise((resolve) => setTimeout(resolve, 2e3));\n continue;\n }\n if (!this.inAdBreak && this.pendingAdBreak === null) {\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n }\n break;\n }\n while (this.preloadPool.length < this.maxPreloadPoolSize) {\n if (!this.preloadPoolActive || this.isGamInCooldown()) {\n break;\n }\n if (this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 0) {\n break;\n }\n }\n const newUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const newUrl = newUrls[0];\n if (newUrl && !this.failedVastUrls.has(newUrl) && !this.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.preloadPoolLoopRunning = false;\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] \\u{1F6D1} Preload loop ended\");\n }\n }\n getPreloadedAd() {\n if (this.preloadPool.length === 0) {\n return null;\n }\n const entry = this.preloadPool.shift();\n if (!entry || !entry.isReady) {\n return null;\n }\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u{1F3AF} Using preloaded ad from pool (${this.preloadPool.length} remaining)`);\n }\n return {\n vastUrl: entry.vastUrl,\n imaController: entry.imaController\n };\n }\n stopPreloadPool() {\n this.preloadPoolActive = false;\n this.preloadPoolLoopRunning = false;\n for (const entry of this.preloadPool) {\n try {\n entry.imaController.destroy();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n }\n }\n }\n this.preloadPool = [];\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] \\u{1F6D1} Preload pool stopped and cleaned up\");\n }\n }\n async handleAdStart(_marker) {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1e3\n );\n if (scheduled) {\n this.consumedVmapBreakIds.add(this.getAdBreakKey(scheduled));\n }\n const tags = this.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else {\n this.clearPendingAdBreak();\n return;\n }\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled?.durationMs;\n if (this.config.debugAdTiming) {\n const mode = this.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F4FA} ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n this.failedVastUrls.clear();\n this.temporaryFailureUrls.clear();\n this.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video in handleAdStart\");\n }\n }\n this.inAdBreak = true;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n this.showAds = true;\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n let firstAdUrl;\n let usePreloadedAd = false;\n let preloadedController;\n const preloaded = this.getPreloadedAd();\n if (preloaded) {\n firstAdUrl = preloaded.vastUrl;\n preloadedController = preloaded.imaController;\n usePreloadedAd = true;\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"preload\", vastUrl: firstAdUrl },\n this.config.adPlayerType\n ).catch(() => {\n });\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F680} Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n console.log(`[CONTINUOUS-FETCH] Pool still has ${this.preloadPool.length} preloaded ads ready`);\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.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u26A0\\uFE0F Pool empty, using prefetched URLs (${this.adRequestQueue.length + 1} available)`);\n }\n this.clearPendingAdBreak();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F680} Generating new ad URLs...\");\n }\n const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n firstAdUrl = firstAdUrlArray[0];\n this.adRequestQueue = [];\n }\n if (!firstAdUrl) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F Failed to get first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F4CB} First VAST URL:\", firstAdUrl);\n }\n try {\n if (usePreloadedAd && preloadedController) {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedController;\n this.attachImaEventListeners();\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n }\n this.ima.resume();\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPoolActive) {\n this.preloadPoolActive = true;\n this.preloadPoolLoop(baseVastUrl);\n }\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n } else {\n await this.enforceGlobalRateLimit();\n this.lastAdRequestTime = Date.now();\n await this.ima.requestAds(firstAdUrl);\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ssp\", vastUrl: firstAdUrl },\n this.config.adPlayerType\n ).catch(() => {\n });\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 First ad request successful, starting playback\");\n }\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPoolActive) {\n this.startPreloadPool(baseVastUrl, []);\n }\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F First ad request failed:\", error);\n }\n if (!usePreloadedAd) {\n const fallbackPreloaded = this.getPreloadedAd();\n if (fallbackPreloaded) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F504} First ad failed, using preloaded fallback\");\n }\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = fallbackPreloaded.imaController;\n this.attachImaEventListeners();\n this.ima.resume();\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPoolActive) {\n this.preloadPoolActive = true;\n this.preloadPoolLoop(baseVastUrl);\n }\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n return;\n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n }\n if (this.isTemporaryAdError(error)) {\n this.temporaryFailureUrls.set(firstAdUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n }\n } else {\n this.failedVastUrls.add(firstAdUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n }\n }\n this.consecutiveFailures++;\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n }\n }\n startContinuousFetching(baseVastUrl) {\n if (!this.continuousFetchingActive) {\n return;\n }\n if (this.continuousFetchLoopRunning) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23ED\\uFE0F Fetch loop already running, skipping duplicate start\");\n }\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F504} Starting continuous ad fetching loop\");\n }\n this.continuousFetchLoopRunning = true;\n this.continuousFetchLoop(baseVastUrl);\n }\n async continuousFetchLoop(baseVastUrl) {\n while (this.continuousFetchingActive && this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F Ad break time expired, stopping URL generation\");\n }\n break;\n }\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n }\n break;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), stopping URL generation`);\n }\n break;\n }\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Maximum ad requests reached (${this.maxTotalAdRequestsPerBreak}), stopping`);\n }\n break;\n }\n const maxQueueSize = 5;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F8\\uFE0F URL queue full (${this.adRequestQueue.length}), waiting...`);\n }\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n continue;\n }\n const newAdUrl = this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];\n if (!newAdUrl || this.failedVastUrls.has(newAdUrl) || this.isUrlInCooldown(newAdUrl)) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n continue;\n }\n if (this.config.debugAdTiming) {\n const queuedUrlsPreview = [...this.adRequestQueue, newAdUrl];\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F4DD} Queued VAST URL (queue size: ${queuedUrlsPreview.length})`,\n { queuedUrls: queuedUrlsPreview }\n );\n }\n this.adRequestQueue.push(newAdUrl);\n this.totalAdsInBreak++;\n const generationDelay = this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, this.consecutiveFailures), 5e3) : 500;\n await new Promise((resolve) => setTimeout(resolve, generationDelay));\n }\n this.continuousFetchLoopRunning = false;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F6D1} 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.hidePlaceholderLayer();\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Stopping continuous ad fetching\");\n }\n }\n async tryNextAvailableAdWithRateLimit() {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n const backoffMultiplier = Math.pow(2, this.consecutiveFailures);\n const backoffDelay = Math.min(this.backoffBaseMs * backoffMultiplier, this.maxBackoffMs);\n const effectiveMinInterval = this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffDelay : 0);\n const timeSinceLastRequest = Date.now() - this.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F3 Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.consecutiveFailures} failures)`);\n }\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n return this.tryNextAvailableAd(0);\n }\n async tryNextAvailableAd(retryCount = 0) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n this.cleanupTemporaryFailures();\n const preloaded = this.getPreloadedAd();\n if (preloaded) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F3AF} Using preloaded ad from pool (${this.preloadPool.length} remaining in pool)`);\n }\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"preload\", vastUrl: preloaded.vastUrl },\n this.config.adPlayerType\n ).catch(() => {\n });\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloaded.imaController;\n this.attachImaEventListeners();\n this.ima.resume();\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n this.consecutiveFailures = 0;\n return;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F Preloaded ad failed to play:\", error);\n }\n }\n }\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) {\n continue;\n }\n if (this.failedVastUrls.has(nextAdUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23ED\\uFE0F Skipping permanently-failed URL, trying next...\");\n }\n continue;\n }\n if (this.isUrlInCooldown(nextAdUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23ED\\uFE0F Skipping URL in cooldown (recent no-fill), trying next...\");\n }\n continue;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F3AC} Requesting next ad via IMA SDK (${this.currentAdIndex + 1}/${this.totalAdsInBreak}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n try {\n await this.playSingleAd(nextAdUrl);\n this.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = error.message;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u274C Ad request failed:\", errorMessage);\n }\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.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.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F3 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.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No more ads available, ending ad break\");\n }\n this.handleAdPodComplete();\n }\n }\n async showPlaceholderAndWaitForAds() {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Skipping placeholder - too many consecutive failures\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (waitTime < 1e3) {\n this.handleAdPodComplete();\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u2B1B Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n }\n this.isShowingPlaceholder = true;\n this.ima.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) {\n return;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Too many failures during placeholder wait\");\n }\n break;\n }\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) {\n continue;\n }\n if (this.failedVastUrls.has(nextAdUrl)) {\n continue;\n }\n if (this.isUrlInCooldown(nextAdUrl)) {\n continue;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 Ad URL available, requesting via IMA SDK\");\n }\n this.isShowingPlaceholder = false;\n this.ima.hidePlaceholder();\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n try {\n await this.playSingleAd(nextAdUrl);\n this.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = error.message;\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F0 Placeholder timeout, ending ad break\");\n }\n this.isShowingPlaceholder = false;\n this.ima.hidePlaceholder();\n this.handleAdPodComplete();\n }\n findCurrentOrNextBreak(nowMs) {\n const schedule = this.vmapBreaks;\n let candidate;\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 const tol = this.config.driftToleranceMs ?? 1e3;\n if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))) {\n candidate = b;\n }\n }\n return candidate;\n }\n onTimeUpdate(currentTimeSec) {\n if (this.ima.isAdPlaying() || this.inAdBreak) return;\n const nowMs = currentTimeSec * 1e3;\n const breakToPlay = this.findBreakForTime(nowMs);\n if (breakToPlay) {\n void this.handleMidAdJoin(breakToPlay, nowMs).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:\",\n error\n );\n }\n });\n }\n }\n async handleMidAdJoin(adBreak, nowMs) {\n const key = this.getAdBreakKey(adBreak);\n if (this.consumedVmapBreakIds.has(key)) {\n return;\n }\n const breakStartMs = this.resolveBreakStartMs(adBreak);\n if (breakStartMs == null) {\n return;\n }\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = breakStartMs + durationMs;\n const tol = this.config.driftToleranceMs ?? 1e3;\n const inWindow = durationMs > 0 ? nowMs > breakStartMs && nowMs < endMs : nowMs + tol >= breakStartMs;\n if (inWindow) {\n this.consumedVmapBreakIds.add(key);\n const remainingMs = durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;\n const tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);\n if (tags && tags.length > 0) {\n const first = tags[0];\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n try {\n await this.playSingleAd(first);\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = remainingMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(remainingMs);\n } catch (error) {\n this.adPodQueue = [];\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:\",\n error\n );\n }\n }\n }\n }\n }\n scheduleAdStopCountdown(remainingMs) {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.ensureAdStoppedByTimer();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.ensureAdStoppedByTimer();\n }, ms);\n }\n clearAdStopTimer() {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = void 0;\n }\n }\n ensureAdStoppedByTimer() {\n if (!this.inAdBreak) return;\n this.adStopTimerId = void 0;\n const adPlaying = this.ima.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1e3)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs = typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n if (adPlaying) {\n this.ima.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n }\n scheduleAdStartIn(delayMs, marker = { type: \"start\" }, cueKey) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0\n );\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.expectedAdBreakDurationMs\n );\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\n updatePtsDrift(ptsSecondsSample) {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n 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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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 async playSingleAd(vastTagUrl) {\n if (this.ima.isAdPlaying()) {\n return;\n }\n if (this.failedVastUrls.has(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n }\n throw new Error(\"VAST URL permanently failed\");\n }\n if (this.isUrlInCooldown(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n }\n throw new Error(\"VAST URL in cooldown after no-fill\");\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n }\n throw new Error(\"Too many consecutive failures\");\n }\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n }\n throw new Error(\"GAM in cooldown\");\n }\n this.recreateImaController();\n const requestToken = ++this.adRequestTokenCounter;\n this.activeAdRequestToken = requestToken;\n this.startAdRequestWatchdog(requestToken);\n try {\n await this.enforceGlobalRateLimit();\n this.lastAdRequestTime = Date.now();\n await this.ima.requestAds(vastTagUrl);\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ssp\", vastUrl: vastTagUrl },\n this.config.adPlayerType\n ).catch(() => {\n });\n this.clearAdRequestWatchdog();\n if (this.activeAdRequestToken !== requestToken) {\n return;\n }\n try {\n this.startAdFailsafeTimer(requestToken);\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n this.consecutiveFailures = 0;\n this.temporaryFailureUrls.delete(vastTagUrl);\n } catch (playError) {\n if (this.config.debugAdTiming) {\n console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n }\n const preloadedFallback = this.getPreloadedAd();\n if (preloadedFallback) {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n }\n try {\n this.clearAdFailsafeTimer();\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedFallback.imaController;\n this.attachImaEventListeners();\n this.ima.resume();\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n return;\n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n if (this.isTemporaryAdError(playError)) {\n this.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n }\n } else {\n this.failedVastUrls.add(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n }\n }\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n throw playError;\n }\n } catch (error) {\n const errorMessage = error?.message || \"\";\n if (this.config.debugAdTiming) {\n console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n }\n const preloadedFallback = this.getPreloadedAd();\n if (preloadedFallback) {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n }\n try {\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedFallback.imaController;\n this.attachImaEventListeners();\n this.ima.resume();\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n await this.ima.play();\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n return;\n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n if (this.isTemporaryAdError(error)) {\n this.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n }\n } else {\n this.failedVastUrls.add(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n }\n }\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n throw error;\n }\n }\n handleAdPodComplete() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] \\u{1F3C1} Ad pod complete - cleaning up\");\n }\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.stopContinuousFetching();\n this.stopPreloadPool();\n this.clearPendingAdBreak();\n if (this.isShowingPlaceholder) {\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n this.adRequestQueue = [];\n this.inAdBreak = false;\n this.adDetectSentForCurrentBreak = false;\n this.activeScte35BreakKey = void 0;\n this.scheduledScte35BreakKey = void 0;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.consecutiveFailures = 0;\n this.globalConsecutiveNoFills = 0;\n this.ima.stop().catch(() => {\n });\n const restoredMuted = this.ima.getOriginalMutedState();\n const restoredVolume = this.ima.getOriginalVolume();\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.video.paused) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n }\n this.video.play()?.catch(() => {\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n }\n handleAdFailure() {\n this.consecutiveFailures++;\n this.recordGamNoFill();\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.consecutiveFailures}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Max consecutive failures reached (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n if (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Ad failed and no time remaining. Failed URLs:\", this.failedVastUrls.size);\n }\n this.handleAdPodComplete();\n }\n }\n startAdRequestWatchdog(token) {\n this.clearAdRequestWatchdog();\n const timeoutMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n this.adRequestWatchdogToken = token;\n this.adRequestWatchdogId = window.setTimeout(() => {\n if (this.adRequestWatchdogToken !== token) {\n return;\n }\n this.adRequestWatchdogId = void 0;\n this.adRequestWatchdogToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n this.handleAdFailure();\n }, timeoutMs);\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n clearAdRequestWatchdog() {\n if (this.adRequestWatchdogId != null) {\n clearTimeout(this.adRequestWatchdogId);\n this.adRequestWatchdogId = void 0;\n }\n if (this.adRequestWatchdogToken != null) {\n this.logAdState(\"ad_request_watchdog_cleared\", {\n token: this.adRequestWatchdogToken\n });\n this.adRequestWatchdogToken = null;\n }\n }\n startAdFailsafeTimer(token) {\n this.clearAdFailsafeTimer();\n const failsafeMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n this.adFailsafeToken = token;\n this.adFailsafeTimerId = window.setTimeout(() => {\n if (this.adFailsafeToken !== token) {\n return;\n }\n this.adFailsafeTimerId = void 0;\n this.adFailsafeToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n this.logAdState(\"ad_failsafe_triggered\", {\n token,\n failsafeMs,\n videoPaused: this.video.paused,\n imaAdPlaying: this.ima.isAdPlaying()\n });\n this.handleAdFailure();\n }, failsafeMs);\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n clearAdFailsafeTimer() {\n if (this.adFailsafeTimerId != null) {\n clearTimeout(this.adFailsafeTimerId);\n this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n this.adFailsafeTimerId = void 0;\n }\n this.adFailsafeToken = null;\n }\n selectVastTagsForBreak(b) {\n if (!b || !b.vastTagUrl) return void 0;\n if (b.vastTagUrl.includes(\",\")) {\n return b.vastTagUrl.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n }\n return [b.vastTagUrl];\n }\n logAdState(event, extra = {}) {\n if (!this.config.debugAdTiming) {\n return;\n }\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n showAds: this.showAds,\n adPlaying: this.ima.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n getRemainingAdMs() {\n if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)\n return 0;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n findBreakForTime(nowMs) {\n const schedule = this.vmapBreaks;\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 const end = breakStartMs + (b.durationMs || 0);\n if (nowMs >= breakStartMs && (b.durationMs ? nowMs < end : nowMs <= breakStartMs + tol)) {\n return b;\n }\n }\n return void 0;\n }\n toggleMute() {\n if (this.ima.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n this.ima.updateOriginalMutedState(newMutedState, this.video.volume);\n this.ima.setAdVolume(newMutedState ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n toggleFullscreen() {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document.exitFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n isMuted() {\n if (this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n setMuted(muted) {\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n this.video.muted = muted;\n if (adPlaying) {\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n this.ima.setAdVolume(muted ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted\n });\n }\n return;\n }\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n setVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying) {\n this.ima.setAdVolume(clampedVolume);\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n getVolume() {\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying) {\n return this.ima.getAdVolume();\n }\n return this.video.volume;\n }\n isFullscreen() {\n return !!document.fullscreenElement;\n }\n isLive() {\n return this.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n resize() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n if (this.ima && this.ima.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 480;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n this.ima.resize(width, height);\n }\n }\n destroy() {\n this.stopContinuousFetching();\n this.stopPreloadPool();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.clearPendingAdBreak();\n if (this.placeholderContainer) {\n if (this.placeholderContainer.parentElement) {\n this.placeholderContainer.parentElement.removeChild(this.placeholderContainer);\n }\n this.placeholderContainer = void 0;\n }\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = void 0;\n }\n this.hls?.destroy();\n this.ima?.destroy();\n this.adRequestQueue = [];\n this.consecutiveFailures = 0;\n }\n};\n\n// src/players/HlsPlayer.tsx\nvar HlsPlayer = class extends import_react2.Component {\n constructor() {\n super(...arguments);\n this.player = null;\n this.mounted = false;\n this.load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n const config = {\n src: this.props.src,\n videoElement: this.props.videoElement\n };\n if (this.props.autoplay !== void 0)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== void 0)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== void 0)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== void 0)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== void 0)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== void 0)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== void 0)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== void 0)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== void 0)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== void 0)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== void 0)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== void 0)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== void 0)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n this.player = new StormcloudVideoPlayer(config);\n this.props.onMount?.(this);\n await this.player.load();\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return this.player.hls;\n return null;\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nHlsPlayer.displayName = \"HlsPlayer\";\nHlsPlayer.canPlay = canPlay.hls;\n\n// src/players/FilePlayer.tsx\nvar import_react3 = require(\"react\");\nvar FilePlayer = class extends import_react3.Component {\n constructor() {\n super(...arguments);\n this.mounted = false;\n this.ready = false;\n this.load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n const video = this.props.videoElement;\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n const handleError = (error) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\n };\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.src = this.props.src;\n if (this.props.autoplay !== void 0) video.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) video.muted = this.props.muted;\n if (this.props.loop !== void 0) video.loop = this.props.loop;\n if (this.props.controls !== void 0) video.controls = this.props.controls;\n if (this.props.playsInline !== void 0)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== void 0)\n video.preload = this.props.preload;\n if (this.props.poster !== void 0) video.poster = this.props.poster;\n this.props.onMount?.(this);\n return () => {\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n };\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[FilePlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n } else {\n console.warn(\"[FilePlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.setLoop = (loop) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n this.enablePIP = async () => {\n if (this.props.videoElement && \"requestPictureInPicture\" in this.props.videoElement) {\n try {\n await this.props.videoElement.requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n this.disablePIP = async () => {\n if (document.pictureInPictureElement) {\n try {\n await document.exitPictureInPicture();\n } catch (error) {\n console.warn(\"Exit Picture-in-Picture failed:\", error);\n }\n }\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nFilePlayer.displayName = \"FilePlayer\";\nFilePlayer.canPlay = canPlay.file;\n\n// src/players/index.ts\nvar players = [\n {\n key: \"hls\",\n name: \"HLS Player\",\n canPlay: canPlay.hls,\n lazyPlayer: lazy(() => Promise.resolve({ default: HlsPlayer }))\n },\n {\n key: \"file\",\n name: \"File Player\",\n canPlay: canPlay.file,\n canEnablePIP: (url) => {\n return canPlay.file(url) && (document.pictureInPictureEnabled || typeof document.webkitSupportsPresentationMode === \"function\");\n },\n lazyPlayer: lazy(() => Promise.resolve({ default: FilePlayer }))\n }\n];\nvar players_default = players;\n","import { lazy } from \"../utils\";\nimport { canPlay } from \"../patterns\";\nimport HlsPlayer from \"./HlsPlayer\";\nimport FilePlayer from \"./FilePlayer\";\n\nexport interface PlayerConfig {\n key: string;\n name: string;\n canPlay: (url: string) => boolean;\n canEnablePIP?: (url: string) => boolean;\n lazyPlayer?: any;\n}\n\nconst players: PlayerConfig[] = [\n {\n key: \"hls\",\n name: \"HLS Player\",\n canPlay: canPlay.hls,\n lazyPlayer: lazy(() => Promise.resolve({ default: HlsPlayer })),\n },\n {\n key: \"file\",\n name: \"File Player\",\n canPlay: canPlay.file,\n canEnablePIP: (url: string) => {\n return (\n canPlay.file(url) &&\n (document.pictureInPictureEnabled ||\n typeof (document as any).webkitSupportsPresentationMode ===\n \"function\")\n );\n },\n lazyPlayer: lazy(() => Promise.resolve({ default: FilePlayer })),\n },\n];\n\nexport default players;\n","import { lazy as reactLazy } from \"react\";\n\nexport const lazy = reactLazy;\n\nexport const omit = <T extends Record<string, any>, K extends keyof T>(\n object: T,\n keys: K[]\n): Omit<T, K> => {\n const result = { ...object };\n keys.forEach((key) => {\n delete result[key];\n });\n return result;\n};\n\nexport const isMediaStream = (url: any): url is MediaStream => {\n return (\n typeof window !== \"undefined\" &&\n window.MediaStream &&\n url instanceof window.MediaStream\n );\n};\n\nexport const supportsWebKitPresentationMode = (): boolean => {\n if (typeof window === \"undefined\") return false;\n const video = document.createElement(\"video\");\n return \"webkitSupportsPresentationMode\" in video;\n};\n\nexport const randomString = (): string => {\n return Math.random().toString(36).substr(2, 9);\n};\n\nexport const parseQuery = (url: string): Record<string, string> => {\n const query: Record<string, string> = {};\n const queryString = url.split(\"?\")[1] || \"\";\n\n if (!queryString) return query;\n\n const manualParse = (qs: string) => {\n qs.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n try {\n query[decodeURIComponent(key)] = value\n ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n : \"\";\n } catch (e) {\n query[key] = value || \"\";\n }\n }\n });\n };\n\n if (typeof URLSearchParams !== \"undefined\") {\n try {\n const params = new URLSearchParams(queryString);\n params.forEach((value, key) => {\n query[key] = value;\n });\n return query;\n } catch (e) {\n manualParse(queryString);\n }\n } else {\n manualParse(queryString);\n }\n\n return query;\n};\n\nexport const merge = <T extends Record<string, any>>(\n target: T,\n ...sources: Partial<T>[]\n): T => {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n merge(target[key] as any, source[key] as any);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return merge(target, ...sources);\n};\n\nconst isObject = (item: any): item is Record<string, any> => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\n\nexport const IS_BROWSER = typeof window !== \"undefined\" && window.document;\nexport const IS_GLOBAL =\n typeof globalThis !== \"undefined\" &&\n globalThis.window &&\n globalThis.window.document;\nexport const IS_IOS =\n IS_BROWSER && /iPad|iPhone|iPod/.test(navigator.userAgent);\nexport const IS_SAFARI =\n IS_BROWSER && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n\nexport const SUPPORTS_HLS = (): boolean => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/vnd.apple.mpegurl\"));\n};\n\nexport const SUPPORTS_DASH = (): boolean => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/dash+xml\"));\n};\n","export const HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nexport const HLS_PATHS = /\\/hls\\//i;\nexport const DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nexport const VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nexport const AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\n\nexport const canPlay = {\n hls: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n\n dash: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n\n video: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n\n audio: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n\n file: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n },\n};\n","import { Component } from \"react\";\nimport { StormcloudVideoPlayer } from \"../player/StormcloudVideoPlayer\";\nimport type { StormcloudVideoPlayerConfig } from \"../types\";\nimport { canPlay } from \"../patterns\";\n\nexport interface HlsPlayerProps extends StormcloudVideoPlayerConfig {\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n}\n\nexport default class HlsPlayer extends Component<HlsPlayerProps> {\n static displayName = \"HlsPlayer\";\n\n static canPlay = canPlay.hls;\n\n private player: StormcloudVideoPlayer | null = null;\n private mounted = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n\n componentDidUpdate(prevProps: HlsPlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n\n const config: StormcloudVideoPlayerConfig = {\n src: this.props.src,\n videoElement: this.props.videoElement,\n };\n\n if (this.props.autoplay !== undefined)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== undefined)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== undefined)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== undefined)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== undefined)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== undefined)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== undefined)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== undefined)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== undefined)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== undefined)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== undefined)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== undefined)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== undefined)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n\n this.player = new StormcloudVideoPlayer(config);\n\n this.props.onMount?.(this);\n\n await this.player.load();\n\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n\n play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource =\n video.src ||\n (video.currentSrc && video.currentSrc !== \"\") ||\n video.readyState >= 1;\n\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return (this.player as any).hls;\n return null;\n };\n\n render() {\n return null;\n }\n}\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n ImaController,\n AdBreak,\n StormcloudApiResponse,\n} from \"../types\";\nimport { createImaController } from \"../sdk/ima\";\nimport { createHlsAdPlayer } from \"../sdk/hlsAdPlayer\";\nimport {\n sendInitialTracking,\n sendHeartbeat,\n sendAdDetectTracking,\n sendAdLoadedTracking,\n sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport {\n supportsGoogleIMA,\n logBrowserInfo,\n getBrowserConfigOverrides,\n} from \"../utils/browserCompat\";\n\ntype Scte35CueSource = \"manifest\" | \"id3\" | \"ts\";\ntype Scte35CueReadiness = \"early\" | \"playback\";\n\ninterface NormalizedScte35Cue {\n marker: Scte35Marker;\n source: Scte35CueSource;\n readiness: Scte35CueReadiness;\n key: string;\n fragmentSn?: number;\n fragmentStartSeconds?: number;\n}\n\ninterface Scte35CueContext {\n source: Scte35CueSource;\n readiness: Scte35CueReadiness;\n fragmentSn?: number;\n fragmentStartSeconds?: number;\n}\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private ima: ImaController;\n private attached = false;\n private inAdBreak = false;\n private currentAdBreakStartWallClockMs: number | undefined;\n private expectedAdBreakDurationMs: number | undefined;\n private adStopTimerId: number | undefined;\n private adStartTimerId: number | undefined;\n private adFailsafeTimerId: number | undefined;\n private ptsDriftEmaMs = 0;\n private adPodQueue: string[] = [];\n private apiVastTagUrl: string | undefined;\n private apiNumberAds: number | undefined;\n private vmapBreaks: AdBreak[] = [];\n private consumedVmapBreakIds: Set<string> = new Set();\n private lastHeartbeatTime: number = 0;\n private heartbeatInterval: number | undefined;\n private currentAdIndex: number = 0;\n private totalAdsInBreak: number = 0;\n private showAds: boolean = false;\n private isLiveStream: boolean = false;\n private nativeHlsMode: boolean = false;\n private videoSrcProtection: string | null = null;\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n private adRequestTokenCounter = 0;\n private activeAdRequestToken: number | null = null;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n private failedVastUrls: Set<string> = new Set();\n private temporaryFailureUrls: Map<string, number> = new Map();\n private readonly temporaryFailureCooldownMs: number = 30000;\n private continuousFetchingActive: boolean = false;\n private adRequestQueue: string[] = [];\n private maxPlaceholderDurationMs: number = 5000;\n private isShowingPlaceholder: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n private readonly tsScte35Pids: Set<number> = new Set();\n private readonly pmtPids: Set<number> = new Set();\n private readonly processedTsScte35Sections: Set<string> = new Set();\n private readonly pendingScte35Cues: Map<string, NormalizedScte35Cue> =\n new Map();\n private readonly recentScte35CueKeys: Map<string, number> = new Map();\n private readonly recentScte35CueLimit: number = 200;\n private pendingScte35CueKey: string | undefined;\n private activeScte35BreakKey: string | undefined;\n private scheduledScte35BreakKey: string | undefined;\n \n private totalAdRequestsInBreak: number = 0;\n private readonly maxTotalAdRequestsPerBreak: number = 10;\n \n private pendingAdBreak: {\n marker: Scte35Marker;\n detectedAtFragmentSn?: number;\n vastUrls: string[];\n isFetching: boolean;\n fetchStartTime?: number;\n } | null = null;\n private prefetchTimerId: number | undefined;\n \n private consecutiveFailures: number = 0;\n private readonly maxConsecutiveFailures: number = 5;\n private lastAdRequestTime: number = 0;\n private readonly minAdRequestIntervalMs: number = 3000;\n private readonly backoffBaseMs: number = 1000;\n private readonly maxBackoffMs: number = 15000;\n private placeholderContainer: HTMLDivElement | undefined;\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 preloadPool: Array<{\n vastUrl: string;\n imaController: ImaController;\n loadedAt: number;\n isReady: boolean;\n loadPromise: Promise<void>;\n }> = [];\n private readonly maxPreloadPoolSize: number = 2;\n private preloadPoolActive: boolean = false;\n private preloadPoolLoopRunning: boolean = false;\n private adDetectSentForCurrentBreak: boolean = false;\n\n constructor(config: StormcloudVideoPlayerConfig) {\n initializePolyfills();\n\n const browserOverrides = getBrowserConfigOverrides();\n \n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n\n logBrowserInfo(config.debugAdTiming);\n\n this.ima = this.createAdPlayer(false);\n }\n\n private createAdPlayer(continueLiveStreamDuringAds: boolean): ImaController {\n const vastMode = this.config.vastMode || \"default\";\n let adPlayerType =\n this.config.adPlayerType || (vastMode === \"adstorm\" ? \"hls\" : \"ima\");\n\n if (adPlayerType === \"ima\" && !supportsGoogleIMA()) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player\"\n );\n }\n adPlayerType = \"hls\";\n }\n\n if (adPlayerType === \"hls\") {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)\"\n );\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...(this.config.licenseKey\n ? { licenseKey: this.config.licenseKey }\n : {}),\n ...(this.hls ? { mainHlsInstance: this.hls } : {}),\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating Google IMA ad player (IMA mode)\"\n );\n }\n return createImaController(this.video, {\n continueLiveStreamDuringAds,\n });\n }\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\n }\n\n try {\n await this.fetchAdConfiguration();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n\n this.initializeTracking();\n\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\",\n }\n );\n }\n\n this.ima.destroy();\n this.ima = this.createAdPlayer(false);\n this.ima.initialize();\n\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n return;\n }\n\n this.hls = new Hls({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1.0,\n ...(this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}),\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1000 * 1000,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1,\n });\n\n this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n\n this.hls.on(Hls.Events.MANIFEST_PARSED, async (_, data: any) => {\n if (this.config.allowNativeHls === false) {\n this.isLiveStream = true;\n } else {\n this.isLiveStream =\n this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n }\n\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds()\n ? \"live (main video continues muted during ads)\"\n : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior,\n });\n }\n\n this.ima.destroy();\n this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.ima.initialize();\n\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n }\n });\n\n this.hls.on(Hls.Events.LEVEL_LOADED, (_evt, data: any) => {\n if (this.inAdBreak || this.pendingAdBreak) {\n return;\n }\n\n const details = data?.details;\n if (!details || !details.fragments || details.fragments.length === 0) {\n return;\n }\n\n const fragmentsToScan = Math.min(5, details.fragments.length);\n \n for (let i = 0; i < fragmentsToScan; i++) {\n const frag = details.fragments[i];\n const tagList: any[] | undefined = frag?.tagList;\n \n if (!Array.isArray(tagList)) continue;\n\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n \n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n }\n }\n\n if (!tag) continue;\n\n if (tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = tag.includes(\"EXT-X-DATERANGE\") \n ? this.parseAttributeList(value)\n : {};\n const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") || \n \"SCTE35-OUT\" in attrs || \n attrs[\"SCTE35-OUT\"] !== undefined;\n\n if (hasScteOut) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value, earlyDetection: true },\n } as Scte35Marker;\n\n if (this.config.debugAdTiming) {\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.onScte35Cue(marker, {\n ...this.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.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_PARSING_METADATA, (_evt, data: any) => {\n const id3Tags: Id3TagInfo[] = (data?.samples || []).map((s: any) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts,\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n\n this.hls.on(Hls.Events.FRAG_LOADED, (_evt, data: any) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : undefined,\n this.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 this.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.activatePendingScte35CuesForFragment(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 = this.parseCueOutCont(value);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(prog?.duration !== undefined\n ? { durationSeconds: prog.duration }\n : {}),\n ...(prog?.elapsed !== undefined\n ? { ptsSeconds: prog.elapsed }\n : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Cue(\n { type: \"end\", raw: { tag, value } },\n {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n }\n );\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { tag, value, attrs },\n } as Scte35Marker;\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n }\n if (hasScteIn) {\n this.onScte35Cue(\n { type: \"end\", raw: { tag, value, attrs } },\n {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n }\n );\n }\n }\n }\n this.activatePendingScte35CuesForFragment(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.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private attachImaEventListeners(): void {\n this.ima.on(\"all_ads_completed\", () => {\n sendAdImpressionTracking(\n this.config.licenseKey,\n { adIndex: this.currentAdIndex },\n this.config.adPlayerType\n ).catch(() => {});\n\n const remaining = this.getRemainingAdMs();\n \n this.consecutiveFailures = 0;\n \n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n\n if (this.inAdBreak) {\n if (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n this.ima.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 this.ima.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n this.resetGamNoFillCounter();\n \n if (this.inAdBreak && this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.ima.on(\"content_resume\", () => {\n sendAdImpressionTracking(\n this.config.licenseKey,\n { adIndex: this.currentAdIndex },\n this.config.adPlayerType\n ).catch(() => {});\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n }\n }\n\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n return;\n }\n\n this.consecutiveFailures = 0;\n\n const remaining = this.getRemainingAdMs();\n \n if (this.config.debugAdTiming) {\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 (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n });\n }\n\n private recreateImaController(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Recreating ImaController for new ad\");\n }\n\n const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n if (shouldShowPlaceholder && this.ima) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController\");\n }\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n\n const preservedMutedState = this.ima.getOriginalMutedState();\n const preservedVolumeState = this.ima.getOriginalVolume();\n\n if (this.ima) {\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Error destroying old ImaController:\", error);\n }\n }\n }\n\n const continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();\n this.ima = this.createAdPlayer(continueLiveStreamDuringAds);\n \n this.ima.initialize();\n this.ima.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n this.attachImaEventListeners();\n\n if (shouldShowPlaceholder) {\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n }\n\n private ensurePlaceholderContainer(): void {\n if (this.placeholderContainer) {\n return;\n }\n\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"5\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n if (!this.video.parentElement) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n\n this.video.parentElement.appendChild(container);\n this.placeholderContainer = container;\n }\n\n private showPlaceholderLayer(): void {\n this.ensurePlaceholderContainer();\n \n if (!this.placeholderContainer) {\n return;\n }\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n\n const wasHidden = this.placeholderContainer.style.display === \"none\" || this.placeholderContainer.style.opacity === \"0\";\n if (wasHidden) {\n this.placeholderContainer.style.transition = \"none\";\n } else {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n \n this.placeholderContainer.style.backgroundColor = \"#000\";\n this.placeholderContainer.style.display = \"flex\";\n this.placeholderContainer.offsetHeight;\n this.placeholderContainer.style.opacity = \"1\";\n this.placeholderContainer.style.pointerEvents = \"auto\";\n \n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)\");\n }\n }\n\n private hidePlaceholderLayer(): void {\n if (!this.placeholderContainer) {\n return;\n }\n\n this.placeholderContainer.style.opacity = \"0\";\n setTimeout(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.display = \"none\";\n this.placeholderContainer.style.pointerEvents = \"none\";\n this.placeholderContainer.style.backgroundColor = \"#000\";\n }\n }, 300);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n\n private attach(): void {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n\n this.ima.initialize();\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachImaEventListeners();\n\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n\n this.emptiedHandler = () => {\n if (\n this.nativeHlsMode &&\n this.videoSrcProtection &&\n !this.ima.isAdPlaying()\n ) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n\n if (streamType === \"other\") {\n return true;\n }\n\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Cue(marker, {\n source: \"id3\",\n readiness: \"playback\",\n });\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return undefined;\n\n const cueOutMatch =\n text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) ||\n text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(dur !== undefined ? { durationSeconds: dur } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(cont?.duration !== undefined\n ? { durationSeconds: cont.duration }\n : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n if (hasScteIn) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n }\n\n if (/SCTE35-OUT/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n }\n\n private decodeId3ValueToText(value: string | Uint8Array): string | undefined {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]!);\n return out;\n } catch {\n return undefined;\n }\n }\n\n private 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 fragmentStartSeconds = this.getFragmentStartSeconds(frag);\n if (fragmentStartSeconds !== undefined) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n return context;\n }\n\n private 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\n private 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.startAdPrefetch(marker, context.fragmentSn, cue.key);\n }\n return;\n }\n\n if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n key: cue.key,\n activeScte35BreakKey: this.activeScte35BreakKey,\n inAdBreak: this.inAdBreak,\n source: cue.source,\n });\n }\n return;\n }\n\n if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n if (this.config.debugAdTiming) {\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.onScte35Marker(marker, cue.key);\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 private 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.activeScte35BreakKey === cue.key ||\n this.scheduledScte35BreakKey === 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.inAdBreak) {\n return false;\n }\n\n if (\n this.isStrongScte35CueKey(this.activeScte35BreakKey) &&\n this.isStrongScte35CueKey(cue.key) &&\n this.activeScte35BreakKey !== cue.key\n ) {\n return false;\n }\n\n return true;\n }\n\n private 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 fragmentStartSeconds =\n cue.fragmentStartSeconds ?? this.getFragmentStartSeconds(frag);\n if (fragmentStartSeconds !== undefined) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n this.onScte35Cue(cue.marker, context);\n });\n }\n\n private onScte35Marker(marker: Scte35Marker, cueKey?: string): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n hasPendingAdBreak: !!this.pendingAdBreak,\n });\n }\n\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n if (marker.durationSeconds != null) {\n const newDurationMs = marker.durationSeconds * 1000;\n if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {\n this.expectedAdBreakDurationMs = newDurationMs;\n const elapsedMs = this.currentAdBreakStartWallClockMs != null\n ? Date.now() - this.currentAdBreakStartWallClockMs\n : 0;\n const remainingMs = Math.max(0, newDurationMs - elapsedMs);\n this.scheduleAdStopCountdown(remainingMs);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${newDurationMs}ms, remaining: ${remainingMs}ms`\n );\n }\n }\n }\n return;\n }\n\n if (!this.adDetectSentForCurrentBreak) {\n this.adDetectSentForCurrentBreak = true;\n const detectPayload: {\n durationSeconds?: number;\n ptsSeconds?: number;\n detectedAtFragmentSn?: number;\n } = {};\n if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;\n if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;\n sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(() => {});\n }\n\n const hasPrefetchedAds = this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;\n\n const durationMs =\n marker.durationSeconds != null\n ? marker.durationSeconds * 1000\n : (this.pendingAdBreak?.marker.durationSeconds != null \n ? this.pendingAdBreak.marker.durationSeconds * 1000 \n : undefined);\n\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n hasPrefetchedAds,\n });\n }\n\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Starting ad immediately (manifest-based)${hasPrefetchedAds ? \" with prefetched ads\" : \"\"}`\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1000;\n const nowMs = this.video.currentTime * 1000;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1000 - estCurrentPtsMs);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1000,\n deltaMs,\n tolerance: tol,\n });\n }\n\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.expectedAdBreakDurationMs = durationMs;\n this.scheduledScte35BreakKey = cueKey;\n this.scheduleAdStartIn(deltaMs, marker, cueKey);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n if (\n this.expectedAdBreakDurationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n \n if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0) {\n this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.ima.isAdPlaying();\n const hasQueuedAds = this.adRequestQueue.length > 0;\n \n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null,\n });\n }\n \n if (adPlaying || (remaining > 1000 && hasQueuedAds)) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active\");\n }\n return;\n }\n \n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n \n if (adPlaying) {\n this.ima.stop().catch(() => {});\n }\n \n this.handleAdPodComplete();\n return;\n }\n }\n\n private startScte35AdBreak(\n marker: Scte35Marker,\n cueKey: string | undefined,\n durationMs: number | undefined\n ): void {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE start marker\");\n }\n }\n\n this.inAdBreak = true;\n this.activeScte35BreakKey = cueKey ?? this.pendingScte35CueKey;\n this.scheduledScte35BreakKey = undefined;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n\n this.handleAdStart(marker);\n\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n }\n\n private parseCueOutDuration(value: string): number | undefined {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match =\n value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) ||\n value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? undefined : d;\n }\n return undefined;\n }\n\n private parseCueOutCont(\n value: string\n ): { elapsed?: number; duration?: number } | undefined {\n const 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\n private parseAttributeList(value: string): Record<string, string> {\n const attrs: Record<string, string> = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(value)) !== null) {\n const key: string = (match[1] ?? \"\") as string;\n let rawVal: string = (match[3] ?? match[4] ?? \"\") as string;\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n\n private toNumber(val: unknown): number | undefined {\n if (val == null) return undefined;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? undefined : n;\n }\n\n private isManifestBasedMarker(marker: Scte35Marker): boolean {\n const raw = marker.raw as any;\n if (!raw) return false;\n\n if (raw.tag) {\n const tag = String(raw.tag);\n return (\n tag.includes(\"EXT-X-CUE-OUT\") ||\n tag.includes(\"EXT-X-CUE-IN\") ||\n tag.includes(\"EXT-X-DATERANGE\")\n );\n }\n\n if (raw.id3) return false;\n\n if (raw.splice_command_type) return false;\n\n return false;\n }\n\n private 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 private processFragmentScte35Payload(\n payloadData: unknown,\n fragmentSn?: number,\n fragmentStartSeconds?: number\n ): void {\n const payload = this.normalizeFragmentPayload(payloadData);\n if (!payload) {\n return;\n }\n\n const markers = this.parseScte35FromTsPackets(payload);\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.onScte35Cue(marker, context);\n });\n }\n\n private parseScte35FromTsPackets(data: Uint8Array): Scte35Marker[] {\n const packetInfo = this.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 this.parsePatSection(payload, payloadUnitStart);\n } else if (this.pmtPids.has(pid)) {\n this.parsePmtSection(payload, payloadUnitStart);\n } else if (this.tsScte35Pids.has(pid)) {\n this.collectScte35SectionsFromPayload(\n pid,\n payload,\n payloadUnitStart,\n sectionAssemblers,\n markers\n );\n }\n }\n\n return markers;\n }\n\n private 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\n private parsePatSection(payload: Uint8Array, payloadUnitStart: boolean): void {\n const sectionStart = this.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 = this.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 this.pmtPids.add(pid);\n }\n }\n }\n\n private parsePmtSection(payload: Uint8Array, payloadUnitStart: boolean): void {\n const sectionStart = this.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 = this.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 this.descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd))\n ) {\n this.tsScte35Pids.add(elementaryPid);\n }\n\n offset = descriptorStart + esInfoLength;\n }\n }\n\n private 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\n private collectScte35SectionsFromPayload(\n pid: number,\n payload: Uint8Array,\n payloadUnitStart: boolean,\n assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n markers: Scte35Marker[]\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 this.appendScte35Bytes(\n pid,\n payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n assemblers,\n markers\n );\n }\n assemblers.delete(pid);\n offset = 1 + pointerField;\n } else {\n this.appendScte35Bytes(pid, payload, assemblers, markers);\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 = this.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 this.addScte35SectionMarker(\n payload.subarray(offset, offset + totalLength),\n markers\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\n private appendScte35Bytes(\n pid: number,\n bytes: Uint8Array,\n assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n markers: Scte35Marker[]\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 this.addScte35SectionMarker(new Uint8Array(assembler.bytes), markers);\n }\n }\n\n private addScte35SectionMarker(\n section: Uint8Array,\n markers: Scte35Marker[]\n ): void {\n if (section[0] !== 0xfc || this.hasProcessedTsScte35Section(section)) {\n return;\n }\n\n const marker = this.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\n private hasProcessedTsScte35Section(section: Uint8Array): 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 (this.processedTsScte35Sections.has(key)) {\n return true;\n }\n\n this.processedTsScte35Sections.add(key);\n if (this.processedTsScte35Sections.size > 200) {\n const firstKey = this.processedTsScte35Sections.values().next().value;\n if (firstKey) {\n this.processedTsScte35Sections.delete(firstKey);\n }\n }\n return false;\n }\n\n private 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\n private getPsiSectionLength(data: Uint8Array, offset: number): number {\n return (((data[offset + 1] ?? 0) & 0x0f) << 8) | (data[offset + 2] ?? 0);\n }\n\n private parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\n class BitReader {\n private bytePos = 0;\n private bitPos = 0;\n constructor(private readonly buf: Uint8Array) {}\n readBits(numBits: number): number {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos]!;\n const shift = remainingInByte - toRead;\n const mask = ((1 << toRead) - 1) & 0xff;\n const bits = (currentByte >> shift) & mask;\n result = (result << toRead) | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n: number): void {\n this.readBits(n);\n }\n get bytePosition(): number {\n return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n }\n }\n\n const 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\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 = this.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\n private 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 = this.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\n private 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 = this.markerTypeFromSegmentationTypeId(segmentationTypeId);\n if (!markerType) {\n return undefined;\n }\n\n return {\n type: markerType,\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n segmentationEventId,\n };\n }\n\n private 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\n private initializeTracking(): void {\n sendInitialTracking(this.config.licenseKey)\n .then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n })\n .catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n });\n }\n\n private sendHeartbeatIfNeeded(): void {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 30000) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n private async fetchAdConfiguration(): Promise<void> {\n if (this.config.vmapUrl) {\n await this.fetchAndParseVmap(this.config.vmapUrl);\n }\n\n const vastMode = this.config.vastMode || \"default\";\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n );\n }\n return;\n }\n\n const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n this.apiVastTagUrl = vastEndpoint;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n vastEndpoint\n );\n }\n return;\n }\n\n if (this.config.vastTagUrl) {\n this.apiVastTagUrl = this.config.vastTagUrl;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n return;\n }\n\n const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n apiUrl\n );\n }\n\n const headers: Record<string, string> = {};\n if (this.config.licenseKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n }\n\n const response = await fetch(apiUrl, { headers });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n );\n }\n return;\n }\n\n const data: StormcloudApiResponse = await response.json();\n\n const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n if (imaPayload) {\n this.apiVastTagUrl = decodeURIComponent(imaPayload);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n );\n }\n }\n\n const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n if (numberAds != null && numberAds > 0) {\n this.apiNumberAds = numberAds;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n\n 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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n }\n return [];\n }\n\n const adBreakNodes = Array.from(\n doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\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 const adTagNode = node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\");\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 // Post-roll: resolved using current media duration at runtime.\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 private getAdBreakKey(adBreak: AdBreak): string {\n if (adBreak.id) {\n return adBreak.id;\n }\n return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n }\n\n private resolveBreakStartMs(adBreak: AdBreak): number | undefined {\n if (adBreak.startTimeMs >= 0) {\n return adBreak.startTimeMs;\n }\n\n // startTimeMs=-1 represents VMAP \"end\" and becomes post-roll.\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 getCurrentAdIndex(): number {\n return this.currentAdIndex;\n }\n\n getTotalAdsInBreak(): number {\n return this.totalAdsInBreak;\n }\n\n getAdRemainingMs(): number {\n return this.getRemainingAdMs();\n }\n\n private generateVastUrlsWithCorrelators(\n baseUrl: string,\n count: number\n ): string[] {\n const urls: string[] = [];\n const baseTimestamp = Date.now();\n \n for (let i = 0; i < count; i++) {\n const timestamp = baseTimestamp + i;\n const random = Math.floor(Math.random() * 1000000000000);\n const uniqueCorrelator = `${timestamp}_${random}_${i}`;\n \n let urlWithCorrelator: string;\n \n const correlatorRegex = /([?&])correlator=([^&]*)/;\n if (correlatorRegex.test(baseUrl)) {\n urlWithCorrelator = baseUrl.replace(correlatorRegex, `$1correlator=${uniqueCorrelator}`);\n } else if (baseUrl.includes(\"?\")) {\n urlWithCorrelator = `${baseUrl}&correlator=${uniqueCorrelator}`;\n } else {\n urlWithCorrelator = `${baseUrl}?correlator=${uniqueCorrelator}`;\n }\n \n urls.push(urlWithCorrelator);\n }\n \n return urls;\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.ima.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.showAds;\n }\n\n getStreamType(): \"hls\" | \"other\" {\n const url = this.config.src.toLowerCase();\n if (\n url.includes(\".m3u8\") ||\n url.includes(\"/hls/\") ||\n url.includes(\"application/vnd.apple.mpegurl\")\n ) {\n return \"hls\";\n }\n return \"other\";\n }\n\n shouldShowNativeControls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(\n this.config.allowNativeHls && !(this.config.showCustomControls ?? false)\n );\n }\n\n private shouldContinueLiveStreamDuringAds(): boolean {\n if (this.config.allowNativeHls) {\n return false;\n }\n\n if (!this.isLiveStream) {\n return false;\n }\n\n return true;\n }\n\n private startAdPrefetch(\n marker: Scte35Marker,\n fragmentSn?: number,\n cueKey?: string\n ): void {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n\n const scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1000);\n const tags = this.selectVastTagsForBreak(scheduled);\n\n let baseVastUrl: string;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] No VAST URL available for prefetch\");\n }\n return;\n }\n\n const urlsToPregenerate = 5;\n const generatedUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, urlsToPregenerate);\n\n this.pendingAdBreak = {\n marker,\n ...(fragmentSn !== undefined ? { detectedAtFragmentSn: fragmentSn } : {}),\n vastUrls: generatedUrls,\n isFetching: false,\n fetchStartTime: Date.now(),\n };\n this.pendingScte35CueKey = cueKey;\n\n this.adDetectSentForCurrentBreak = true;\n const detectPayload: {\n durationSeconds?: number;\n ptsSeconds?: number;\n detectedAtFragmentSn?: number;\n } = {};\n if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;\n if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;\n if (fragmentSn !== undefined) detectPayload.detectedAtFragmentSn = fragmentSn;\n sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(() => {});\n\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] 🔄 Starting ad prefetch for upcoming ad break\");\n console.log(`[PREFETCH] 📋 Pre-generated ${generatedUrls.length} VAST URLs`);\n }\n\n this.startPreloadPool(baseVastUrl, generatedUrls.slice(0, this.maxPreloadPoolSize));\n }\n\n private clearPendingAdBreak(): void {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = undefined;\n }\n this.pendingAdBreak = null;\n this.pendingScte35CueKey = undefined;\n }\n\n private startPreloadPool(baseVastUrl: string, initialUrls: string[]): void {\n if (this.preloadPoolActive) {\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n }\n return;\n }\n\n this.preloadPoolActive = true;\n \n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] 🏊 Starting preload pool EARLY (target size: ${this.maxPreloadPoolSize})`);\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.preloadPool.length < this.maxPreloadPoolSize) {\n this.preloadAdIntoPool(url);\n }\n }\n\n this.preloadPoolLoop(baseVastUrl);\n }\n\n private async preloadAdIntoPool(vastUrl: string): Promise<void> {\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n }\n return;\n }\n\n if (\n this.preloadPool.some(entry => entry.vastUrl === vastUrl) ||\n this.failedVastUrls.has(vastUrl) ||\n this.isUrlInCooldown(vastUrl)\n ) {\n return;\n }\n\n if (this.preloadPool.length >= this.maxPreloadPoolSize) {\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] 📥 Preloading ad into pool: ${vastUrl}`);\n }\n\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.shouldContinueLiveStreamDuringAds();\n const preloadIma = this.createAdPlayer(continueLiveStreamDuringAds);\n preloadIma.initialize();\n \n const errorListener = (payload?: any) => {\n hasAdError = true;\n adErrorPayload = payload;\n };\n preloadIma.on(\"ad_error\", errorListener);\n errorListenerCleanup = () => preloadIma.off(\"ad_error\", errorListener);\n\n await this.enforceGlobalRateLimit();\n await preloadIma.requestAds(vastUrl);\n \n preloadIma.pause();\n \n await new Promise(resolve => setTimeout(resolve, 1500));\n \n preloadIma.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 preloadIma.destroy();\n \n this.recordGamNoFill();\n\n if (isNoFill) {\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] ⚠️ Ad preload returned no-fill: ${vastUrl}`);\n }\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n } else {\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] ⚠️ Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n }\n if (adErrorPayload && !this.isTemporaryAdError(adErrorPayload as Error)) {\n this.failedVastUrls.add(vastUrl);\n } else {\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n return;\n }\n \n const poolEntry = {\n vastUrl,\n imaController: preloadIma,\n loadedAt: Date.now(),\n isReady: true,\n loadPromise: Promise.resolve(),\n };\n \n const lateErrorListener = (payload?: any) => {\n const index = this.preloadPool.findIndex(entry => entry.vastUrl === vastUrl);\n if (index >= 0) {\n this.preloadPool.splice(index, 1);\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] ⚠️ Late error detected, removed from pool: ${vastUrl}`, payload);\n }\n try {\n preloadIma.destroy();\n } catch {}\n }\n };\n preloadIma.on(\"ad_error\", lateErrorListener);\n \n this.preloadPool.push(poolEntry);\n \n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] ✅ Ad preloaded (no errors detected within timeout) (pool size: ${this.preloadPool.length}/${this.maxPreloadPoolSize})`);\n }\n \n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n } catch (error) {\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n \n this.recordGamNoFill();\n\n if (this.config.debugAdTiming) {\n console.warn(`[PRELOAD-POOL] ⚠️ Failed to preload ad: ${vastUrl}`, error);\n }\n \n if (error instanceof Error && !this.isTemporaryAdError(error)) {\n this.failedVastUrls.add(vastUrl);\n } else if (error instanceof Error && this.isTemporaryAdError(error)) {\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n })();\n\n loadPromise.catch(() => {});\n }\n\n private async preloadPoolLoop(baseVastUrl: string): Promise<void> {\n if (this.preloadPoolLoopRunning) {\n return;\n }\n\n this.preloadPoolLoopRunning = true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] 🔄 Starting continuous preload loop\");\n }\n\n while (this.preloadPoolActive) {\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n }\n break;\n }\n\n if (!this.inAdBreak && this.preloadPool.length >= this.maxPreloadPoolSize) {\n await new Promise(resolve => setTimeout(resolve, 2000));\n continue;\n }\n\n if (!this.inAdBreak && this.pendingAdBreak === null) {\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n }\n break;\n }\n\n while (this.preloadPool.length < this.maxPreloadPoolSize) {\n if (!this.preloadPoolActive || this.isGamInCooldown()) {\n break;\n }\n\n if (this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 0) {\n break;\n }\n }\n\n const newUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const newUrl = newUrls[0];\n \n if (newUrl && !this.failedVastUrls.has(newUrl) && !this.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.preloadPoolLoopRunning = false;\n\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] 🛑 Preload loop ended\");\n }\n }\n\n private getPreloadedAd(): { vastUrl: string; imaController: ImaController } | null {\n if (this.preloadPool.length === 0) {\n return null;\n }\n\n const entry = this.preloadPool.shift();\n if (!entry || !entry.isReady) {\n return null;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] 🎯 Using preloaded ad from pool (${this.preloadPool.length} remaining)`);\n }\n\n return {\n vastUrl: entry.vastUrl,\n imaController: entry.imaController,\n };\n }\n\n private stopPreloadPool(): void {\n this.preloadPoolActive = false;\n this.preloadPoolLoopRunning = false;\n\n for (const entry of this.preloadPool) {\n try {\n entry.imaController.destroy();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n }\n }\n }\n\n this.preloadPool = [];\n\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] 🛑 Preload pool stopped and cleaned up\");\n }\n }\n\n private async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1000\n );\n if (scheduled) {\n this.consumedVmapBreakIds.add(this.getAdBreakKey(scheduled));\n }\n const tags = this.selectVastTagsForBreak(scheduled);\n\n let baseVastUrl: string;\n\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.apiVastTagUrl) {\n baseVastUrl = this.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.config.debugAdTiming) {\n const mode = this.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] 📺 ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n\n this.failedVastUrls.clear();\n this.temporaryFailureUrls.clear();\n this.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video in handleAdStart\");\n }\n }\n\n this.inAdBreak = true;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n \n this.showAds = true;\n \n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n\n if (\n this.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n\n let firstAdUrl: string | undefined;\n let usePreloadedAd = false;\n let preloadedController: ImaController | undefined;\n \n const preloaded = this.getPreloadedAd();\n if (preloaded) {\n firstAdUrl = preloaded.vastUrl;\n preloadedController = preloaded.imaController;\n usePreloadedAd = true;\n \n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"preload\", vastUrl: firstAdUrl },\n this.config.adPlayerType\n ).catch(() => {});\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🚀 Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n console.log(`[CONTINUOUS-FETCH] Pool still has ${this.preloadPool.length} preloaded ads ready`);\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.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🚀 Generating new ad URLs...\");\n }\n \n const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n firstAdUrl = firstAdUrlArray[0];\n this.adRequestQueue = [];\n }\n \n if (!firstAdUrl) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ Failed to get first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 📋 First VAST URL:\", firstAdUrl);\n }\n\n try {\n if (usePreloadedAd && preloadedController) {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedController;\n \n this.attachImaEventListeners();\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n }\n \n this.ima.resume();\n \n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n \n if (!this.preloadPoolActive) {\n this.preloadPoolActive = true;\n this.preloadPoolLoop(baseVastUrl);\n }\n \n await this.ima.play();\n\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n } else {\n await this.enforceGlobalRateLimit();\n this.lastAdRequestTime = Date.now();\n await this.ima.requestAds(firstAdUrl);\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ssp\", vastUrl: firstAdUrl },\n this.config.adPlayerType\n ).catch(() => {});\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ First ad request successful, starting playback\");\n }\n\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n \n if (!this.preloadPoolActive) {\n this.startPreloadPool(baseVastUrl, []);\n }\n \n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ First ad request failed:\", error);\n }\n \n if (!usePreloadedAd) {\n const fallbackPreloaded = this.getPreloadedAd();\n if (fallbackPreloaded) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🔄 First ad failed, using preloaded fallback\");\n }\n \n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = fallbackPreloaded.imaController;\n this.attachImaEventListeners();\n \n this.ima.resume();\n \n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n \n if (!this.preloadPoolActive) {\n this.preloadPoolActive = true;\n this.preloadPoolLoop(baseVastUrl);\n }\n \n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n return; \n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n }\n \n if (this.isTemporaryAdError(error as Error)) {\n this.temporaryFailureUrls.set(firstAdUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n }\n } else {\n this.failedVastUrls.add(firstAdUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n }\n }\n this.consecutiveFailures++;\n \n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n }\n }\n\n private continuousFetchLoopRunning = false;\n\n private startContinuousFetching(baseVastUrl: string): void {\n if (!this.continuousFetchingActive) {\n return;\n }\n\n if (this.continuousFetchLoopRunning) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏭️ Fetch loop already running, skipping duplicate start\");\n }\n return;\n }\n\n if (this.config.debugAdTiming) {\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 while (this.continuousFetchingActive && this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n \n if (remaining <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ Ad break time expired, stopping URL generation\");\n }\n break;\n }\n\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n }\n break;\n }\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), stopping URL generation`);\n }\n break;\n }\n\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Maximum ad requests reached (${this.maxTotalAdRequestsPerBreak}), stopping`);\n }\n break;\n }\n\n const maxQueueSize = 5;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.config.debugAdTiming) {\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.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];\n \n if (!newAdUrl || this.failedVastUrls.has(newAdUrl) || this.isUrlInCooldown(newAdUrl)) {\n await new Promise(resolve => setTimeout(resolve, 500));\n continue;\n }\n\n if (this.config.debugAdTiming) {\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 this.totalAdsInBreak++;\n \n const generationDelay = this.consecutiveFailures > 0 \n ? Math.min(1000 * Math.pow(2, this.consecutiveFailures), 5000)\n : 500;\n await new Promise(resolve => setTimeout(resolve, generationDelay));\n }\n\n this.continuousFetchLoopRunning = false;\n\n if (this.config.debugAdTiming) {\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 private stopContinuousFetching(): void {\n this.continuousFetchingActive = false;\n this.continuousFetchLoopRunning = false;\n \n this.hidePlaceholderLayer();\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Stopping continuous ad fetching\");\n }\n }\n\n private async tryNextAvailableAdWithRateLimit(): Promise<void> {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n const backoffMultiplier = Math.pow(2, this.consecutiveFailures);\n const backoffDelay = Math.min(this.backoffBaseMs * backoffMultiplier, this.maxBackoffMs);\n const effectiveMinInterval = this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffDelay : 0);\n \n const timeSinceLastRequest = Date.now() - this.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏳ Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.consecutiveFailures} failures)`);\n }\n await new Promise(resolve => setTimeout(resolve, waitTime));\n }\n\n return this.tryNextAvailableAd(0);\n }\n\n private async tryNextAvailableAd(retryCount: number = 0): Promise<void> {\n const remaining = this.getRemainingAdMs();\n \n if (remaining <= 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n this.cleanupTemporaryFailures();\n\n const preloaded = this.getPreloadedAd();\n if (preloaded) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🎯 Using preloaded ad from pool (${this.preloadPool.length} remaining in pool)`);\n }\n \n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"preload\", vastUrl: preloaded.vastUrl },\n this.config.adPlayerType\n ).catch(() => {});\n\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloaded.imaController;\n this.attachImaEventListeners();\n\n this.ima.resume();\n\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n \n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n this.consecutiveFailures = 0;\n return;\n } catch (error) {\n if (this.config.debugAdTiming) {\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) {\n continue;\n }\n \n if (this.failedVastUrls.has(nextAdUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏭️ Skipping permanently-failed URL, trying next...\");\n }\n continue;\n }\n \n if (this.isUrlInCooldown(nextAdUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏭️ Skipping URL in cooldown (recent no-fill), trying next...\");\n }\n continue;\n }\n \n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🎬 Requesting next ad via IMA SDK (${this.currentAdIndex + 1}/${this.totalAdsInBreak}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n \n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n \n try {\n await this.playSingleAd(nextAdUrl);\n this.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = (error as Error).message;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ❌ Ad request failed:\", errorMessage);\n }\n \n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.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.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏳ Queue empty, waiting for URLs... (${retryCount + 1}/${maxRetries})`);\n }\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.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No more ads available, ending ad break\");\n }\n this.handleAdPodComplete();\n }\n }\n\n private async showPlaceholderAndWaitForAds(): Promise<void> {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n }\n this.handleAdPodComplete();\n return;\n }\n \n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Skipping placeholder - too many consecutive failures\");\n }\n this.handleAdPodComplete();\n return;\n }\n \n if (waitTime < 1000) {\n this.handleAdPodComplete();\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⬛ Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n }\n\n this.isShowingPlaceholder = true;\n \n this.ima.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) {\n return;\n }\n \n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Too many failures during placeholder wait\");\n }\n break;\n }\n\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n \n if (!nextAdUrl) {\n continue;\n }\n \n if (this.failedVastUrls.has(nextAdUrl)) {\n continue;\n }\n \n if (this.isUrlInCooldown(nextAdUrl)) {\n continue;\n }\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ Ad URL available, requesting via IMA SDK\");\n }\n \n this.isShowingPlaceholder = false;\n this.ima.hidePlaceholder();\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n \n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n \n try {\n await this.playSingleAd(nextAdUrl);\n this.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = (error as Error).message;\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏰ Placeholder timeout, ending ad break\");\n }\n \n this.isShowingPlaceholder = false;\n this.ima.hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n private findCurrentOrNextBreak(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = this.vmapBreaks;\n let candidate: AdBreak | undefined;\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 const tol = this.config.driftToleranceMs ?? 1000;\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 private onTimeUpdate(currentTimeSec: number): void {\n if (this.ima.isAdPlaying() || this.inAdBreak) return;\n const nowMs = currentTimeSec * 1000;\n const breakToPlay = this.findBreakForTime(nowMs);\n if (breakToPlay) {\n void this.handleMidAdJoin(breakToPlay, nowMs).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:\",\n error\n );\n }\n });\n }\n }\n\n private async handleMidAdJoin(\n adBreak: AdBreak,\n nowMs: number\n ): Promise<void> {\n const key = this.getAdBreakKey(adBreak);\n if (this.consumedVmapBreakIds.has(key)) {\n return;\n }\n\n const breakStartMs = this.resolveBreakStartMs(adBreak);\n if (breakStartMs == null) {\n return;\n }\n\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = breakStartMs + durationMs;\n const tol = this.config.driftToleranceMs ?? 1000;\n const inWindow =\n durationMs > 0\n ? nowMs > breakStartMs && nowMs < endMs\n : nowMs + tol >= breakStartMs;\n\n if (inWindow) {\n this.consumedVmapBreakIds.add(key);\n const remainingMs =\n durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;\n const tags =\n this.selectVastTagsForBreak(adBreak) ||\n (this.apiVastTagUrl ? [this.apiVastTagUrl] : undefined);\n if (tags && tags.length > 0) {\n const first = tags[0] as string;\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n \n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n\n try {\n await this.playSingleAd(first);\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = remainingMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(remainingMs);\n } catch (error) {\n // Keep runtime stable when VMAP break has no-fill/timeouts.\n this.adPodQueue = [];\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:\",\n error\n );\n }\n }\n }\n }\n }\n\n private scheduleAdStopCountdown(remainingMs: number): void {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.ensureAdStoppedByTimer();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.ensureAdStoppedByTimer();\n }, ms) as unknown as number;\n }\n\n private clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private ensureAdStoppedByTimer(): void {\n if (!this.inAdBreak) return;\n\n this.adStopTimerId = undefined;\n\n const adPlaying = this.ima.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1000)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs =\n typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0\n ? maxExtensionMsConfig\n : 60000;\n\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n\n const shouldExtendAdBreak =\n (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n\n if (adPlaying) {\n this.ima.stop().catch(() => {});\n }\n\n this.handleAdPodComplete();\n }\n\n private scheduleAdStartIn(\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.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1000 : undefined\n );\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1000 : this.expectedAdBreakDurationMs\n );\n }, ms) as unknown as number;\n }\n\n private clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n private updatePtsDrift(ptsSecondsSample: number): void {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1000;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 60000) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n\n private 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 \n if (message.includes(\"timeout\")) {\n return true;\n }\n \n if (message.includes(\"rate limit\") || message.includes(\"too many requests\")) {\n return true;\n }\n \n if (message.includes(\"ad playback error\")) {\n return true;\n }\n \n return false;\n }\n\n private 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 private 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 private isGamInCooldown(): boolean {\n return Date.now() < this.globalNoFillCooldownUntil;\n }\n\n private 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.config.debugAdTiming) {\n console.log(\n `[CIRCUIT-BREAKER] GAM cooldown activated: ${backoff}ms (${this.globalConsecutiveNoFills} consecutive no-fills)`\n );\n }\n }\n }\n\n private resetGamNoFillCounter(): void {\n if (this.globalConsecutiveNoFills > 0 && this.config.debugAdTiming) {\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 private 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.config.debugAdTiming) {\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 private async playSingleAd(vastTagUrl: string): Promise<void> {\n if (this.ima.isAdPlaying()) {\n return;\n }\n\n if (this.failedVastUrls.has(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n }\n throw new Error(\"VAST URL permanently failed\");\n }\n\n if (this.isUrlInCooldown(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n }\n throw new Error(\"VAST URL in cooldown after no-fill\");\n }\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n }\n throw new Error(\"Too many consecutive failures\");\n }\n\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n }\n throw new Error(\"GAM in cooldown\");\n }\n\n this.recreateImaController();\n\n const requestToken = ++this.adRequestTokenCounter;\n this.activeAdRequestToken = requestToken;\n \n this.startAdRequestWatchdog(requestToken);\n\n try {\n await this.enforceGlobalRateLimit();\n this.lastAdRequestTime = Date.now();\n await this.ima.requestAds(vastTagUrl);\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ssp\", vastUrl: vastTagUrl },\n this.config.adPlayerType\n ).catch(() => {});\n\n this.clearAdRequestWatchdog();\n\n if (this.activeAdRequestToken !== requestToken) {\n return;\n }\n\n try {\n this.startAdFailsafeTimer(requestToken);\n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n this.consecutiveFailures = 0;\n this.temporaryFailureUrls.delete(vastTagUrl);\n } catch (playError) {\n if (this.config.debugAdTiming) {\n console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n }\n \n const preloadedFallback = this.getPreloadedAd();\n if (preloadedFallback) {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n }\n \n try {\n this.clearAdFailsafeTimer();\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedFallback.imaController;\n this.attachImaEventListeners();\n \n this.ima.resume();\n \n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n \n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n return; \n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n \n if (this.isTemporaryAdError(playError as Error)) {\n this.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n }\n } else {\n this.failedVastUrls.add(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n }\n }\n \n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n throw playError;\n }\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"\";\n if (this.config.debugAdTiming) {\n console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n }\n \n const preloadedFallback = this.getPreloadedAd();\n if (preloadedFallback) {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n }\n \n try {\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n \n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedFallback.imaController;\n this.attachImaEventListeners();\n \n this.ima.resume();\n \n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n \n await this.ima.play();\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n return;\n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n \n if (this.isTemporaryAdError(error as Error)) {\n this.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n }\n } else {\n this.failedVastUrls.add(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n }\n }\n\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n\n throw error;\n }\n }\n\n private handleAdPodComplete(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] 🏁 Ad pod complete - cleaning up\");\n }\n\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n\n this.stopContinuousFetching();\n this.stopPreloadPool();\n this.clearPendingAdBreak();\n \n if (this.isShowingPlaceholder) {\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n\n this.adRequestQueue = [];\n\n this.inAdBreak = false;\n this.adDetectSentForCurrentBreak = false;\n this.activeScte35BreakKey = undefined;\n this.scheduledScte35BreakKey = undefined;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.consecutiveFailures = 0;\n this.globalConsecutiveNoFills = 0;\n\n this.ima.stop().catch(() => {});\n\n const restoredMuted = this.ima.getOriginalMutedState();\n const restoredVolume = this.ima.getOriginalVolume();\n\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.video.paused) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n }\n this.video.play()?.catch(() => {});\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n }\n\n private handleAdFailure(): void {\n this.consecutiveFailures++;\n this.recordGamNoFill();\n const remaining = this.getRemainingAdMs();\n \n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.consecutiveFailures}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n \n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Max consecutive failures reached (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n \n if (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Ad failed and no time remaining. Failed URLs:\", this.failedVastUrls.size);\n }\n this.handleAdPodComplete();\n }\n }\n\n private startAdRequestWatchdog(token: number): void {\n this.clearAdRequestWatchdog();\n\n const timeoutMs = this.config.adFailsafeTimeoutMs ?? 10000;\n this.adRequestWatchdogToken = token;\n this.adRequestWatchdogId = window.setTimeout(() => {\n if (this.adRequestWatchdogToken !== token) {\n return;\n }\n\n this.adRequestWatchdogId = undefined;\n this.adRequestWatchdogToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n\n this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n this.handleAdFailure();\n }, timeoutMs) as unknown as number;\n\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n\n private clearAdRequestWatchdog(): void {\n if (this.adRequestWatchdogId != null) {\n clearTimeout(this.adRequestWatchdogId);\n this.adRequestWatchdogId = undefined;\n }\n\n if (this.adRequestWatchdogToken != null) {\n this.logAdState(\"ad_request_watchdog_cleared\", {\n token: this.adRequestWatchdogToken,\n });\n this.adRequestWatchdogToken = null;\n }\n }\n\n private startAdFailsafeTimer(token: number): void {\n this.clearAdFailsafeTimer();\n\n const failsafeMs = this.config.adFailsafeTimeoutMs ?? 10000;\n this.adFailsafeToken = token;\n\n this.adFailsafeTimerId = window.setTimeout(() => {\n if (this.adFailsafeToken !== token) {\n return;\n }\n\n this.adFailsafeTimerId = undefined;\n this.adFailsafeToken = null;\n\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n\n this.logAdState(\"ad_failsafe_triggered\", {\n token,\n failsafeMs,\n videoPaused: this.video.paused,\n imaAdPlaying: this.ima.isAdPlaying(),\n });\n\n this.handleAdFailure();\n }, failsafeMs) as unknown as number;\n\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n\n private clearAdFailsafeTimer(): void {\n if (this.adFailsafeTimerId != null) {\n clearTimeout(this.adFailsafeTimerId);\n this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n this.adFailsafeTimerId = undefined;\n }\n\n this.adFailsafeToken = null;\n }\n\n private selectVastTagsForBreak(b?: AdBreak): string[] | undefined {\n if (!b || !b.vastTagUrl) return undefined;\n if (b.vastTagUrl.includes(\",\")) {\n return b.vastTagUrl\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n }\n return [b.vastTagUrl];\n }\n\n private logAdState(event: string, extra: Record<string, unknown> = {}): void {\n if (!this.config.debugAdTiming) {\n return;\n }\n\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: new Date().toISOString(),\n showAds: this.showAds,\n adPlaying: this.ima.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n private getRemainingAdMs(): number {\n if (\n this.expectedAdBreakDurationMs == null ||\n this.currentAdBreakStartWallClockMs == null\n )\n return 0;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n\n private findBreakForTime(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = this.vmapBreaks;\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 const end = breakStartMs + (b.durationMs || 0);\n if (\n nowMs >= breakStartMs &&\n (b.durationMs ? nowMs < end : nowMs <= breakStartMs + tol)\n ) {\n return b;\n }\n }\n return undefined;\n }\n\n toggleMute(): void {\n if (this.ima.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n\n this.ima.updateOriginalMutedState(newMutedState, this.video.volume);\n this.ima.setAdVolume(newMutedState ? 0 : 1);\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n\n toggleFullscreen(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container\n .requestFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document\n .exitFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n\n isMuted(): boolean {\n if (this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n const adPlaying = this.ima.isAdPlaying();\n\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n\n this.video.muted = muted;\n\n if (adPlaying) {\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n this.ima.setAdVolume(muted ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted,\n });\n }\n return;\n }\n\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n\n setVolume(volume: number): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.ima.isAdPlaying();\n\n if (adPlaying) {\n this.ima.setAdVolume(clampedVolume);\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume,\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n\n getVolume(): number {\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying) {\n return this.ima.getAdVolume();\n }\n return this.video.volume;\n }\n\n isFullscreen(): boolean {\n return !!document.fullscreenElement;\n }\n\n isLive(): boolean {\n return this.isLiveStream;\n }\n\n get videoElement(): HTMLVideoElement {\n return this.video;\n }\n\n resize(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n\n if (this.ima && this.ima.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 480;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n\n this.ima.resize(width, height);\n }\n }\n\n destroy(): void {\n this.stopContinuousFetching();\n this.stopPreloadPool();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.clearPendingAdBreak();\n \n if (this.placeholderContainer) {\n if (this.placeholderContainer.parentElement) {\n this.placeholderContainer.parentElement.removeChild(this.placeholderContainer);\n }\n this.placeholderContainer = undefined;\n }\n \n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n \n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n this.hls?.destroy();\n this.ima?.destroy();\n this.adRequestQueue = [];\n this.consecutiveFailures = 0;\n }\n}\n","interface NavigatorUAData {\n platform?: string;\n brands?: Array<{ brand: string; version: string }>;\n mobile?: boolean;\n}\n\ndeclare global {\n interface Navigator {\n userAgentData?: NavigatorUAData;\n }\n}\n\nexport interface BrowserInfo {\n name: string;\n version: string;\n majorVersion: number;\n isSmartTV: boolean;\n isLegacyTV: boolean;\n platform: string;\n supportsIMA: boolean;\n supportsModernJS: boolean;\n recommendedAdPlayer: 'ima' | 'hls';\n 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 supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer: 'ima' | 'hls' = 'ima';\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 if (webOSVersion !== undefined && webOSVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (webOSVersion !== undefined && webOSVersion >= 3) {\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/Tizen/i.test(ua)) {\n name = 'Samsung Tizen';\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n tizenVersion = majorVersion;\n }\n \n if (tizenVersion !== undefined && tizenVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (tizenVersion !== undefined && tizenVersion >= 3 && chromeVersion >= 47) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else {\n if (chromeVersion > 0) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (chromeVersion < 50) {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n\n if (typeof URLSearchParams === 'undefined') {\n supportsModernJS = false;\n }\n\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum,\n };\n}\n\nexport function supportsGoogleIMA(): boolean {\n const browser = detectBrowser();\n\n if (browser.isLegacyTV) {\n return false;\n }\n\n if (typeof document === 'undefined' ||\n typeof document.createElement !== 'function') {\n return false;\n }\n\n try {\n const video = document.createElement('video');\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n\n if (typeof Promise === 'undefined') {\n return false;\n }\n\n return browser.supportsIMA;\n}\n\nexport function getRecommendedAdPlayer(): 'ima' | 'hls' {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\n}\n\nexport function supportsModernJS(): boolean {\n try {\n return (\n typeof Promise !== 'undefined' &&\n typeof Map !== 'undefined' &&\n typeof Set !== 'undefined' &&\n typeof Array.from !== 'undefined' &&\n typeof Object.assign !== 'undefined' &&\n typeof Array.prototype.forEach !== 'undefined' &&\n typeof String.prototype.includes !== 'undefined'\n );\n } catch (e) {\n return false;\n }\n}\n\nexport function logBrowserInfo(debug: boolean = false): void {\n if (!debug) return;\n\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n\n console.log('[StormcloudVideoPlayer] Browser Compatibility Info:', {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n ...(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 getBrowserConfigOverrides(): {\n adPlayerType?: 'ima' | 'hls';\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: { adPlayerType?: 'ima' | 'hls'; allowNativeHls?: boolean } = {};\n\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = 'hls';\n }\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'ima':\n return supportsGoogleIMA();\n case 'urlsearchparams':\n return typeof URLSearchParams !== 'undefined';\n case 'textencoder':\n return typeof TextEncoder !== 'undefined';\n case 'promises':\n return typeof Promise !== 'undefined';\n case 'fetch':\n return typeof fetch !== 'undefined';\n case 'crypto':\n return typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined';\n default:\n return false;\n }\n}\n\n","import type { ImaController } from \"../types\";\nimport { supportsGoogleIMA } from \"../utils/browserCompat\";\n\ndeclare global {\n interface Window {\n google?: any;\n }\n}\n\nexport function createImaController(\n video: HTMLVideoElement,\n options?: { continueLiveStreamDuringAds?: boolean }\n): ImaController {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume =\n typeof video.volume === \"number\" && !Number.isNaN(video.volume)\n ? Math.max(0, Math.min(1, video.volume))\n : 1;\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n let adVideoElement: HTMLVideoElement | undefined;\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n\n function hideContentVideo(): void {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n\n function showContentVideo(): void {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"2\";\n adVideo.playsInline = true;\n\n adVideo.volume = originalVolume;\n adVideo.muted = originalMutedState;\n\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n\n return adVideo;\n }\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {}\n }\n }\n\n function ensureImaLoaded(): Promise<void> {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n\n try {\n const frameEl = window.frameElement as HTMLIFrameElement | null;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n // eslint-disable-next-line no-console\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {}\n\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n ) as HTMLScriptElement | null;\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 10000);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n\n let adsManager: any | undefined;\n let adsLoader: any | undefined;\n let adDisplayContainer: any | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let lastAdTagUrl: string | undefined;\n let adsLoadedPromise: Promise<void> | undefined;\n let adsLoadedResolve: (() => void) | undefined;\n let adsLoadedReject: ((error: Error) => void) | undefined;\n\n function makeAdsRequest(google: any, vastTagUrl: string) {\n const adsRequest = new google.ima.AdsRequest();\n \n const companionSizes = [\n { width: 728, height: 90 },\n { width: 300, height: 250 },\n { width: 180, height: 150 },\n { width: 120, height: 60 },\n { width: 88, height: 31 },\n { width: 300, height: 60 },\n { width: 300, height: 100 },\n { width: 320, height: 50 },\n { width: 468, height: 60 },\n { width: 300, height: 600 },\n { width: 160, height: 600 },\n ];\n\n const ciuSzsValue = companionSizes\n .map((size) => `fluid|${size.width}x${size.height}`)\n .join(\",\");\n\n const currentLocation = typeof window !== \"undefined\" ? window.location : null;\n const topLocation = typeof window !== \"undefined\" && window.top ? window.top.location : currentLocation;\n const currentUrl = currentLocation?.href || \"\";\n const topUrl = topLocation?.href || currentUrl;\n const currentDomain = currentLocation?.hostname || \"\";\n\n let modifiedVastTagUrl = vastTagUrl;\n try {\n const url = new URL(vastTagUrl);\n \n url.searchParams.set(\"ciu_szs\", ciuSzsValue);\n \n if (!url.searchParams.has(\"mpt\")) {\n url.searchParams.set(\"mpt\", \"h5_vsi\");\n }\n \n if (!url.searchParams.has(\"ctv\")) {\n url.searchParams.set(\"ctv\", \"0\");\n }\n \n if (!url.searchParams.has(\"gdpr\")) {\n url.searchParams.set(\"gdpr\", \"0\");\n }\n \n if (!url.searchParams.has(\"top\") && topUrl) {\n url.searchParams.set(\"top\", topUrl);\n }\n \n if (!url.searchParams.has(\"loc\") && currentUrl) {\n url.searchParams.set(\"loc\", currentUrl);\n }\n \n if (!url.searchParams.has(\"cdm\") && currentDomain) {\n url.searchParams.set(\"cdm\", currentDomain);\n }\n \n if (!url.searchParams.has(\"eoidce\")) {\n url.searchParams.set(\"eoidce\", \"1\");\n }\n \n if (!url.searchParams.has(\"fbidx\")) {\n url.searchParams.set(\"fbidx\", \"0\");\n }\n \n modifiedVastTagUrl = url.toString();\n } catch (e) {\n let baseUrl = vastTagUrl;\n \n const paramsToRemove = [\"ciu_szs\", \"mpt\", \"ctv\", \"gdpr\", \"top\", \"loc\", \"cdm\", \"eoidce\", \"fbidx\"];\n paramsToRemove.forEach((param) => {\n if (baseUrl.includes(`${param}=`)) {\n baseUrl = baseUrl.replace(new RegExp(`[?&]${param}=[^&]*`, \"g\"), \"\");\n }\n });\n baseUrl = baseUrl.replace(/[?&]$/, \"\");\n \n const params = new URLSearchParams();\n params.set(\"ciu_szs\", ciuSzsValue);\n params.set(\"mpt\", \"h5_vsi\");\n params.set(\"ctv\", \"0\");\n params.set(\"gdpr\", \"0\");\n if (topUrl) params.set(\"top\", topUrl);\n if (currentUrl) params.set(\"loc\", currentUrl);\n if (currentDomain) params.set(\"cdm\", currentDomain);\n params.set(\"eoidce\", \"1\");\n params.set(\"fbidx\", \"0\");\n \n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n modifiedVastTagUrl = `${baseUrl}${separator}${params.toString()}`;\n }\n \n adsRequest.adTagUrl = modifiedVastTagUrl;\n\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 480;\n\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n\n if (typeof adsRequest.setCompanionSlots === \"function\") {\n try {\n const companionSlots: any[] = [];\n\n for (const size of companionSizes) {\n const slot = new google.ima.CompanionAdSlot();\n slot.width = size.width;\n slot.height = size.height;\n companionSlots.push(slot);\n }\n\n adsRequest.setCompanionSlots(companionSlots);\n } catch (error) {\n console.warn(\"[IMA] Failed to set companion slots:\", error);\n }\n }\n\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n\n adsRequest.vastLoadTimeout = 10000;\n\n adsLoader.requestAds(adsRequest);\n }\n\n function ensurePlaceholderContainer(): void {\n if (adContainerEl) {\n return;\n }\n\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {}\n adsManager = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n\n function destroyAdsLoader() {\n if (adsLoader) {\n try {\n adsLoader.destroy();\n } catch {}\n adsLoader = undefined;\n }\n }\n\n return {\n initialize() {\n ensureImaLoaded()\n .then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {}\n }\n })\n .catch(() => {});\n },\n async requestAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n return Promise.reject(error);\n }\n\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n return Promise.reject(error);\n }\n\n if (adPlaying) {\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n\n destroyAdsManager();\n destroyAdsLoader();\n\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n\n let currentReject: ((error: Error) => void) | undefined;\n adsLoadedPromise = new Promise<void>((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n }, 10000);\n });\n\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition =\n \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n\n video.parentElement.appendChild(container);\n adContainerEl = container;\n\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n\n }\n\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n\n if (\n !videoWidth ||\n !videoHeight ||\n videoWidth === 0 ||\n videoHeight === 0\n ) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n currentReject?.(error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt: any) => {\n try {\n const adsRenderingSettings =\n new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent: any) => {\n const error = errorEvent.getError();\n const errorCode = error.getErrorCode?.() || \"unknown\";\n const vastErrorCode = error.getVastErrorCode?.() || \"N/A\";\n const errorMessage = error.getMessage?.() || \"Unknown error\";\n \n let innerError: string | undefined;\n try {\n if (typeof error.getInnerError === \"function\") {\n const inner = error.getInnerError();\n if (inner) {\n innerError = typeof inner === \"string\" ? inner : (inner.message || String(inner));\n }\n }\n if (!innerError && error.cause) {\n innerError = typeof error.cause === \"string\" ? error.cause : (error.cause.message || String(error.cause));\n }\n if (!innerError && error.innerError) {\n innerError = typeof error.innerError === \"string\" ? error.innerError : (error.innerError.message || String(error.innerError));\n }\n } catch (e) {\n }\n \n const isNoFill = errorCode === 303 || vastErrorCode === 303;\n \n\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n\n emit(\"ad_error\", { \n code: errorCode, \n vastErrorCode, \n message: errorMessage,\n cause: innerError,\n isNoFill \n });\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {});\n }\n }\n }\n );\n\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n\n adPlaying = true;\n setAdPlayingFlag(true);\n \n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adsManager) {\n try {\n adsManager.setVolume(adVolume);\n } catch {}\n }\n \n emit(\"content_pause\");\n }\n );\n\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n\n hideContentVideo();\n\n if (adVideoElement) {\n const adVolume = originalVolume;\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n \n if (adsManager) {\n try {\n adsManager.setVolume(originalMutedState ? 0 : adVolume);\n } catch {}\n }\n }\n\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n \n showContentVideo();\n \n emit(\"content_resume\");\n }\n );\n\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n emit(\"all_ads_completed\");\n });\n\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = undefined;\n adsLoadedReject = undefined;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent: any) => {\n const error = adErrorEvent.getError();\n const errorCode = error.getErrorCode?.() || \"unknown\";\n const vastErrorCode = error.getVastErrorCode?.() || \"N/A\";\n const errorMessage = error.getMessage?.() || \"Unknown error\";\n \n let innerError: string | undefined;\n try {\n if (typeof error.getInnerError === \"function\") {\n const inner = error.getInnerError();\n if (inner) {\n innerError = typeof inner === \"string\" ? inner : (inner.message || String(inner));\n }\n }\n if (!innerError && error.cause) {\n innerError = typeof error.cause === \"string\" ? error.cause : (error.cause.message || String(error.cause));\n }\n if (!innerError && error.innerError) {\n innerError = typeof error.innerError === \"string\" ? error.innerError : (error.innerError.message || String(error.innerError));\n }\n } catch (e) {\n }\n \n const isNoFill = errorCode === 303 || vastErrorCode === 303;\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(isNoFill ? \"No ads available\" : \"Ads loader error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\", { \n code: errorCode, \n vastErrorCode, \n message: errorMessage,\n isNoFill,\n cause: innerError\n });\n },\n false\n );\n }\n\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n\n currentReject?.(error as Error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 480;\n\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n\n adPlaying = true;\n\n const adVolume = originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n\n try {\n adsManager.setVolume(originalMutedState ? 0 : adVolume);\n } catch {}\n\n adsManager.start();\n\n return Promise.resolve();\n } catch (error) {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {});\n }\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adsManager || !adPlaying) {\n return;\n }\n\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n\n if (adsManager && typeof adsManager.pause === \"function\") {\n adsManager.pause();\n }\n } catch (error) {\n console.warn(\"[IMA] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adsManager || !adPlaying) {\n return;\n }\n\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {});\n }\n\n if (adsManager && typeof adsManager.resume === \"function\") {\n adsManager.resume();\n }\n } catch (error) {\n console.warn(\"[IMA] Error resuming ad:\", error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n console.log(\"[IMA] Content video paused in live mode on stop, resuming playback\");\n video.play().catch(() => {});\n }\n } else if (video.paused) {\n video.play().catch(() => {});\n }\n\n try {\n adsManager?.stop?.();\n } catch {}\n\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"none\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n adVideoElement = undefined;\n }\n }, 500);\n }\n\n showContentVideo();\n\n try {\n adsLoader?.destroy?.();\n } catch {}\n\n adDisplayContainer = undefined;\n adsLoader = undefined;\n contentVideoHidden = false;\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width: number, height: number) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume: number) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {}\n }\n },\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n \n hideContentVideo();\n \n if (adContainerEl) {\n const wasHidden = adContainerEl.style.display === \"none\" || adContainerEl.style.opacity === \"0\";\n if (wasHidden) {\n adContainerEl.style.transition = \"none\";\n } else {\n adContainerEl.style.transition = \"opacity 0.3s ease-in-out\";\n }\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (adContainerEl) {\n adContainerEl.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.backgroundColor = \"#000\";\n }\n }, 300);\n }\n },\n };\n}\n","import type { ImaController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): ImaController {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n const preloadedAds = new Map<string, VastAd>();\n const preloadingAds = new Map<string, Promise<void>>();\n let destroyed = false;\n let pendingTimeouts: number[] = [];\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n if (sessionId) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function getMainStreamQuality(): {\n width: number;\n height: number;\n bitrate: number;\n } | null {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level = mainHlsInstance.levels[autoLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n return null;\n }\n\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n\n const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n return { file, score, resolutionDiff, bitrateDiff };\n });\n\n scoredFiles.sort((a, b) => a.score - b.score);\n\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff,\n });\n\n return bestMatch.file;\n }\n\n function 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 parseVastXml(xmlString: string): VastAd | null {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const isNoAdAvailable =\n adId === \"empty\" ||\n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\n\n const durationText =\n xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n\n 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 null;\n }\n\n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string\n ): Promise<VastAd | null> {\n const response = await fetch(vastTagUrl, {\n 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\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml);\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n\n video.volume = 1.0;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\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 contentVideo.volume = 0;\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 contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n 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 = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\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 = originalMutedState ? 0 : originalVolume;\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n \n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n },\n };\n}\n","import type {\n ClientInfo,\n TrackingData,\n HeartbeatData,\n AdDetectInfo,\n AdLoadedInfo,\n AdImpressionInfo,\n AdTrackingSource,\n} from \"../types\";\n\nlet cachedBrowserId: string | null = null;\n\nexport function getClientInfo(): ClientInfo {\n const ua = navigator.userAgent;\n const platform = navigator.platform;\n const vendor = navigator.vendor || \"\";\n const maxTouchPoints = navigator.maxTouchPoints || 0;\n const memory = (navigator as any).deviceMemory || null;\n const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n\n const screenInfo = {\n width: screen?.width,\n height: screen?.height,\n availWidth: screen?.availWidth,\n availHeight: screen?.availHeight,\n orientation: (screen?.orientation as any)?.type || \"\",\n pixelDepth: screen?.pixelDepth,\n };\n\n let deviceType: \"tv\" | \"mobile\" | \"tablet\" | \"desktop\" = \"desktop\";\n let brand = \"Unknown\";\n let os = \"Unknown\";\n let model = \"\";\n let isSmartTV = false;\n let isAndroid = false;\n let isWebView = false;\n let isWebApp = false;\n\n if (ua.includes(\"Web0S\")) {\n brand = \"LG\";\n os = \"webOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n } else if (ua.includes(\"Tizen\")) {\n brand = \"Samsung\";\n os = \"Tizen\";\n isSmartTV = true;\n deviceType = \"tv\";\n const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n model = tizenMatch\n ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim()\n : \"Tizen TV\";\n } else if (ua.includes(\"Philips\")) {\n brand = \"Philips\";\n os = \"Saphi\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n brand = \"Sharp\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (\n ua.includes(\"Android\") &&\n (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))\n ) {\n brand = \"Sony\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (\n ua.includes(\"Android\") &&\n (ua.includes(\"NetCast\") || ua.includes(\"LG\"))\n ) {\n brand = \"LG\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n brand = \"Roku\";\n os = \"Roku OS\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"AppleTV\")) {\n brand = \"Apple\";\n os = \"tvOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n }\n\n if (ua.includes(\"Android\")) {\n isAndroid = true;\n os = \"Android\";\n deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n\n if (\n ua.includes(\"Android\") &&\n (maxTouchPoints === 0 ||\n ua.includes(\"Google TV\") ||\n ua.includes(\"XiaoMi\"))\n ) {\n deviceType = \"tv\";\n isSmartTV = true;\n brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n }\n\n const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n if (androidModelMatch && androidModelMatch[1]) {\n model = androidModelMatch[1];\n }\n }\n\n if (/iPad|iPhone|iPod/.test(ua)) {\n os = \"iOS\";\n deviceType = \"mobile\";\n brand = \"Apple\";\n if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n deviceType = \"tablet\";\n }\n }\n\n if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n if (ua.includes(\"Windows\")) {\n os = \"Windows\";\n deviceType = \"desktop\";\n } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n os = \"macOS\";\n deviceType = \"desktop\";\n if (maxTouchPoints > 1) deviceType = \"tablet\";\n } else if (ua.includes(\"Linux\")) {\n os = \"Linux\";\n deviceType = \"desktop\";\n }\n }\n\n if (brand === \"Unknown\") {\n if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n if (vendor.includes(\"Apple\")) brand = \"Apple\";\n if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n }\n\n isWebView = /wv|WebView|Linux; U;/.test(ua);\n\n if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n isWebView = true;\n }\n\n isWebApp =\n window.matchMedia(\"(display-mode: standalone)\").matches ||\n (window.navigator as any).standalone === true ||\n window.screen?.orientation?.angle !== undefined;\n\n return {\n brand,\n os,\n model: model || ua.substring(0, 50) + \"...\",\n deviceType,\n isSmartTV,\n isAndroid,\n isWebView,\n isWebApp,\n domain: window.location.hostname,\n origin: window.location.origin,\n path: window.location.pathname,\n userAgent: ua,\n vendor,\n platform,\n screen: screenInfo,\n hardwareConcurrency,\n deviceMemory: memory,\n maxTouchPoints,\n language: navigator.language,\n languages: navigator.languages?.join(\",\") || \"\",\n cookieEnabled: navigator.cookieEnabled,\n doNotTrack: navigator.doNotTrack || \"\",\n referrer: document.referrer,\n visibilityState: document.visibilityState,\n };\n}\n\nexport async function getBrowserID(clientInfo: ClientInfo): Promise<string> {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n\n const fingerprintString = JSON.stringify(clientInfo);\n\n if (typeof crypto !== \"undefined\" && crypto.subtle && crypto.subtle.digest) {\n try {\n await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n\n let encodedData: BufferSource;\n if (typeof TextEncoder !== \"undefined\") {\n encodedData = new TextEncoder().encode(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\n const buffer = new Uint8Array(utf8.length);\n for (let i = 0; i < utf8.length; i++) {\n buffer[i] = utf8.charCodeAt(i);\n }\n encodedData = buffer;\n }\n\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n\n const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n const timestamp = Date.now().toString(16).padStart(12, \"0\");\n const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n\n cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\n\nexport async function sendInitialTracking(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const trackingData: TrackingData = {\n browserId,\n ...clientInfo,\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\n\nexport async function sendHeartbeat(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const heartbeatData: HeartbeatData = {\n browserId,\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\n\nconst TRACK_API_URL =\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\n\nfunction mapToAdTrackingSource(\n source: string | undefined,\n adPlayerType?: \"ima\" | \"hls\"\n): AdTrackingSource {\n if (source === \"prebid\" || source === \"ima\" || source === \"hls\") {\n return source;\n }\n if (source === \"preload\" || source === \"ssp\") {\n return source === \"ssp\" ? \"prebid\" : \"ima\";\n }\n return adPlayerType === \"hls\" ? \"hls\" : \"ima\";\n}\n\nasync function postAdTracking(\n licenseKey: string | undefined,\n body: Record<string, unknown>\n): Promise<void> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_API_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\n\nexport async function sendAdDetectTracking(\n licenseKey: string | undefined,\n payload: Omit<AdDetectInfo, \"source\" | \"timestamp\"> & Partial<Pick<AdDetectInfo, \"source\" | \"timestamp\">>\n): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const adDetectInfo: AdDetectInfo = {\n source: payload.source ?? \"scte35\",\n timestamp: payload.timestamp ?? new Date().toISOString(),\n ...(payload.durationSeconds != null && { durationSeconds: payload.durationSeconds }),\n ...(payload.ptsSeconds != null && { ptsSeconds: payload.ptsSeconds }),\n ...(payload.detectedAtFragmentSn != null && { detectedAtFragmentSn: payload.detectedAtFragmentSn }),\n };\n const body = {\n browserId,\n ...clientInfo,\n ...(licenseKey && { licenseKey }),\n adDetectInfo,\n };\n await postAdTracking(licenseKey, body);\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending ad-detect tracking:\", error);\n }\n}\n\nexport async function sendAdLoadedTracking(\n licenseKey: string | undefined,\n payload: Omit<AdLoadedInfo, \"timestamp\" | \"source\"> & { source?: AdTrackingSource | string },\n adPlayerType?: \"ima\" | \"hls\"\n): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const source = mapToAdTrackingSource(payload.source, adPlayerType);\n const adLoadedInfo: AdLoadedInfo = {\n source,\n timestamp: new Date().toISOString(),\n ...(payload.vastUrl != null && { vastUrl: payload.vastUrl }),\n ...(payload.durationSeconds != null && { durationSeconds: payload.durationSeconds }),\n };\n const body = {\n browserId,\n ...clientInfo,\n ...(licenseKey && { licenseKey }),\n adLoadedInfo,\n };\n await postAdTracking(licenseKey, body);\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending ad-loaded tracking:\", error);\n }\n}\n\nexport type AdImpressionTrackingPayload = {\n adIndex: number;\n source?: AdTrackingSource | string;\n durationSeconds?: number;\n};\n\nexport async function sendAdImpressionTracking(\n licenseKey: string | undefined,\n payload: AdImpressionTrackingPayload,\n adPlayerType?: \"ima\" | \"hls\"\n): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const source = mapToAdTrackingSource(payload.source, adPlayerType);\n const adImpressionInfo: AdImpressionInfo = {\n source,\n adIndex: payload.adIndex,\n timestamp: new Date().toISOString(),\n ...(payload.durationSeconds != null && { durationSeconds: payload.durationSeconds }),\n };\n const body = {\n browserId,\n ...clientInfo,\n ...(licenseKey && { licenseKey }),\n adImpressionInfo,\n };\n await postAdTracking(licenseKey, body);\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending ad-impression tracking:\", 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"]}
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/players/index.cjs","../../src/players/index.ts","../../src/utils.ts","../../src/patterns.ts","../../src/players/HlsPlayer.tsx","../../src/player/StormcloudVideoPlayer.ts","../../src/utils/browserCompat.ts","../../src/sdk/ima.ts","../../src/sdk/hlsAdPlayer.ts","../../src/utils/tracking.ts","../../src/utils/polyfills.ts"],"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","players_exports","default","players_default","module","exports","import_react","lazy","require","reactLazy","IS_BROWSER","window","document","IS_GLOBAL","globalThis","IS_IOS","test","navigator","userAgent","url","IS_SAFARI","HLS_EXTENSIONS","DASH_EXTENSIONS","VIDEO_EXTENSIONS","canPlay","hls","HLS_PATHS","dash","video","audio","AUDIO_EXTENSIONS","file","import_hls","getChromeVersion","ua","match","parseInt","getWebKitVersion","getPlatform","userAgentData","platform","detectBrowser","version","majorVersion","isSmartTV","isLegacyTV","supportsIMA","supportsModernJS","recommendedAdPlayer","webOSVersion","tizenVersion","chromeVersionNum","chromeVersion","webkitVersion","parts","split","toString","Promise","Map","Set","URLSearchParams","supportsGoogleIMA","browser","createElement","e","imaSupport","contentVideoHidden","style","transition","setTimeout","baseUrl","replace","RegExp","param","logBrowserInfo","debug","console","log","getBrowserConfigOverrides","overrides","adPlayerType","allowNativeHls","createImaController","options","adPlaying","originalMutedState","originalVolume","volume","Number","isNaN","Math","max","min","listeners","adVideoElement","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","hideContentVideo","opacity","visibility","muted","showContentVideo","offsetHeight","createAdVideoElement","adVideo","position","top","left","width","height","objectFit","backgroundColor","zIndex","playsInline","addEventListener","event","payload","Array","set","fn","ensureImaLoaded","warn","reject","Error","frameEl","frameElement","sandboxAttr","getAttribute","t","trim","filter","length","allowsScripts","tokens","has","error","google","ima","resolve","existing","querySelector","timeout","clearTimeout","script","async","defer","setAttribute","onload","onerror","head","appendChild","adsManager","adsLoader","adDisplayContainer","adContainerEl","lastAdTagUrl","adsLoadedPromise","adsLoadedReject","makeAdsRequest","vastTagUrl","adsRequest","AdsRequest","companionSizes","size","ciuSzsValue","map","join","currentLocation","location","topLocation","currentUrl","href","topUrl","currentDomain","hostname","modifiedVastTagUrl","URL","searchParams","paramsToRemove","forEach","includes","params","adTagUrl","linearAdSlotWidth","separator","videoWidth","offsetWidth","clientWidth","videoHeight","clientHeight","linearAdSlotHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","setCompanionSlots","companionSlots","slot","CompanionAdSlot","push","setAdWillAutoPlay","willAutoPlay","paused","autoplay","setAdWillPlayMuted","willPlayMuted","vastLoadTimeout","requestAds","ensurePlaceholderContainer","container","right","bottom","display","alignItems","justifyContent","pointerEvents","parentElement","destroyAdsManager","destroy","destroyAdsLoader","initialize","then","AdDisplayContainer","catch","currentReject","adsLoaderCls","adsLoadedResolve","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","evt","adsRenderingSettings","AdsRenderingSettings","enablePreloading","getAdsManager","AdEvent","AdErrorEvent","AD_ERROR","errorEvent","getError","errorCode","getErrorCode","vastErrorCode","getVastErrorCode","errorMessage","getMessage","innerError","getInnerError","inner","message","String","cause","isNoFill","emit","code","continueLiveStreamDuringAds","play","CONTENT_PAUSE_REQUESTED","pause","adVolume","setVolume","STARTED","CONTENT_RESUME_REQUESTED","ALL_ADS_COMPLETED","adErrorEvent","init","ViewMode","NORMAL","start","resume","stop","removeChild","isAdPlaying","resize","on","listener","add","off","delete","updateOriginalMutedState","nextVolume","getOriginalMutedState","getOriginalVolume","setAdVolume","clampedVolume","getAdVolume","getVolume","showPlaceholder","wasHidden","destroyed","requestAnimationFrame","hidePlaceholder","createHlsAdPlayer","contentVideo","licenseKey","mainHlsInstance","adHls","currentAd","sessionId","preloadedAds","preloadingAds","pendingTimeouts","trackingFired","impression","midpoint","thirdQuartile","complete","generateSessionId","Date","now","random","substr","fireTrackingPixels","urls","trackingUrl","img","Image","src","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","bitrate","selectBestMediaFile","mediaFiles","firstFile","mainQuality","scoredFiles","widthDiff","heightDiff","abs","fileBitrate","bitrateDiff","score","resolutionDiff","sort","a","b","bestMatch","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","isProgressiveMediaFile","startsWith","endsWith","parseVastXml","xmlString","xmlDoc","parser","DOMParser","parseFromString","parserError","textContent","adElement","adId","title","isNoAdAvailable","durationText","durationParts","duration","mediaFileElements","querySelectorAll","mf","index","bitrateAttr","bitrateValue","trackingUrls","firstQuartile","el","mute","unmute","fullscreen","exitFullscreen","skip","eventKey","clickThrough","id","fetchAndParseVastAd","response","vastXml","fetch","mode","credentials","headers","referrerPolicy","ok","statusText","text","substring","setupAdEventListeners","progress","currentTime","handleAdComplete","handleAdError","ended","ad","contentVolume","isHlsAd","Hls","isSupported","enableWorker","lowLatencyMode","Events","MANIFEST_PARSED","data","fatal","load","previousMutedState","timeoutId","remove","clear","cachedBrowserId","getClientInfo","screen","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isAndroid","isWebView","isWebApp","webosMatch","tizenMatch","tvMatch","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","origin","path","pathname","language","languages","fingerprintString","cookieEnabled","doNotTrack","referrer","visibilityState","getBrowserID","clientInfo","encodedData","utf8","buffer","i","hashBuffer","hashArray","hashHex","hash","char","fallbackHash","timestamp","JSON","stringify","crypto","subtle","digest","Uint8Array","TextEncoder","encode","unescape","encodeURIComponent","charCodeAt","padStart","padEnd","TRACK_URL","PLAYER_TRACKING_BASE_URL","HEARTBEAT_URL","IMPRESSIONS_URL","buildHeaders","method","body","status","json","postJson","buildPlayerMetricEvent","context","flags","browserId","captureAt","toISOString","device_type","input_stream_type","inputStreamType","ad_loaded","adLoaded","ad_detect","adDetect","license_key","capture_at","sendInitialTracking","trackingData","sendTrackRequest","events","player_id","sendAdDetectTracking","adDetectInfo","sendHeartbeat","sendAdLoadedTracking","adLoadedInfo","sendAdImpressionTracking","adImpressionInfo","metricEvent","ad_played_count","ad_url","adUrl","heartbeatData","polyfillURLSearchParams","URLSearchParamsPolyfill","parseQueryString","append","query","cleanQuery","slice","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","values","getAll","callback","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","finally","constructor","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","len","result","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","polyfillStringIncludes","indexOf","initializePolyfills","StormcloudVideoPlayer","config","attached","inAdBreak","ptsDriftEmaMs","adPodQueue","vmapBreaks","consumedVmapBreakIds","lastHeartbeatTime","currentAdIndex","totalAdsInBreak","showAds","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","adRequestTokenCounter","activeAdRequestToken","adRequestWatchdogToken","adFailsafeToken","failedVastUrls","temporaryFailureUrls","temporaryFailureCooldownMs","continuousFetchingActive","adRequestQueue","maxPlaceholderDurationMs","isShowingPlaceholder","tsScte35Pids","pmtPids","processedTsScte35Sections","pendingScte35Cues","recentScte35CueKeys","recentScte35CueLimit","maxTotalAdRequestsPerBreak","pendingAdBreak","consecutiveFailures","maxConsecutiveFailures","lastAdRequestTime","minAdRequestIntervalMs","backoffBaseMs","maxBackoffMs","globalConsecutiveNoFills","globalNoFillThreshold","globalNoFillCooldownUntil","globalNoFillBackoffBaseMs","globalNoFillBackoffMaxMs","globalLastGamRequestTime","globalMinGamIntervalMs","preloadPool","maxPreloadPoolSize","preloadPoolActive","preloadPoolLoopRunning","adDetectSentForCurrentBreak","continuousFetchLoopRunning","browserOverrides","videoElement","debugAdTiming","createAdPlayer","vastMode","attach","fetchAdConfiguration","initializeTracking","shouldUseNativeHls","isLive","adBehavior","import_hls2","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","loadSource","_","minSegments","some","details","live","shouldContinueLiveStreamDuringAds","minSegmentsBeforePlay","LEVEL_LOADED","_evt","fragments","fragmentsToScan","frag","tagList","isArray","entry","tag","idx","attrs","parseAttributeList","hasScteOut","durationSeconds","parseCueOutDuration","marker","raw","earlyDetection","onScte35Cue","createScte35CueContext","FRAG_BUFFERED","err","FRAG_PARSING_METADATA","id3Tags","samples","s","ptsSeconds","pts","onId3Tag","FRAG_LOADED","processFragmentScte35Payload","sn","getFragmentStartSeconds","FRAG_DECRYPTED","FRAG_CHANGED","activatePendingScte35CuesForFragment","prog","parseCueOutCont","elapsed","hasScteIn","klass","toNumber","ERROR","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","attachMedia","attachImaEventListeners","adIndex","remaining","getRemainingAdMs","queuedUrls","tryNextAvailableAdWithRateLimit","handleAdPodComplete","errorPayload","causeMessage","handleAdFailure","clearAdFailsafeTimer","clearAdRequestWatchdog","resetGamNoFillCounter","expectedAdBreakDurationMs","adStopTimerId","scheduleAdStopCountdown","currentMuted","currentVolume","source","recreateImaController","shouldShowPlaceholder","showPlaceholderLayer","preservedMutedState","preservedVolumeState","placeholderContainer","hidePlaceholderLayer","onTimeUpdate","timeUpdateHandler","emptiedHandler","wasPaused","streamType","getStreamType","canNative","canPlayType","updatePtsDrift","parseScte35FromId3","readiness","decodeId3ValueToText","cueOutMatch","dur","arg","id3","cueOutContMatch","cont","cueInMatch","daterangeMatch","out","bin","parseScte35Binary","decoder","TextDecoder","fromCharCode","fragmentSn","fragmentStartSeconds","candidates","startPTS","candidate","isFinite","cue","createScte35Cue","pendingKey","trimRecentScte35CueMaps","startAdPrefetch","shouldAcceptScte35EndCue","activeScte35BreakKey","hasRecentlyHandledScte35Cue","markScte35CueHandled","onScte35Marker","getScte35CueKey","getScte35MarkerRaw","spliceEventId","toIdentityString","splice_event_id","segmentationEventId","segmentation_event_id","daterangeId","ID","scteValue","round","floor","getPendingScte35CueKey","isStrongScte35CueKey","scheduledScte35BreakKey","recentKey","firstKey","keys","next","matchingCues","entries","hasPendingAdBreak","tol","driftToleranceMs","cueKey","newDurationMs","elapsedMs","currentAdBreakStartWallClockMs","remainingMs","detectPayload","hasPrefetchedAds","vastUrls","durationMs","isManifestMarker","isManifestBasedMarker","forceImmediate","immediateManifestAds","hasPts","clearAdStartTimer","startScte35AdBreak","nowMs","estCurrentPtsMs","deltaMs","markerPtsMs","tolerance","scheduleAdStartIn","hasQueuedAds","activeAdRequest","clearAdStopTimer","pendingScte35CueKey","d","parseFloat","regex","markers","tsStart","thirdByte","packetStart","packetInfo","tsPayloadOffset","parsePatSection","payloadUnitStart","num","dStr","res","elapsedMatch","durationMatch","slashMatch","exec","rawVal","val","n","splice_command_type","normalizeFragmentPayload","ArrayBuffer","isView","view","byteOffset","byteLength","payloadData","parseScte35FromTsPackets","detectTsPacketFormat","sectionAssemblers","secondByte","fourthByte","pid","adaptationFieldControl","hasPayload","payloadStart","adaptationLength","payloadEnd","subarray","parsePmtSection","packetSizes","packetSize","offset","matchedPackets","sectionStart","getPsiSectionStart","sectionLength","getPsiSectionLength","sectionEnd","programNumber","programInfoLength","elementaryPid","esInfoLength","descriptorStart","descriptorEnd","descriptorsIdentifyScte35","end","registration","hasProcessedTsScte35Section","checksum","collectScte35SectionsFromPayload","assemblers","pointerField","previousAssembler","appendScte35Bytes","tableId","totalLength","addScte35SectionMarker","bytes","expectedLength","assembler","section","r","readBits","BitReader","buf","bytePos","bitPos","numBits","remainingInByte","toRead","currentByte","shift","mask","bits","skipBits","bytePosition","readSpliceTime","ptsAdjustmentTicks","timeSpecifiedFlag","high","low","ptsTicks","ptsAdjHigh","ptsAdjLow","spliceCommandLength","spliceCommandType","markerType","commandBodyStart","cancel","outOfNetwork","programSpliceFlag","durationFlag","spliceImmediateFlag","componentCount","componentPtsSeconds","expectedDescriptorOffset","durationTicks","descriptorMarker","parseScte35SegmentationDescriptors","descriptorLoopLength","descriptorOffset","descriptorTag","descriptorLength","descriptorDataStart","descriptorDataEnd","parseScte35SegmentationDescriptor","descriptor","identifier","cancelIndicator","programSegmentationFlag","segmentationDurationFlag","segmentationUpidLength","segmentationTypeId","markerTypeFromSegmentationTypeId","heartbeatInterval","setInterval","sendHeartbeatIfNeeded","vastEndpoint","apiUrl","imaPayload","numberAds","vmapUrl","fetchAndParseVmap","apiVastTagUrl","apiNumberAds","vmapXml","parseVmapToBreaks","doc","adBreakNodes","parsed","node","timeOffsetRaw","startTimeMs","parseVmapTimeOffsetToMs","adTagNode","breakId","aStart","MAX_SAFE_INTEGER","bStart","timeOffset","normalized","hms","hh","mm","ss","ms","hours","minutes","seconds","millis","percent","ratio","durationSec","getAdBreakKey","adBreak","resolveBreakStartMs","getCurrentAdIndex","getTotalAdsInBreak","getAdRemainingMs","generateVastUrlsWithCorrelators","count","baseTimestamp","uniqueCorrelator","urlWithCorrelator","correlatorRegex","isShowingAds","shouldShowNativeControls","showCustomControls","scheduled","findCurrentOrNextBreak","tags","selectVastTagsForBreak","baseVastUrl","urlsToPregenerate","generatedUrls","detectedAtFragmentSn","isFetching","fetchStartTime","startPreloadPool","clearPendingAdBreak","prefetchTimerId","initialUrls","preloadAdIntoPool","preloadPoolLoop","vastUrl","loadPromise","isGamInCooldown","isUrlInCooldown","hasAdError","adErrorPayload","errorListenerCleanup","preloadIma","errorListener","poolEntry","lateErrorListener","enforceGlobalRateLimit","recordGamNoFill","isTemporaryAdError","imaController","loadedAt","isReady","findIndex","splice","newUrls","newUrl","getPreloadedAd","stopPreloadPool","handleAdStart","_marker","adBreakDurationMs","firstAdUrl","usePreloadedAd","preloadedController","preloaded","firstAdUrlArray","fallbackPreloaded","fallbackError","totalAdRequestsInBreak"],"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/players/index.ts\nvar players_exports = {};\n__export(players_exports, {\n default: () => players_default\n});\nmodule.exports = __toCommonJS(players_exports);\n\n// src/utils.ts\nvar import_react = require(\"react\");\nvar lazy = import_react.lazy;\nvar IS_BROWSER = typeof window !== \"undefined\" && window.document;\nvar IS_GLOBAL = typeof globalThis !== \"undefined\" && globalThis.window && globalThis.window.document;\nvar IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(navigator.userAgent);\nvar IS_SAFARI = IS_BROWSER && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n\n// src/patterns.ts\nvar HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nvar HLS_PATHS = /\\/hls\\//i;\nvar DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nvar VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nvar AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\nvar canPlay = {\n hls: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n dash: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n video: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n audio: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n file: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n }\n};\n\n// src/players/HlsPlayer.tsx\nvar import_react2 = require(\"react\");\n\n// src/player/StormcloudVideoPlayer.ts\nvar import_hls2 = __toESM(require(\"hls.js\"), 1);\n\n// src/utils/browserCompat.ts\nfunction getChromeVersion(ua) {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getWebKitVersion(ua) {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getPlatform() {\n if (\"userAgentData\" in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? \"iPhone\" : \"MacIntel\";\n }\n if (/Win/i.test(ua)) {\n return \"Win32\";\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? \"Linux armv8l\" : \"Linux x86_64\";\n }\n if (/CrOS/i.test(ua)) {\n return \"CrOS\";\n }\n return navigator.platform || \"Unknown\";\n}\nfunction detectBrowser() {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n let name = \"Unknown\";\n let version = \"0\";\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer = \"ima\";\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 if (webOSVersion !== void 0 && webOSVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (webOSVersion !== void 0 && webOSVersion >= 3) {\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/Tizen/i.test(ua)) {\n name = \"Samsung Tizen\";\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n tizenVersion = majorVersion;\n }\n if (tizenVersion !== void 0 && tizenVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (tizenVersion !== void 0 && tizenVersion >= 3 && chromeVersion >= 47) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else {\n if (chromeVersion > 0) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (chromeVersion < 50) {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\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 supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum\n };\n}\nfunction supportsGoogleIMA() {\n const browser = detectBrowser();\n if (browser.isLegacyTV) {\n return false;\n }\n if (typeof document === \"undefined\" || typeof document.createElement !== \"function\") {\n return false;\n }\n try {\n const video = document.createElement(\"video\");\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n if (typeof Promise === \"undefined\") {\n return false;\n }\n return browser.supportsIMA;\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n console.log(\"[StormcloudVideoPlayer] Browser Compatibility Info:\", {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n ...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}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = \"hls\";\n }\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\n\n// src/sdk/ima.ts\nfunction createImaController(video, options) {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume = typeof video.volume === \"number\" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;\n const listeners = /* @__PURE__ */ new Map();\n let adVideoElement;\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n function hideContentVideo() {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n function showContentVideo() {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n function createAdVideoElement() {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"2\";\n adVideo.playsInline = true;\n adVideo.volume = originalVolume;\n adVideo.muted = originalMutedState;\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n return adVideo;\n }\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {\n }\n }\n }\n function ensureImaLoaded() {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n try {\n const frameEl = window.frameElement;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr.split(/\\s+/).map((t) => t.trim()).filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {\n }\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n );\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 1e4);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n let adsManager;\n let adsLoader;\n let adDisplayContainer;\n let adContainerEl;\n let lastAdTagUrl;\n let adsLoadedPromise;\n let adsLoadedResolve;\n let adsLoadedReject;\n function makeAdsRequest(google, vastTagUrl) {\n const adsRequest = new google.ima.AdsRequest();\n const companionSizes = [\n { width: 728, height: 90 },\n { width: 300, height: 250 },\n { width: 180, height: 150 },\n { width: 120, height: 60 },\n { width: 88, height: 31 },\n { width: 300, height: 60 },\n { width: 300, height: 100 },\n { width: 320, height: 50 },\n { width: 468, height: 60 },\n { width: 300, height: 600 },\n { width: 160, height: 600 }\n ];\n const ciuSzsValue = companionSizes.map((size) => `fluid|${size.width}x${size.height}`).join(\",\");\n const currentLocation = typeof window !== \"undefined\" ? window.location : null;\n const topLocation = typeof window !== \"undefined\" && window.top ? window.top.location : currentLocation;\n const currentUrl = currentLocation?.href || \"\";\n const topUrl = topLocation?.href || currentUrl;\n const currentDomain = currentLocation?.hostname || \"\";\n let modifiedVastTagUrl = vastTagUrl;\n try {\n const url = new URL(vastTagUrl);\n url.searchParams.set(\"ciu_szs\", ciuSzsValue);\n if (!url.searchParams.has(\"mpt\")) {\n url.searchParams.set(\"mpt\", \"h5_vsi\");\n }\n if (!url.searchParams.has(\"ctv\")) {\n url.searchParams.set(\"ctv\", \"0\");\n }\n if (!url.searchParams.has(\"gdpr\")) {\n url.searchParams.set(\"gdpr\", \"0\");\n }\n if (!url.searchParams.has(\"top\") && topUrl) {\n url.searchParams.set(\"top\", topUrl);\n }\n if (!url.searchParams.has(\"loc\") && currentUrl) {\n url.searchParams.set(\"loc\", currentUrl);\n }\n if (!url.searchParams.has(\"cdm\") && currentDomain) {\n url.searchParams.set(\"cdm\", currentDomain);\n }\n if (!url.searchParams.has(\"eoidce\")) {\n url.searchParams.set(\"eoidce\", \"1\");\n }\n if (!url.searchParams.has(\"fbidx\")) {\n url.searchParams.set(\"fbidx\", \"0\");\n }\n modifiedVastTagUrl = url.toString();\n } catch (e) {\n let baseUrl = vastTagUrl;\n const paramsToRemove = [\"ciu_szs\", \"mpt\", \"ctv\", \"gdpr\", \"top\", \"loc\", \"cdm\", \"eoidce\", \"fbidx\"];\n paramsToRemove.forEach((param) => {\n if (baseUrl.includes(`${param}=`)) {\n baseUrl = baseUrl.replace(new RegExp(`[?&]${param}=[^&]*`, \"g\"), \"\");\n }\n });\n baseUrl = baseUrl.replace(/[?&]$/, \"\");\n const params = new URLSearchParams();\n params.set(\"ciu_szs\", ciuSzsValue);\n params.set(\"mpt\", \"h5_vsi\");\n params.set(\"ctv\", \"0\");\n params.set(\"gdpr\", \"0\");\n if (topUrl) params.set(\"top\", topUrl);\n if (currentUrl) params.set(\"loc\", currentUrl);\n if (currentDomain) params.set(\"cdm\", currentDomain);\n params.set(\"eoidce\", \"1\");\n params.set(\"fbidx\", \"0\");\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n modifiedVastTagUrl = `${baseUrl}${separator}${params.toString()}`;\n }\n adsRequest.adTagUrl = modifiedVastTagUrl;\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 480;\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n if (typeof adsRequest.setCompanionSlots === \"function\") {\n try {\n const companionSlots = [];\n for (const size of companionSizes) {\n const slot = new google.ima.CompanionAdSlot();\n slot.width = size.width;\n slot.height = size.height;\n companionSlots.push(slot);\n }\n adsRequest.setCompanionSlots(companionSlots);\n } catch (error) {\n console.warn(\"[IMA] Failed to set companion slots:\", error);\n }\n }\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n adsRequest.vastLoadTimeout = 1e4;\n adsLoader.requestAds(adsRequest);\n }\n function ensurePlaceholderContainer() {\n if (adContainerEl) {\n return;\n }\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {\n }\n adsManager = void 0;\n }\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n function destroyAdsLoader() {\n if (adsLoader) {\n try {\n adsLoader.destroy();\n } catch {\n }\n adsLoader = void 0;\n }\n }\n return {\n initialize() {\n ensureImaLoaded().then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {\n }\n }\n }).catch(() => {\n });\n },\n async requestAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n return Promise.reject(error);\n }\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n return Promise.reject(error);\n }\n if (adPlaying) {\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n destroyAdsManager();\n destroyAdsLoader();\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n let currentReject;\n adsLoadedPromise = new Promise((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n }, 1e4);\n });\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n video.parentElement.appendChild(container);\n adContainerEl = container;\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n }\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt) => {\n try {\n const adsRenderingSettings = new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent) => {\n const error = errorEvent.getError();\n const errorCode = error.getErrorCode?.() || \"unknown\";\n const vastErrorCode = error.getVastErrorCode?.() || \"N/A\";\n const errorMessage = error.getMessage?.() || \"Unknown error\";\n let innerError;\n try {\n if (typeof error.getInnerError === \"function\") {\n const inner = error.getInnerError();\n if (inner) {\n innerError = typeof inner === \"string\" ? inner : inner.message || String(inner);\n }\n }\n if (!innerError && error.cause) {\n innerError = typeof error.cause === \"string\" ? error.cause : error.cause.message || String(error.cause);\n }\n if (!innerError && error.innerError) {\n innerError = typeof error.innerError === \"string\" ? error.innerError : error.innerError.message || String(error.innerError);\n }\n } catch (e) {\n }\n const isNoFill = errorCode === 303 || vastErrorCode === 303;\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\", {\n code: errorCode,\n vastErrorCode,\n message: errorMessage,\n cause: innerError,\n isNoFill\n });\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {\n });\n }\n }\n }\n );\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adsManager) {\n try {\n adsManager.setVolume(adVolume);\n } catch {\n }\n }\n emit(\"content_pause\");\n }\n );\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n hideContentVideo();\n if (adVideoElement) {\n const adVolume = originalVolume;\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n if (adsManager) {\n try {\n adsManager.setVolume(originalMutedState ? 0 : adVolume);\n } catch {\n }\n }\n }\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n showContentVideo();\n emit(\"content_resume\");\n }\n );\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n emit(\"all_ads_completed\");\n });\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = void 0;\n adsLoadedReject = void 0;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent) => {\n const error = adErrorEvent.getError();\n const errorCode = error.getErrorCode?.() || \"unknown\";\n const vastErrorCode = error.getVastErrorCode?.() || \"N/A\";\n const errorMessage = error.getMessage?.() || \"Unknown error\";\n let innerError;\n try {\n if (typeof error.getInnerError === \"function\") {\n const inner = error.getInnerError();\n if (inner) {\n innerError = typeof inner === \"string\" ? inner : inner.message || String(inner);\n }\n }\n if (!innerError && error.cause) {\n innerError = typeof error.cause === \"string\" ? error.cause : error.cause.message || String(error.cause);\n }\n if (!innerError && error.innerError) {\n innerError = typeof error.innerError === \"string\" ? error.innerError : error.innerError.message || String(error.innerError);\n }\n } catch (e) {\n }\n const isNoFill = errorCode === 303 || vastErrorCode === 303;\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(isNoFill ? \"No ads available\" : \"Ads loader error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\", {\n code: errorCode,\n vastErrorCode,\n message: errorMessage,\n isNoFill,\n cause: innerError\n });\n },\n false\n );\n }\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 480;\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n adPlaying = true;\n const adVolume = originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n try {\n adsManager.setVolume(originalMutedState ? 0 : adVolume);\n } catch {\n }\n adsManager.start();\n return Promise.resolve();\n } catch (error) {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {\n });\n }\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adsManager || !adPlaying) {\n return;\n }\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n if (adsManager && typeof adsManager.pause === \"function\") {\n adsManager.pause();\n }\n } catch (error) {\n console.warn(\"[IMA] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adsManager || !adPlaying) {\n return;\n }\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {\n });\n }\n if (adsManager && typeof adsManager.resume === \"function\") {\n adsManager.resume();\n }\n } catch (error) {\n console.warn(\"[IMA] Error resuming ad:\", error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n console.log(\"[IMA] Content video paused in live mode on stop, resuming playback\");\n video.play().catch(() => {\n });\n }\n } else if (video.paused) {\n video.play().catch(() => {\n });\n }\n try {\n adsManager?.stop?.();\n } catch {\n }\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"none\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n adVideoElement = void 0;\n }\n }, 500);\n }\n showContentVideo();\n try {\n adsLoader?.destroy?.();\n } catch {\n }\n adDisplayContainer = void 0;\n adsLoader = void 0;\n contentVideoHidden = false;\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {\n }\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n hideContentVideo();\n if (adContainerEl) {\n const wasHidden = adContainerEl.style.display === \"none\" || adContainerEl.style.opacity === \"0\";\n if (wasHidden) {\n adContainerEl.style.transition = \"none\";\n } else {\n adContainerEl.style.transition = \"opacity 0.3s ease-in-out\";\n }\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (adContainerEl) {\n adContainerEl.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.backgroundColor = \"#000\";\n }\n }, 300);\n }\n }\n };\n}\n\n// src/sdk/hlsAdPlayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\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 parseVastXml(xmlString) {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n 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 null;\n }\n const trackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: []\n };\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n async function fetchAndParseVastAd(vastTagUrl) {\n const response = await fetch(vastTagUrl, {\n 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 const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml);\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n video.volume = 1;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n const progress = adVideoElement.currentTime / currentAd.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function handleAdComplete() {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\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 contentVideo.volume = 0;\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 contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n 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 = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\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 = originalMutedState ? 0 : originalVolume;\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n }\n };\n}\n\n// src/utils/tracking.ts\nvar cachedBrowserId = null;\nfunction getClientInfo() {\n const ua = navigator.userAgent;\n const platform = navigator.platform;\n const vendor = navigator.vendor || \"\";\n const maxTouchPoints = navigator.maxTouchPoints || 0;\n const memory = navigator.deviceMemory || null;\n const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n const screenInfo = {\n width: screen?.width,\n height: screen?.height,\n availWidth: screen?.availWidth,\n availHeight: screen?.availHeight,\n orientation: screen?.orientation?.type || \"\",\n pixelDepth: screen?.pixelDepth\n };\n let deviceType = \"desktop\";\n let brand = \"Unknown\";\n let os = \"Unknown\";\n let model = \"\";\n let isSmartTV = false;\n let isAndroid = false;\n let isWebView = false;\n let isWebApp = false;\n if (ua.includes(\"Web0S\")) {\n brand = \"LG\";\n os = \"webOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n } else if (ua.includes(\"Tizen\")) {\n brand = \"Samsung\";\n os = \"Tizen\";\n isSmartTV = true;\n deviceType = \"tv\";\n const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n model = tizenMatch ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim() : \"Tizen TV\";\n } else if (ua.includes(\"Philips\")) {\n brand = \"Philips\";\n os = \"Saphi\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n brand = \"Sharp\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Android\") && (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))) {\n brand = \"Sony\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Android\") && (ua.includes(\"NetCast\") || ua.includes(\"LG\"))) {\n brand = \"LG\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n brand = \"Roku\";\n os = \"Roku OS\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"AppleTV\")) {\n brand = \"Apple\";\n os = \"tvOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n }\n if (ua.includes(\"Android\")) {\n isAndroid = true;\n os = \"Android\";\n deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n if (ua.includes(\"Android\") && (maxTouchPoints === 0 || ua.includes(\"Google TV\") || ua.includes(\"XiaoMi\"))) {\n deviceType = \"tv\";\n isSmartTV = true;\n brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n }\n const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n if (androidModelMatch && androidModelMatch[1]) {\n model = androidModelMatch[1];\n }\n }\n if (/iPad|iPhone|iPod/.test(ua)) {\n os = \"iOS\";\n deviceType = \"mobile\";\n brand = \"Apple\";\n if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n deviceType = \"tablet\";\n }\n }\n if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n if (ua.includes(\"Windows\")) {\n os = \"Windows\";\n deviceType = \"desktop\";\n } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n os = \"macOS\";\n deviceType = \"desktop\";\n if (maxTouchPoints > 1) deviceType = \"tablet\";\n } else if (ua.includes(\"Linux\")) {\n os = \"Linux\";\n deviceType = \"desktop\";\n }\n }\n if (brand === \"Unknown\") {\n if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n if (vendor.includes(\"Apple\")) brand = \"Apple\";\n if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n }\n isWebView = /wv|WebView|Linux; U;/.test(ua);\n if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n isWebView = true;\n }\n isWebApp = window.matchMedia(\"(display-mode: standalone)\").matches || window.navigator.standalone === true || window.screen?.orientation?.angle !== void 0;\n return {\n brand,\n os,\n model: model || ua.substring(0, 50) + \"...\",\n deviceType,\n isSmartTV,\n isAndroid,\n isWebView,\n isWebApp,\n domain: window.location.hostname,\n origin: window.location.origin,\n path: window.location.pathname,\n userAgent: ua,\n vendor,\n platform,\n screen: screenInfo,\n hardwareConcurrency,\n deviceMemory: memory,\n maxTouchPoints,\n language: navigator.language,\n languages: navigator.languages?.join(\",\") || \"\",\n cookieEnabled: navigator.cookieEnabled,\n doNotTrack: navigator.doNotTrack || \"\",\n referrer: document.referrer,\n visibilityState: document.visibilityState\n };\n}\nasync function getBrowserID(clientInfo) {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n const fingerprintString = JSON.stringify(clientInfo);\n if (typeof crypto !== \"undefined\" && crypto.subtle && crypto.subtle.digest) {\n try {\n await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n let encodedData;\n if (typeof TextEncoder !== \"undefined\") {\n encodedData = new TextEncoder().encode(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\n const buffer = new Uint8Array(utf8.length);\n for (let i = 0; i < utf8.length; i++) {\n buffer[i] = utf8.charCodeAt(i);\n }\n encodedData = buffer;\n }\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n const timestamp = Date.now().toString(16).padStart(12, \"0\");\n const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\nvar PLAYER_TRACKING_BASE_URL = \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking\";\nvar TRACK_URL = `${PLAYER_TRACKING_BASE_URL}/metrics/ingest`;\nvar HEARTBEAT_URL = `${PLAYER_TRACKING_BASE_URL}/heartbeat`;\nvar IMPRESSIONS_URL = `${PLAYER_TRACKING_BASE_URL}/impressions/ingest`;\nfunction buildHeaders(licenseKey) {\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n return headers;\n}\nasync function sendTrackRequest(licenseKey, body) {\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers: buildHeaders(licenseKey),\n body: JSON.stringify(body)\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\nasync function postJson(url, licenseKey, body) {\n const response = await fetch(url, {\n method: \"POST\",\n headers: buildHeaders(licenseKey),\n body: JSON.stringify(body)\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\nasync function buildPlayerMetricEvent(licenseKey, context = {}, flags = {}) {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const captureAt = flags.captureAt ?? (/* @__PURE__ */ new Date()).toISOString();\n return {\n player_id: browserId,\n browserId,\n device_type: clientInfo.deviceType,\n deviceType: clientInfo.deviceType,\n input_stream_type: context.inputStreamType,\n os: clientInfo.os,\n ad_loaded: flags.adLoaded,\n ad_detect: flags.adDetect,\n license_key: licenseKey,\n capture_at: captureAt,\n timestamp: captureAt\n };\n}\nasync function sendInitialTracking(licenseKey, context = {}) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = {\n browserId,\n ...clientInfo\n };\n await sendTrackRequest(licenseKey, {\n events: [\n {\n player_id: browserId,\n device_type: clientInfo.deviceType,\n input_stream_type: context.inputStreamType,\n os: clientInfo.os,\n ad_loaded: false,\n ad_detect: false,\n license_key: licenseKey,\n capture_at: (/* @__PURE__ */ new Date()).toISOString()\n }\n ],\n trackingData\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 try {\n const metricEvent = await buildPlayerMetricEvent(licenseKey, context, {\n captureAt: adImpressionInfo.timestamp\n });\n await Promise.all([\n postJson(HEARTBEAT_URL, licenseKey, metricEvent),\n postJson(IMPRESSIONS_URL, licenseKey, {\n events: [\n {\n player_id: metricEvent.player_id,\n ad_played_count: 1,\n ad_url: adImpressionInfo.adUrl,\n license_key: licenseKey,\n capture_at: adImpressionInfo.timestamp\n }\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 try {\n const heartbeatData = await buildPlayerMetricEvent(\n licenseKey,\n context,\n flags\n );\n await postJson(HEARTBEAT_URL, licenseKey, 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/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.adPodQueue = [];\n this.vmapBreaks = [];\n this.consumedVmapBreakIds = /* @__PURE__ */ new Set();\n this.lastHeartbeatTime = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.showAds = false;\n this.isLiveStream = false;\n this.nativeHlsMode = false;\n this.videoSrcProtection = null;\n this.bufferedSegmentsCount = 0;\n this.shouldAutoplayAfterBuffering = false;\n this.hasInitialBufferCompleted = false;\n this.adRequestTokenCounter = 0;\n this.activeAdRequestToken = null;\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.failedVastUrls = /* @__PURE__ */ new Set();\n this.temporaryFailureUrls = /* @__PURE__ */ new Map();\n this.temporaryFailureCooldownMs = 3e4;\n this.continuousFetchingActive = false;\n this.adRequestQueue = [];\n this.maxPlaceholderDurationMs = 5e3;\n this.isShowingPlaceholder = false;\n this.tsScte35Pids = /* @__PURE__ */ new Set();\n this.pmtPids = /* @__PURE__ */ new Set();\n this.processedTsScte35Sections = /* @__PURE__ */ new Set();\n this.pendingScte35Cues = /* @__PURE__ */ new Map();\n this.recentScte35CueKeys = /* @__PURE__ */ new Map();\n this.recentScte35CueLimit = 200;\n this.totalAdRequestsInBreak = 0;\n this.maxTotalAdRequestsPerBreak = 10;\n this.pendingAdBreak = null;\n this.consecutiveFailures = 0;\n this.maxConsecutiveFailures = 5;\n this.lastAdRequestTime = 0;\n this.minAdRequestIntervalMs = 3e3;\n this.backoffBaseMs = 1e3;\n this.maxBackoffMs = 15e3;\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.preloadPool = [];\n this.maxPreloadPoolSize = 2;\n this.preloadPoolActive = false;\n this.preloadPoolLoopRunning = false;\n this.adDetectSentForCurrentBreak = false;\n this.continuousFetchLoopRunning = false;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.ima = this.createAdPlayer(false);\n }\n createAdPlayer(continueLiveStreamDuringAds) {\n const vastMode = this.config.vastMode || \"default\";\n let adPlayerType = this.config.adPlayerType || (vastMode === \"adstorm\" ? \"hls\" : \"ima\");\n if (adPlayerType === \"ima\" && !supportsGoogleIMA()) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player\"\n );\n }\n adPlayerType = \"hls\";\n }\n if (adPlayerType === \"hls\") {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)\"\n );\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},\n ...this.hls ? { mainHlsInstance: this.hls } : {}\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating Google IMA ad player (IMA mode)\"\n );\n }\n return createImaController(this.video, {\n continueLiveStreamDuringAds\n });\n }\n }\n async load() {\n if (!this.attached) {\n this.attach();\n }\n try {\n await this.fetchAdConfiguration();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n this.initializeTracking();\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\"\n }\n );\n }\n this.ima.destroy();\n this.ima = this.createAdPlayer(false);\n this.ima.initialize();\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n return;\n }\n this.hls = new 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 if (this.config.allowNativeHls === false) {\n this.isLiveStream = true;\n } else {\n this.isLiveStream = this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n }\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds() ? \"live (main video continues muted during ads)\" : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior\n });\n }\n this.ima.destroy();\n this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.ima.initialize();\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n }\n });\n this.hls.on(import_hls2.default.Events.LEVEL_LOADED, (_evt, data) => {\n if (this.inAdBreak || this.pendingAdBreak) {\n return;\n }\n const details = data?.details;\n if (!details || !details.fragments || details.fragments.length === 0) {\n return;\n }\n const fragmentsToScan = Math.min(5, details.fragments.length);\n for (let i = 0; i < fragmentsToScan; i++) {\n const frag = details.fragments[i];\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) continue;\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n }\n }\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = tag.includes(\"EXT-X-DATERANGE\") ? this.parseAttributeList(value) : {};\n const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") || \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n if (hasScteOut) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value, earlyDetection: true }\n };\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] \\u{1F3AF} EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n }\n this.onScte35Cue(marker, {\n ...this.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.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n this.hls.on(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 this.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 this.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.activatePendingScte35CuesForFragment(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 = this.parseCueOutCont(value);\n const marker = {\n type: \"progress\",\n ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},\n ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},\n raw: { tag, value }\n };\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Cue(\n { type: \"end\", raw: { tag, value } },\n {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n }\n );\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { tag, value, attrs }\n };\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n });\n }\n if (hasScteIn) {\n this.onScte35Cue(\n { type: \"end\", raw: { tag, value, attrs } },\n {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag)\n }\n );\n }\n }\n }\n this.activatePendingScte35CuesForFragment(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.destroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n attachImaEventListeners() {\n this.ima.on(\"all_ads_completed\", () => {\n sendAdImpressionTracking(\n this.config.licenseKey,\n { source: \"ima\", adIndex: this.currentAdIndex, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n const remaining = this.getRemainingAdMs();\n this.consecutiveFailures = 0;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.inAdBreak) {\n if (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n this.ima.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 this.ima.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n this.resetGamNoFillCounter();\n if (this.inAdBreak && this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.ima.on(\"content_resume\", () => {\n sendAdImpressionTracking(\n this.config.licenseKey,\n { source: \"ima\", adIndex: this.currentAdIndex, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n }\n }\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n return;\n }\n this.consecutiveFailures = 0;\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\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 (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n });\n }\n recreateImaController() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Recreating ImaController for new ad\");\n }\n const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n if (shouldShowPlaceholder && this.ima) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController\");\n }\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n const preservedMutedState = this.ima.getOriginalMutedState();\n const preservedVolumeState = this.ima.getOriginalVolume();\n if (this.ima) {\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Error destroying old ImaController:\", error);\n }\n }\n }\n const continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();\n this.ima = this.createAdPlayer(continueLiveStreamDuringAds);\n this.ima.initialize();\n this.ima.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n this.attachImaEventListeners();\n if (shouldShowPlaceholder) {\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n }\n ensurePlaceholderContainer() {\n if (this.placeholderContainer) {\n return;\n }\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"5\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!this.video.parentElement) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n this.video.parentElement.appendChild(container);\n this.placeholderContainer = container;\n }\n showPlaceholderLayer() {\n this.ensurePlaceholderContainer();\n if (!this.placeholderContainer) {\n return;\n }\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n const wasHidden = this.placeholderContainer.style.display === \"none\" || this.placeholderContainer.style.opacity === \"0\";\n if (wasHidden) {\n this.placeholderContainer.style.transition = \"none\";\n } else {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n this.placeholderContainer.style.backgroundColor = \"#000\";\n this.placeholderContainer.style.display = \"flex\";\n this.placeholderContainer.offsetHeight;\n this.placeholderContainer.style.opacity = \"1\";\n this.placeholderContainer.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)\");\n }\n }\n hidePlaceholderLayer() {\n if (!this.placeholderContainer) {\n return;\n }\n this.placeholderContainer.style.opacity = \"0\";\n setTimeout(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.display = \"none\";\n this.placeholderContainer.style.pointerEvents = \"none\";\n this.placeholderContainer.style.backgroundColor = \"#000\";\n }\n }, 300);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n attach() {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n this.ima.initialize();\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachImaEventListeners();\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {\n });\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n shouldUseNativeHls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Cue(marker, {\n source: \"id3\",\n readiness: \"playback\"\n });\n }\n }\n parseScte35FromId3(tag) {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return void 0;\n const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) || text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...dur !== void 0 ? { durationSeconds: dur } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker = {\n type: \"progress\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n if (hasScteIn) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n }\n if (/SCTE35-OUT/i.test(text)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n }\n decodeId3ValueToText(value) {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]);\n return out;\n } catch {\n return void 0;\n }\n }\n createScte35CueContext(source, readiness, frag) {\n const context = { source, readiness };\n if (typeof frag?.sn === \"number\") {\n context.fragmentSn = frag.sn;\n }\n const fragmentStartSeconds = this.getFragmentStartSeconds(frag);\n if (fragmentStartSeconds !== void 0) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n return context;\n }\n 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 }\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.startAdPrefetch(marker, context.fragmentSn, cue.key);\n }\n return;\n }\n if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n key: cue.key,\n activeScte35BreakKey: this.activeScte35BreakKey,\n inAdBreak: this.inAdBreak,\n source: cue.source\n });\n }\n return;\n }\n if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n if (this.config.debugAdTiming) {\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.onScte35Marker(marker, cue.key);\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.activeScte35BreakKey === cue.key || this.scheduledScte35BreakKey === 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.inAdBreak) {\n return false;\n }\n if (this.isStrongScte35CueKey(this.activeScte35BreakKey) && this.isStrongScte35CueKey(cue.key) && this.activeScte35BreakKey !== cue.key) {\n return false;\n }\n return true;\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 fragmentStartSeconds = cue.fragmentStartSeconds ?? this.getFragmentStartSeconds(frag);\n if (fragmentStartSeconds !== void 0) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n this.onScte35Cue(cue.marker, context);\n });\n }\n onScte35Marker(marker, cueKey) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n hasPendingAdBreak: !!this.pendingAdBreak\n });\n }\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n if (marker.durationSeconds != null) {\n const newDurationMs = marker.durationSeconds * 1e3;\n if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {\n this.expectedAdBreakDurationMs = newDurationMs;\n const elapsedMs = this.currentAdBreakStartWallClockMs != null ? Date.now() - this.currentAdBreakStartWallClockMs : 0;\n const remainingMs = Math.max(0, newDurationMs - elapsedMs);\n this.scheduleAdStopCountdown(remainingMs);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${newDurationMs}ms, remaining: ${remainingMs}ms`\n );\n }\n }\n }\n return;\n }\n if (!this.adDetectSentForCurrentBreak) {\n this.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.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.pendingAdBreak?.marker.durationSeconds != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n hasPrefetchedAds\n });\n }\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Starting ad immediately (manifest-based)${hasPrefetchedAds ? \" with prefetched ads\" : \"\"}`\n );\n }\n this.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.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1e3,\n deltaMs,\n tolerance: tol\n });\n }\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.expectedAdBreakDurationMs = durationMs;\n this.scheduledScte35BreakKey = cueKey;\n this.scheduleAdStartIn(deltaMs, marker, cueKey);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0) {\n this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.ima.isAdPlaying();\n const hasQueuedAds = this.adRequestQueue.length > 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null\n });\n }\n if (adPlaying || remaining > 1e3 && hasQueuedAds) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active\");\n }\n return;\n }\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n if (adPlaying) {\n this.ima.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n return;\n }\n }\n startScte35AdBreak(marker, cueKey, durationMs) {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE start marker\");\n }\n }\n this.inAdBreak = true;\n this.activeScte35BreakKey = cueKey ?? this.pendingScte35CueKey;\n this.scheduledScte35BreakKey = void 0;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.handleAdStart(marker);\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n }\n parseCueOutDuration(value) {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match = value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) || value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? void 0 : d;\n }\n return void 0;\n }\n parseCueOutCont(value) {\n const 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 }\n parseAttributeList(value) {\n const attrs = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match;\n while ((match = regex.exec(value)) !== null) {\n const key = match[1] ?? \"\";\n let rawVal = match[3] ?? match[4] ?? \"\";\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n toNumber(val) {\n if (val == null) return void 0;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? void 0 : n;\n }\n isManifestBasedMarker(marker) {\n const raw = marker.raw;\n if (!raw) return false;\n if (raw.tag) {\n const tag = String(raw.tag);\n return tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-CUE-IN\") || tag.includes(\"EXT-X-DATERANGE\");\n }\n if (raw.id3) return false;\n if (raw.splice_command_type) return false;\n return false;\n }\n 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 }\n processFragmentScte35Payload(payloadData, fragmentSn, fragmentStartSeconds) {\n const payload = this.normalizeFragmentPayload(payloadData);\n if (!payload) {\n return;\n }\n const markers = this.parseScte35FromTsPackets(payload);\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.onScte35Cue(marker, context);\n });\n }\n parseScte35FromTsPackets(data) {\n const packetInfo = this.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 this.parsePatSection(payload, payloadUnitStart);\n } else if (this.pmtPids.has(pid)) {\n this.parsePmtSection(payload, payloadUnitStart);\n } else if (this.tsScte35Pids.has(pid)) {\n this.collectScte35SectionsFromPayload(\n pid,\n payload,\n payloadUnitStart,\n sectionAssemblers,\n markers\n );\n }\n }\n return markers;\n }\n 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 }\n parsePatSection(payload, payloadUnitStart) {\n const sectionStart = this.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 = this.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 this.pmtPids.add(pid);\n }\n }\n }\n parsePmtSection(payload, payloadUnitStart) {\n const sectionStart = this.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 = this.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 && this.descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd)) {\n this.tsScte35Pids.add(elementaryPid);\n }\n offset = descriptorStart + esInfoLength;\n }\n }\n 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 }\n collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, assemblers, markers) {\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 this.appendScte35Bytes(\n pid,\n payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n assemblers,\n markers\n );\n }\n assemblers.delete(pid);\n offset = 1 + pointerField;\n } else {\n this.appendScte35Bytes(pid, payload, assemblers, markers);\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 = this.getPsiSectionLength(payload, offset);\n const totalLength = 3 + sectionLength;\n if (sectionLength <= 0 || totalLength <= 3) {\n return;\n }\n if (offset + totalLength <= payload.length) {\n this.addScte35SectionMarker(\n payload.subarray(offset, offset + totalLength),\n markers\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 appendScte35Bytes(pid, bytes, assemblers, markers) {\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 this.addScte35SectionMarker(new Uint8Array(assembler.bytes), markers);\n }\n }\n addScte35SectionMarker(section, markers) {\n if (section[0] !== 252 || this.hasProcessedTsScte35Section(section)) {\n return;\n }\n const marker = this.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 }\n hasProcessedTsScte35Section(section) {\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 (this.processedTsScte35Sections.has(key)) {\n return true;\n }\n this.processedTsScte35Sections.add(key);\n if (this.processedTsScte35Sections.size > 200) {\n const firstKey = this.processedTsScte35Sections.values().next().value;\n if (firstKey) {\n this.processedTsScte35Sections.delete(firstKey);\n }\n }\n return false;\n }\n 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 }\n getPsiSectionLength(data, offset) {\n return ((data[offset + 1] ?? 0) & 15) << 8 | (data[offset + 2] ?? 0);\n }\n parseScte35Binary(data) {\n class BitReader {\n constructor(buf) {\n this.buf = buf;\n this.bytePos = 0;\n this.bitPos = 0;\n }\n readBits(numBits) {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos];\n const shift = remainingInByte - toRead;\n const mask = (1 << toRead) - 1 & 255;\n const bits = currentByte >> shift & mask;\n result = result << toRead | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n) {\n this.readBits(n);\n }\n get bytePosition() {\n return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n }\n }\n const readSpliceTime = (r2, ptsAdjustmentTicks2) => {\n const timeSpecifiedFlag = r2.readBits(1) === 1;\n if (!timeSpecifiedFlag) {\n r2.readBits(7);\n return void 0;\n }\n r2.readBits(6);\n const high = r2.readBits(1);\n const low = r2.readBits(32);\n const ptsTicks = (high * 4294967296 + low + ptsAdjustmentTicks2) % 8589934592;\n return ptsTicks / 9e4;\n };\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 252) return void 0;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n 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 = this.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 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 = this.parseScte35SegmentationDescriptor(\n data.subarray(descriptorDataStart, descriptorDataEnd)\n );\n if (descriptorMarker) {\n return descriptorMarker;\n }\n }\n descriptorOffset = descriptorDataEnd;\n }\n return void 0;\n }\n 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 = this.markerTypeFromSegmentationTypeId(segmentationTypeId);\n if (!markerType) {\n return void 0;\n }\n return {\n type: markerType,\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n segmentationEventId\n };\n }\n 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 }\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n });\n }\n sendHeartbeatIfNeeded() {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n async fetchAdConfiguration() {\n if (this.config.vmapUrl) {\n await this.fetchAndParseVmap(this.config.vmapUrl);\n }\n const vastMode = this.config.vastMode || \"default\";\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n );\n }\n return;\n }\n const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n this.apiVastTagUrl = vastEndpoint;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n vastEndpoint\n );\n }\n return;\n }\n if (this.config.vastTagUrl) {\n this.apiVastTagUrl = this.config.vastTagUrl;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n return;\n }\n const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n apiUrl\n );\n }\n const headers = {};\n if (this.config.licenseKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n }\n const response = await fetch(apiUrl, { headers });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n );\n }\n return;\n }\n const data = await response.json();\n const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n if (imaPayload) {\n this.apiVastTagUrl = decodeURIComponent(imaPayload);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n );\n }\n }\n const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n if (numberAds != null && numberAds > 0) {\n this.apiNumberAds = numberAds;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n 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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n }\n return [];\n }\n const adBreakNodes = Array.from(\n doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\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 const adTagNode = node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\");\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 getCurrentAdIndex() {\n return this.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.totalAdsInBreak;\n }\n getAdRemainingMs() {\n return this.getRemainingAdMs();\n }\n generateVastUrlsWithCorrelators(baseUrl, count) {\n const urls = [];\n const baseTimestamp = Date.now();\n for (let i = 0; i < count; i++) {\n const timestamp = baseTimestamp + i;\n const random = Math.floor(Math.random() * 1e12);\n const uniqueCorrelator = `${timestamp}_${random}_${i}`;\n let urlWithCorrelator;\n const correlatorRegex = /([?&])correlator=([^&]*)/;\n if (correlatorRegex.test(baseUrl)) {\n urlWithCorrelator = baseUrl.replace(correlatorRegex, `$1correlator=${uniqueCorrelator}`);\n } else if (baseUrl.includes(\"?\")) {\n urlWithCorrelator = `${baseUrl}&correlator=${uniqueCorrelator}`;\n } else {\n urlWithCorrelator = `${baseUrl}?correlator=${uniqueCorrelator}`;\n }\n urls.push(urlWithCorrelator);\n }\n return urls;\n }\n isAdPlaying() {\n return this.inAdBreak && this.ima.isAdPlaying();\n }\n isShowingAds() {\n return this.showAds;\n }\n getStreamType() {\n const url = this.config.src.toLowerCase();\n if (url.includes(\".m3u8\") || url.includes(\"/hls/\") || url.includes(\"application/vnd.apple.mpegurl\")) {\n return \"hls\";\n }\n return \"other\";\n }\n shouldShowNativeControls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));\n }\n shouldContinueLiveStreamDuringAds() {\n if (this.config.allowNativeHls) {\n return false;\n }\n if (!this.isLiveStream) {\n return false;\n }\n return true;\n }\n startAdPrefetch(marker, fragmentSn, cueKey) {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n const scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);\n const tags = this.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] No VAST URL available for prefetch\");\n }\n return;\n }\n const urlsToPregenerate = 5;\n const generatedUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, urlsToPregenerate);\n this.pendingAdBreak = {\n marker,\n ...fragmentSn !== void 0 ? { detectedAtFragmentSn: fragmentSn } : {},\n vastUrls: generatedUrls,\n isFetching: false,\n fetchStartTime: Date.now()\n };\n this.pendingScte35CueKey = cueKey;\n this.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.config.debugAdTiming) {\n console.log(\"[PREFETCH] \\u{1F504} Starting ad prefetch for upcoming ad break\");\n console.log(`[PREFETCH] \\u{1F4CB} Pre-generated ${generatedUrls.length} VAST URLs`);\n }\n this.startPreloadPool(baseVastUrl, generatedUrls.slice(0, this.maxPreloadPoolSize));\n }\n clearPendingAdBreak() {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = void 0;\n }\n this.pendingAdBreak = null;\n this.pendingScte35CueKey = void 0;\n }\n startPreloadPool(baseVastUrl, initialUrls) {\n if (this.preloadPoolActive) {\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n }\n return;\n }\n this.preloadPoolActive = true;\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u{1F3CA} Starting preload pool EARLY (target size: ${this.maxPreloadPoolSize})`);\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.preloadPool.length < this.maxPreloadPoolSize) {\n this.preloadAdIntoPool(url);\n }\n }\n this.preloadPoolLoop(baseVastUrl);\n }\n async preloadAdIntoPool(vastUrl) {\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n }\n return;\n }\n if (this.preloadPool.some((entry) => entry.vastUrl === vastUrl) || this.failedVastUrls.has(vastUrl) || this.isUrlInCooldown(vastUrl)) {\n return;\n }\n if (this.preloadPool.length >= this.maxPreloadPoolSize) {\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u{1F4E5} Preloading ad into pool: ${vastUrl}`);\n }\n const loadPromise = (async () => {\n let hasAdError = false;\n let adErrorPayload = null;\n let errorListenerCleanup = null;\n try {\n const continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();\n const preloadIma = this.createAdPlayer(continueLiveStreamDuringAds);\n preloadIma.initialize();\n const errorListener = (payload) => {\n hasAdError = true;\n adErrorPayload = payload;\n };\n preloadIma.on(\"ad_error\", errorListener);\n errorListenerCleanup = () => preloadIma.off(\"ad_error\", errorListener);\n await this.enforceGlobalRateLimit();\n await preloadIma.requestAds(vastUrl);\n preloadIma.pause();\n await new Promise((resolve) => setTimeout(resolve, 1500));\n preloadIma.pause();\n if (hasAdError) {\n const isNoFill = adErrorPayload?.isNoFill || adErrorPayload?.code === 303 || adErrorPayload?.vastErrorCode === 303;\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n preloadIma.destroy();\n this.recordGamNoFill();\n if (isNoFill) {\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u26A0\\uFE0F Ad preload returned no-fill: ${vastUrl}`);\n }\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n } else {\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u26A0\\uFE0F Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n }\n if (adErrorPayload && !this.isTemporaryAdError(adErrorPayload)) {\n this.failedVastUrls.add(vastUrl);\n } else {\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n return;\n }\n const poolEntry = {\n vastUrl,\n imaController: preloadIma,\n loadedAt: Date.now(),\n isReady: true,\n loadPromise: Promise.resolve()\n };\n const lateErrorListener = (payload) => {\n const index = this.preloadPool.findIndex((entry) => entry.vastUrl === vastUrl);\n if (index >= 0) {\n this.preloadPool.splice(index, 1);\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u26A0\\uFE0F Late error detected, removed from pool: ${vastUrl}`, payload);\n }\n try {\n preloadIma.destroy();\n } catch {\n }\n }\n };\n preloadIma.on(\"ad_error\", lateErrorListener);\n this.preloadPool.push(poolEntry);\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u2705 Ad preloaded (no errors detected within timeout) (pool size: ${this.preloadPool.length}/${this.maxPreloadPoolSize})`);\n }\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n } catch (error) {\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n this.recordGamNoFill();\n if (this.config.debugAdTiming) {\n console.warn(`[PRELOAD-POOL] \\u26A0\\uFE0F Failed to preload ad: ${vastUrl}`, error);\n }\n if (error instanceof Error && !this.isTemporaryAdError(error)) {\n this.failedVastUrls.add(vastUrl);\n } else if (error instanceof Error && this.isTemporaryAdError(error)) {\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n })();\n loadPromise.catch(() => {\n });\n }\n async preloadPoolLoop(baseVastUrl) {\n if (this.preloadPoolLoopRunning) {\n return;\n }\n this.preloadPoolLoopRunning = true;\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] \\u{1F504} Starting continuous preload loop\");\n }\n while (this.preloadPoolActive) {\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n }\n break;\n }\n if (!this.inAdBreak && this.preloadPool.length >= this.maxPreloadPoolSize) {\n await new Promise((resolve) => setTimeout(resolve, 2e3));\n continue;\n }\n if (!this.inAdBreak && this.pendingAdBreak === null) {\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n }\n break;\n }\n while (this.preloadPool.length < this.maxPreloadPoolSize) {\n if (!this.preloadPoolActive || this.isGamInCooldown()) {\n break;\n }\n if (this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 0) {\n break;\n }\n }\n const newUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const newUrl = newUrls[0];\n if (newUrl && !this.failedVastUrls.has(newUrl) && !this.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.preloadPoolLoopRunning = false;\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] \\u{1F6D1} Preload loop ended\");\n }\n }\n getPreloadedAd() {\n if (this.preloadPool.length === 0) {\n return null;\n }\n const entry = this.preloadPool.shift();\n if (!entry || !entry.isReady) {\n return null;\n }\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] \\u{1F3AF} Using preloaded ad from pool (${this.preloadPool.length} remaining)`);\n }\n return {\n vastUrl: entry.vastUrl,\n imaController: entry.imaController\n };\n }\n stopPreloadPool() {\n this.preloadPoolActive = false;\n this.preloadPoolLoopRunning = false;\n for (const entry of this.preloadPool) {\n try {\n entry.imaController.destroy();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n }\n }\n }\n this.preloadPool = [];\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] \\u{1F6D1} Preload pool stopped and cleaned up\");\n }\n }\n async handleAdStart(_marker) {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1e3\n );\n if (scheduled) {\n this.consumedVmapBreakIds.add(this.getAdBreakKey(scheduled));\n }\n const tags = this.selectVastTagsForBreak(scheduled);\n let baseVastUrl;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else {\n this.clearPendingAdBreak();\n return;\n }\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled?.durationMs;\n if (this.config.debugAdTiming) {\n const mode = this.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F4FA} ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n this.failedVastUrls.clear();\n this.temporaryFailureUrls.clear();\n this.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video in handleAdStart\");\n }\n }\n this.inAdBreak = true;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n this.showAds = true;\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n let firstAdUrl;\n let usePreloadedAd = false;\n let preloadedController;\n const preloaded = this.getPreloadedAd();\n if (preloaded) {\n firstAdUrl = preloaded.vastUrl;\n preloadedController = preloaded.imaController;\n usePreloadedAd = true;\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ima\", vastUrl: firstAdUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F680} Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n console.log(`[CONTINUOUS-FETCH] Pool still has ${this.preloadPool.length} preloaded ads ready`);\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.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u26A0\\uFE0F Pool empty, using prefetched URLs (${this.adRequestQueue.length + 1} available)`);\n }\n this.clearPendingAdBreak();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F680} Generating new ad URLs...\");\n }\n const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n firstAdUrl = firstAdUrlArray[0];\n this.adRequestQueue = [];\n }\n if (!firstAdUrl) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F Failed to get first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F4CB} First VAST URL:\", firstAdUrl);\n }\n try {\n if (usePreloadedAd && preloadedController) {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedController;\n this.attachImaEventListeners();\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n }\n this.ima.resume();\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPoolActive) {\n this.preloadPoolActive = true;\n this.preloadPoolLoop(baseVastUrl);\n }\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n } else {\n await this.enforceGlobalRateLimit();\n this.lastAdRequestTime = Date.now();\n await this.ima.requestAds(firstAdUrl);\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ima\", vastUrl: firstAdUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 First ad request successful, starting playback\");\n }\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPoolActive) {\n this.startPreloadPool(baseVastUrl, []);\n }\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F First ad request failed:\", error);\n }\n if (!usePreloadedAd) {\n const fallbackPreloaded = this.getPreloadedAd();\n if (fallbackPreloaded) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F504} First ad failed, using preloaded fallback\");\n }\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = fallbackPreloaded.imaController;\n this.attachImaEventListeners();\n this.ima.resume();\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n if (!this.preloadPoolActive) {\n this.preloadPoolActive = true;\n this.preloadPoolLoop(baseVastUrl);\n }\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n return;\n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n }\n if (this.isTemporaryAdError(error)) {\n this.temporaryFailureUrls.set(firstAdUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n }\n } else {\n this.failedVastUrls.add(firstAdUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n }\n }\n this.consecutiveFailures++;\n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n }\n }\n startContinuousFetching(baseVastUrl) {\n if (!this.continuousFetchingActive) {\n return;\n }\n if (this.continuousFetchLoopRunning) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23ED\\uFE0F Fetch loop already running, skipping duplicate start\");\n }\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F504} Starting continuous ad fetching loop\");\n }\n this.continuousFetchLoopRunning = true;\n this.continuousFetchLoop(baseVastUrl);\n }\n async continuousFetchLoop(baseVastUrl) {\n while (this.continuousFetchingActive && this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F Ad break time expired, stopping URL generation\");\n }\n break;\n }\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n }\n break;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), stopping URL generation`);\n }\n break;\n }\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Maximum ad requests reached (${this.maxTotalAdRequestsPerBreak}), stopping`);\n }\n break;\n }\n const maxQueueSize = 5;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F8\\uFE0F URL queue full (${this.adRequestQueue.length}), waiting...`);\n }\n await new Promise((resolve) => setTimeout(resolve, 1e3));\n continue;\n }\n const newAdUrl = this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];\n if (!newAdUrl || this.failedVastUrls.has(newAdUrl) || this.isUrlInCooldown(newAdUrl)) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n continue;\n }\n if (this.config.debugAdTiming) {\n const queuedUrlsPreview = [...this.adRequestQueue, newAdUrl];\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F4DD} Queued VAST URL (queue size: ${queuedUrlsPreview.length})`,\n { queuedUrls: queuedUrlsPreview }\n );\n }\n this.adRequestQueue.push(newAdUrl);\n this.totalAdsInBreak++;\n const generationDelay = this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, this.consecutiveFailures), 5e3) : 500;\n await new Promise((resolve) => setTimeout(resolve, generationDelay));\n }\n this.continuousFetchLoopRunning = false;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F6D1} 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.hidePlaceholderLayer();\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Stopping continuous ad fetching\");\n }\n }\n async tryNextAvailableAdWithRateLimit() {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n const backoffMultiplier = Math.pow(2, this.consecutiveFailures);\n const backoffDelay = Math.min(this.backoffBaseMs * backoffMultiplier, this.maxBackoffMs);\n const effectiveMinInterval = this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffDelay : 0);\n const timeSinceLastRequest = Date.now() - this.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F3 Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.consecutiveFailures} failures)`);\n }\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n return this.tryNextAvailableAd(0);\n }\n async tryNextAvailableAd(retryCount = 0) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n this.cleanupTemporaryFailures();\n const preloaded = this.getPreloadedAd();\n if (preloaded) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F3AF} Using preloaded ad from pool (${this.preloadPool.length} remaining in pool)`);\n }\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ima\", vastUrl: preloaded.vastUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloaded.imaController;\n this.attachImaEventListeners();\n this.ima.resume();\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n this.consecutiveFailures = 0;\n return;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F Preloaded ad failed to play:\", error);\n }\n }\n }\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) {\n continue;\n }\n if (this.failedVastUrls.has(nextAdUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23ED\\uFE0F Skipping permanently-failed URL, trying next...\");\n }\n continue;\n }\n if (this.isUrlInCooldown(nextAdUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23ED\\uFE0F Skipping URL in cooldown (recent no-fill), trying next...\");\n }\n continue;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F3AC} Requesting next ad via IMA SDK (${this.currentAdIndex + 1}/${this.totalAdsInBreak}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n try {\n await this.playSingleAd(nextAdUrl);\n this.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = error.message;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u274C Ad request failed:\", errorMessage);\n }\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.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.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F3 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.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No more ads available, ending ad break\");\n }\n this.handleAdPodComplete();\n }\n }\n async showPlaceholderAndWaitForAds() {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Skipping placeholder - too many consecutive failures\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (waitTime < 1e3) {\n this.handleAdPodComplete();\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u2B1B Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n }\n this.isShowingPlaceholder = true;\n this.ima.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) {\n return;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Too many failures during placeholder wait\");\n }\n break;\n }\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n if (!nextAdUrl) {\n continue;\n }\n if (this.failedVastUrls.has(nextAdUrl)) {\n continue;\n }\n if (this.isUrlInCooldown(nextAdUrl)) {\n continue;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 Ad URL available, requesting via IMA SDK\");\n }\n this.isShowingPlaceholder = false;\n this.ima.hidePlaceholder();\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n try {\n await this.playSingleAd(nextAdUrl);\n this.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = error.message;\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F0 Placeholder timeout, ending ad break\");\n }\n this.isShowingPlaceholder = false;\n this.ima.hidePlaceholder();\n this.handleAdPodComplete();\n }\n findCurrentOrNextBreak(nowMs) {\n const schedule = this.vmapBreaks;\n let candidate;\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 const tol = this.config.driftToleranceMs ?? 1e3;\n if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))) {\n candidate = b;\n }\n }\n return candidate;\n }\n onTimeUpdate(currentTimeSec) {\n if (this.ima.isAdPlaying() || this.inAdBreak) return;\n const nowMs = currentTimeSec * 1e3;\n const breakToPlay = this.findBreakForTime(nowMs);\n if (breakToPlay) {\n void this.handleMidAdJoin(breakToPlay, nowMs).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:\",\n error\n );\n }\n });\n }\n }\n async handleMidAdJoin(adBreak, nowMs) {\n const key = this.getAdBreakKey(adBreak);\n if (this.consumedVmapBreakIds.has(key)) {\n return;\n }\n const breakStartMs = this.resolveBreakStartMs(adBreak);\n if (breakStartMs == null) {\n return;\n }\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = breakStartMs + durationMs;\n const tol = this.config.driftToleranceMs ?? 1e3;\n const inWindow = durationMs > 0 ? nowMs > breakStartMs && nowMs < endMs : nowMs + tol >= breakStartMs;\n if (inWindow) {\n this.consumedVmapBreakIds.add(key);\n const remainingMs = durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;\n const tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);\n if (tags && tags.length > 0) {\n const first = tags[0];\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n try {\n await this.playSingleAd(first);\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = remainingMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(remainingMs);\n } catch (error) {\n this.adPodQueue = [];\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:\",\n error\n );\n }\n }\n }\n }\n }\n scheduleAdStopCountdown(remainingMs) {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.ensureAdStoppedByTimer();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.ensureAdStoppedByTimer();\n }, ms);\n }\n clearAdStopTimer() {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = void 0;\n }\n }\n ensureAdStoppedByTimer() {\n if (!this.inAdBreak) return;\n this.adStopTimerId = void 0;\n const adPlaying = this.ima.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1e3)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs = typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n if (adPlaying) {\n this.ima.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n }\n scheduleAdStartIn(delayMs, marker = { type: \"start\" }, cueKey) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0\n );\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.expectedAdBreakDurationMs\n );\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\n updatePtsDrift(ptsSecondsSample) {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n 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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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 async playSingleAd(vastTagUrl) {\n if (this.ima.isAdPlaying()) {\n return;\n }\n if (this.failedVastUrls.has(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n }\n throw new Error(\"VAST URL permanently failed\");\n }\n if (this.isUrlInCooldown(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n }\n throw new Error(\"VAST URL in cooldown after no-fill\");\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n }\n throw new Error(\"Too many consecutive failures\");\n }\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n }\n throw new Error(\"GAM in cooldown\");\n }\n this.recreateImaController();\n const requestToken = ++this.adRequestTokenCounter;\n this.activeAdRequestToken = requestToken;\n this.startAdRequestWatchdog(requestToken);\n try {\n await this.enforceGlobalRateLimit();\n this.lastAdRequestTime = Date.now();\n await this.ima.requestAds(vastTagUrl);\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ima\", vastUrl: vastTagUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n ).catch(() => {\n });\n this.clearAdRequestWatchdog();\n if (this.activeAdRequestToken !== requestToken) {\n return;\n }\n try {\n this.startAdFailsafeTimer(requestToken);\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n this.consecutiveFailures = 0;\n this.temporaryFailureUrls.delete(vastTagUrl);\n } catch (playError) {\n if (this.config.debugAdTiming) {\n console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n }\n const preloadedFallback = this.getPreloadedAd();\n if (preloadedFallback) {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n }\n try {\n this.clearAdFailsafeTimer();\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedFallback.imaController;\n this.attachImaEventListeners();\n this.ima.resume();\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n await this.ima.play();\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n return;\n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n if (this.isTemporaryAdError(playError)) {\n this.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n }\n } else {\n this.failedVastUrls.add(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n }\n }\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n throw playError;\n }\n } catch (error) {\n const errorMessage = error?.message || \"\";\n if (this.config.debugAdTiming) {\n console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n }\n const preloadedFallback = this.getPreloadedAd();\n if (preloadedFallback) {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n }\n try {\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedFallback.imaController;\n this.attachImaEventListeners();\n this.ima.resume();\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n await this.ima.play();\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n return;\n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n if (this.isTemporaryAdError(error)) {\n this.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n }\n } else {\n this.failedVastUrls.add(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n }\n }\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n throw error;\n }\n }\n handleAdPodComplete() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] \\u{1F3C1} Ad pod complete - cleaning up\");\n }\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.stopContinuousFetching();\n this.stopPreloadPool();\n this.clearPendingAdBreak();\n if (this.isShowingPlaceholder) {\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n this.adRequestQueue = [];\n this.inAdBreak = false;\n this.adDetectSentForCurrentBreak = false;\n this.activeScte35BreakKey = void 0;\n this.scheduledScte35BreakKey = void 0;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.consecutiveFailures = 0;\n this.globalConsecutiveNoFills = 0;\n this.ima.stop().catch(() => {\n });\n const restoredMuted = this.ima.getOriginalMutedState();\n const restoredVolume = this.ima.getOriginalVolume();\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.video.paused) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n }\n this.video.play()?.catch(() => {\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n }\n handleAdFailure() {\n this.consecutiveFailures++;\n this.recordGamNoFill();\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.consecutiveFailures}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Max consecutive failures reached (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n if (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Ad failed and no time remaining. Failed URLs:\", this.failedVastUrls.size);\n }\n this.handleAdPodComplete();\n }\n }\n startAdRequestWatchdog(token) {\n this.clearAdRequestWatchdog();\n const timeoutMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n this.adRequestWatchdogToken = token;\n this.adRequestWatchdogId = window.setTimeout(() => {\n if (this.adRequestWatchdogToken !== token) {\n return;\n }\n this.adRequestWatchdogId = void 0;\n this.adRequestWatchdogToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n this.handleAdFailure();\n }, timeoutMs);\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n clearAdRequestWatchdog() {\n if (this.adRequestWatchdogId != null) {\n clearTimeout(this.adRequestWatchdogId);\n this.adRequestWatchdogId = void 0;\n }\n if (this.adRequestWatchdogToken != null) {\n this.logAdState(\"ad_request_watchdog_cleared\", {\n token: this.adRequestWatchdogToken\n });\n this.adRequestWatchdogToken = null;\n }\n }\n startAdFailsafeTimer(token) {\n this.clearAdFailsafeTimer();\n const failsafeMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n this.adFailsafeToken = token;\n this.adFailsafeTimerId = window.setTimeout(() => {\n if (this.adFailsafeToken !== token) {\n return;\n }\n this.adFailsafeTimerId = void 0;\n this.adFailsafeToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n this.logAdState(\"ad_failsafe_triggered\", {\n token,\n failsafeMs,\n videoPaused: this.video.paused,\n imaAdPlaying: this.ima.isAdPlaying()\n });\n this.handleAdFailure();\n }, failsafeMs);\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n clearAdFailsafeTimer() {\n if (this.adFailsafeTimerId != null) {\n clearTimeout(this.adFailsafeTimerId);\n this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n this.adFailsafeTimerId = void 0;\n }\n this.adFailsafeToken = null;\n }\n selectVastTagsForBreak(b) {\n if (!b || !b.vastTagUrl) return void 0;\n if (b.vastTagUrl.includes(\",\")) {\n return b.vastTagUrl.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n }\n return [b.vastTagUrl];\n }\n logAdState(event, extra = {}) {\n if (!this.config.debugAdTiming) {\n return;\n }\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n showAds: this.showAds,\n adPlaying: this.ima.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n getRemainingAdMs() {\n if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)\n return 0;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n findBreakForTime(nowMs) {\n const schedule = this.vmapBreaks;\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 const end = breakStartMs + (b.durationMs || 0);\n if (nowMs >= breakStartMs && (b.durationMs ? nowMs < end : nowMs <= breakStartMs + tol)) {\n return b;\n }\n }\n return void 0;\n }\n toggleMute() {\n if (this.ima.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n this.ima.updateOriginalMutedState(newMutedState, this.video.volume);\n this.ima.setAdVolume(newMutedState ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n toggleFullscreen() {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document.exitFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n isMuted() {\n if (this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n setMuted(muted) {\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n this.video.muted = muted;\n if (adPlaying) {\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n this.ima.setAdVolume(muted ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted\n });\n }\n return;\n }\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n setVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying) {\n this.ima.setAdVolume(clampedVolume);\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n getVolume() {\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying) {\n return this.ima.getAdVolume();\n }\n return this.video.volume;\n }\n isFullscreen() {\n return !!document.fullscreenElement;\n }\n isLive() {\n return this.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n resize() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n if (this.ima && this.ima.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 480;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n this.ima.resize(width, height);\n }\n }\n destroy() {\n this.stopContinuousFetching();\n this.stopPreloadPool();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.clearPendingAdBreak();\n if (this.placeholderContainer) {\n if (this.placeholderContainer.parentElement) {\n this.placeholderContainer.parentElement.removeChild(this.placeholderContainer);\n }\n this.placeholderContainer = void 0;\n }\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = void 0;\n }\n this.hls?.destroy();\n this.ima?.destroy();\n this.adRequestQueue = [];\n this.consecutiveFailures = 0;\n }\n};\n\n// src/players/HlsPlayer.tsx\nvar HlsPlayer = class extends import_react2.Component {\n constructor() {\n super(...arguments);\n this.player = null;\n this.mounted = false;\n this.load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n const config = {\n src: this.props.src,\n videoElement: this.props.videoElement\n };\n if (this.props.autoplay !== void 0)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== void 0)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== void 0)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== void 0)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== void 0)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== void 0)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== void 0)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== void 0)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== void 0)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== void 0)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== void 0)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== void 0)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== void 0)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n this.player = new StormcloudVideoPlayer(config);\n this.props.onMount?.(this);\n await this.player.load();\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return this.player.hls;\n return null;\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nHlsPlayer.displayName = \"HlsPlayer\";\nHlsPlayer.canPlay = canPlay.hls;\n\n// src/players/FilePlayer.tsx\nvar import_react3 = require(\"react\");\nvar FilePlayer = class extends import_react3.Component {\n constructor() {\n super(...arguments);\n this.mounted = false;\n this.ready = false;\n this.load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n const video = this.props.videoElement;\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n const handleError = (error) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\n };\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.src = this.props.src;\n if (this.props.autoplay !== void 0) video.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) video.muted = this.props.muted;\n if (this.props.loop !== void 0) video.loop = this.props.loop;\n if (this.props.controls !== void 0) video.controls = this.props.controls;\n if (this.props.playsInline !== void 0)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== void 0)\n video.preload = this.props.preload;\n if (this.props.poster !== void 0) video.poster = this.props.poster;\n this.props.onMount?.(this);\n return () => {\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n };\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[FilePlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n } else {\n console.warn(\"[FilePlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.setLoop = (loop) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n this.enablePIP = async () => {\n if (this.props.videoElement && \"requestPictureInPicture\" in this.props.videoElement) {\n try {\n await this.props.videoElement.requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n this.disablePIP = async () => {\n if (document.pictureInPictureElement) {\n try {\n await document.exitPictureInPicture();\n } catch (error) {\n console.warn(\"Exit Picture-in-Picture failed:\", error);\n }\n }\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nFilePlayer.displayName = \"FilePlayer\";\nFilePlayer.canPlay = canPlay.file;\n\n// src/players/index.ts\nvar players = [\n {\n key: \"hls\",\n name: \"HLS Player\",\n canPlay: canPlay.hls,\n lazyPlayer: lazy(() => Promise.resolve({ default: HlsPlayer }))\n },\n {\n key: \"file\",\n name: \"File Player\",\n canPlay: canPlay.file,\n canEnablePIP: (url) => {\n return canPlay.file(url) && (document.pictureInPictureEnabled || typeof document.webkitSupportsPresentationMode === \"function\");\n },\n lazyPlayer: lazy(() => Promise.resolve({ default: FilePlayer }))\n }\n];\nvar players_default = players;\n","import { lazy } from \"../utils\";\nimport { canPlay } from \"../patterns\";\nimport HlsPlayer from \"./HlsPlayer\";\nimport FilePlayer from \"./FilePlayer\";\n\nexport interface PlayerConfig {\n key: string;\n name: string;\n canPlay: (url: string) => boolean;\n canEnablePIP?: (url: string) => boolean;\n lazyPlayer?: any;\n}\n\nconst players: PlayerConfig[] = [\n {\n key: \"hls\",\n name: \"HLS Player\",\n canPlay: canPlay.hls,\n lazyPlayer: lazy(() => Promise.resolve({ default: HlsPlayer })),\n },\n {\n key: \"file\",\n name: \"File Player\",\n canPlay: canPlay.file,\n canEnablePIP: (url: string) => {\n return (\n canPlay.file(url) &&\n (document.pictureInPictureEnabled ||\n typeof (document as any).webkitSupportsPresentationMode ===\n \"function\")\n );\n },\n lazyPlayer: lazy(() => Promise.resolve({ default: FilePlayer })),\n },\n];\n\nexport default players;\n","import { lazy as reactLazy } from \"react\";\n\nexport const lazy = reactLazy;\n\nexport const omit = <T extends Record<string, any>, K extends keyof T>(\n object: T,\n keys: K[]\n): Omit<T, K> => {\n const result = { ...object };\n keys.forEach((key) => {\n delete result[key];\n });\n return result;\n};\n\nexport const isMediaStream = (url: any): url is MediaStream => {\n return (\n typeof window !== \"undefined\" &&\n window.MediaStream &&\n url instanceof window.MediaStream\n );\n};\n\nexport const supportsWebKitPresentationMode = (): boolean => {\n if (typeof window === \"undefined\") return false;\n const video = document.createElement(\"video\");\n return \"webkitSupportsPresentationMode\" in video;\n};\n\nexport const randomString = (): string => {\n return Math.random().toString(36).substr(2, 9);\n};\n\nexport const parseQuery = (url: string): Record<string, string> => {\n const query: Record<string, string> = {};\n const queryString = url.split(\"?\")[1] || \"\";\n\n if (!queryString) return query;\n\n const manualParse = (qs: string) => {\n qs.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n try {\n query[decodeURIComponent(key)] = value\n ? decodeURIComponent(value.replace(/\\+/g, \" \"))\n : \"\";\n } catch (e) {\n query[key] = value || \"\";\n }\n }\n });\n };\n\n if (typeof URLSearchParams !== \"undefined\") {\n try {\n const params = new URLSearchParams(queryString);\n params.forEach((value, key) => {\n query[key] = value;\n });\n return query;\n } catch (e) {\n manualParse(queryString);\n }\n } else {\n manualParse(queryString);\n }\n\n return query;\n};\n\nexport const merge = <T extends Record<string, any>>(\n target: T,\n ...sources: Partial<T>[]\n): T => {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n merge(target[key] as any, source[key] as any);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return merge(target, ...sources);\n};\n\nconst isObject = (item: any): item is Record<string, any> => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\n\nexport const IS_BROWSER = typeof window !== \"undefined\" && window.document;\nexport const IS_GLOBAL =\n typeof globalThis !== \"undefined\" &&\n globalThis.window &&\n globalThis.window.document;\nexport const IS_IOS =\n IS_BROWSER && /iPad|iPhone|iPod/.test(navigator.userAgent);\nexport const IS_SAFARI =\n IS_BROWSER && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n\nexport const SUPPORTS_HLS = (): boolean => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/vnd.apple.mpegurl\"));\n};\n\nexport const SUPPORTS_DASH = (): boolean => {\n if (!IS_BROWSER) return false;\n const video = document.createElement(\"video\");\n return Boolean(video.canPlayType(\"application/dash+xml\"));\n};\n","export const HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nexport const HLS_PATHS = /\\/hls\\//i;\nexport const DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nexport const VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nexport const AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\n\nexport const canPlay = {\n hls: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n\n dash: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n\n video: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n\n audio: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n\n file: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n },\n};\n","import { Component } from \"react\";\nimport { StormcloudVideoPlayer } from \"../player/StormcloudVideoPlayer\";\nimport type { StormcloudVideoPlayerConfig } from \"../types\";\nimport { canPlay } from \"../patterns\";\n\nexport interface HlsPlayerProps extends StormcloudVideoPlayerConfig {\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n}\n\nexport default class HlsPlayer extends Component<HlsPlayerProps> {\n static displayName = \"HlsPlayer\";\n\n static canPlay = canPlay.hls;\n\n private player: StormcloudVideoPlayer | null = null;\n private mounted = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n\n componentDidUpdate(prevProps: HlsPlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n\n const config: StormcloudVideoPlayerConfig = {\n src: this.props.src,\n videoElement: this.props.videoElement,\n };\n\n if (this.props.autoplay !== undefined)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== undefined)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== undefined)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== undefined)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== undefined)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== undefined)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== undefined)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== undefined)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== undefined)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== undefined)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== undefined)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== undefined)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== undefined)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n\n this.player = new StormcloudVideoPlayer(config);\n\n this.props.onMount?.(this);\n\n await this.player.load();\n\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n\n play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource =\n video.src ||\n (video.currentSrc && video.currentSrc !== \"\") ||\n video.readyState >= 1;\n\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return (this.player as any).hls;\n return null;\n };\n\n render() {\n return null;\n }\n}\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n ImaController,\n AdBreak,\n StormcloudApiResponse,\n} from \"../types\";\nimport { createImaController } from \"../sdk/ima\";\nimport { createHlsAdPlayer } from \"../sdk/hlsAdPlayer\";\nimport {\n sendInitialTracking,\n sendHeartbeat,\n sendAdDetectTracking,\n sendAdLoadedTracking,\n sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport {\n supportsGoogleIMA,\n logBrowserInfo,\n getBrowserConfigOverrides,\n} from \"../utils/browserCompat\";\n\ntype Scte35CueSource = \"manifest\" | \"id3\" | \"ts\";\ntype Scte35CueReadiness = \"early\" | \"playback\";\n\ninterface NormalizedScte35Cue {\n marker: Scte35Marker;\n source: Scte35CueSource;\n readiness: Scte35CueReadiness;\n key: string;\n fragmentSn?: number;\n fragmentStartSeconds?: number;\n}\n\ninterface Scte35CueContext {\n source: Scte35CueSource;\n readiness: Scte35CueReadiness;\n fragmentSn?: number;\n fragmentStartSeconds?: number;\n}\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private ima: ImaController;\n private attached = false;\n private inAdBreak = false;\n private currentAdBreakStartWallClockMs: number | undefined;\n private expectedAdBreakDurationMs: number | undefined;\n private adStopTimerId: number | undefined;\n private adStartTimerId: number | undefined;\n private adFailsafeTimerId: number | undefined;\n private ptsDriftEmaMs = 0;\n private adPodQueue: string[] = [];\n private apiVastTagUrl: string | undefined;\n private apiNumberAds: number | undefined;\n private vmapBreaks: AdBreak[] = [];\n private consumedVmapBreakIds: Set<string> = new Set();\n private lastHeartbeatTime: number = 0;\n private heartbeatInterval: number | undefined;\n private currentAdIndex: number = 0;\n private totalAdsInBreak: number = 0;\n private showAds: boolean = false;\n private isLiveStream: boolean = false;\n private nativeHlsMode: boolean = false;\n private videoSrcProtection: string | null = null;\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n private adRequestTokenCounter = 0;\n private activeAdRequestToken: number | null = null;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n private failedVastUrls: Set<string> = new Set();\n private temporaryFailureUrls: Map<string, number> = new Map();\n private readonly temporaryFailureCooldownMs: number = 30000;\n private continuousFetchingActive: boolean = false;\n private adRequestQueue: string[] = [];\n private maxPlaceholderDurationMs: number = 5000;\n private isShowingPlaceholder: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n private readonly tsScte35Pids: Set<number> = new Set();\n private readonly pmtPids: Set<number> = new Set();\n private readonly processedTsScte35Sections: Set<string> = new Set();\n private readonly pendingScte35Cues: Map<string, NormalizedScte35Cue> =\n new Map();\n private readonly recentScte35CueKeys: Map<string, number> = new Map();\n private readonly recentScte35CueLimit: number = 200;\n private pendingScte35CueKey: string | undefined;\n private activeScte35BreakKey: string | undefined;\n private scheduledScte35BreakKey: string | undefined;\n \n private totalAdRequestsInBreak: number = 0;\n private readonly maxTotalAdRequestsPerBreak: number = 10;\n \n private pendingAdBreak: {\n marker: Scte35Marker;\n detectedAtFragmentSn?: number;\n vastUrls: string[];\n isFetching: boolean;\n fetchStartTime?: number;\n } | null = null;\n private prefetchTimerId: number | undefined;\n \n private consecutiveFailures: number = 0;\n private readonly maxConsecutiveFailures: number = 5;\n private lastAdRequestTime: number = 0;\n private readonly minAdRequestIntervalMs: number = 3000;\n private readonly backoffBaseMs: number = 1000;\n private readonly maxBackoffMs: number = 15000;\n private placeholderContainer: HTMLDivElement | undefined;\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 preloadPool: Array<{\n vastUrl: string;\n imaController: ImaController;\n loadedAt: number;\n isReady: boolean;\n loadPromise: Promise<void>;\n }> = [];\n private readonly maxPreloadPoolSize: number = 2;\n private preloadPoolActive: boolean = false;\n private preloadPoolLoopRunning: boolean = false;\n private adDetectSentForCurrentBreak: boolean = false;\n\n constructor(config: StormcloudVideoPlayerConfig) {\n initializePolyfills();\n\n const browserOverrides = getBrowserConfigOverrides();\n \n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n\n logBrowserInfo(config.debugAdTiming);\n\n this.ima = this.createAdPlayer(false);\n }\n\n private createAdPlayer(continueLiveStreamDuringAds: boolean): ImaController {\n const vastMode = this.config.vastMode || \"default\";\n let adPlayerType =\n this.config.adPlayerType || (vastMode === \"adstorm\" ? \"hls\" : \"ima\");\n\n if (adPlayerType === \"ima\" && !supportsGoogleIMA()) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player\"\n );\n }\n adPlayerType = \"hls\";\n }\n\n if (adPlayerType === \"hls\") {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)\"\n );\n }\n return createHlsAdPlayer(this.video, {\n continueLiveStreamDuringAds,\n ...(this.config.licenseKey\n ? { licenseKey: this.config.licenseKey }\n : {}),\n ...(this.hls ? { mainHlsInstance: this.hls } : {}),\n });\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Creating Google IMA ad player (IMA mode)\"\n );\n }\n return createImaController(this.video, {\n continueLiveStreamDuringAds,\n });\n }\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\n }\n\n try {\n await this.fetchAdConfiguration();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n error\n );\n }\n }\n\n this.initializeTracking();\n\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\",\n }\n );\n }\n\n this.ima.destroy();\n this.ima = this.createAdPlayer(false);\n this.ima.initialize();\n\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n return;\n }\n\n this.hls = new Hls({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1.0,\n ...(this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}),\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1000 * 1000,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1,\n });\n\n this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n\n this.hls.on(Hls.Events.MANIFEST_PARSED, async (_, data: any) => {\n if (this.config.allowNativeHls === false) {\n this.isLiveStream = true;\n } else {\n this.isLiveStream =\n this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n }\n\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds()\n ? \"live (main video continues muted during ads)\"\n : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior,\n });\n }\n\n this.ima.destroy();\n this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n this.ima.initialize();\n\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n }\n });\n\n this.hls.on(Hls.Events.LEVEL_LOADED, (_evt, data: any) => {\n if (this.inAdBreak || this.pendingAdBreak) {\n return;\n }\n\n const details = data?.details;\n if (!details || !details.fragments || details.fragments.length === 0) {\n return;\n }\n\n const fragmentsToScan = Math.min(5, details.fragments.length);\n \n for (let i = 0; i < fragmentsToScan; i++) {\n const frag = details.fragments[i];\n const tagList: any[] | undefined = frag?.tagList;\n \n if (!Array.isArray(tagList)) continue;\n\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n \n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n }\n }\n\n if (!tag) continue;\n\n if (tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = tag.includes(\"EXT-X-DATERANGE\") \n ? this.parseAttributeList(value)\n : {};\n const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") || \n \"SCTE35-OUT\" in attrs || \n attrs[\"SCTE35-OUT\"] !== undefined;\n\n if (hasScteOut) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value, earlyDetection: true },\n } as Scte35Marker;\n\n if (this.config.debugAdTiming) {\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.onScte35Cue(marker, {\n ...this.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.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_PARSING_METADATA, (_evt, data: any) => {\n const id3Tags: Id3TagInfo[] = (data?.samples || []).map((s: any) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts,\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n\n this.hls.on(Hls.Events.FRAG_LOADED, (_evt, data: any) => {\n this.processFragmentScte35Payload(\n data?.payload,\n typeof data?.frag?.sn === \"number\" ? data.frag.sn : undefined,\n this.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 this.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.activatePendingScte35CuesForFragment(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 = this.parseCueOutCont(value);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(prog?.duration !== undefined\n ? { durationSeconds: prog.duration }\n : {}),\n ...(prog?.elapsed !== undefined\n ? { ptsSeconds: prog.elapsed }\n : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Cue(\n { type: \"end\", raw: { tag, value } },\n {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n }\n );\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { tag, value, attrs },\n } as Scte35Marker;\n this.onScte35Cue(marker, {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n });\n }\n if (hasScteIn) {\n this.onScte35Cue(\n { type: \"end\", raw: { tag, value, attrs } },\n {\n ...this.createScte35CueContext(\"manifest\", \"playback\", frag),\n }\n );\n }\n }\n }\n this.activatePendingScte35CuesForFragment(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.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private attachImaEventListeners(): void {\n this.ima.on(\"all_ads_completed\", () => {\n sendAdImpressionTracking(\n this.config.licenseKey,\n { source: \"ima\", adIndex: this.currentAdIndex, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n const remaining = this.getRemainingAdMs();\n \n this.consecutiveFailures = 0;\n \n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] IMA all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n\n if (this.inAdBreak) {\n if (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n }\n });\n this.ima.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 this.ima.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n this.resetGamNoFillCounter();\n \n if (this.inAdBreak && this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.ima.on(\"content_resume\", () => {\n sendAdImpressionTracking(\n this.config.licenseKey,\n { source: \"ima\", adIndex: this.currentAdIndex, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n }\n }\n\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n return;\n }\n\n this.consecutiveFailures = 0;\n\n const remaining = this.getRemainingAdMs();\n \n if (this.config.debugAdTiming) {\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 (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n this.handleAdPodComplete();\n }\n });\n }\n\n private recreateImaController(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Recreating ImaController for new ad\");\n }\n\n const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n if (shouldShowPlaceholder && this.ima) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController\");\n }\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n\n const preservedMutedState = this.ima.getOriginalMutedState();\n const preservedVolumeState = this.ima.getOriginalVolume();\n\n if (this.ima) {\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Error destroying old ImaController:\", error);\n }\n }\n }\n\n const continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();\n this.ima = this.createAdPlayer(continueLiveStreamDuringAds);\n \n this.ima.initialize();\n this.ima.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n this.attachImaEventListeners();\n\n if (shouldShowPlaceholder) {\n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n this.isShowingPlaceholder = true;\n }\n }\n\n private ensurePlaceholderContainer(): void {\n if (this.placeholderContainer) {\n return;\n }\n\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"5\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n if (!this.video.parentElement) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n\n this.video.parentElement.appendChild(container);\n this.placeholderContainer = container;\n }\n\n private showPlaceholderLayer(): void {\n this.ensurePlaceholderContainer();\n \n if (!this.placeholderContainer) {\n return;\n }\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n\n const wasHidden = this.placeholderContainer.style.display === \"none\" || this.placeholderContainer.style.opacity === \"0\";\n if (wasHidden) {\n this.placeholderContainer.style.transition = \"none\";\n } else {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n \n this.placeholderContainer.style.backgroundColor = \"#000\";\n this.placeholderContainer.style.display = \"flex\";\n this.placeholderContainer.offsetHeight;\n this.placeholderContainer.style.opacity = \"1\";\n this.placeholderContainer.style.pointerEvents = \"auto\";\n \n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)\");\n }\n }\n\n private hidePlaceholderLayer(): void {\n if (!this.placeholderContainer) {\n return;\n }\n\n this.placeholderContainer.style.opacity = \"0\";\n setTimeout(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.display = \"none\";\n this.placeholderContainer.style.pointerEvents = \"none\";\n this.placeholderContainer.style.backgroundColor = \"#000\";\n }\n }, 300);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n\n private attach(): void {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n\n this.ima.initialize();\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachImaEventListeners();\n\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n\n this.emptiedHandler = () => {\n if (\n this.nativeHlsMode &&\n this.videoSrcProtection &&\n !this.ima.isAdPlaying()\n ) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n\n if (streamType === \"other\") {\n return true;\n }\n\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Cue(marker, {\n source: \"id3\",\n readiness: \"playback\",\n });\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return undefined;\n\n const cueOutMatch =\n text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) ||\n text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(dur !== undefined ? { durationSeconds: dur } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(cont?.duration !== undefined\n ? { durationSeconds: cont.duration }\n : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n if (hasScteIn) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n }\n\n if (/SCTE35-OUT/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n }\n\n private decodeId3ValueToText(value: string | Uint8Array): string | undefined {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]!);\n return out;\n } catch {\n return undefined;\n }\n }\n\n private 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 fragmentStartSeconds = this.getFragmentStartSeconds(frag);\n if (fragmentStartSeconds !== undefined) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n return context;\n }\n\n private 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\n private 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.startAdPrefetch(marker, context.fragmentSn, cue.key);\n }\n return;\n }\n\n if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n key: cue.key,\n activeScte35BreakKey: this.activeScte35BreakKey,\n inAdBreak: this.inAdBreak,\n source: cue.source,\n });\n }\n return;\n }\n\n if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n if (this.config.debugAdTiming) {\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.onScte35Marker(marker, cue.key);\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 private 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.activeScte35BreakKey === cue.key ||\n this.scheduledScte35BreakKey === 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.inAdBreak) {\n return false;\n }\n\n if (\n this.isStrongScte35CueKey(this.activeScte35BreakKey) &&\n this.isStrongScte35CueKey(cue.key) &&\n this.activeScte35BreakKey !== cue.key\n ) {\n return false;\n }\n\n return true;\n }\n\n private 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 fragmentStartSeconds =\n cue.fragmentStartSeconds ?? this.getFragmentStartSeconds(frag);\n if (fragmentStartSeconds !== undefined) {\n context.fragmentStartSeconds = fragmentStartSeconds;\n }\n this.onScte35Cue(cue.marker, context);\n });\n }\n\n private onScte35Marker(marker: Scte35Marker, cueKey?: string): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n hasPendingAdBreak: !!this.pendingAdBreak,\n });\n }\n\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n if (marker.durationSeconds != null) {\n const newDurationMs = marker.durationSeconds * 1000;\n if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {\n this.expectedAdBreakDurationMs = newDurationMs;\n const elapsedMs = this.currentAdBreakStartWallClockMs != null\n ? Date.now() - this.currentAdBreakStartWallClockMs\n : 0;\n const remainingMs = Math.max(0, newDurationMs - elapsedMs);\n this.scheduleAdStopCountdown(remainingMs);\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${newDurationMs}ms, remaining: ${remainingMs}ms`\n );\n }\n }\n }\n return;\n }\n\n if (!this.adDetectSentForCurrentBreak) {\n this.adDetectSentForCurrentBreak = true;\n const detectPayload: {\n durationSeconds?: number;\n ptsSeconds?: number;\n detectedAtFragmentSn?: number;\n } = {};\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: new Date().toISOString(), ...detectPayload }).catch(() => {});\n }\n\n const hasPrefetchedAds = this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;\n\n const durationMs =\n marker.durationSeconds != null\n ? marker.durationSeconds * 1000\n : (this.pendingAdBreak?.marker.durationSeconds != null \n ? this.pendingAdBreak.marker.durationSeconds * 1000 \n : undefined);\n\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n hasPrefetchedAds,\n });\n }\n\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Starting ad immediately (manifest-based)${hasPrefetchedAds ? \" with prefetched ads\" : \"\"}`\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1000;\n const nowMs = this.video.currentTime * 1000;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1000 - estCurrentPtsMs);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1000,\n deltaMs,\n tolerance: tol,\n });\n }\n\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.expectedAdBreakDurationMs = durationMs;\n this.scheduledScte35BreakKey = cueKey;\n this.scheduleAdStartIn(deltaMs, marker, cueKey);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.startScte35AdBreak(marker, cueKey, durationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n if (\n this.expectedAdBreakDurationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n \n if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0) {\n this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.ima.isAdPlaying();\n const hasQueuedAds = this.adRequestQueue.length > 0;\n \n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null,\n });\n }\n \n if (adPlaying || (remaining > 1000 && hasQueuedAds)) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active\");\n }\n return;\n }\n \n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n \n if (adPlaying) {\n this.ima.stop().catch(() => {});\n }\n \n this.handleAdPodComplete();\n return;\n }\n }\n\n private startScte35AdBreak(\n marker: Scte35Marker,\n cueKey: string | undefined,\n durationMs: number | undefined\n ): void {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE start marker\");\n }\n }\n\n this.inAdBreak = true;\n this.activeScte35BreakKey = cueKey ?? this.pendingScte35CueKey;\n this.scheduledScte35BreakKey = undefined;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n\n this.handleAdStart(marker);\n\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n }\n\n private parseCueOutDuration(value: string): number | undefined {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match =\n value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) ||\n value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? undefined : d;\n }\n return undefined;\n }\n\n private parseCueOutCont(\n value: string\n ): { elapsed?: number; duration?: number } | undefined {\n const 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\n private parseAttributeList(value: string): Record<string, string> {\n const attrs: Record<string, string> = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(value)) !== null) {\n const key: string = (match[1] ?? \"\") as string;\n let rawVal: string = (match[3] ?? match[4] ?? \"\") as string;\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n\n private toNumber(val: unknown): number | undefined {\n if (val == null) return undefined;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? undefined : n;\n }\n\n private isManifestBasedMarker(marker: Scte35Marker): boolean {\n const raw = marker.raw as any;\n if (!raw) return false;\n\n if (raw.tag) {\n const tag = String(raw.tag);\n return (\n tag.includes(\"EXT-X-CUE-OUT\") ||\n tag.includes(\"EXT-X-CUE-IN\") ||\n tag.includes(\"EXT-X-DATERANGE\")\n );\n }\n\n if (raw.id3) return false;\n\n if (raw.splice_command_type) return false;\n\n return false;\n }\n\n private 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 private processFragmentScte35Payload(\n payloadData: unknown,\n fragmentSn?: number,\n fragmentStartSeconds?: number\n ): void {\n const payload = this.normalizeFragmentPayload(payloadData);\n if (!payload) {\n return;\n }\n\n const markers = this.parseScte35FromTsPackets(payload);\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.onScte35Cue(marker, context);\n });\n }\n\n private parseScte35FromTsPackets(data: Uint8Array): Scte35Marker[] {\n const packetInfo = this.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 this.parsePatSection(payload, payloadUnitStart);\n } else if (this.pmtPids.has(pid)) {\n this.parsePmtSection(payload, payloadUnitStart);\n } else if (this.tsScte35Pids.has(pid)) {\n this.collectScte35SectionsFromPayload(\n pid,\n payload,\n payloadUnitStart,\n sectionAssemblers,\n markers\n );\n }\n }\n\n return markers;\n }\n\n private 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\n private parsePatSection(payload: Uint8Array, payloadUnitStart: boolean): void {\n const sectionStart = this.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 = this.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 this.pmtPids.add(pid);\n }\n }\n }\n\n private parsePmtSection(payload: Uint8Array, payloadUnitStart: boolean): void {\n const sectionStart = this.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 = this.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 this.descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd))\n ) {\n this.tsScte35Pids.add(elementaryPid);\n }\n\n offset = descriptorStart + esInfoLength;\n }\n }\n\n private 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\n private collectScte35SectionsFromPayload(\n pid: number,\n payload: Uint8Array,\n payloadUnitStart: boolean,\n assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n markers: Scte35Marker[]\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 this.appendScte35Bytes(\n pid,\n payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n assemblers,\n markers\n );\n }\n assemblers.delete(pid);\n offset = 1 + pointerField;\n } else {\n this.appendScte35Bytes(pid, payload, assemblers, markers);\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 = this.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 this.addScte35SectionMarker(\n payload.subarray(offset, offset + totalLength),\n markers\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\n private appendScte35Bytes(\n pid: number,\n bytes: Uint8Array,\n assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n markers: Scte35Marker[]\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 this.addScte35SectionMarker(new Uint8Array(assembler.bytes), markers);\n }\n }\n\n private addScte35SectionMarker(\n section: Uint8Array,\n markers: Scte35Marker[]\n ): void {\n if (section[0] !== 0xfc || this.hasProcessedTsScte35Section(section)) {\n return;\n }\n\n const marker = this.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\n private hasProcessedTsScte35Section(section: Uint8Array): 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 (this.processedTsScte35Sections.has(key)) {\n return true;\n }\n\n this.processedTsScte35Sections.add(key);\n if (this.processedTsScte35Sections.size > 200) {\n const firstKey = this.processedTsScte35Sections.values().next().value;\n if (firstKey) {\n this.processedTsScte35Sections.delete(firstKey);\n }\n }\n return false;\n }\n\n private 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\n private getPsiSectionLength(data: Uint8Array, offset: number): number {\n return (((data[offset + 1] ?? 0) & 0x0f) << 8) | (data[offset + 2] ?? 0);\n }\n\n private parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\n class BitReader {\n private bytePos = 0;\n private bitPos = 0;\n constructor(private readonly buf: Uint8Array) {}\n readBits(numBits: number): number {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos]!;\n const shift = remainingInByte - toRead;\n const mask = ((1 << toRead) - 1) & 0xff;\n const bits = (currentByte >> shift) & mask;\n result = (result << toRead) | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n: number): void {\n this.readBits(n);\n }\n get bytePosition(): number {\n return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n }\n }\n\n const 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\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 = this.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\n private 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 = this.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\n private 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 = this.markerTypeFromSegmentationTypeId(segmentationTypeId);\n if (!markerType) {\n return undefined;\n }\n\n return {\n type: markerType,\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n segmentationEventId,\n };\n }\n\n private 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\n private initializeTracking(): void {\n sendInitialTracking(this.config.licenseKey)\n .then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n })\n .catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n });\n }\n\n private sendHeartbeatIfNeeded(): void {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 30000) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n private async fetchAdConfiguration(): Promise<void> {\n if (this.config.vmapUrl) {\n await this.fetchAndParseVmap(this.config.vmapUrl);\n }\n\n const vastMode = this.config.vastMode || \"default\";\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n }\n\n if (vastMode === \"adstorm\") {\n if (!this.config.licenseKey) {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n );\n }\n return;\n }\n\n const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n this.apiVastTagUrl = vastEndpoint;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n vastEndpoint\n );\n }\n return;\n }\n\n if (this.config.vastTagUrl) {\n this.apiVastTagUrl = this.config.vastTagUrl;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n this.apiVastTagUrl\n );\n }\n return;\n }\n\n const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n apiUrl\n );\n }\n\n const headers: Record<string, string> = {};\n if (this.config.licenseKey) {\n headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n }\n\n const response = await fetch(apiUrl, { headers });\n if (!response.ok) {\n if (this.config.debugAdTiming) {\n console.warn(\n `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n );\n }\n return;\n }\n\n const data: StormcloudApiResponse = await response.json();\n\n const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n if (imaPayload) {\n this.apiVastTagUrl = decodeURIComponent(imaPayload);\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:\",\n this.apiVastTagUrl\n );\n }\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n );\n }\n }\n\n const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n if (numberAds != null && numberAds > 0) {\n this.apiNumberAds = numberAds;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n this.apiNumberAds\n );\n }\n }\n }\n\n 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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n }\n return [];\n }\n\n const adBreakNodes = Array.from(\n doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\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 const adTagNode = node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\");\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 // Post-roll: resolved using current media duration at runtime.\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 private getAdBreakKey(adBreak: AdBreak): string {\n if (adBreak.id) {\n return adBreak.id;\n }\n return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n }\n\n private resolveBreakStartMs(adBreak: AdBreak): number | undefined {\n if (adBreak.startTimeMs >= 0) {\n return adBreak.startTimeMs;\n }\n\n // startTimeMs=-1 represents VMAP \"end\" and becomes post-roll.\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 getCurrentAdIndex(): number {\n return this.currentAdIndex;\n }\n\n getTotalAdsInBreak(): number {\n return this.totalAdsInBreak;\n }\n\n getAdRemainingMs(): number {\n return this.getRemainingAdMs();\n }\n\n private generateVastUrlsWithCorrelators(\n baseUrl: string,\n count: number\n ): string[] {\n const urls: string[] = [];\n const baseTimestamp = Date.now();\n \n for (let i = 0; i < count; i++) {\n const timestamp = baseTimestamp + i;\n const random = Math.floor(Math.random() * 1000000000000);\n const uniqueCorrelator = `${timestamp}_${random}_${i}`;\n \n let urlWithCorrelator: string;\n \n const correlatorRegex = /([?&])correlator=([^&]*)/;\n if (correlatorRegex.test(baseUrl)) {\n urlWithCorrelator = baseUrl.replace(correlatorRegex, `$1correlator=${uniqueCorrelator}`);\n } else if (baseUrl.includes(\"?\")) {\n urlWithCorrelator = `${baseUrl}&correlator=${uniqueCorrelator}`;\n } else {\n urlWithCorrelator = `${baseUrl}?correlator=${uniqueCorrelator}`;\n }\n \n urls.push(urlWithCorrelator);\n }\n \n return urls;\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.ima.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.showAds;\n }\n\n getStreamType(): \"hls\" | \"other\" {\n const url = this.config.src.toLowerCase();\n if (\n url.includes(\".m3u8\") ||\n url.includes(\"/hls/\") ||\n url.includes(\"application/vnd.apple.mpegurl\")\n ) {\n return \"hls\";\n }\n return \"other\";\n }\n\n shouldShowNativeControls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(\n this.config.allowNativeHls && !(this.config.showCustomControls ?? false)\n );\n }\n\n private shouldContinueLiveStreamDuringAds(): boolean {\n if (this.config.allowNativeHls) {\n return false;\n }\n\n if (!this.isLiveStream) {\n return false;\n }\n\n return true;\n }\n\n private startAdPrefetch(\n marker: Scte35Marker,\n fragmentSn?: number,\n cueKey?: string\n ): void {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n\n const scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1000);\n const tags = this.selectVastTagsForBreak(scheduled);\n\n let baseVastUrl: string;\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.apiVastTagUrl) {\n baseVastUrl = this.apiVastTagUrl;\n } else {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] No VAST URL available for prefetch\");\n }\n return;\n }\n\n const urlsToPregenerate = 5;\n const generatedUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, urlsToPregenerate);\n\n this.pendingAdBreak = {\n marker,\n ...(fragmentSn !== undefined ? { detectedAtFragmentSn: fragmentSn } : {}),\n vastUrls: generatedUrls,\n isFetching: false,\n fetchStartTime: Date.now(),\n };\n this.pendingScte35CueKey = cueKey;\n\n this.adDetectSentForCurrentBreak = true;\n const detectPayload: {\n durationSeconds?: number;\n ptsSeconds?: number;\n detectedAtFragmentSn?: number;\n } = {};\n if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;\n if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;\n if (fragmentSn !== undefined) detectPayload.detectedAtFragmentSn = fragmentSn;\n sendAdDetectTracking(this.config.licenseKey, { source: \"scte35\", timestamp: new Date().toISOString(), ...detectPayload }).catch(() => {});\n\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] 🔄 Starting ad prefetch for upcoming ad break\");\n console.log(`[PREFETCH] 📋 Pre-generated ${generatedUrls.length} VAST URLs`);\n }\n\n this.startPreloadPool(baseVastUrl, generatedUrls.slice(0, this.maxPreloadPoolSize));\n }\n\n private clearPendingAdBreak(): void {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = undefined;\n }\n this.pendingAdBreak = null;\n this.pendingScte35CueKey = undefined;\n }\n\n private startPreloadPool(baseVastUrl: string, initialUrls: string[]): void {\n if (this.preloadPoolActive) {\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n }\n return;\n }\n\n this.preloadPoolActive = true;\n \n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] 🏊 Starting preload pool EARLY (target size: ${this.maxPreloadPoolSize})`);\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.preloadPool.length < this.maxPreloadPoolSize) {\n this.preloadAdIntoPool(url);\n }\n }\n\n this.preloadPoolLoop(baseVastUrl);\n }\n\n private async preloadAdIntoPool(vastUrl: string): Promise<void> {\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n }\n return;\n }\n\n if (\n this.preloadPool.some(entry => entry.vastUrl === vastUrl) ||\n this.failedVastUrls.has(vastUrl) ||\n this.isUrlInCooldown(vastUrl)\n ) {\n return;\n }\n\n if (this.preloadPool.length >= this.maxPreloadPoolSize) {\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] 📥 Preloading ad into pool: ${vastUrl}`);\n }\n\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.shouldContinueLiveStreamDuringAds();\n const preloadIma = this.createAdPlayer(continueLiveStreamDuringAds);\n preloadIma.initialize();\n \n const errorListener = (payload?: any) => {\n hasAdError = true;\n adErrorPayload = payload;\n };\n preloadIma.on(\"ad_error\", errorListener);\n errorListenerCleanup = () => preloadIma.off(\"ad_error\", errorListener);\n\n await this.enforceGlobalRateLimit();\n await preloadIma.requestAds(vastUrl);\n \n preloadIma.pause();\n \n await new Promise(resolve => setTimeout(resolve, 1500));\n \n preloadIma.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 preloadIma.destroy();\n \n this.recordGamNoFill();\n\n if (isNoFill) {\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] ⚠️ Ad preload returned no-fill: ${vastUrl}`);\n }\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n } else {\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] ⚠️ Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n }\n if (adErrorPayload && !this.isTemporaryAdError(adErrorPayload as Error)) {\n this.failedVastUrls.add(vastUrl);\n } else {\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n return;\n }\n \n const poolEntry = {\n vastUrl,\n imaController: preloadIma,\n loadedAt: Date.now(),\n isReady: true,\n loadPromise: Promise.resolve(),\n };\n \n const lateErrorListener = (payload?: any) => {\n const index = this.preloadPool.findIndex(entry => entry.vastUrl === vastUrl);\n if (index >= 0) {\n this.preloadPool.splice(index, 1);\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] ⚠️ Late error detected, removed from pool: ${vastUrl}`, payload);\n }\n try {\n preloadIma.destroy();\n } catch {}\n }\n };\n preloadIma.on(\"ad_error\", lateErrorListener);\n \n this.preloadPool.push(poolEntry);\n \n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] ✅ Ad preloaded (no errors detected within timeout) (pool size: ${this.preloadPool.length}/${this.maxPreloadPoolSize})`);\n }\n \n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n } catch (error) {\n if (errorListenerCleanup) {\n errorListenerCleanup();\n }\n \n this.recordGamNoFill();\n\n if (this.config.debugAdTiming) {\n console.warn(`[PRELOAD-POOL] ⚠️ Failed to preload ad: ${vastUrl}`, error);\n }\n \n if (error instanceof Error && !this.isTemporaryAdError(error)) {\n this.failedVastUrls.add(vastUrl);\n } else if (error instanceof Error && this.isTemporaryAdError(error)) {\n this.temporaryFailureUrls.set(vastUrl, Date.now());\n }\n }\n })();\n\n loadPromise.catch(() => {});\n }\n\n private async preloadPoolLoop(baseVastUrl: string): Promise<void> {\n if (this.preloadPoolLoopRunning) {\n return;\n }\n\n this.preloadPoolLoopRunning = true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] 🔄 Starting continuous preload loop\");\n }\n\n while (this.preloadPoolActive) {\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n }\n break;\n }\n\n if (!this.inAdBreak && this.preloadPool.length >= this.maxPreloadPoolSize) {\n await new Promise(resolve => setTimeout(resolve, 2000));\n continue;\n }\n\n if (!this.inAdBreak && this.pendingAdBreak === null) {\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n }\n break;\n }\n\n while (this.preloadPool.length < this.maxPreloadPoolSize) {\n if (!this.preloadPoolActive || this.isGamInCooldown()) {\n break;\n }\n\n if (this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 0) {\n break;\n }\n }\n\n const newUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n const newUrl = newUrls[0];\n \n if (newUrl && !this.failedVastUrls.has(newUrl) && !this.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.preloadPoolLoopRunning = false;\n\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] 🛑 Preload loop ended\");\n }\n }\n\n private getPreloadedAd(): { vastUrl: string; imaController: ImaController } | null {\n if (this.preloadPool.length === 0) {\n return null;\n }\n\n const entry = this.preloadPool.shift();\n if (!entry || !entry.isReady) {\n return null;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[PRELOAD-POOL] 🎯 Using preloaded ad from pool (${this.preloadPool.length} remaining)`);\n }\n\n return {\n vastUrl: entry.vastUrl,\n imaController: entry.imaController,\n };\n }\n\n private stopPreloadPool(): void {\n this.preloadPoolActive = false;\n this.preloadPoolLoopRunning = false;\n\n for (const entry of this.preloadPool) {\n try {\n entry.imaController.destroy();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n }\n }\n }\n\n this.preloadPool = [];\n\n if (this.config.debugAdTiming) {\n console.log(\"[PRELOAD-POOL] 🛑 Preload pool stopped and cleaned up\");\n }\n }\n\n private async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const scheduled = this.findCurrentOrNextBreak(\n this.video.currentTime * 1000\n );\n if (scheduled) {\n this.consumedVmapBreakIds.add(this.getAdBreakKey(scheduled));\n }\n const tags = this.selectVastTagsForBreak(scheduled);\n\n let baseVastUrl: string;\n\n if (tags && tags.length > 0 && tags[0]) {\n baseVastUrl = tags[0];\n } else if (this.apiVastTagUrl) {\n baseVastUrl = this.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.config.debugAdTiming) {\n const mode = this.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] 📺 ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n\n this.failedVastUrls.clear();\n this.temporaryFailureUrls.clear();\n this.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video in handleAdStart\");\n }\n }\n\n this.inAdBreak = true;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n \n this.showAds = true;\n \n this.showPlaceholderLayer();\n this.ima.showPlaceholder();\n\n if (\n this.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n\n let firstAdUrl: string | undefined;\n let usePreloadedAd = false;\n let preloadedController: ImaController | undefined;\n \n const preloaded = this.getPreloadedAd();\n if (preloaded) {\n firstAdUrl = preloaded.vastUrl;\n preloadedController = preloaded.imaController;\n usePreloadedAd = true;\n \n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ima\", vastUrl: firstAdUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🚀 Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n console.log(`[CONTINUOUS-FETCH] Pool still has ${this.preloadPool.length} preloaded ads ready`);\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.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🚀 Generating new ad URLs...\");\n }\n \n const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n firstAdUrl = firstAdUrlArray[0];\n this.adRequestQueue = [];\n }\n \n if (!firstAdUrl) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ Failed to get first ad URL\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 📋 First VAST URL:\", firstAdUrl);\n }\n\n try {\n if (usePreloadedAd && preloadedController) {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedController;\n \n this.attachImaEventListeners();\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n }\n \n this.ima.resume();\n \n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n \n if (!this.preloadPoolActive) {\n this.preloadPoolActive = true;\n this.preloadPoolLoop(baseVastUrl);\n }\n \n await this.ima.play();\n\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n } else {\n await this.enforceGlobalRateLimit();\n this.lastAdRequestTime = Date.now();\n await this.ima.requestAds(firstAdUrl);\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ima\", vastUrl: firstAdUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ First ad request successful, starting playback\");\n }\n\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n \n if (!this.preloadPoolActive) {\n this.startPreloadPool(baseVastUrl, []);\n }\n \n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ First ad request failed:\", error);\n }\n \n if (!usePreloadedAd) {\n const fallbackPreloaded = this.getPreloadedAd();\n if (fallbackPreloaded) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🔄 First ad failed, using preloaded fallback\");\n }\n \n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = fallbackPreloaded.imaController;\n this.attachImaEventListeners();\n \n this.ima.resume();\n \n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.startContinuousFetching(baseVastUrl);\n \n if (!this.preloadPoolActive) {\n this.preloadPoolActive = true;\n this.preloadPoolLoop(baseVastUrl);\n }\n \n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n return; \n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n }\n \n if (this.isTemporaryAdError(error as Error)) {\n this.temporaryFailureUrls.set(firstAdUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n }\n } else {\n this.failedVastUrls.add(firstAdUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n }\n }\n this.consecutiveFailures++;\n \n this.startContinuousFetching(baseVastUrl);\n await this.tryNextAvailableAdWithRateLimit();\n }\n }\n\n private continuousFetchLoopRunning = false;\n\n private startContinuousFetching(baseVastUrl: string): void {\n if (!this.continuousFetchingActive) {\n return;\n }\n\n if (this.continuousFetchLoopRunning) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏭️ Fetch loop already running, skipping duplicate start\");\n }\n return;\n }\n\n if (this.config.debugAdTiming) {\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 while (this.continuousFetchingActive && this.inAdBreak) {\n const remaining = this.getRemainingAdMs();\n \n if (remaining <= 0) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ Ad break time expired, stopping URL generation\");\n }\n break;\n }\n\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n }\n break;\n }\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), stopping URL generation`);\n }\n break;\n }\n\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Maximum ad requests reached (${this.maxTotalAdRequestsPerBreak}), stopping`);\n }\n break;\n }\n\n const maxQueueSize = 5;\n if (this.adRequestQueue.length >= maxQueueSize) {\n if (this.config.debugAdTiming) {\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.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];\n \n if (!newAdUrl || this.failedVastUrls.has(newAdUrl) || this.isUrlInCooldown(newAdUrl)) {\n await new Promise(resolve => setTimeout(resolve, 500));\n continue;\n }\n\n if (this.config.debugAdTiming) {\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 this.totalAdsInBreak++;\n \n const generationDelay = this.consecutiveFailures > 0 \n ? Math.min(1000 * Math.pow(2, this.consecutiveFailures), 5000)\n : 500;\n await new Promise(resolve => setTimeout(resolve, generationDelay));\n }\n\n this.continuousFetchLoopRunning = false;\n\n if (this.config.debugAdTiming) {\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 private stopContinuousFetching(): void {\n this.continuousFetchingActive = false;\n this.continuousFetchLoopRunning = false;\n \n this.hidePlaceholderLayer();\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Stopping continuous ad fetching\");\n }\n }\n\n private async tryNextAvailableAdWithRateLimit(): Promise<void> {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n const backoffMultiplier = Math.pow(2, this.consecutiveFailures);\n const backoffDelay = Math.min(this.backoffBaseMs * backoffMultiplier, this.maxBackoffMs);\n const effectiveMinInterval = this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffDelay : 0);\n \n const timeSinceLastRequest = Date.now() - this.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏳ Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.consecutiveFailures} failures)`);\n }\n await new Promise(resolve => setTimeout(resolve, waitTime));\n }\n\n return this.tryNextAvailableAd(0);\n }\n\n private async tryNextAvailableAd(retryCount: number = 0): Promise<void> {\n const remaining = this.getRemainingAdMs();\n \n if (remaining <= 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n this.cleanupTemporaryFailures();\n\n const preloaded = this.getPreloadedAd();\n if (preloaded) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🎯 Using preloaded ad from pool (${this.preloadPool.length} remaining in pool)`);\n }\n \n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ima\", vastUrl: preloaded.vastUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n try {\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloaded.imaController;\n this.attachImaEventListeners();\n\n this.ima.resume();\n\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n \n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n this.consecutiveFailures = 0;\n return;\n } catch (error) {\n if (this.config.debugAdTiming) {\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) {\n continue;\n }\n \n if (this.failedVastUrls.has(nextAdUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏭️ Skipping permanently-failed URL, trying next...\");\n }\n continue;\n }\n \n if (this.isUrlInCooldown(nextAdUrl)) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏭️ Skipping URL in cooldown (recent no-fill), trying next...\");\n }\n continue;\n }\n \n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🎬 Requesting next ad via IMA SDK (${this.currentAdIndex + 1}/${this.totalAdsInBreak}, ${this.adRequestQueue.length} remaining in queue)`);\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n \n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n \n try {\n await this.playSingleAd(nextAdUrl);\n this.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = (error as Error).message;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ❌ Ad request failed:\", errorMessage);\n }\n \n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.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.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏳ Queue empty, waiting for URLs... (${retryCount + 1}/${maxRetries})`);\n }\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.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No more ads available, ending ad break\");\n }\n this.handleAdPodComplete();\n }\n }\n\n private async showPlaceholderAndWaitForAds(): Promise<void> {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n }\n this.handleAdPodComplete();\n return;\n }\n \n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Skipping placeholder - too many consecutive failures\");\n }\n this.handleAdPodComplete();\n return;\n }\n \n if (waitTime < 1000) {\n this.handleAdPodComplete();\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⬛ Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n }\n\n this.isShowingPlaceholder = true;\n \n this.ima.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) {\n return;\n }\n \n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Too many failures during placeholder wait\");\n }\n break;\n }\n\n while (this.adRequestQueue.length > 0) {\n const nextAdUrl = this.adRequestQueue.shift();\n \n if (!nextAdUrl) {\n continue;\n }\n \n if (this.failedVastUrls.has(nextAdUrl)) {\n continue;\n }\n \n if (this.isUrlInCooldown(nextAdUrl)) {\n continue;\n }\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ Ad URL available, requesting via IMA SDK\");\n }\n \n this.isShowingPlaceholder = false;\n this.ima.hidePlaceholder();\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n this.ima.updateOriginalMutedState(currentMuted, currentVolume);\n \n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n this.lastAdRequestTime = Date.now();\n \n try {\n await this.playSingleAd(nextAdUrl);\n this.consecutiveFailures = 0;\n } catch (error) {\n const errorMessage = (error as Error).message;\n if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n this.consecutiveFailures++;\n }\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏰ Placeholder timeout, ending ad break\");\n }\n \n this.isShowingPlaceholder = false;\n this.ima.hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n private findCurrentOrNextBreak(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = this.vmapBreaks;\n let candidate: AdBreak | undefined;\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 const tol = this.config.driftToleranceMs ?? 1000;\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 private onTimeUpdate(currentTimeSec: number): void {\n if (this.ima.isAdPlaying() || this.inAdBreak) return;\n const nowMs = currentTimeSec * 1000;\n const breakToPlay = this.findBreakForTime(nowMs);\n if (breakToPlay) {\n void this.handleMidAdJoin(breakToPlay, nowMs).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:\",\n error\n );\n }\n });\n }\n }\n\n private async handleMidAdJoin(\n adBreak: AdBreak,\n nowMs: number\n ): Promise<void> {\n const key = this.getAdBreakKey(adBreak);\n if (this.consumedVmapBreakIds.has(key)) {\n return;\n }\n\n const breakStartMs = this.resolveBreakStartMs(adBreak);\n if (breakStartMs == null) {\n return;\n }\n\n const durationMs = adBreak.durationMs ?? 0;\n const endMs = breakStartMs + durationMs;\n const tol = this.config.driftToleranceMs ?? 1000;\n const inWindow =\n durationMs > 0\n ? nowMs > breakStartMs && nowMs < endMs\n : nowMs + tol >= breakStartMs;\n\n if (inWindow) {\n this.consumedVmapBreakIds.add(key);\n const remainingMs =\n durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;\n const tags =\n this.selectVastTagsForBreak(adBreak) ||\n (this.apiVastTagUrl ? [this.apiVastTagUrl] : undefined);\n if (tags && tags.length > 0) {\n const first = tags[0] as string;\n const rest = tags.slice(1);\n this.adPodQueue = rest;\n \n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n\n try {\n await this.playSingleAd(first);\n this.inAdBreak = true;\n this.expectedAdBreakDurationMs = remainingMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.scheduleAdStopCountdown(remainingMs);\n } catch (error) {\n // Keep runtime stable when VMAP break has no-fill/timeouts.\n this.adPodQueue = [];\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:\",\n error\n );\n }\n }\n }\n }\n }\n\n private scheduleAdStopCountdown(remainingMs: number): void {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.ensureAdStoppedByTimer();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.ensureAdStoppedByTimer();\n }, ms) as unknown as number;\n }\n\n private clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private ensureAdStoppedByTimer(): void {\n if (!this.inAdBreak) return;\n\n this.adStopTimerId = undefined;\n\n const adPlaying = this.ima.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1000)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs =\n typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0\n ? maxExtensionMsConfig\n : 60000;\n\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n\n const shouldExtendAdBreak =\n (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n\n if (adPlaying) {\n this.ima.stop().catch(() => {});\n }\n\n this.handleAdPodComplete();\n }\n\n private scheduleAdStartIn(\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.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1000 : undefined\n );\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.startScte35AdBreak(\n marker,\n cueKey,\n marker.durationSeconds != null ? marker.durationSeconds * 1000 : this.expectedAdBreakDurationMs\n );\n }, ms) as unknown as number;\n }\n\n private clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n private updatePtsDrift(ptsSecondsSample: number): void {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1000;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 60000) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n\n private 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 \n if (message.includes(\"timeout\")) {\n return true;\n }\n \n if (message.includes(\"rate limit\") || message.includes(\"too many requests\")) {\n return true;\n }\n \n if (message.includes(\"ad playback error\")) {\n return true;\n }\n \n return false;\n }\n\n private 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 private 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 private isGamInCooldown(): boolean {\n return Date.now() < this.globalNoFillCooldownUntil;\n }\n\n private 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.config.debugAdTiming) {\n console.log(\n `[CIRCUIT-BREAKER] GAM cooldown activated: ${backoff}ms (${this.globalConsecutiveNoFills} consecutive no-fills)`\n );\n }\n }\n }\n\n private resetGamNoFillCounter(): void {\n if (this.globalConsecutiveNoFills > 0 && this.config.debugAdTiming) {\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 private 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.config.debugAdTiming) {\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 private async playSingleAd(vastTagUrl: string): Promise<void> {\n if (this.ima.isAdPlaying()) {\n return;\n }\n\n if (this.failedVastUrls.has(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n }\n throw new Error(\"VAST URL permanently failed\");\n }\n\n if (this.isUrlInCooldown(vastTagUrl)) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n }\n throw new Error(\"VAST URL in cooldown after no-fill\");\n }\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n }\n throw new Error(\"Too many consecutive failures\");\n }\n\n if (this.isGamInCooldown()) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n }\n throw new Error(\"GAM in cooldown\");\n }\n\n this.recreateImaController();\n\n const requestToken = ++this.adRequestTokenCounter;\n this.activeAdRequestToken = requestToken;\n \n this.startAdRequestWatchdog(requestToken);\n\n try {\n await this.enforceGlobalRateLimit();\n this.lastAdRequestTime = Date.now();\n await this.ima.requestAds(vastTagUrl);\n sendAdLoadedTracking(\n this.config.licenseKey,\n { source: \"ima\", vastUrl: vastTagUrl, timestamp: new Date().toISOString() }\n ).catch(() => {});\n\n this.clearAdRequestWatchdog();\n\n if (this.activeAdRequestToken !== requestToken) {\n return;\n }\n\n try {\n this.startAdFailsafeTimer(requestToken);\n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n this.consecutiveFailures = 0;\n this.temporaryFailureUrls.delete(vastTagUrl);\n } catch (playError) {\n if (this.config.debugAdTiming) {\n console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n }\n \n const preloadedFallback = this.getPreloadedAd();\n if (preloadedFallback) {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n }\n \n try {\n this.clearAdFailsafeTimer();\n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedFallback.imaController;\n this.attachImaEventListeners();\n \n this.ima.resume();\n \n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n \n await this.ima.play();\n \n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n return; \n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n \n if (this.isTemporaryAdError(playError as Error)) {\n this.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n }\n } else {\n this.failedVastUrls.add(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n }\n }\n \n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n throw playError;\n }\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"\";\n if (this.config.debugAdTiming) {\n console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n }\n \n const preloadedFallback = this.getPreloadedAd();\n if (preloadedFallback) {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n }\n \n try {\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n \n this.ima.destroy();\n this.video.muted = true;\n this.video.volume = 0;\n this.ima = preloadedFallback.imaController;\n this.attachImaEventListeners();\n \n this.ima.resume();\n \n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n \n await this.ima.play();\n \n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.ima.setAdVolume(adVolume);\n \n return;\n } catch (fallbackError) {\n if (this.config.debugAdTiming) {\n console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n }\n }\n }\n \n if (this.isTemporaryAdError(error as Error)) {\n this.temporaryFailureUrls.set(vastTagUrl, Date.now());\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n }\n } else {\n this.failedVastUrls.add(vastTagUrl);\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n }\n }\n\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n if (this.activeAdRequestToken === requestToken) {\n this.activeAdRequestToken = null;\n }\n\n throw error;\n }\n }\n\n private handleAdPodComplete(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] 🏁 Ad pod complete - cleaning up\");\n }\n\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n\n this.stopContinuousFetching();\n this.stopPreloadPool();\n this.clearPendingAdBreak();\n \n if (this.isShowingPlaceholder) {\n this.ima.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n\n this.adRequestQueue = [];\n\n this.inAdBreak = false;\n this.adDetectSentForCurrentBreak = false;\n this.activeScte35BreakKey = undefined;\n this.scheduledScte35BreakKey = undefined;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.consecutiveFailures = 0;\n this.globalConsecutiveNoFills = 0;\n\n this.ima.stop().catch(() => {});\n\n const restoredMuted = this.ima.getOriginalMutedState();\n const restoredVolume = this.ima.getOriginalVolume();\n\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.video.paused) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n }\n this.video.play()?.catch(() => {});\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n }\n\n private handleAdFailure(): void {\n this.consecutiveFailures++;\n this.recordGamNoFill();\n const remaining = this.getRemainingAdMs();\n \n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.consecutiveFailures}`,\n this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n );\n }\n \n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Max consecutive failures reached (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n \n if (remaining > 500) {\n this.tryNextAvailableAdWithRateLimit();\n } else {\n if (this.config.debugAdTiming) {\n console.log(\"[AD-ERROR] Ad failed and no time remaining. Failed URLs:\", this.failedVastUrls.size);\n }\n this.handleAdPodComplete();\n }\n }\n\n private startAdRequestWatchdog(token: number): void {\n this.clearAdRequestWatchdog();\n\n const timeoutMs = this.config.adFailsafeTimeoutMs ?? 10000;\n this.adRequestWatchdogToken = token;\n this.adRequestWatchdogId = window.setTimeout(() => {\n if (this.adRequestWatchdogToken !== token) {\n return;\n }\n\n this.adRequestWatchdogId = undefined;\n this.adRequestWatchdogToken = null;\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n\n this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n this.handleAdFailure();\n }, timeoutMs) as unknown as number;\n\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n\n private clearAdRequestWatchdog(): void {\n if (this.adRequestWatchdogId != null) {\n clearTimeout(this.adRequestWatchdogId);\n this.adRequestWatchdogId = undefined;\n }\n\n if (this.adRequestWatchdogToken != null) {\n this.logAdState(\"ad_request_watchdog_cleared\", {\n token: this.adRequestWatchdogToken,\n });\n this.adRequestWatchdogToken = null;\n }\n }\n\n private startAdFailsafeTimer(token: number): void {\n this.clearAdFailsafeTimer();\n\n const failsafeMs = this.config.adFailsafeTimeoutMs ?? 10000;\n this.adFailsafeToken = token;\n\n this.adFailsafeTimerId = window.setTimeout(() => {\n if (this.adFailsafeToken !== token) {\n return;\n }\n\n this.adFailsafeTimerId = undefined;\n this.adFailsafeToken = null;\n\n if (this.activeAdRequestToken === token) {\n this.activeAdRequestToken = null;\n }\n\n this.logAdState(\"ad_failsafe_triggered\", {\n token,\n failsafeMs,\n videoPaused: this.video.paused,\n imaAdPlaying: this.ima.isAdPlaying(),\n });\n\n this.handleAdFailure();\n }, failsafeMs) as unknown as number;\n\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n\n private clearAdFailsafeTimer(): void {\n if (this.adFailsafeTimerId != null) {\n clearTimeout(this.adFailsafeTimerId);\n this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n this.adFailsafeTimerId = undefined;\n }\n\n this.adFailsafeToken = null;\n }\n\n private selectVastTagsForBreak(b?: AdBreak): string[] | undefined {\n if (!b || !b.vastTagUrl) return undefined;\n if (b.vastTagUrl.includes(\",\")) {\n return b.vastTagUrl\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n }\n return [b.vastTagUrl];\n }\n\n private logAdState(event: string, extra: Record<string, unknown> = {}): void {\n if (!this.config.debugAdTiming) {\n return;\n }\n\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: new Date().toISOString(),\n showAds: this.showAds,\n adPlaying: this.ima.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n private getRemainingAdMs(): number {\n if (\n this.expectedAdBreakDurationMs == null ||\n this.currentAdBreakStartWallClockMs == null\n )\n return 0;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n\n private findBreakForTime(nowMs: number): AdBreak | undefined {\n const schedule: AdBreak[] = this.vmapBreaks;\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 const end = breakStartMs + (b.durationMs || 0);\n if (\n nowMs >= breakStartMs &&\n (b.durationMs ? nowMs < end : nowMs <= breakStartMs + tol)\n ) {\n return b;\n }\n }\n return undefined;\n }\n\n toggleMute(): void {\n if (this.ima.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n\n this.ima.updateOriginalMutedState(newMutedState, this.video.volume);\n this.ima.setAdVolume(newMutedState ? 0 : 1);\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n\n toggleFullscreen(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container\n .requestFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document\n .exitFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n\n isMuted(): boolean {\n if (this.ima.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n const adPlaying = this.ima.isAdPlaying();\n\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n\n this.video.muted = muted;\n\n if (adPlaying) {\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n this.ima.setAdVolume(muted ? 0 : 1);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted,\n });\n }\n return;\n }\n\n this.ima.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n\n setVolume(volume: number): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.ima.isAdPlaying();\n\n if (adPlaying) {\n this.ima.setAdVolume(clampedVolume);\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume,\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.ima.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n\n getVolume(): number {\n const adPlaying = this.ima.isAdPlaying();\n if (adPlaying) {\n return this.ima.getAdVolume();\n }\n return this.video.volume;\n }\n\n isFullscreen(): boolean {\n return !!document.fullscreenElement;\n }\n\n isLive(): boolean {\n return this.isLiveStream;\n }\n\n get videoElement(): HTMLVideoElement {\n return this.video;\n }\n\n resize(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n\n if (this.ima && this.ima.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 480;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n\n this.ima.resize(width, height);\n }\n }\n\n destroy(): void {\n this.stopContinuousFetching();\n this.stopPreloadPool();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.clearPendingAdBreak();\n \n if (this.placeholderContainer) {\n if (this.placeholderContainer.parentElement) {\n this.placeholderContainer.parentElement.removeChild(this.placeholderContainer);\n }\n this.placeholderContainer = undefined;\n }\n \n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n \n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n this.hls?.destroy();\n this.ima?.destroy();\n this.adRequestQueue = [];\n this.consecutiveFailures = 0;\n }\n}\n","interface NavigatorUAData {\n platform?: string;\n brands?: Array<{ brand: string; version: string }>;\n mobile?: boolean;\n}\n\ndeclare global {\n interface Navigator {\n userAgentData?: NavigatorUAData;\n }\n}\n\nexport interface BrowserInfo {\n name: string;\n version: string;\n majorVersion: number;\n isSmartTV: boolean;\n isLegacyTV: boolean;\n platform: string;\n supportsIMA: boolean;\n supportsModernJS: boolean;\n recommendedAdPlayer: 'ima' | 'hls';\n 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 supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer: 'ima' | 'hls' = 'ima';\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 if (webOSVersion !== undefined && webOSVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (webOSVersion !== undefined && webOSVersion >= 3) {\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/Tizen/i.test(ua)) {\n name = 'Samsung Tizen';\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n tizenVersion = majorVersion;\n }\n \n if (tizenVersion !== undefined && tizenVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (tizenVersion !== undefined && tizenVersion >= 3 && chromeVersion >= 47) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else {\n if (chromeVersion > 0) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (chromeVersion < 50) {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n\n if (typeof URLSearchParams === 'undefined') {\n supportsModernJS = false;\n }\n\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum,\n };\n}\n\nexport function supportsGoogleIMA(): boolean {\n const browser = detectBrowser();\n\n if (browser.isLegacyTV) {\n return false;\n }\n\n if (typeof document === 'undefined' ||\n typeof document.createElement !== 'function') {\n return false;\n }\n\n try {\n const video = document.createElement('video');\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n\n if (typeof Promise === 'undefined') {\n return false;\n }\n\n return browser.supportsIMA;\n}\n\nexport function getRecommendedAdPlayer(): 'ima' | 'hls' {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\n}\n\nexport function supportsModernJS(): boolean {\n try {\n return (\n typeof Promise !== 'undefined' &&\n typeof Map !== 'undefined' &&\n typeof Set !== 'undefined' &&\n typeof Array.from !== 'undefined' &&\n typeof Object.assign !== 'undefined' &&\n typeof Array.prototype.forEach !== 'undefined' &&\n typeof String.prototype.includes !== 'undefined'\n );\n } catch (e) {\n return false;\n }\n}\n\nexport function logBrowserInfo(debug: boolean = false): void {\n if (!debug) return;\n\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n\n console.log('[StormcloudVideoPlayer] Browser Compatibility Info:', {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n ...(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 getBrowserConfigOverrides(): {\n adPlayerType?: 'ima' | 'hls';\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: { adPlayerType?: 'ima' | 'hls'; allowNativeHls?: boolean } = {};\n\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = 'hls';\n }\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'ima':\n return supportsGoogleIMA();\n case 'urlsearchparams':\n return typeof URLSearchParams !== 'undefined';\n case 'textencoder':\n return typeof TextEncoder !== 'undefined';\n case 'promises':\n return typeof Promise !== 'undefined';\n case 'fetch':\n return typeof fetch !== 'undefined';\n case 'crypto':\n return typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined';\n default:\n return false;\n }\n}\n\n","import type { ImaController } from \"../types\";\nimport { supportsGoogleIMA } from \"../utils/browserCompat\";\n\ndeclare global {\n interface Window {\n google?: any;\n }\n}\n\nexport function createImaController(\n video: HTMLVideoElement,\n options?: { continueLiveStreamDuringAds?: boolean }\n): ImaController {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume =\n typeof video.volume === \"number\" && !Number.isNaN(video.volume)\n ? Math.max(0, Math.min(1, video.volume))\n : 1;\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n let adVideoElement: HTMLVideoElement | undefined;\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n\n function hideContentVideo(): void {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n\n function showContentVideo(): void {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"2\";\n adVideo.playsInline = true;\n\n adVideo.volume = originalVolume;\n adVideo.muted = originalMutedState;\n\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n\n return adVideo;\n }\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {}\n }\n }\n\n function ensureImaLoaded(): Promise<void> {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n\n try {\n const frameEl = window.frameElement as HTMLIFrameElement | null;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n // eslint-disable-next-line no-console\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {}\n\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n ) as HTMLScriptElement | null;\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 10000);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n\n let adsManager: any | undefined;\n let adsLoader: any | undefined;\n let adDisplayContainer: any | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let lastAdTagUrl: string | undefined;\n let adsLoadedPromise: Promise<void> | undefined;\n let adsLoadedResolve: (() => void) | undefined;\n let adsLoadedReject: ((error: Error) => void) | undefined;\n\n function makeAdsRequest(google: any, vastTagUrl: string) {\n const adsRequest = new google.ima.AdsRequest();\n \n const companionSizes = [\n { width: 728, height: 90 },\n { width: 300, height: 250 },\n { width: 180, height: 150 },\n { width: 120, height: 60 },\n { width: 88, height: 31 },\n { width: 300, height: 60 },\n { width: 300, height: 100 },\n { width: 320, height: 50 },\n { width: 468, height: 60 },\n { width: 300, height: 600 },\n { width: 160, height: 600 },\n ];\n\n const ciuSzsValue = companionSizes\n .map((size) => `fluid|${size.width}x${size.height}`)\n .join(\",\");\n\n const currentLocation = typeof window !== \"undefined\" ? window.location : null;\n const topLocation = typeof window !== \"undefined\" && window.top ? window.top.location : currentLocation;\n const currentUrl = currentLocation?.href || \"\";\n const topUrl = topLocation?.href || currentUrl;\n const currentDomain = currentLocation?.hostname || \"\";\n\n let modifiedVastTagUrl = vastTagUrl;\n try {\n const url = new URL(vastTagUrl);\n \n url.searchParams.set(\"ciu_szs\", ciuSzsValue);\n \n if (!url.searchParams.has(\"mpt\")) {\n url.searchParams.set(\"mpt\", \"h5_vsi\");\n }\n \n if (!url.searchParams.has(\"ctv\")) {\n url.searchParams.set(\"ctv\", \"0\");\n }\n \n if (!url.searchParams.has(\"gdpr\")) {\n url.searchParams.set(\"gdpr\", \"0\");\n }\n \n if (!url.searchParams.has(\"top\") && topUrl) {\n url.searchParams.set(\"top\", topUrl);\n }\n \n if (!url.searchParams.has(\"loc\") && currentUrl) {\n url.searchParams.set(\"loc\", currentUrl);\n }\n \n if (!url.searchParams.has(\"cdm\") && currentDomain) {\n url.searchParams.set(\"cdm\", currentDomain);\n }\n \n if (!url.searchParams.has(\"eoidce\")) {\n url.searchParams.set(\"eoidce\", \"1\");\n }\n \n if (!url.searchParams.has(\"fbidx\")) {\n url.searchParams.set(\"fbidx\", \"0\");\n }\n \n modifiedVastTagUrl = url.toString();\n } catch (e) {\n let baseUrl = vastTagUrl;\n \n const paramsToRemove = [\"ciu_szs\", \"mpt\", \"ctv\", \"gdpr\", \"top\", \"loc\", \"cdm\", \"eoidce\", \"fbidx\"];\n paramsToRemove.forEach((param) => {\n if (baseUrl.includes(`${param}=`)) {\n baseUrl = baseUrl.replace(new RegExp(`[?&]${param}=[^&]*`, \"g\"), \"\");\n }\n });\n baseUrl = baseUrl.replace(/[?&]$/, \"\");\n \n const params = new URLSearchParams();\n params.set(\"ciu_szs\", ciuSzsValue);\n params.set(\"mpt\", \"h5_vsi\");\n params.set(\"ctv\", \"0\");\n params.set(\"gdpr\", \"0\");\n if (topUrl) params.set(\"top\", topUrl);\n if (currentUrl) params.set(\"loc\", currentUrl);\n if (currentDomain) params.set(\"cdm\", currentDomain);\n params.set(\"eoidce\", \"1\");\n params.set(\"fbidx\", \"0\");\n \n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n modifiedVastTagUrl = `${baseUrl}${separator}${params.toString()}`;\n }\n \n adsRequest.adTagUrl = modifiedVastTagUrl;\n\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 480;\n\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n\n if (typeof adsRequest.setCompanionSlots === \"function\") {\n try {\n const companionSlots: any[] = [];\n\n for (const size of companionSizes) {\n const slot = new google.ima.CompanionAdSlot();\n slot.width = size.width;\n slot.height = size.height;\n companionSlots.push(slot);\n }\n\n adsRequest.setCompanionSlots(companionSlots);\n } catch (error) {\n console.warn(\"[IMA] Failed to set companion slots:\", error);\n }\n }\n\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n\n adsRequest.vastLoadTimeout = 10000;\n\n adsLoader.requestAds(adsRequest);\n }\n\n function ensurePlaceholderContainer(): void {\n if (adContainerEl) {\n return;\n }\n\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {}\n adsManager = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n\n function destroyAdsLoader() {\n if (adsLoader) {\n try {\n adsLoader.destroy();\n } catch {}\n adsLoader = undefined;\n }\n }\n\n return {\n initialize() {\n ensureImaLoaded()\n .then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {}\n }\n })\n .catch(() => {});\n },\n async requestAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n return Promise.reject(error);\n }\n\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n return Promise.reject(error);\n }\n\n if (adPlaying) {\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n\n destroyAdsManager();\n destroyAdsLoader();\n\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n\n let currentReject: ((error: Error) => void) | undefined;\n adsLoadedPromise = new Promise<void>((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n }, 10000);\n });\n\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition =\n \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n\n video.parentElement.appendChild(container);\n adContainerEl = container;\n\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n\n }\n\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n\n if (\n !videoWidth ||\n !videoHeight ||\n videoWidth === 0 ||\n videoHeight === 0\n ) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n currentReject?.(error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt: any) => {\n try {\n const adsRenderingSettings =\n new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent: any) => {\n const error = errorEvent.getError();\n const errorCode = error.getErrorCode?.() || \"unknown\";\n const vastErrorCode = error.getVastErrorCode?.() || \"N/A\";\n const errorMessage = error.getMessage?.() || \"Unknown error\";\n \n let innerError: string | undefined;\n try {\n if (typeof error.getInnerError === \"function\") {\n const inner = error.getInnerError();\n if (inner) {\n innerError = typeof inner === \"string\" ? inner : (inner.message || String(inner));\n }\n }\n if (!innerError && error.cause) {\n innerError = typeof error.cause === \"string\" ? error.cause : (error.cause.message || String(error.cause));\n }\n if (!innerError && error.innerError) {\n innerError = typeof error.innerError === \"string\" ? error.innerError : (error.innerError.message || String(error.innerError));\n }\n } catch (e) {\n }\n \n const isNoFill = errorCode === 303 || vastErrorCode === 303;\n \n\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n\n emit(\"ad_error\", { \n code: errorCode, \n vastErrorCode, \n message: errorMessage,\n cause: innerError,\n isNoFill \n });\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {});\n }\n }\n }\n );\n\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n\n adPlaying = true;\n setAdPlayingFlag(true);\n \n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adsManager) {\n try {\n adsManager.setVolume(adVolume);\n } catch {}\n }\n \n emit(\"content_pause\");\n }\n );\n\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n\n hideContentVideo();\n\n if (adVideoElement) {\n const adVolume = originalVolume;\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n \n if (adsManager) {\n try {\n adsManager.setVolume(originalMutedState ? 0 : adVolume);\n } catch {}\n }\n }\n\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n \n showContentVideo();\n \n emit(\"content_resume\");\n }\n );\n\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n emit(\"all_ads_completed\");\n });\n\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = undefined;\n adsLoadedReject = undefined;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent: any) => {\n const error = adErrorEvent.getError();\n const errorCode = error.getErrorCode?.() || \"unknown\";\n const vastErrorCode = error.getVastErrorCode?.() || \"N/A\";\n const errorMessage = error.getMessage?.() || \"Unknown error\";\n \n let innerError: string | undefined;\n try {\n if (typeof error.getInnerError === \"function\") {\n const inner = error.getInnerError();\n if (inner) {\n innerError = typeof inner === \"string\" ? inner : (inner.message || String(inner));\n }\n }\n if (!innerError && error.cause) {\n innerError = typeof error.cause === \"string\" ? error.cause : (error.cause.message || String(error.cause));\n }\n if (!innerError && error.innerError) {\n innerError = typeof error.innerError === \"string\" ? error.innerError : (error.innerError.message || String(error.innerError));\n }\n } catch (e) {\n }\n \n const isNoFill = errorCode === 303 || vastErrorCode === 303;\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(isNoFill ? \"No ads available\" : \"Ads loader error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\", { \n code: errorCode, \n vastErrorCode, \n message: errorMessage,\n isNoFill,\n cause: innerError\n });\n },\n false\n );\n }\n\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n\n currentReject?.(error as Error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 480;\n\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n\n adPlaying = true;\n\n const adVolume = originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n\n try {\n adsManager.setVolume(originalMutedState ? 0 : adVolume);\n } catch {}\n\n adsManager.start();\n\n return Promise.resolve();\n } catch (error) {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {});\n }\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adsManager || !adPlaying) {\n return;\n }\n\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n\n if (adsManager && typeof adsManager.pause === \"function\") {\n adsManager.pause();\n }\n } catch (error) {\n console.warn(\"[IMA] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adsManager || !adPlaying) {\n return;\n }\n\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {});\n }\n\n if (adsManager && typeof adsManager.resume === \"function\") {\n adsManager.resume();\n }\n } catch (error) {\n console.warn(\"[IMA] Error resuming ad:\", error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n console.log(\"[IMA] Content video paused in live mode on stop, resuming playback\");\n video.play().catch(() => {});\n }\n } else if (video.paused) {\n video.play().catch(() => {});\n }\n\n try {\n adsManager?.stop?.();\n } catch {}\n\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"none\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n adVideoElement = undefined;\n }\n }, 500);\n }\n\n showContentVideo();\n\n try {\n adsLoader?.destroy?.();\n } catch {}\n\n adDisplayContainer = undefined;\n adsLoader = undefined;\n contentVideoHidden = false;\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width: number, height: number) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume: number) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {}\n }\n },\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n \n hideContentVideo();\n \n if (adContainerEl) {\n const wasHidden = adContainerEl.style.display === \"none\" || adContainerEl.style.opacity === \"0\";\n if (wasHidden) {\n adContainerEl.style.transition = \"none\";\n } else {\n adContainerEl.style.transition = \"opacity 0.3s ease-in-out\";\n }\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (adContainerEl) {\n adContainerEl.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.backgroundColor = \"#000\";\n }\n }, 300);\n }\n },\n };\n}\n","import type { ImaController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): ImaController {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n const preloadedAds = new Map<string, VastAd>();\n const preloadingAds = new Map<string, Promise<void>>();\n let destroyed = false;\n let pendingTimeouts: number[] = [];\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n if (sessionId) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function getMainStreamQuality(): {\n width: number;\n height: number;\n bitrate: number;\n } | null {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level = mainHlsInstance.levels[autoLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n return null;\n }\n\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n\n const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n return { file, score, resolutionDiff, bitrateDiff };\n });\n\n scoredFiles.sort((a, b) => a.score - b.score);\n\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff,\n });\n\n return bestMatch.file;\n }\n\n function 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 parseVastXml(xmlString: string): VastAd | null {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const isNoAdAvailable =\n adId === \"empty\" ||\n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\n\n const durationText =\n xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n\n 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 null;\n }\n\n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string\n ): Promise<VastAd | null> {\n const response = await fetch(vastTagUrl, {\n 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\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml);\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n\n video.volume = 1.0;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\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 contentVideo.volume = 0;\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 contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n 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 = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\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 = originalMutedState ? 0 : originalVolume;\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n \n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n },\n };\n}\n","import type {\n ClientInfo,\n TrackingData,\n AdDetectInfo,\n AdLoadedInfo,\n AdImpressionInfo,\n PlayerAnalyticsContext,\n} from \"../types\";\n\nlet cachedBrowserId: string | null = null;\n\nexport function getClientInfo(): ClientInfo {\n const ua = navigator.userAgent;\n const platform = navigator.platform;\n const vendor = navigator.vendor || \"\";\n const maxTouchPoints = navigator.maxTouchPoints || 0;\n const memory = (navigator as any).deviceMemory || null;\n const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n\n const screenInfo = {\n width: screen?.width,\n height: screen?.height,\n availWidth: screen?.availWidth,\n availHeight: screen?.availHeight,\n orientation: (screen?.orientation as any)?.type || \"\",\n pixelDepth: screen?.pixelDepth,\n };\n\n let deviceType: \"tv\" | \"mobile\" | \"tablet\" | \"desktop\" = \"desktop\";\n let brand = \"Unknown\";\n let os = \"Unknown\";\n let model = \"\";\n let isSmartTV = false;\n let isAndroid = false;\n let isWebView = false;\n let isWebApp = false;\n\n if (ua.includes(\"Web0S\")) {\n brand = \"LG\";\n os = \"webOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n } else if (ua.includes(\"Tizen\")) {\n brand = \"Samsung\";\n os = \"Tizen\";\n isSmartTV = true;\n deviceType = \"tv\";\n const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n model = tizenMatch\n ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim()\n : \"Tizen TV\";\n } else if (ua.includes(\"Philips\")) {\n brand = \"Philips\";\n os = \"Saphi\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n brand = \"Sharp\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (\n ua.includes(\"Android\") &&\n (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))\n ) {\n brand = \"Sony\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (\n ua.includes(\"Android\") &&\n (ua.includes(\"NetCast\") || ua.includes(\"LG\"))\n ) {\n brand = \"LG\";\n os = \"Android TV\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n brand = \"Roku\";\n os = \"Roku OS\";\n isSmartTV = true;\n deviceType = \"tv\";\n } else if (ua.includes(\"AppleTV\")) {\n brand = \"Apple\";\n os = \"tvOS\";\n isSmartTV = true;\n deviceType = \"tv\";\n }\n\n if (ua.includes(\"Android\")) {\n isAndroid = true;\n os = \"Android\";\n deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n\n if (\n ua.includes(\"Android\") &&\n (maxTouchPoints === 0 ||\n ua.includes(\"Google TV\") ||\n ua.includes(\"XiaoMi\"))\n ) {\n deviceType = \"tv\";\n isSmartTV = true;\n brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n }\n\n const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n if (androidModelMatch && androidModelMatch[1]) {\n model = androidModelMatch[1];\n }\n }\n\n if (/iPad|iPhone|iPod/.test(ua)) {\n os = \"iOS\";\n deviceType = \"mobile\";\n brand = \"Apple\";\n if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n deviceType = \"tablet\";\n }\n }\n\n if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n if (ua.includes(\"Windows\")) {\n os = \"Windows\";\n deviceType = \"desktop\";\n } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n os = \"macOS\";\n deviceType = \"desktop\";\n if (maxTouchPoints > 1) deviceType = \"tablet\";\n } else if (ua.includes(\"Linux\")) {\n os = \"Linux\";\n deviceType = \"desktop\";\n }\n }\n\n if (brand === \"Unknown\") {\n if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n if (vendor.includes(\"Apple\")) brand = \"Apple\";\n if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n }\n\n isWebView = /wv|WebView|Linux; U;/.test(ua);\n\n if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n isWebView = true;\n }\n\n isWebApp =\n window.matchMedia(\"(display-mode: standalone)\").matches ||\n (window.navigator as any).standalone === true ||\n window.screen?.orientation?.angle !== undefined;\n\n return {\n brand,\n os,\n model: model || ua.substring(0, 50) + \"...\",\n deviceType,\n isSmartTV,\n isAndroid,\n isWebView,\n isWebApp,\n domain: window.location.hostname,\n origin: window.location.origin,\n path: window.location.pathname,\n userAgent: ua,\n vendor,\n platform,\n screen: screenInfo,\n hardwareConcurrency,\n deviceMemory: memory,\n maxTouchPoints,\n language: navigator.language,\n languages: navigator.languages?.join(\",\") || \"\",\n cookieEnabled: navigator.cookieEnabled,\n doNotTrack: navigator.doNotTrack || \"\",\n referrer: document.referrer,\n visibilityState: document.visibilityState,\n };\n}\n\nexport async function getBrowserID(clientInfo: ClientInfo): Promise<string> {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n\n const fingerprintString = JSON.stringify(clientInfo);\n\n if (typeof crypto !== \"undefined\" && crypto.subtle && crypto.subtle.digest) {\n try {\n await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n\n let encodedData: BufferSource;\n if (typeof TextEncoder !== \"undefined\") {\n encodedData = new TextEncoder().encode(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\n const buffer = new Uint8Array(utf8.length);\n for (let i = 0; i < utf8.length; i++) {\n buffer[i] = utf8.charCodeAt(i);\n }\n encodedData = buffer;\n }\n\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n\n const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n const timestamp = Date.now().toString(16).padStart(12, \"0\");\n const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n\n cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\n\nconst PLAYER_TRACKING_BASE_URL =\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking\";\nconst TRACK_URL = `${PLAYER_TRACKING_BASE_URL}/metrics/ingest`;\nconst HEARTBEAT_URL = `${PLAYER_TRACKING_BASE_URL}/heartbeat`;\nconst IMPRESSIONS_URL = `${PLAYER_TRACKING_BASE_URL}/impressions/ingest`;\n\ntype PlayerMetricFlags = {\n adLoaded?: boolean;\n adDetect?: boolean;\n captureAt?: string;\n};\n\nfunction buildHeaders(licenseKey: string | undefined): Record<string, string> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n return headers;\n}\n\nasync function sendTrackRequest(\n licenseKey: string | undefined,\n body: Record<string, unknown>\n): Promise<void> {\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers: buildHeaders(licenseKey),\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\n\nasync function postJson(\n url: string,\n licenseKey: string | undefined,\n body: Record<string, unknown>\n): Promise<void> {\n const response = await fetch(url, {\n method: \"POST\",\n headers: buildHeaders(licenseKey),\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\n\nasync function buildPlayerMetricEvent(\n licenseKey: string | undefined,\n context: PlayerAnalyticsContext = {},\n flags: PlayerMetricFlags = {}\n): Promise<Record<string, unknown>> {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const captureAt = flags.captureAt ?? new Date().toISOString();\n\n return {\n player_id: browserId,\n browserId,\n device_type: clientInfo.deviceType,\n deviceType: clientInfo.deviceType,\n input_stream_type: context.inputStreamType,\n os: clientInfo.os,\n ad_loaded: flags.adLoaded,\n ad_detect: flags.adDetect,\n license_key: licenseKey,\n capture_at: captureAt,\n timestamp: captureAt,\n };\n}\n\nexport async function sendInitialTracking(\n licenseKey?: string,\n context: PlayerAnalyticsContext = {}\n): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const trackingData: TrackingData = {\n browserId,\n ...clientInfo,\n };\n\n await sendTrackRequest(licenseKey, {\n events: [\n {\n player_id: browserId,\n device_type: clientInfo.deviceType,\n input_stream_type: context.inputStreamType,\n os: clientInfo.os,\n ad_loaded: false,\n ad_detect: false,\n license_key: licenseKey,\n capture_at: new Date().toISOString(),\n },\n ],\n trackingData,\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 try {\n const metricEvent = await buildPlayerMetricEvent(licenseKey, context, {\n captureAt: adImpressionInfo.timestamp,\n });\n await Promise.all([\n postJson(HEARTBEAT_URL, licenseKey, metricEvent),\n postJson(IMPRESSIONS_URL, licenseKey, {\n events: [\n {\n player_id: metricEvent.player_id,\n ad_played_count: 1,\n ad_url: adImpressionInfo.adUrl,\n license_key: licenseKey,\n capture_at: adImpressionInfo.timestamp,\n },\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 try {\n const heartbeatData = await buildPlayerMetricEvent(\n licenseKey,\n context,\n flags\n );\n await postJson(HEARTBEAT_URL, licenseKey, 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"]}
|