stormcloud-video-player 0.5.19 → 0.5.21
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 +55 -17
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +55 -17
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +55 -17
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +55 -17
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +55 -17
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/prebidAdLayer.cjs +0 -9
- package/lib/sdk/prebidAdLayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +55 -17
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/player/StormcloudVideoPlayer.cjs","../../src/player/StormcloudVideoPlayer.ts","../../src/sdk/prebid.ts","../../src/sdk/vastParser.ts","../../src/sdk/prebidAdLayer.ts","../../src/utils/tracking.ts","../../src/utils/polyfills.ts","../../src/utils/browserCompat.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","StormcloudVideoPlayer_exports","StormcloudVideoPlayer","module","exports","import_hls","require","DEFAULT_TIMEOUT_MS","AUCTION_URL","createPrebidManager","options","initialized","debug","log","args","console","warn","parseResponse","data","bids","seatbids","seatbid","currency","cur","seat","bidArray","bid","cacheUrl","ext","prebid","cache","vastXml","url","adm","bidResponse","bidder","cpm","price","width","w","height","h","adId","id","impId","impid","creativeId","crid","vastUrl","adomain","push","sort","a","b","initialize","requestBids","timeout","controller","timeoutId","fetchOptions","response","body","error","Error","AbortController","setTimeout","abort","method","signal","fetch","clearTimeout","ok","text","catch","status","slice","json","responsetimemillis","errors","length","toFixed","REQUEST_BIDS_MAX_RETRIES","REQUEST_BIDS_BACKOFF_MS","requestBidsUntilResponse","lastError","attempt","err","delay","Promise","resolve","isMp4Type","destroy","isInitialized","isHlsType","type","includes","parseVastXml","xmlString","filter","logPrefix","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","textContent","adElement","getAttribute","title","isNoAdAvailable","toLowerCase","durationText","durationParts","split","duration","parseInt","Math","round","parseFloat","mediaFileElements","querySelectorAll","mediaFiles","forEach","mf","index","trim","substring","isHls","isMp4","accepted","bitrateAttr","bitrateValue","bitrate","aIsMp4","bIsMp4","trackingUrls","impression","start","firstQuartile","midpoint","thirdQuartile","complete","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","el","event","eventKey","clickThrough","fetchAndParseVastAd","vastTagUrl","mode","credentials","headers","Accept","referrerPolicy","statusText","fireTrackingPixels","urls","createEmptyTrackingState","sessionId","trackingUrl","img","Image","onerror","src","LOG","resolveBidToVastAd","winner","ad","createPrebidAdLayer","contentVideo","adPlaying","originalMutedState","originalVolume","max","min","volume","listeners","Map","mainHlsInstance","continueLiveStreamDuringAds","adVideoElement","adHls","adContainerEl","currentAd","destroyed","tornDown","trackingFired","emit","payload","set","Array","fn","generateSessionId","Date","now","random","toString","substr","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","selectBestMediaFile","scoredFiles","firstFile","mainQuality","map","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","video","style","left","objectFit","playsInline","setupAdEventListeners","progress","currentTime","isHlsMediaFile","createAdVideoElement","position","top","backgroundColor","muted","addEventListener","handleAdComplete","e","handleAdError","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","visibility","opacity","play","removeAttribute","load","startNativePlayback","mediaFile","startHlsPlayback","Hls","isSupported","loadSource","enableWorker","lowLatencyMode","attachMedia","on","Events","MANIFEST_PARSED","ERROR","_event","fatal","canPlayType","playAd","container","contentVolume","adVolume","reject","document","createElement","right","bottom","alignItems","justifyContent","zIndex","parentElement","appendChild","teardownCurrentPlayback","startPlayback","updateOptions","opts","paused","stop","remove","removeChild","clear","isAdPlaying","resize","listener","has","Set","add","off","delete","updateOriginalMutedState","nextVolume","getOriginalMutedState","getOriginalVolume","setAdVolume","getAdVolume","showPlaceholder","hidePlaceholder","cachedBrowserId","getClientInfo","screen","window","navigator","ua","userAgent","platform","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isSmartTV","isAndroid","isWebView","isWebApp","webosMatch","match","tizenMatch","tvMatch","test","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","location","hostname","origin","path","pathname","language","languages","join","cookieEnabled","doNotTrack","referrer","visibilityState","getBrowserID","clientInfo","fingerprintString","encodedData","utf8","buffer","i","hashBuffer","hashArray","hashHex","hash","char","fallbackHash","timestamp","JSON","stringify","crypto","subtle","digest","Uint8Array","TextEncoder","encode","unescape","encodeURIComponent","charCodeAt","padStart","padEnd","TRACK_URL","sendTrackRequest","licenseKey","sendInitialTracking","browserId","trackingData","sendAdDetectTracking","adDetectInfo","sendAdLoadedTracking","adLoadedInfo","sendAdImpressionTracking","adImpressionInfo","sendHeartbeat","heartbeatData","toISOString","polyfillURLSearchParams","URLSearchParams","URLSearchParamsPolyfill","init","params","parseQueryString","append","query","cleanQuery","startsWith","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","replace","values","String","getAll","callback","parts","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","finally","constructor","then","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","result","len","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","endsWith","polyfillStringIncludes","indexOf","initializePolyfills","getChromeVersion","getWebKitVersion","getPlatform","userAgentData","detectBrowser","webOSVersion","version","majorVersion","isLegacyTV","supportsIMA","supportsModernJS","recommendedAdPlayer","tizenVersion","chromeVersionNum","chromeVersion","webkitVersion","supportsGoogleIMA","browser","logBrowserInfo","imaSupport","getBrowserConfigOverrides","overrides","allowNativeHls","pendingNextAdBids","continuousFetchLoopPromise","attached","ptsDriftEmaMs","adPodQueue","lastHeartbeatTime","currentAdIndex","totalAdsInBreak","showAds","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","activeAdRequestToken","adRequestWatchdogToken","adFailsafeToken","continuousFetchingActive","isInAdTransition","maxPlaceholderDurationMs","isShowingPlaceholder","totalAdRequestsInBreak","maxTotalAdRequestsPerBreak","pendingAdBreak","savedMutedStateBeforeScte","config","maxConsecutiveFailures","lastAdRequestTime","minAdRequestIntervalMs","backoffBaseMs","maxBackoffMs","adTransitionGapMs","browserOverrides","videoElement","debugAdTiming","prebidManager","adLayer","adRequest","attach","initializeTracking","shouldUseNativeHls","isLive","adBehavior","autoplay","hls","import_hls2","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","maxBufferLength","maxMaxBufferLength","maxBufferHole","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","_","minSegments","some","details","live","shouldContinueLiveStreamDuringAds","minSegmentsBeforePlay","LEVEL_LOADED","_evt","inAdBreak","fragments","fragmentsToScan","tagList","entry","tag","isArray","idx","hasScteOut","attrs","durationSeconds","parseCueOutDuration","marker","raw","earlyDetection","frag","FRAG_BUFFERED","FRAG_PARSING_METADATA","id3Tags","samples","s","ptsSeconds","pts","onId3Tag","prog","parseCueOutCont","elapsed","onScte35Marker","parseAttributeList","hasScteIn","klass","toNumber","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","getAdSource","attachAdLayerEventListeners","source","adIndex","errorPayload","errorMessage","errorCode","code","vastErrorCode","message","cause","innerError","causeMessage","handleAdFailure","clearAdFailsafeTimer","clearAdRequestWatchdog","expectedAdBreakDurationMs","adStopTimerId","scheduleAdStopCountdown","getRemainingAdMs","hidePlaceholderLayer","remaining","syncMainContentAudioWhenVisible","consecutiveFailures","showPlaceholderLayer","freshBids","handleAdPodComplete","ensurePlaceholderContainer","placeholderContainer","transition","wasHidden","offsetHeight","requestAnimationFrame","timeUpdateHandler","onTimeUpdate","emptiedHandler","wasPaused","streamType","getStreamType","canNative","updatePtsDrift","parseScte35FromId3","decodeId3ValueToText","cueOutMatch","arg","dur","id3","cueOutContMatch","cont","cueInMatch","daterangeMatch","bin","parseScte35Binary","decoder","TextDecoder","decode","out","fromCharCode","hasPendingAdBreak","durationMs","currentAdBreakStartWallClockMs","detectedAtFragmentSn","isManifestMarker","isManifestBasedMarker","forceImmediate","immediateManifestAds","hasPts"],"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/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer_exports = {};\n__export(StormcloudVideoPlayer_exports, {\n StormcloudVideoPlayer: () => StormcloudVideoPlayer\n});\nmodule.exports = __toCommonJS(StormcloudVideoPlayer_exports);\nvar import_hls2 = __toESM(require(\"hls.js\"), 1);\n\n// src/sdk/prebid.ts\nvar DEFAULT_TIMEOUT_MS = 3e3;\nvar AUCTION_URL = \"https://sspproxy.adstorm.co/openrtb2/auction/adstorm\";\nfunction createPrebidManager(options = {}) {\n let initialized = false;\n const debug = options.debug ?? false;\n function log(...args) {\n if (debug) {\n console.log(\"[Prebid]\", ...args);\n }\n }\n function warn(...args) {\n console.warn(\"[Prebid]\", ...args);\n }\n function parseResponse(data) {\n const bids = [];\n const seatbids = data?.seatbid || [];\n const currency = data?.cur || \"USD\";\n for (const seatbid of seatbids) {\n const seat = seatbid.seat || \"unknown\";\n const bidArray = seatbid.bid || [];\n for (const bid of bidArray) {\n const cacheUrl = bid.ext?.prebid?.cache?.vastXml?.url;\n const vastXml = bid.adm || void 0;\n const bidResponse = {\n bidder: seat,\n cpm: bid.price || 0,\n width: bid.w || 0,\n height: bid.h || 0,\n adId: bid.id || \"\",\n impId: bid.impid || \"\",\n creativeId: bid.crid || \"\",\n currency\n };\n if (cacheUrl) bidResponse.vastUrl = cacheUrl;\n if (vastXml) bidResponse.vastXml = vastXml;\n if (bid.adomain) bidResponse.adomain = bid.adomain;\n bids.push(bidResponse);\n }\n }\n bids.sort((a, b) => b.cpm - a.cpm);\n return bids;\n }\n async function initialize() {\n if (initialized) return;\n initialized = true;\n log(\"Initialized, auction URL:\", AUCTION_URL);\n }\n async function requestBids() {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n const timeout = DEFAULT_TIMEOUT_MS;\n log(\"Fetching auction response from:\", AUCTION_URL);\n const controller = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timeoutId = setTimeout(() => {\n controller?.abort();\n }, timeout + 2e3);\n try {\n const fetchOptions = {\n method: \"POST\"\n };\n if (controller) {\n fetchOptions.signal = controller.signal;\n }\n const response = await fetch(AUCTION_URL, fetchOptions);\n clearTimeout(timeoutId);\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new Error(\n `Prebid Server returned HTTP ${response.status}: ${body.slice(0, 200)}`\n );\n }\n const data = await response.json();\n if (debug && data?.ext?.responsetimemillis) {\n log(\"Bidder response times:\", data.ext.responsetimemillis);\n }\n if (debug && data?.ext?.errors) {\n warn(\"Auction errors:\", data.ext.errors);\n }\n const bids = parseResponse(data);\n log(`Received ${bids.length} bid(s)`);\n if (debug) {\n for (const b of bids) {\n log(\n ` ${b.bidder}: $${b.cpm.toFixed(2)} ${b.currency} ${b.width}x${b.height}` + (b.vastUrl ? \" [cached VAST]\" : \"\") + (b.vastXml && !b.vastUrl ? \" [VAST XML]\" : \"\")\n );\n }\n }\n return bids;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error?.name === \"AbortError\") {\n warn(`Auction request timed out after ${timeout + 2e3}ms`);\n return [];\n }\n throw error;\n }\n }\n const REQUEST_BIDS_MAX_RETRIES = 3;\n const REQUEST_BIDS_BACKOFF_MS = 1500;\n async function requestBidsUntilResponse() {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n let lastError;\n for (let attempt = 1; attempt <= REQUEST_BIDS_MAX_RETRIES; attempt++) {\n try {\n const bids = await requestBids();\n if (bids.length > 0) {\n log(`requestBidsUntilResponse: got ${bids.length} bid(s) on attempt ${attempt}`);\n return bids;\n }\n log(`requestBidsUntilResponse: no bids on attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES}`);\n } catch (err) {\n lastError = err;\n warn(`requestBidsUntilResponse: attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES} failed:`, err);\n }\n if (attempt < REQUEST_BIDS_MAX_RETRIES) {\n const delay = REQUEST_BIDS_BACKOFF_MS * attempt;\n log(`requestBidsUntilResponse: waiting ${delay}ms before retry`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n return [];\n }\n function destroy() {\n initialized = false;\n log(\"Destroyed\");\n }\n return {\n initialize,\n requestBids,\n requestBidsUntilResponse,\n destroy,\n get isInitialized() {\n return initialized;\n }\n };\n}\n\n// src/sdk/vastParser.ts\nfunction isHlsType(type) {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\nfunction isMp4Type(type) {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\nfunction parseVastXml(xmlString, filter = \"all\", logPrefix = \"[VastParser]\") {\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 `${logPrefix} 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(`${logPrefix} 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 + Math.round(parseFloat(durationParts[2] || \"0\"));\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0\n });\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible 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(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\nasync function fetchAndParseVastAd(vastTagUrl, filter = \"all\", logPrefix = \"[VastParser]\") {\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(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml, filter, logPrefix);\n}\nfunction createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n}\nfunction fireTrackingPixels(urls, sessionId, logPrefix = \"[VastParser]\") {\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 const img = new Image(1, 1);\n img.onerror = () => {\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n\n// src/sdk/prebidAdLayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar LOG = \"[PrebidAdLayer]\";\nfunction resolveBidToVastAd(winner, logPrefix) {\n if (winner.vastXml) {\n const ad = parseVastXml(winner.vastXml, \"mp4-first\", logPrefix);\n return Promise.resolve(ad);\n }\n if (winner.vastUrl) {\n return fetchAndParseVastAd(winner.vastUrl, \"mp4-first\", logPrefix);\n }\n return Promise.resolve(null);\n}\nfunction createPrebidAdLayer(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 let mainHlsInstance = options?.mainHlsInstance;\n let continueLiveStreamDuringAds = options?.continueLiveStreamDuringAds ?? false;\n const debug = options?.debug ?? false;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n let destroyed = false;\n let tornDown = false;\n let trackingFired = createEmptyTrackingState();\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(`${LOG} Error in event listener for ${event}:`, error);\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels2(urls) {\n fireTrackingPixels(urls, sessionId, LOG);\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance?.levels) return null;\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) throw new Error(\"No media files available\");\n const firstFile = mediaFiles[0];\n if (mediaFiles.length === 1) return firstFile;\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n if (debug) console.log(`${LOG} No main stream quality info, using first media file`);\n return firstFile;\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 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 };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n return scoredFiles[0]?.file ?? firstFile;\n }\n function isHlsMediaFile(file) {\n return file.type === \"application/x-mpegURL\" || file.type.includes(\"m3u8\");\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 return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n const ad = currentAd;\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels2(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels2(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels2(ad.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n const ad = currentAd;\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels2(ad.trackingUrls.start);\n if (debug) console.log(`${LOG} Ad started playing`);\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (tornDown || !currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels2(currentAd.trackingUrls.complete);\n if (debug) console.log(`${LOG} Ad completed`);\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd || !adVideoElement) return;\n if (adVideoElement.muted) {\n fireTrackingPixels2(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels2(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && adVideoElement && !adVideoElement.ended) {\n fireTrackingPixels2(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {\n fireTrackingPixels2(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 if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad completion`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {\n });\n }\n emit(\"ad_impression\");\n emit(\"content_resume\");\n }\n function handleAdError() {\n if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad error`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n function teardownCurrentPlayback() {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n }\n function startNativePlayback(mediaFile) {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting native MP4 playback: ${mediaFile.url}`);\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native ad playback:`, error);\n handleAdError();\n });\n }\n function startHlsPlayback(mediaFile) {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting HLS playback: ${mediaFile.url}`);\n if (import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adHls = new import_hls.default({ enableWorker: true, lowLatencyMode: false });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting HLS ad playback:`, error);\n handleAdError();\n });\n });\n adHls.on(import_hls.default.Events.ERROR, (_event, data) => {\n if (data.fatal) handleAdError();\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native HLS ad playback:`, error);\n handleAdError();\n });\n } else {\n console.error(`${LOG} HLS not supported on this platform`);\n handleAdError();\n }\n }\n function startPlayback(mediaFile) {\n if (!adVideoElement) return;\n if (isHlsMediaFile(mediaFile)) {\n startHlsPlayback(mediaFile);\n } else {\n startNativePlayback(mediaFile);\n }\n }\n async function playAd(bids) {\n if (destroyed) {\n return Promise.reject(new Error(\"Layer has been destroyed\"));\n }\n if (bids.length === 0) {\n return Promise.reject(new Error(\"No bids provided\"));\n }\n const winner = bids[0];\n if (debug) {\n console.log(`${LOG} Winning bid: ${winner.bidder} $${winner.cpm.toFixed(2)} ${winner.currency}`);\n }\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad) {\n if (debug) console.warn(`${LOG} Winning bid has no VAST URL or XML`);\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No VAST from bid\"));\n }\n if (debug) {\n console.log(`${LOG} Ad parsed: ${ad.title}, duration: ${ad.duration}s, mediaFiles: ${ad.mediaFiles.length}`);\n }\n sessionId = generateSessionId();\n currentAd = ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels2(ad.trackingUrls.impression);\n trackingFired.impression = true;\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 (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n setupAdEventListeners();\n } else {\n teardownCurrentPlayback();\n }\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume = originalMutedState ? 1 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (debug) console.log(`${LOG} Loading ad from: ${mediaFile.url}`);\n startPlayback(mediaFile);\n }\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n updateOptions(opts) {\n if (opts.continueLiveStreamDuringAds !== void 0) {\n continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;\n }\n if (opts.mainHlsInstance !== void 0) {\n mainHlsInstance = opts.mainHlsInstance ?? void 0;\n }\n },\n playAd,\n pause() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (!adVideoElement.paused) adVideoElement.pause();\n } catch (error) {\n if (debug) console.warn(`${LOG} Error pausing ad:`, error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (adVideoElement.paused) adVideoElement.play().catch(() => {\n });\n } catch (error) {\n if (debug) console.warn(`${LOG} Error resuming ad:`, error);\n }\n },\n async stop() {\n tornDown = true;\n if (debug) console.log(`${LOG} Stopping ad`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {\n });\n }\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n currentAd = void 0;\n tornDown = false;\n },\n destroy() {\n tornDown = true;\n if (debug) console.log(`${LOG} Destroying`);\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"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 },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, 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 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 TRACK_URL = \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\nasync function sendTrackRequest(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_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 sendInitialTracking(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = {\n browserId,\n ...clientInfo\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData)\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 sendAdDetectTracking(licenseKey, adDetectInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adDetectInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n error\n );\n }\n}\nasync function sendAdLoadedTracking(licenseKey, adLoadedInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adLoadedInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n error\n );\n }\n}\nasync function sendAdImpressionTracking(licenseKey, adImpressionInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adImpressionInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\nasync function sendHeartbeat(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const heartbeatData = {\n browserId,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\n\n// src/utils/polyfills.ts\nfunction polyfillURLSearchParams() {\n if (typeof URLSearchParams !== \"undefined\") {\n return;\n }\n class URLSearchParamsPolyfill {\n constructor(init) {\n this.params = /* @__PURE__ */ new Map();\n if (typeof init === \"string\") {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n parseQueryString(query) {\n const cleanQuery = query.startsWith(\"?\") ? query.slice(1) : query;\n if (!cleanQuery) return;\n cleanQuery.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : \"\";\n this.append(decodedKey, decodedValue);\n }\n });\n }\n safeDecodeURIComponent(str) {\n try {\n return decodeURIComponent(str.replace(/\\+/g, \" \"));\n } catch (e) {\n return str;\n }\n }\n append(name, value) {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n delete(name) {\n this.params.delete(name);\n }\n get(name) {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;\n }\n getAll(name) {\n return this.params.get(name) || [];\n }\n has(name) {\n return this.params.has(name);\n }\n set(name, value) {\n this.params.set(name, [String(value)]);\n }\n forEach(callback) {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n toString() {\n const parts = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join(\"&\");\n }\n }\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\nfunction polyfillTextEncoder() {\n if (typeof TextEncoder !== \"undefined\") {\n return;\n }\n class TextEncoderPolyfill {\n constructor() {\n this.encoding = \"utf-8\";\n }\n encode(str) {\n const utf8 = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 128) {\n utf8.push(charcode);\n } else if (charcode < 2048) {\n utf8.push(192 | charcode >> 6, 128 | charcode & 63);\n } else if (charcode < 55296 || charcode >= 57344) {\n utf8.push(\n 224 | charcode >> 12,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n } else {\n i++;\n charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);\n utf8.push(\n 240 | charcode >> 18,\n 128 | charcode >> 12 & 63,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n window.TextEncoder = TextEncoderPolyfill;\n}\nfunction polyfillPromiseFinally() {\n if (typeof Promise !== \"undefined\" && !Promise.prototype.finally) {\n Promise.prototype.finally = function(callback) {\n const constructor = this.constructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) => constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\nfunction polyfillObjectAssign() {\n if (typeof Object.assign !== \"function\") {\n Object.assign = function(target, ...sources) {\n if (target == null) {\n throw new TypeError(\"Cannot convert undefined or null to object\");\n }\n const to = Object(target);\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n }\n}\nfunction polyfillArrayFrom() {\n if (!Array.from) {\n Array.from = function(arrayLike, mapFn, thisArg) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError(\"Array.from requires an array-like object\");\n }\n const len = items.length >>> 0;\n const result = new Array(len);\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n return result;\n };\n }\n}\nfunction polyfillStringStartsWith() {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function(search, pos) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\nfunction polyfillStringEndsWith() {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function(search, length) {\n if (length === void 0 || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\nfunction polyfillStringIncludes() {\n if (!String.prototype.includes) {\n String.prototype.includes = function(search, start) {\n if (typeof start !== \"number\") {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\nfunction initializePolyfills() {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n// src/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.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.pendingNextAdBids = null;\n this.continuousFetchLoopPromise = null;\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.adPodQueue = [];\n this.lastHeartbeatTime = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.showAds = false;\n this.isLiveStream = false;\n this.nativeHlsMode = false;\n this.videoSrcProtection = null;\n this.bufferedSegmentsCount = 0;\n this.shouldAutoplayAfterBuffering = false;\n this.hasInitialBufferCompleted = false;\n this.activeAdRequestToken = null;\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.continuousFetchingActive = false;\n this.isInAdTransition = false;\n this.maxPlaceholderDurationMs = 5e3;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n this.maxTotalAdRequestsPerBreak = 20;\n this.pendingAdBreak = null;\n this.savedMutedStateBeforeScte = null;\n this.consecutiveFailures = 0;\n this.maxConsecutiveFailures = 5;\n this.lastAdRequestTime = 0;\n this.minAdRequestIntervalMs = 2500;\n this.backoffBaseMs = 1e3;\n this.maxBackoffMs = 15e3;\n this.adTransitionGapMs = 1500;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.prebidManager = createPrebidManager(\n config.debugAdTiming !== void 0 ? { debug: !!config.debugAdTiming } : {}\n );\n this.adLayer = createPrebidAdLayer(this.video, {\n continueLiveStreamDuringAds: false,\n debug: !!config.debugAdTiming\n });\n }\n async adRequest() {\n await this.prebidManager.initialize();\n return this.prebidManager.requestBidsUntilResponse();\n }\n async load() {\n if (!this.attached) {\n this.attach();\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.adLayer.updateOptions({ continueLiveStreamDuringAds: false, mainHlsInstance: null });\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.adLayer.updateOptions({\n continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds(),\n mainHlsInstance: this.hls ?? null\n });\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.startAdPrefetch(marker, frag?.sn);\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_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n const marker = {\n type: \"progress\",\n ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},\n ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { tag, value, attrs }\n };\n this.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n this.hls.on(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 getAdSource() {\n return \"prebid\";\n }\n attachAdLayerEventListeners() {\n this.adLayer.on(\"ad_impression\", () => {\n if (this.config.licenseKey) {\n sendAdImpressionTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n adIndex: this.currentAdIndex,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n });\n this.adLayer.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.adLayer.stop().catch(() => {\n });\n this.handleAdFailure();\n });\n this.adLayer.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\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 this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.hidePlaceholderLayer();\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.adLayer.on(\"content_resume\", () => {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, pendingNext=%s\",\n this.inAdBreak,\n remaining,\n !!this.pendingNextAdBids\n );\n }\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n this.syncMainContentAudioWhenVisible();\n return;\n }\n this.consecutiveFailures = 0;\n if (this.pendingNextAdBids && this.pendingNextAdBids.length > 0) {\n const bids = [...this.pendingNextAdBids];\n this.pendingNextAdBids = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n this.isInAdTransition = true;\n setTimeout(() => {\n this.isInAdTransition = false;\n if (!this.inAdBreak || bids.length === 0) return;\n const freshBids = this.pendingNextAdBids ?? bids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(freshBids).catch((err) => {\n if (this.config.debugAdTiming) console.warn(\"[StormcloudVideoPlayer] playAd(pending) failed:\", err);\n this.handleAdFailure();\n });\n }, this.adTransitionGapMs);\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] content_resume: no more ads, ending ad pod and restoring main content sound\");\n }\n this.handleAdPodComplete();\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\");\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.adLayer.initialize();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachAdLayerEventListeners();\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.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {\n });\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n shouldUseNativeHls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n parseScte35FromId3(tag) {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return void 0;\n const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) || text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...dur !== void 0 ? { durationSeconds: dur } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker = {\n type: \"progress\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n if (hasScteIn) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n }\n if (/SCTE35-OUT/i.test(text)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n }\n decodeId3ValueToText(value) {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]);\n return out;\n } catch {\n return void 0;\n }\n }\n onScte35Marker(marker) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n hasPendingAdBreak: !!this.pendingAdBreak\n });\n }\n if (marker.type === \"start\") {\n if (this.savedMutedStateBeforeScte == null) {\n this.savedMutedStateBeforeScte = {\n muted: this.video.muted,\n volume: this.video.volume\n };\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\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 SCTE start marker\");\n }\n }\n if (this.inAdBreak) {\n if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n if (this.config.debugAdTiming) {\n console.log(`[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${this.expectedAdBreakDurationMs}ms`);\n }\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.pendingAdBreak?.marker.durationSeconds != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n if (this.config.licenseKey) {\n const adDetectInfo = {\n source: \"scte35\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n ...marker.durationSeconds != null && { durationSeconds: marker.durationSeconds },\n ...marker.ptsSeconds != null && { ptsSeconds: marker.ptsSeconds },\n ...this.pendingAdBreak?.detectedAtFragmentSn != null && {\n detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn\n }\n };\n sendAdDetectTracking(this.config.licenseKey, adDetectInfo);\n }\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\"\n });\n }\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1e3;\n const nowMs = this.video.currentTime * 1e3;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1e3,\n deltaMs,\n tolerance: tol\n });\n }\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch(() => this.handleAdFailure());\n }\n return;\n }\n if (marker.type === \"end\") {\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.adLayer.isAdPlaying();\n const hasQueuedAds = this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n inAdBreak: this.inAdBreak,\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null\n });\n }\n if (!this.inAdBreak) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end marker - not in ad break\");\n }\n return;\n }\n if (adPlaying || remaining > 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining\");\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.adLayer.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n return;\n }\n }\n parseCueOutDuration(value) {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match = value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) || value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? void 0 : d;\n }\n return void 0;\n }\n parseCueOutCont(value) {\n const 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 parseScte35Binary(data) {\n class BitReader {\n constructor(buf) {\n this.buf = buf;\n this.bytePos = 0;\n this.bitPos = 0;\n }\n readBits(numBits) {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos];\n const shift = remainingInByte - toRead;\n const mask = (1 << toRead) - 1 & 255;\n const bits = currentByte >> shift & mask;\n result = result << toRead | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n) {\n this.readBits(n);\n }\n }\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 252) return void 0;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return void 0;\n }\n r.readBits(32);\n const cancel = r.readBits(1) === 1;\n r.readBits(7);\n if (cancel) return void 0;\n const outOfNetwork = r.readBits(1) === 1;\n const programSpliceFlag = r.readBits(1) === 1;\n const durationFlag = r.readBits(1) === 1;\n const spliceImmediateFlag = r.readBits(1) === 1;\n r.readBits(4);\n if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n } else if (!programSpliceFlag) {\n const componentCount = r.readBits(8);\n for (let i = 0; i < componentCount; i++) {\n r.readBits(8);\n if (!spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds = void 0;\n if (durationFlag) {\n r.readBits(6);\n r.readBits(1);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const durationTicks = high * 4294967296 + low;\n durationSeconds = durationTicks / 9e4;\n }\n r.readBits(16);\n r.readBits(8);\n r.readBits(8);\n if (outOfNetwork) {\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { splice_command_type: 5 }\n };\n return marker;\n }\n return void 0;\n }\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n });\n }\n sendHeartbeatIfNeeded() {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n getCurrentAdIndex() {\n return this.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.totalAdsInBreak;\n }\n isAdPlaying() {\n return this.inAdBreak && this.adLayer.isAdPlaying();\n }\n isShowingAds() {\n return this.showAds;\n }\n syncMainContentAudioWhenVisible() {\n const adLayerShowing = this.showAds || this.adLayer.isAdPlaying();\n if (adLayerShowing) return;\n const muted = this.adLayer.getOriginalMutedState();\n const volume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== muted) this.video.muted = muted;\n if (Math.abs(this.video.volume - volume) > 0.01) this.video.volume = volume;\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) {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n this.pendingAdBreak = {\n marker,\n ...fragmentSn !== void 0 ? { detectedAtFragmentSn: fragmentSn } : {},\n isFetching: false,\n fetchStartTime: Date.now()\n };\n void this.adRequest().then(() => {\n }).catch(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Prebid auction prefetch failed, will request at playback time\");\n }\n });\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Ad break marker registered, auction prefetch started\");\n }\n }\n clearPendingAdBreak() {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = void 0;\n }\n this.pendingAdBreak = null;\n }\n startContinuousFetchLoop() {\n if (this.continuousFetchLoopPromise != null) return;\n this.continuousFetchLoopPromise = this.runContinuousFetchLoop();\n }\n async runContinuousFetchLoop() {\n const backoffMs = () => {\n const mult = Math.pow(2, this.consecutiveFailures);\n return Math.min(this.backoffBaseMs * mult, this.maxBackoffMs);\n };\n while (this.inAdBreak && this.continuousFetchingActive) {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) break;\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) break;\n const delay = this.lastAdRequestTime ? this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;\n const elapsed = Date.now() - this.lastAdRequestTime;\n if (elapsed < delay && this.lastAdRequestTime > 0) {\n await new Promise((r) => setTimeout(r, delay - elapsed));\n }\n if (!this.inAdBreak || !this.continuousFetchingActive) break;\n try {\n const bids = await this.adRequest();\n this.lastAdRequestTime = Date.now();\n if (!this.inAdBreak) break;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.adLayer.isAdPlaying() || this.isInAdTransition) {\n this.pendingNextAdBids = bids;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] Next ad response stored (ad currently playing or in transition)\");\n }\n } else {\n this.currentAdIndex++;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (err) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] adRequest failed:\", err);\n }\n }\n await new Promise((r) => setTimeout(r, backoffMs()));\n }\n this.continuousFetchLoopPromise = null;\n }\n async handleAdStart(_marker) {\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : void 0;\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.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.continuousFetchLoopPromise = null;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n if (this.savedMutedStateBeforeScte == null && !this.video.muted) {\n this.savedMutedStateBeforeScte = {\n muted: false,\n volume: this.video.volume\n };\n }\n const state = this.savedMutedStateBeforeScte ?? {\n muted: this.video.muted,\n volume: this.video.volume\n };\n this.adLayer.updateOriginalMutedState(state.muted, state.volume);\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.adLayer.showPlaceholder();\n if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n this.clearPendingAdBreak();\n const adBreakToken = Date.now();\n this.activeAdRequestToken = adBreakToken;\n this.startAdFailsafeTimer(adBreakToken);\n this.startAdRequestWatchdog(adBreakToken);\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 First ad request successful, starting playback\");\n }\n this.currentAdIndex++;\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = state.muted ? 1 : state.volume;\n this.adLayer.setAdVolume(adVolume);\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F First ad request failed:\", error);\n }\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n this.startContinuousFetchLoop();\n }\n stopContinuousFetching() {\n this.continuousFetchingActive = 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 if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Max ad requests per break (${this.maxTotalAdRequestsPerBreak}) reached`);\n }\n this.handleAdPodComplete();\n return;\n }\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\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.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 try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n if (this.adLayer.isAdPlaying() || this.isInAdTransition) {\n this.pendingNextAdBids = bids;\n } else {\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] tryNextAvailableAd request failed:\", error);\n }\n await this.showPlaceholderAndWaitForAds();\n }\n }\n async showPlaceholderAndWaitForAds() {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\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 response`);\n }\n this.isShowingPlaceholder = true;\n this.adLayer.showPlaceholder();\n const checkInterval = 300;\n const maxChecks = Math.floor(waitTime / checkInterval);\n for (let i = 0; i < maxChecks; i++) {\n await new Promise((resolve) => setTimeout(resolve, checkInterval));\n if (!this.inAdBreak) return;\n if (this.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 if (this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.currentAdIndex++;\n try {\n await this.adLayer.playAd(bids);\n this.consecutiveFailures = 0;\n } catch {\n this.consecutiveFailures++;\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (this.adLayer.isAdPlaying()) {\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\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.adLayer.hidePlaceholder();\n this.handleAdPodComplete();\n }\n onTimeUpdate(_currentTimeSec) {\n if (this.adLayer.isAdPlaying()) return;\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.adLayer.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.adLayer.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n }\n scheduleAdStartIn(delayMs) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\n updatePtsDrift(ptsSecondsSample) {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n 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.isInAdTransition = false;\n this.stopContinuousFetching();\n this.clearPendingAdBreak();\n this.pendingNextAdBids = null;\n if (this.isShowingPlaceholder) {\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.totalAdRequestsInBreak = 0;\n this.consecutiveFailures = 0;\n const restoredMuted = this.savedMutedStateBeforeScte?.muted ?? this.adLayer.getOriginalMutedState();\n const restoredVolume = this.savedMutedStateBeforeScte?.volume ?? this.adLayer.getOriginalVolume();\n this.adLayer.updateOriginalMutedState(restoredMuted, restoredVolume);\n this.adLayer.stop().catch(() => {\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 const isTizen = detectBrowser().tizenVersion !== void 0;\n if (isTizen && this.hls) {\n this.hls.attachMedia(this.video);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Tizen: re-attached HLS to video element after ad break to restore audio\");\n }\n }\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.config.debugAdTiming) {\n if (this.video.paused) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n } else {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n this.video.play()?.catch(() => {\n });\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n this.syncMainContentAudioWhenVisible();\n if (!restoredMuted) {\n requestAnimationFrame(() => {\n this.syncMainContentAudioWhenVisible();\n });\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 0);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 50);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 100);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 150);\n }\n this.savedMutedStateBeforeScte = null;\n }\n handleAdFailure() {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: consecutiveFailures=${this.consecutiveFailures}`\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 }\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.adLayer.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 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.adLayer.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n getRemainingAdMs() {\n if (this.currentAdBreakStartWallClockMs == null) return 0;\n if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n toggleMute() {\n if (this.adLayer.isAdPlaying()) {\n const isAdCurrentlyMuted = this.adLayer.getAdVolume() === 0;\n if (isAdCurrentlyMuted) {\n const savedVolume = this.adLayer.getOriginalVolume() || 1;\n this.adLayer.setAdVolume(savedVolume);\n this.adLayer.updateOriginalMutedState(false, savedVolume);\n } else {\n const currentAdVolume = this.adLayer.getAdVolume();\n this.adLayer.setAdVolume(0);\n this.adLayer.updateOriginalMutedState(true, currentAdVolume);\n }\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad:\",\n isAdCurrentlyMuted ? \"unmuted\" : \"muted\"\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.adLayer.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.adLayer.isAdPlaying()) {\n const adMuted = this.adLayer.getAdVolume() === 0;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() during ad playback ->\",\n adMuted\n );\n }\n return adMuted;\n }\n return this.video.muted;\n }\n setMuted(muted) {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n const savedVolume = this.adLayer.getOriginalVolume() || 1;\n this.adLayer.setAdVolume(muted ? 0 : savedVolume);\n this.adLayer.updateOriginalMutedState(muted, savedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied to ad layer (content stays muted)\", {\n muted,\n savedVolume\n });\n }\n return;\n }\n this.video.muted = muted;\n if (!this.inAdBreak) {\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n }\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.adLayer.isAdPlaying();\n if (adPlaying) {\n this.adLayer.setAdVolume(clampedVolume);\n const preservedVolume = clampedVolume > 0 ? clampedVolume : this.adLayer.getOriginalVolume();\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, preservedVolume);\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 if (!this.inAdBreak) {\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n getVolume() {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n return this.adLayer.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.adLayer && this.adLayer.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.adLayer.resize(width, height);\n }\n }\n destroy() {\n this.stopContinuousFetching();\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.adLayer?.destroy();\n this.consecutiveFailures = 0;\n }\n};\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n StormcloudVideoPlayer\n});\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n} from \"../types\";\nimport type { PrebidBidResponse } from \"../types\";\nimport { createPrebidManager } from \"../sdk/prebid\";\nimport { createPrebidAdLayer } from \"../sdk/prebidAdLayer\";\nimport type { PrebidAdLayer } from \"../sdk/prebidAdLayer\";\nimport {\n sendInitialTracking,\n sendHeartbeat,\n sendAdDetectTracking,\n sendAdLoadedTracking,\n sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport { logBrowserInfo, getBrowserConfigOverrides, detectBrowser } from \"../utils/browserCompat\";\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private prebidManager: ReturnType<typeof createPrebidManager>;\n private adLayer: PrebidAdLayer;\n private pendingNextAdBids: PrebidBidResponse[] | null = null;\n private continuousFetchLoopPromise: Promise<void> | null = null;\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 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 activeAdRequestToken: number | null = null;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n private continuousFetchingActive: boolean = false;\n private isInAdTransition: boolean = false;\n private maxPlaceholderDurationMs: number = 5000;\n private isShowingPlaceholder: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n \n private totalAdRequestsInBreak: number = 0;\n private readonly maxTotalAdRequestsPerBreak: number = 20;\n \n private pendingAdBreak: {\n marker: Scte35Marker;\n detectedAtFragmentSn?: number;\n isFetching: boolean;\n fetchStartTime?: number;\n } | null = null;\n private prefetchTimerId: number | undefined;\n private savedMutedStateBeforeScte: { muted: boolean; volume: number } | null = null;\n\n private consecutiveFailures: number = 0;\n private readonly maxConsecutiveFailures: number = 5;\n private lastAdRequestTime: number = 0;\n private readonly minAdRequestIntervalMs: number = 2500;\n private readonly backoffBaseMs: number = 1000;\n private readonly maxBackoffMs: number = 15000;\n private readonly adTransitionGapMs: number = 1500;\n private placeholderContainer: HTMLDivElement | undefined;\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.prebidManager = createPrebidManager(\n config.debugAdTiming !== undefined ? { debug: !!config.debugAdTiming } : {}\n );\n this.adLayer = createPrebidAdLayer(this.video, {\n continueLiveStreamDuringAds: false,\n debug: !!config.debugAdTiming,\n });\n }\n\n private async adRequest(): Promise<PrebidBidResponse[]> {\n await this.prebidManager.initialize();\n return this.prebidManager.requestBidsUntilResponse();\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\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.adLayer.updateOptions({ continueLiveStreamDuringAds: false, mainHlsInstance: null });\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.adLayer.updateOptions({\n continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds(),\n mainHlsInstance: this.hls ?? null,\n });\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.startAdPrefetch(marker, frag?.sn);\n return;\n }\n }\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_BUFFERED, async (_evt, data: any) => {\n if (this.hasInitialBufferCompleted) {\n return;\n }\n\n this.bufferedSegmentsCount++;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_PARSING_METADATA, (_evt, data: any) => {\n const id3Tags: Id3TagInfo[] = (data?.samples || []).map((s: any) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts,\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n\n this.hls.on(Hls.Events.FRAG_CHANGED, (_evt, data: any) => {\n const frag = data?.frag;\n const tagList: any[] | undefined = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(prog?.duration !== undefined\n ? { durationSeconds: prog.duration }\n : {}),\n ...(prog?.elapsed !== undefined\n ? { ptsSeconds: prog.elapsed }\n : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { tag, value, attrs },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n\n this.hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case Hls.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case Hls.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private getAdSource(): \"prebid\" {\n return \"prebid\";\n }\n\n private attachAdLayerEventListeners(): void {\n this.adLayer.on(\"ad_impression\", () => {\n if (this.config.licenseKey) {\n sendAdImpressionTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n adIndex: this.currentAdIndex,\n timestamp: new Date().toISOString(),\n });\n }\n });\n this.adLayer.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.adLayer.stop().catch(() => {});\n this.handleAdFailure();\n });\n this.adLayer.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\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 this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.hidePlaceholderLayer();\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.adLayer.on(\"content_resume\", () => {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, pendingNext=%s\",\n this.inAdBreak,\n remaining,\n !!this.pendingNextAdBids\n );\n }\n\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n this.syncMainContentAudioWhenVisible();\n return;\n }\n\n this.consecutiveFailures = 0;\n\n if (this.pendingNextAdBids && this.pendingNextAdBids.length > 0) {\n const bids = [...this.pendingNextAdBids];\n this.pendingNextAdBids = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n this.isInAdTransition = true;\n setTimeout(() => {\n this.isInAdTransition = false;\n if (!this.inAdBreak || bids.length === 0) return;\n const freshBids = this.pendingNextAdBids ?? bids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(freshBids).catch((err) => {\n if (this.config.debugAdTiming) console.warn(\"[StormcloudVideoPlayer] playAd(pending) failed:\", err);\n this.handleAdFailure();\n });\n }, this.adTransitionGapMs);\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] content_resume: no more ads, ending ad pod and restoring main content sound\");\n }\n this.handleAdPodComplete();\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\");\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.adLayer.initialize();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachAdLayerEventListeners();\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.adLayer.isAdPlaying()\n ) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n\n if (streamType === \"other\") {\n return true;\n }\n\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return undefined;\n\n const cueOutMatch =\n text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) ||\n text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(dur !== undefined ? { durationSeconds: dur } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(cont?.duration !== undefined\n ? { durationSeconds: cont.duration }\n : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n if (hasScteIn) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n }\n\n if (/SCTE35-OUT/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n }\n\n private decodeId3ValueToText(value: string | Uint8Array): string | undefined {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]!);\n return out;\n } catch {\n return undefined;\n }\n }\n\n private onScte35Marker(marker: Scte35Marker): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n hasPendingAdBreak: !!this.pendingAdBreak,\n });\n }\n\n if (marker.type === \"start\") {\n if (this.savedMutedStateBeforeScte == null) {\n this.savedMutedStateBeforeScte = {\n muted: this.video.muted,\n volume: this.video.volume,\n };\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\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 SCTE start marker\");\n }\n }\n\n if (this.inAdBreak) {\n if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n if (this.config.debugAdTiming) {\n console.log(`[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${this.expectedAdBreakDurationMs}ms`);\n }\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n\n this.inAdBreak = true;\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 this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n\n if (this.config.licenseKey) {\n const adDetectInfo = {\n source: \"scte35\" as const,\n timestamp: new Date().toISOString(),\n ...(marker.durationSeconds != null && { durationSeconds: marker.durationSeconds }),\n ...(marker.ptsSeconds != null && { ptsSeconds: marker.ptsSeconds }),\n ...(this.pendingAdBreak?.detectedAtFragmentSn != null && {\n detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn,\n }),\n };\n sendAdDetectTracking(this.config.licenseKey, adDetectInfo);\n }\n\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n });\n }\n\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1000;\n const nowMs = this.video.currentTime * 1000;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1000 - estCurrentPtsMs);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1000,\n deltaMs,\n tolerance: tol,\n });\n }\n\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n if (\n this.expectedAdBreakDurationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n \n if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch(() => this.handleAdFailure());\n }\n return;\n }\n if (marker.type === \"end\") {\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.adLayer.isAdPlaying();\n const hasQueuedAds = this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0;\n \n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n inAdBreak: this.inAdBreak,\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null,\n });\n }\n\n if (!this.inAdBreak) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end marker - not in ad break\");\n }\n return;\n }\n \n if (adPlaying || remaining > 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining\");\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.adLayer.stop().catch(() => {});\n }\n \n this.handleAdPodComplete();\n return;\n }\n }\n\n private parseCueOutDuration(value: string): number | undefined {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match =\n value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) ||\n value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? undefined : d;\n }\n return undefined;\n }\n\n private parseCueOutCont(\n value: string\n ): { elapsed?: number; duration?: number } | undefined {\n const 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 parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\n class BitReader {\n private bytePos = 0;\n private bitPos = 0;\n constructor(private readonly buf: Uint8Array) {}\n readBits(numBits: number): number {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos]!;\n const shift = remainingInByte - toRead;\n const mask = ((1 << toRead) - 1) & 0xff;\n const bits = (currentByte >> shift) & mask;\n result = (result << toRead) | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n: number): void {\n this.readBits(n);\n }\n }\n\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 0xfc) return undefined;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return undefined;\n }\n r.readBits(32);\n const cancel = r.readBits(1) === 1;\n r.readBits(7);\n if (cancel) return undefined;\n const outOfNetwork = r.readBits(1) === 1;\n const programSpliceFlag = r.readBits(1) === 1;\n const durationFlag = r.readBits(1) === 1;\n const spliceImmediateFlag = r.readBits(1) === 1;\n r.readBits(4);\n if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n } else if (!programSpliceFlag) {\n const componentCount = r.readBits(8);\n for (let i = 0; i < componentCount; i++) {\n r.readBits(8);\n if (!spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds: number | undefined = undefined;\n if (durationFlag) {\n r.readBits(6);\n r.readBits(1);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const durationTicks = high * 0x100000000 + low;\n durationSeconds = durationTicks / 90000;\n }\n r.readBits(16);\n r.readBits(8);\n r.readBits(8);\n\n if (outOfNetwork) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { splice_command_type: 5 },\n } as Scte35Marker;\n return marker;\n }\n return undefined;\n }\n\n private initializeTracking(): void {\n sendInitialTracking(this.config.licenseKey)\n .then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n })\n .catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n });\n }\n\n private sendHeartbeatIfNeeded(): void {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 30000) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n getCurrentAdIndex(): number {\n return this.currentAdIndex;\n }\n\n getTotalAdsInBreak(): number {\n return this.totalAdsInBreak;\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.adLayer.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.showAds;\n }\n\n private syncMainContentAudioWhenVisible(): void {\n const adLayerShowing = this.showAds || this.adLayer.isAdPlaying();\n if (adLayerShowing) return;\n const muted = this.adLayer.getOriginalMutedState();\n const volume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== muted) this.video.muted = muted;\n if (Math.abs(this.video.volume - volume) > 0.01) this.video.volume = volume;\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(marker: Scte35Marker, fragmentSn?: number): void {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n\n this.pendingAdBreak = {\n marker,\n ...(fragmentSn !== undefined ? { detectedAtFragmentSn: fragmentSn } : {}),\n isFetching: false,\n fetchStartTime: Date.now(),\n };\n\n void this.adRequest().then(() => {}).catch(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Prebid auction prefetch failed, will request at playback time\");\n }\n });\n\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Ad break marker registered, auction prefetch started\");\n }\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 }\n\n private startContinuousFetchLoop(): void {\n if (this.continuousFetchLoopPromise != null) return;\n this.continuousFetchLoopPromise = this.runContinuousFetchLoop();\n }\n\n private async runContinuousFetchLoop(): Promise<void> {\n const backoffMs = () => {\n const mult = Math.pow(2, this.consecutiveFailures);\n return Math.min(this.backoffBaseMs * mult, this.maxBackoffMs);\n };\n while (this.inAdBreak && this.continuousFetchingActive) {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) break;\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) break;\n const delay = this.lastAdRequestTime ? this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;\n const elapsed = Date.now() - this.lastAdRequestTime;\n if (elapsed < delay && this.lastAdRequestTime > 0) {\n await new Promise((r) => setTimeout(r, delay - elapsed));\n }\n if (!this.inAdBreak || !this.continuousFetchingActive) break;\n try {\n const bids = await this.adRequest();\n this.lastAdRequestTime = Date.now();\n if (!this.inAdBreak) break;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.adLayer.isAdPlaying() || this.isInAdTransition) {\n this.pendingNextAdBids = bids;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] Next ad response stored (ad currently playing or in transition)\");\n }\n } else {\n this.currentAdIndex++;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (err) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] adRequest failed:\", err);\n }\n }\n await new Promise((r) => setTimeout(r, backoffMs()));\n }\n this.continuousFetchLoopPromise = null;\n }\n\n private async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const adBreakDurationMs =\n _marker.durationSeconds != null\n ? _marker.durationSeconds * 1000\n : undefined;\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.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.continuousFetchLoopPromise = null;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n\n if (this.savedMutedStateBeforeScte == null && !this.video.muted) {\n this.savedMutedStateBeforeScte = {\n muted: false,\n volume: this.video.volume,\n };\n }\n\n const state = this.savedMutedStateBeforeScte ?? {\n muted: this.video.muted,\n volume: this.video.volume,\n };\n this.adLayer.updateOriginalMutedState(state.muted, state.volume);\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.adLayer.showPlaceholder();\n\n if (\n this.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n\n this.clearPendingAdBreak();\n\n const adBreakToken = Date.now();\n this.activeAdRequestToken = adBreakToken;\n this.startAdFailsafeTimer(adBreakToken);\n this.startAdRequestWatchdog(adBreakToken);\n\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ First ad request successful, starting playback\");\n }\n this.currentAdIndex++;\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = state.muted ? 1 : state.volume;\n this.adLayer.setAdVolume(adVolume);\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ First ad request failed:\", error);\n }\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n\n this.startContinuousFetchLoop();\n }\n\n private stopContinuousFetching(): void {\n this.continuousFetchingActive = 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 if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Max ad requests per break (${this.maxTotalAdRequestsPerBreak}) reached`);\n }\n this.handleAdPodComplete();\n return;\n }\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\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.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 try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n if (this.adLayer.isAdPlaying() || this.isInAdTransition) {\n this.pendingNextAdBids = bids;\n } else {\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] tryNextAvailableAd request failed:\", error);\n }\n await this.showPlaceholderAndWaitForAds();\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.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 response`);\n }\n\n this.isShowingPlaceholder = true;\n this.adLayer.showPlaceholder();\n\n const checkInterval = 300;\n const maxChecks = Math.floor(waitTime / checkInterval);\n\n for (let i = 0; i < maxChecks; i++) {\n await new Promise((resolve) => setTimeout(resolve, checkInterval));\n\n if (!this.inAdBreak) return;\n\n if (this.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 if (this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.currentAdIndex++;\n try {\n await this.adLayer.playAd(bids);\n this.consecutiveFailures = 0;\n } catch {\n this.consecutiveFailures++;\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n\n if (this.adLayer.isAdPlaying()) {\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\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.adLayer.hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n private onTimeUpdate(_currentTimeSec: number): void {\n if (this.adLayer.isAdPlaying()) return;\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.adLayer.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.adLayer.stop().catch(() => {});\n }\n\n this.handleAdPodComplete();\n }\n\n private scheduleAdStartIn(delayMs: number): void {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n }, ms) as unknown as number;\n }\n\n private clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n private updatePtsDrift(ptsSecondsSample: number): void {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1000;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 60000) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n\n private 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.isInAdTransition = false;\n this.stopContinuousFetching();\n this.clearPendingAdBreak();\n this.pendingNextAdBids = null;\n\n if (this.isShowingPlaceholder) {\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n\n this.inAdBreak = false;\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.totalAdRequestsInBreak = 0;\n this.consecutiveFailures = 0;\n\n const restoredMuted = this.savedMutedStateBeforeScte?.muted ?? this.adLayer.getOriginalMutedState();\n const restoredVolume = this.savedMutedStateBeforeScte?.volume ?? this.adLayer.getOriginalVolume();\n this.adLayer.updateOriginalMutedState(restoredMuted, restoredVolume);\n\n this.adLayer.stop().catch(() => {});\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 const isTizen = detectBrowser().tizenVersion !== undefined;\n if (isTizen && this.hls) {\n this.hls.attachMedia(this.video);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Tizen: re-attached HLS to video element after ad break to restore audio\");\n }\n }\n\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.config.debugAdTiming) {\n if (this.video.paused) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n } else {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n this.video.play()?.catch(() => {});\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n\n this.syncMainContentAudioWhenVisible();\n\n if (!restoredMuted) {\n requestAnimationFrame(() => {\n this.syncMainContentAudioWhenVisible();\n });\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 0);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 50);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 100);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 150);\n }\n\n this.savedMutedStateBeforeScte = null;\n }\n\n private handleAdFailure(): void {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: consecutiveFailures=${this.consecutiveFailures}`\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 }\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.adLayer.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 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.adLayer.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n private getRemainingAdMs(): number {\n if (this.currentAdBreakStartWallClockMs == null) return 0;\n if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n\n toggleMute(): void {\n if (this.adLayer.isAdPlaying()) {\n const isAdCurrentlyMuted = this.adLayer.getAdVolume() === 0;\n if (isAdCurrentlyMuted) {\n const savedVolume = this.adLayer.getOriginalVolume() || 1;\n this.adLayer.setAdVolume(savedVolume);\n this.adLayer.updateOriginalMutedState(false, savedVolume);\n } else {\n const currentAdVolume = this.adLayer.getAdVolume();\n this.adLayer.setAdVolume(0);\n this.adLayer.updateOriginalMutedState(true, currentAdVolume);\n }\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad:\", isAdCurrentlyMuted ? \"unmuted\" : \"muted\"\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.adLayer.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.adLayer.isAdPlaying()) {\n const adMuted = this.adLayer.getAdVolume() === 0;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() during ad playback ->\", adMuted\n );\n }\n return adMuted;\n }\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n const adPlaying = this.adLayer.isAdPlaying();\n\n if (adPlaying) {\n const savedVolume = this.adLayer.getOriginalVolume() || 1;\n this.adLayer.setAdVolume(muted ? 0 : savedVolume);\n this.adLayer.updateOriginalMutedState(muted, savedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied to ad layer (content stays muted)\", {\n muted, savedVolume,\n });\n }\n return;\n }\n\n this.video.muted = muted;\n\n if (!this.inAdBreak) {\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n }\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.adLayer.isAdPlaying();\n\n if (adPlaying) {\n this.adLayer.setAdVolume(clampedVolume);\n const preservedVolume = clampedVolume > 0 ? clampedVolume : this.adLayer.getOriginalVolume();\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, preservedVolume);\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 if (!this.inAdBreak) {\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n\n getVolume(): number {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n return this.adLayer.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.adLayer && this.adLayer.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.adLayer.resize(width, height);\n }\n }\n\n destroy(): void {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n 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.adLayer?.destroy();\n this.consecutiveFailures = 0;\n }\n}\n","import type { PrebidBidResponse, PrebidManager } from \"../types\";\n\nconst DEFAULT_TIMEOUT_MS = 3000;\nconst AUCTION_URL = \"https://sspproxy.adstorm.co/openrtb2/auction/adstorm\";\n\nexport interface PrebidManagerOptions {\n debug?: boolean;\n}\n\nexport function createPrebidManager(\n options: PrebidManagerOptions = {}\n): PrebidManager {\n let initialized = false;\n const debug = options.debug ?? false;\n\n function log(...args: any[]): void {\n if (debug) {\n console.log(\"[Prebid]\", ...args);\n }\n }\n\n function warn(...args: any[]): void {\n console.warn(\"[Prebid]\", ...args);\n }\n\n function parseResponse(data: any): PrebidBidResponse[] {\n const bids: PrebidBidResponse[] = [];\n const seatbids: any[] = data?.seatbid || [];\n const currency: string = data?.cur || \"USD\";\n\n for (const seatbid of seatbids) {\n const seat: string = seatbid.seat || \"unknown\";\n const bidArray: any[] = seatbid.bid || [];\n\n for (const bid of bidArray) {\n const cacheUrl: string | undefined =\n bid.ext?.prebid?.cache?.vastXml?.url;\n const vastXml: string | undefined = bid.adm || undefined;\n\n const bidResponse: PrebidBidResponse = {\n bidder: seat,\n cpm: bid.price || 0,\n width: bid.w || 0,\n height: bid.h || 0,\n adId: bid.id || \"\",\n impId: bid.impid || \"\",\n creativeId: bid.crid || \"\",\n currency,\n };\n if (cacheUrl) bidResponse.vastUrl = cacheUrl;\n if (vastXml) bidResponse.vastXml = vastXml;\n if (bid.adomain) bidResponse.adomain = bid.adomain;\n\n bids.push(bidResponse);\n }\n }\n\n bids.sort((a, b) => b.cpm - a.cpm);\n return bids;\n }\n\n async function initialize(): Promise<void> {\n if (initialized) return;\n initialized = true;\n log(\"Initialized, auction URL:\", AUCTION_URL);\n }\n\n async function requestBids(): Promise<PrebidBidResponse[]> {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n\n const timeout = DEFAULT_TIMEOUT_MS;\n\n log(\"Fetching auction response from:\", AUCTION_URL);\n\n const controller =\n typeof AbortController !== \"undefined\"\n ? new AbortController()\n : null;\n const timeoutId = setTimeout(() => {\n controller?.abort();\n }, timeout + 2000);\n\n try {\n const fetchOptions: RequestInit = {\n method: \"POST\",\n };\n if (controller) {\n fetchOptions.signal = controller.signal;\n }\n\n const response = await fetch(AUCTION_URL, fetchOptions);\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new Error(\n `Prebid Server returned HTTP ${response.status}: ${body.slice(0, 200)}`\n );\n }\n\n const data = await response.json();\n\n if (debug && data?.ext?.responsetimemillis) {\n log(\"Bidder response times:\", data.ext.responsetimemillis);\n }\n if (debug && data?.ext?.errors) {\n warn(\"Auction errors:\", data.ext.errors);\n }\n\n const bids = parseResponse(data);\n log(`Received ${bids.length} bid(s)`);\n\n if (debug) {\n for (const b of bids) {\n log(\n ` ${b.bidder}: $${b.cpm.toFixed(2)} ${b.currency}` +\n ` ${b.width}x${b.height}` +\n (b.vastUrl ? \" [cached VAST]\" : \"\") +\n (b.vastXml && !b.vastUrl ? \" [VAST XML]\" : \"\")\n );\n }\n }\n\n return bids;\n } catch (error: any) {\n clearTimeout(timeoutId);\n\n if (error?.name === \"AbortError\") {\n warn(`Auction request timed out after ${timeout + 2000}ms`);\n return [];\n }\n\n throw error;\n }\n }\n\n const REQUEST_BIDS_MAX_RETRIES = 3;\n const REQUEST_BIDS_BACKOFF_MS = 1500;\n\n async function requestBidsUntilResponse(): Promise<PrebidBidResponse[]> {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n let lastError: unknown;\n for (let attempt = 1; attempt <= REQUEST_BIDS_MAX_RETRIES; attempt++) {\n try {\n const bids = await requestBids();\n if (bids.length > 0) {\n log(`requestBidsUntilResponse: got ${bids.length} bid(s) on attempt ${attempt}`);\n return bids;\n }\n log(`requestBidsUntilResponse: no bids on attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES}`);\n } catch (err) {\n lastError = err;\n warn(`requestBidsUntilResponse: attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES} failed:`, err);\n }\n if (attempt < REQUEST_BIDS_MAX_RETRIES) {\n const delay = REQUEST_BIDS_BACKOFF_MS * attempt;\n log(`requestBidsUntilResponse: waiting ${delay}ms before retry`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n return [];\n }\n\n function destroy(): void {\n initialized = false;\n log(\"Destroyed\");\n }\n\n return {\n initialize,\n requestBids,\n requestBidsUntilResponse,\n destroy,\n get isInitialized() {\n return initialized;\n },\n };\n}\n","export interface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\nexport interface 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\nexport interface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport type MediaFileFilter = \"hls-only\" | \"mp4-first\" | \"all\";\n\nfunction isHlsType(type: string): boolean {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\n\nfunction isMp4Type(type: string): boolean {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\n\nexport function parseVastXml(\n xmlString: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): 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 `${logPrefix} 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(`${logPrefix} 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 Math.round(parseFloat(durationParts[2] || \"0\"));\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : undefined;\n\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible 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(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\n\nexport async function fetchAndParseVastAd(\n vastTagUrl: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\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(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml, filter, logPrefix);\n}\n\nexport function createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n}\n\nexport function fireTrackingPixels(\n urls: string[],\n sessionId?: string,\n logPrefix = \"[VastParser]\"\n): 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 const img = new Image(1, 1);\n img.onerror = () => {\n // 502 or other network errors are fire-and-forget; do not affect playback\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n","import type { PrebidBidResponse } from \"../types\";\nimport type { VastAd, VastMediaFile } from \"./vastParser\";\nimport {\n parseVastXml,\n fetchAndParseVastAd,\n fireTrackingPixels as fireTrackingPixelsShared,\n createEmptyTrackingState,\n} from \"./vastParser\";\nimport Hls from \"hls.js\";\n\nconst LOG = \"[PrebidAdLayer]\";\n\nexport interface PrebidAdLayerOptions {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls;\n debug?: boolean;\n}\n\nexport interface PrebidAdLayerOptionsUpdate {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls | null;\n}\n\nexport interface PrebidAdLayer {\n initialize: () => void;\n updateOptions: (opts: PrebidAdLayerOptionsUpdate) => void;\n playAd: (bids: PrebidBidResponse[]) => Promise<void>;\n pause: () => void;\n resume: () => void;\n stop: () => Promise<void>;\n destroy: () => void;\n isAdPlaying: () => boolean;\n resize: (width: number, height: number) => void;\n on: (event: string, listener: (payload?: any) => void) => void;\n off: (event: string, listener: (payload?: any) => void) => void;\n updateOriginalMutedState: (muted: boolean, volume?: number) => void;\n getOriginalMutedState: () => boolean;\n getOriginalVolume: () => number;\n setAdVolume: (volume: number) => void;\n getAdVolume: () => number;\n showPlaceholder: () => void;\n hidePlaceholder: () => void;\n}\n\nfunction resolveBidToVastAd(winner: PrebidBidResponse, logPrefix: string): Promise<VastAd | null> {\n if (winner.vastXml) {\n const ad = parseVastXml(winner.vastXml, \"mp4-first\", logPrefix);\n return Promise.resolve(ad);\n }\n if (winner.vastUrl) {\n return fetchAndParseVastAd(winner.vastUrl, \"mp4-first\", logPrefix);\n }\n return Promise.resolve(null);\n}\n\nexport function createPrebidAdLayer(\n contentVideo: HTMLVideoElement,\n options?: PrebidAdLayerOptions\n): PrebidAdLayer {\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 let mainHlsInstance: Hls | undefined = options?.mainHlsInstance;\n let continueLiveStreamDuringAds = options?.continueLiveStreamDuringAds ?? false;\n const debug = options?.debug ?? false;\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 let destroyed = false;\n let tornDown = false;\n let trackingFired = createEmptyTrackingState();\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(`${LOG} Error in event listener for ${event}:`, error);\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 fireTrackingPixelsShared(urls, sessionId, LOG);\n }\n\n function getMainStreamQuality(): { width: number; height: number; bitrate: number } | null {\n if (!mainHlsInstance?.levels) return null;\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 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) throw new Error(\"No media files available\");\n const firstFile = mediaFiles[0]!;\n if (mediaFiles.length === 1) return firstFile;\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n if (debug) console.log(`${LOG} No main stream quality info, using first media file`);\n return firstFile;\n }\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 const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n return { file, score };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n return scoredFiles[0]?.file ?? firstFile;\n }\n\n function isHlsMediaFile(file: VastMediaFile): boolean {\n return file.type === \"application/x-mpegURL\" || file.type.includes(\"m3u8\");\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 video.volume = 1.0;\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n const ad = currentAd;\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(ad.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n const ad = currentAd;\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(ad.trackingUrls.start);\n if (debug) console.log(`${LOG} Ad started playing`);\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (tornDown || !currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n if (debug) console.log(`${LOG} Ad completed`);\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels(currentAd.trackingUrls.error);\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd || !adVideoElement) 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 && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement && 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 if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad completion`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n }\n\n emit(\"ad_impression\");\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad error`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n emit(\"ad_error\");\n }\n\n function teardownCurrentPlayback(): void {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n }\n\n function startNativePlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting native MP4 playback: ${mediaFile.url}`);\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native ad playback:`, error);\n handleAdError();\n });\n }\n\n function startHlsPlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting HLS playback: ${mediaFile.url}`);\n\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n adHls = new Hls({ enableWorker: true, lowLatencyMode: false });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n adVideoElement!.play().catch((error) => {\n console.error(`${LOG} Error starting HLS ad playback:`, error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (_event, data) => {\n if (data.fatal) handleAdError();\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native HLS ad playback:`, error);\n handleAdError();\n });\n } else {\n console.error(`${LOG} HLS not supported on this platform`);\n handleAdError();\n }\n }\n\n function startPlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (isHlsMediaFile(mediaFile)) {\n startHlsPlayback(mediaFile);\n } else {\n startNativePlayback(mediaFile);\n }\n }\n\n async function playAd(bids: PrebidBidResponse[]): Promise<void> {\n if (destroyed) {\n return Promise.reject(new Error(\"Layer has been destroyed\"));\n }\n if (bids.length === 0) {\n return Promise.reject(new Error(\"No bids provided\"));\n }\n\n const winner = bids[0]!;\n if (debug) {\n console.log(`${LOG} Winning bid: ${winner.bidder} $${winner.cpm.toFixed(2)} ${winner.currency}`);\n }\n\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad) {\n if (debug) console.warn(`${LOG} Winning bid has no VAST URL or XML`);\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No VAST from bid\"));\n }\n\n if (debug) {\n console.log(`${LOG} Ad parsed: ${ad.title}, duration: ${ad.duration}s, mediaFiles: ${ad.mediaFiles.length}`);\n }\n\n sessionId = generateSessionId();\n currentAd = ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\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 contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n setupAdEventListeners();\n } else {\n teardownCurrentPlayback();\n }\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n const adVolume = originalMutedState ? 1 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\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(ad.mediaFiles);\n if (debug) console.log(`${LOG} Loading ad from: ${mediaFile.url}`);\n startPlayback(mediaFile);\n }\n\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n\n updateOptions(opts: PrebidAdLayerOptionsUpdate) {\n if (opts.continueLiveStreamDuringAds !== undefined) {\n continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;\n }\n if (opts.mainHlsInstance !== undefined) {\n mainHlsInstance = opts.mainHlsInstance ?? undefined;\n }\n },\n\n playAd,\n\n pause() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (!adVideoElement.paused) adVideoElement.pause();\n } catch (error) {\n if (debug) console.warn(`${LOG} Error pausing ad:`, error);\n }\n },\n\n resume() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (adVideoElement.paused) adVideoElement.play().catch(() => {});\n } catch (error) {\n if (debug) console.warn(`${LOG} Error resuming ad:`, error);\n }\n },\n\n async stop() {\n tornDown = true;\n if (debug) console.log(`${LOG} Stopping ad`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n }\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n currentAd = undefined;\n tornDown = false;\n },\n\n destroy() {\n tornDown = true;\n if (debug) console.log(`${LOG} Destroying`);\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\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\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 originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\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\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\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","import type {\n ClientInfo,\n TrackingData,\n HeartbeatData,\n AdDetectInfo,\n AdLoadedInfo,\n AdImpressionInfo,\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 TRACK_URL =\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\n\nasync function sendTrackRequest(\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_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 sendInitialTracking(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const trackingData: TrackingData = {\n browserId,\n ...clientInfo,\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(TRACK_URL, {\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\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 sendAdDetectTracking(\n licenseKey: string | undefined,\n adDetectInfo: AdDetectInfo\n): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adDetectInfo,\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adLoadedInfo,\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adImpressionInfo,\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\n\nexport async function sendHeartbeat(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const heartbeatData: HeartbeatData = {\n browserId,\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\n","export function polyfillURLSearchParams(): void {\n if (typeof URLSearchParams !== 'undefined') {\n return;\n }\n\n class URLSearchParamsPolyfill {\n private params: Map<string, string[]>;\n\n constructor(init?: string | URLSearchParamsPolyfill) {\n this.params = new Map();\n\n if (typeof init === 'string') {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n\n private parseQueryString(query: string): void {\n const cleanQuery = query.startsWith('?') ? query.slice(1) : query;\n if (!cleanQuery) return;\n\n cleanQuery.split('&').forEach((param) => {\n const [key, value] = param.split('=');\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : '';\n this.append(decodedKey, decodedValue);\n }\n });\n }\n\n private safeDecodeURIComponent(str: string): string {\n try {\n return decodeURIComponent(str.replace(/\\+/g, ' '));\n } catch (e) {\n return str;\n }\n }\n\n append(name: string, value: string): void {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n\n delete(name: string): void {\n this.params.delete(name);\n }\n\n get(name: string): string | null {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== undefined ? values[0] : null;\n }\n\n getAll(name: string): string[] {\n return this.params.get(name) || [];\n }\n\n has(name: string): boolean {\n return this.params.has(name);\n }\n\n set(name: string, value: string): void {\n this.params.set(name, [String(value)]);\n }\n\n forEach(callback: (value: string, key: string, parent: URLSearchParamsPolyfill) => void): void {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n\n toString(): string {\n const parts: string[] = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join('&');\n }\n }\n\n // @ts-ignore\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\n\nexport function polyfillTextEncoder(): void {\n if (typeof TextEncoder !== 'undefined') {\n return;\n }\n\n class TextEncoderPolyfill {\n encoding = 'utf-8';\n\n encode(str: string): Uint8Array {\n const utf8: number[] = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 0x80) {\n utf8.push(charcode);\n } else if (charcode < 0x800) {\n utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));\n } else if (charcode < 0xd800 || charcode >= 0xe000) {\n utf8.push(\n 0xe0 | (charcode >> 12),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n } else {\n i++;\n charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));\n utf8.push(\n 0xf0 | (charcode >> 18),\n 0x80 | ((charcode >> 12) & 0x3f),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n\n // @ts-ignore\n window.TextEncoder = TextEncoderPolyfill;\n}\n\nexport function polyfillPromiseFinally(): void {\n if (typeof Promise !== 'undefined' && !Promise.prototype.finally) {\n Promise.prototype.finally = function (callback: () => void) {\n const constructor = this.constructor as PromiseConstructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) =>\n constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\n\nexport function polyfillObjectAssign(): void {\n if (typeof Object.assign !== 'function') {\n Object.assign = function (target: any, ...sources: any[]) {\n if (target == null) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n const to = Object(target);\n\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n\n return to;\n };\n }\n}\n\nexport function polyfillArrayFrom(): void {\n if (!Array.from) {\n Array.from = function (arrayLike: any, mapFn?: any, thisArg?: any) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object');\n }\n\n const len = items.length >>> 0;\n const result = new Array(len);\n\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n\n return result;\n };\n }\n}\n\nexport function polyfillStringStartsWith(): void {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function (search: string, pos?: number) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\n\nexport function polyfillStringEndsWith(): void {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function (search: string, length?: number) {\n if (length === undefined || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\n\nexport function polyfillStringIncludes(): void {\n if (!String.prototype.includes) {\n String.prototype.includes = function (search: string, start?: number) {\n if (typeof start !== 'number') {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\n\nexport function initializePolyfills(): void {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n","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 allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: { allowNativeHls?: boolean } = {};\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function 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"]}
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/player/StormcloudVideoPlayer.cjs","../../src/player/StormcloudVideoPlayer.ts","../../src/sdk/prebid.ts","../../src/sdk/vastParser.ts","../../src/sdk/prebidAdLayer.ts","../../src/utils/tracking.ts","../../src/utils/polyfills.ts","../../src/utils/browserCompat.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","StormcloudVideoPlayer_exports","StormcloudVideoPlayer","module","exports","import_hls","require","DEFAULT_TIMEOUT_MS","AUCTION_URL","createPrebidManager","options","initialized","debug","log","args","console","warn","parseResponse","data","bids","seatbids","seatbid","currency","cur","seat","bidArray","bid","cacheUrl","ext","prebid","cache","vastXml","url","adm","bidResponse","bidder","cpm","price","width","w","height","h","adId","id","impId","impid","creativeId","crid","vastUrl","adomain","push","sort","a","b","initialize","requestBids","timeout","controller","timeoutId","fetchOptions","response","body","error","Error","AbortController","setTimeout","abort","method","signal","fetch","clearTimeout","ok","text","catch","status","slice","json","responsetimemillis","errors","length","toFixed","REQUEST_BIDS_MAX_RETRIES","REQUEST_BIDS_BACKOFF_MS","requestBidsUntilResponse","lastError","attempt","err","delay","destroy","Promise","resolve","isInitialized","isHlsType","type","includes","isMp4Type","xmlString","parseVastXml","filter","logPrefix","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","textContent","adElement","getAttribute","title","isNoAdAvailable","toLowerCase","durationText","durationParts","split","duration","parseInt","Math","round","parseFloat","mediaFileElements","querySelectorAll","mediaFiles","forEach","mf","index","trim","substring","isHls","isMp4","accepted","bitrateAttr","bitrateValue","bitrate","aIsMp4","bIsMp4","trackingUrls","impression","start","firstQuartile","midpoint","thirdQuartile","complete","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","el","event","eventKey","clickThrough","fetchAndParseVastAd","vastTagUrl","mode","credentials","headers","Accept","referrerPolicy","statusText","createEmptyTrackingState","firstFile","fireTrackingPixels","urls","sessionId","trackingUrl","img","Image","onerror","src","LOG","resolveBidToVastAd","winner","ad","createPrebidAdLayer","contentVideo","adPlaying","originalMutedState","originalVolume","max","min","volume","listeners","Map","mainHlsInstance","continueLiveStreamDuringAds","adVideoElement","adHls","adContainerEl","currentAd","destroyed","tornDown","trackingFired","emit","payload","set","Array","fn","generateSessionId","Date","now","random","toString","substr","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","selectBestMediaFile","scoredFiles","mainQuality","map","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","isHlsMediaFile","video","style","top","playsInline","createAdVideoElement","document","createElement","position","left","objectFit","backgroundColor","muted","addEventListener","progress","currentTime","handleAdComplete","e","handleAdError","ended","dataset","stormcloudAdPlaying","display","setAdPlayingFlag","pointerEvents","teardownCurrentPlayback","removeAttribute","startNativePlayback","mediaFile","load","Hls","isSupported","enableWorker","lowLatencyMode","loadSource","attachMedia","on","Events","MANIFEST_PARSED","play","ERROR","_event","fatal","canPlayType","startPlayback","startHlsPlayback","playAd","container","contentVolume","adVolume","reject","right","bottom","alignItems","justifyContent","zIndex","parentElement","appendChild","updateOptions","opts","paused","stop","visibility","opacity","remove","removeChild","clear","isAdPlaying","resize","listener","has","Set","add","off","delete","nextVolume","Number","isNaN","getOriginalMutedState","getOriginalVolume","setAdVolume","getAdVolume","showPlaceholder","hidePlaceholder","cachedBrowserId","getClientInfo","screen","window","navigator","ua","userAgent","platform","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isSmartTV","isAndroid","isWebView","isWebApp","webosMatch","match","tizenMatch","tvMatch","test","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","location","hostname","origin","path","pathname","language","languages","join","cookieEnabled","doNotTrack","referrer","visibilityState","getBrowserID","clientInfo","fingerprintString","encodedData","utf8","buffer","i","hashBuffer","hashArray","hashHex","hash","char","fallbackHash","timestamp","JSON","stringify","crypto","subtle","digest","Uint8Array","TextEncoder","encode","charCodeAt","padStart","padEnd","TRACK_URL","sendTrackRequest","licenseKey","sendInitialTracking","browserId","trackingData","sendAdDetectTracking","adDetectInfo","sendAdLoadedTracking","adLoadedInfo","sendAdImpressionTracking","adImpressionInfo","sendHeartbeat","heartbeatData","toISOString","polyfillURLSearchParams","URLSearchParams","URLSearchParamsPolyfill","init","params","parseQueryString","query","cleanQuery","startsWith","param","decodedKey","safeDecodeURIComponent","decodedValue","append","str","decodeURIComponent","replace","values","String","getAll","callback","parts","encodeURIComponent","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","finally","constructor","then","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","len","result","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","endsWith","polyfillStringIncludes","indexOf","initializePolyfills","getChromeVersion","getPlatform","userAgentData","detectBrowser","version","majorVersion","isLegacyTV","supportsIMA","supportsModernJS","recommendedAdPlayer","webOSVersion","tizenVersion","chromeVersionNum","chromeVersion","webkitVersion","getWebKitVersion","supportsGoogleIMA","browser","logBrowserInfo","imaSupport","getBrowserConfigOverrides","overrides","allowNativeHls","config","pendingNextAdBids","continuousFetchLoopPromise","attached","inAdBreak","ptsDriftEmaMs","adPodQueue","lastHeartbeatTime","totalAdsInBreak","showAds","isLiveStream","nativeHlsMode","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","activeAdRequestToken","adRequestWatchdogToken","adFailsafeToken","continuousFetchingActive","isInAdTransition","maxPlaceholderDurationMs","isShowingPlaceholder","totalAdRequestsInBreak","maxTotalAdRequestsPerBreak","pendingAdBreak","savedMutedStateBeforeScte","consecutiveFailures","maxConsecutiveFailures","lastAdRequestTime","minAdRequestIntervalMs","backoffBaseMs","maxBackoffMs","adTransitionGapMs","browserOverrides","currentAdIndex","videoElement","debugAdTiming","prebidManager","adLayer","adRequest","attach","initializeTracking","shouldUseNativeHls","videoSrcProtection","isLive","adBehavior","autoplay","hls","import_hls2","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","_","minSegments","some","details","live","shouldContinueLiveStreamDuringAds","minSegmentsBeforePlay","LEVEL_LOADED","_evt","fragments","fragmentsToScan","frag","tagList","isArray","entry","tag","idx","attrs","parseAttributeList","hasScteOut","durationSeconds","parseCueOutDuration","marker","earlyDetection","startAdPrefetch","sn","FRAG_BUFFERED","FRAG_PARSING_METADATA","id3Tags","samples","s","ptsSeconds","pts","prog","parseCueOutCont","elapsed","raw","onScte35Marker","hasScteIn","klass","toNumber","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","getAdSource","attachAdLayerEventListeners","adIndex","errorPayload","errorMessage","errorCode","code","vastErrorCode","message","cause","innerError","causeMessage","handleAdFailure","clearAdFailsafeTimer","clearAdRequestWatchdog","expectedAdBreakDurationMs","adStopTimerId","scheduleAdStopCountdown","getRemainingAdMs","hidePlaceholderLayer","remaining","syncMainContentAudioWhenVisible","showPlaceholderLayer","freshBids","handleAdPodComplete","ensurePlaceholderContainer","placeholderContainer","transition","wasHidden","offsetHeight","requestAnimationFrame","timeUpdateHandler","onTimeUpdate","emptiedHandler","wasPaused","streamType","getStreamType","canNative","onId3Tag","updatePtsDrift","parseScte35FromId3","decodeId3ValueToText","cueOutMatch","arg","dur","id3","cueOutContMatch","cont","cueInMatch","daterangeMatch","bin","parseScte35Binary","decoder","TextDecoder","decode","out","fromCharCode","hasPendingAdBreak","updateOriginalMutedState","durationMs","currentAdBreakStartWallClockMs","source","detectedAtFragmentSn","isManifestMarker","isManifestBasedMarker","forceImmediate","immediateManifestAds","hasPts","clearAdStartTimer","handleAdStart","tol","driftToleranceMs","nowMs","estCurrentPtsMs","deltaMs","floor","markerPtsMs","tolerance"],"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/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer_exports = {};\n__export(StormcloudVideoPlayer_exports, {\n StormcloudVideoPlayer: () => StormcloudVideoPlayer\n});\nmodule.exports = __toCommonJS(StormcloudVideoPlayer_exports);\nvar import_hls2 = __toESM(require(\"hls.js\"), 1);\n\n// src/sdk/prebid.ts\nvar DEFAULT_TIMEOUT_MS = 3e3;\nvar AUCTION_URL = \"https://sspproxy.adstorm.co/openrtb2/auction/adstorm\";\nfunction createPrebidManager(options = {}) {\n let initialized = false;\n const debug = options.debug ?? false;\n function log(...args) {\n if (debug) {\n console.log(\"[Prebid]\", ...args);\n }\n }\n function warn(...args) {\n console.warn(\"[Prebid]\", ...args);\n }\n function parseResponse(data) {\n const bids = [];\n const seatbids = data?.seatbid || [];\n const currency = data?.cur || \"USD\";\n for (const seatbid of seatbids) {\n const seat = seatbid.seat || \"unknown\";\n const bidArray = seatbid.bid || [];\n for (const bid of bidArray) {\n const cacheUrl = bid.ext?.prebid?.cache?.vastXml?.url;\n const vastXml = bid.adm || void 0;\n const bidResponse = {\n bidder: seat,\n cpm: bid.price || 0,\n width: bid.w || 0,\n height: bid.h || 0,\n adId: bid.id || \"\",\n impId: bid.impid || \"\",\n creativeId: bid.crid || \"\",\n currency\n };\n if (cacheUrl) bidResponse.vastUrl = cacheUrl;\n if (vastXml) bidResponse.vastXml = vastXml;\n if (bid.adomain) bidResponse.adomain = bid.adomain;\n bids.push(bidResponse);\n }\n }\n bids.sort((a, b) => b.cpm - a.cpm);\n return bids;\n }\n async function initialize() {\n if (initialized) return;\n initialized = true;\n log(\"Initialized, auction URL:\", AUCTION_URL);\n }\n async function requestBids() {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n const timeout = DEFAULT_TIMEOUT_MS;\n log(\"Fetching auction response from:\", AUCTION_URL);\n const controller = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timeoutId = setTimeout(() => {\n controller?.abort();\n }, timeout + 2e3);\n try {\n const fetchOptions = {\n method: \"POST\"\n };\n if (controller) {\n fetchOptions.signal = controller.signal;\n }\n const response = await fetch(AUCTION_URL, fetchOptions);\n clearTimeout(timeoutId);\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new Error(\n `Prebid Server returned HTTP ${response.status}: ${body.slice(0, 200)}`\n );\n }\n const data = await response.json();\n if (debug && data?.ext?.responsetimemillis) {\n log(\"Bidder response times:\", data.ext.responsetimemillis);\n }\n if (debug && data?.ext?.errors) {\n warn(\"Auction errors:\", data.ext.errors);\n }\n const bids = parseResponse(data);\n log(`Received ${bids.length} bid(s)`);\n if (debug) {\n for (const b of bids) {\n log(\n ` ${b.bidder}: $${b.cpm.toFixed(2)} ${b.currency} ${b.width}x${b.height}` + (b.vastUrl ? \" [cached VAST]\" : \"\") + (b.vastXml && !b.vastUrl ? \" [VAST XML]\" : \"\")\n );\n }\n }\n return bids;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error?.name === \"AbortError\") {\n warn(`Auction request timed out after ${timeout + 2e3}ms`);\n return [];\n }\n throw error;\n }\n }\n const REQUEST_BIDS_MAX_RETRIES = 3;\n const REQUEST_BIDS_BACKOFF_MS = 1500;\n async function requestBidsUntilResponse() {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n let lastError;\n for (let attempt = 1; attempt <= REQUEST_BIDS_MAX_RETRIES; attempt++) {\n try {\n const bids = await requestBids();\n if (bids.length > 0) {\n log(`requestBidsUntilResponse: got ${bids.length} bid(s) on attempt ${attempt}`);\n return bids;\n }\n log(`requestBidsUntilResponse: no bids on attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES}`);\n } catch (err) {\n lastError = err;\n warn(`requestBidsUntilResponse: attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES} failed:`, err);\n }\n if (attempt < REQUEST_BIDS_MAX_RETRIES) {\n const delay = REQUEST_BIDS_BACKOFF_MS * attempt;\n log(`requestBidsUntilResponse: waiting ${delay}ms before retry`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n return [];\n }\n function destroy() {\n initialized = false;\n log(\"Destroyed\");\n }\n return {\n initialize,\n requestBids,\n requestBidsUntilResponse,\n destroy,\n get isInitialized() {\n return initialized;\n }\n };\n}\n\n// src/sdk/vastParser.ts\nfunction isHlsType(type) {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\nfunction isMp4Type(type) {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\nfunction parseVastXml(xmlString, filter = \"all\", logPrefix = \"[VastParser]\") {\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 `${logPrefix} 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(`${logPrefix} 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 + Math.round(parseFloat(durationParts[2] || \"0\"));\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0\n });\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible 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(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\nasync function fetchAndParseVastAd(vastTagUrl, filter = \"all\", logPrefix = \"[VastParser]\") {\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(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml, filter, logPrefix);\n}\nfunction createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n}\nfunction fireTrackingPixels(urls, sessionId, logPrefix = \"[VastParser]\") {\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 const img = new Image(1, 1);\n img.onerror = () => {\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n\n// src/sdk/prebidAdLayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar LOG = \"[PrebidAdLayer]\";\nfunction resolveBidToVastAd(winner, logPrefix) {\n if (winner.vastXml) {\n const ad = parseVastXml(winner.vastXml, \"mp4-first\", logPrefix);\n return Promise.resolve(ad);\n }\n if (winner.vastUrl) {\n return fetchAndParseVastAd(winner.vastUrl, \"mp4-first\", logPrefix);\n }\n return Promise.resolve(null);\n}\nfunction createPrebidAdLayer(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 let mainHlsInstance = options?.mainHlsInstance;\n let continueLiveStreamDuringAds = options?.continueLiveStreamDuringAds ?? false;\n const debug = options?.debug ?? false;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n let destroyed = false;\n let tornDown = false;\n let trackingFired = createEmptyTrackingState();\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(`${LOG} Error in event listener for ${event}:`, error);\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels2(urls) {\n fireTrackingPixels(urls, sessionId, LOG);\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance?.levels) return null;\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) throw new Error(\"No media files available\");\n const firstFile = mediaFiles[0];\n if (mediaFiles.length === 1) return firstFile;\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n if (debug) console.log(`${LOG} No main stream quality info, using first media file`);\n return firstFile;\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 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 };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n return scoredFiles[0]?.file ?? firstFile;\n }\n function isHlsMediaFile(file) {\n return file.type === \"application/x-mpegURL\" || file.type.includes(\"m3u8\");\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 return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n const ad = currentAd;\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels2(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels2(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels2(ad.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n const ad = currentAd;\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels2(ad.trackingUrls.start);\n if (debug) console.log(`${LOG} Ad started playing`);\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (tornDown || !currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels2(currentAd.trackingUrls.complete);\n if (debug) console.log(`${LOG} Ad completed`);\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd || !adVideoElement) return;\n if (adVideoElement.muted) {\n fireTrackingPixels2(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels2(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && adVideoElement && !adVideoElement.ended) {\n fireTrackingPixels2(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {\n fireTrackingPixels2(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 if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad completion`);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_impression\");\n emit(\"content_resume\");\n }\n function handleAdError() {\n if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad error`);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n function teardownCurrentPlayback() {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n }\n function startNativePlayback(mediaFile) {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting native MP4 playback: ${mediaFile.url}`);\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native ad playback:`, error);\n handleAdError();\n });\n }\n function startHlsPlayback(mediaFile) {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting HLS playback: ${mediaFile.url}`);\n if (import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adHls = new import_hls.default({ enableWorker: true, lowLatencyMode: false });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting HLS ad playback:`, error);\n handleAdError();\n });\n });\n adHls.on(import_hls.default.Events.ERROR, (_event, data) => {\n if (data.fatal) handleAdError();\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native HLS ad playback:`, error);\n handleAdError();\n });\n } else {\n console.error(`${LOG} HLS not supported on this platform`);\n handleAdError();\n }\n }\n function startPlayback(mediaFile) {\n if (!adVideoElement) return;\n if (isHlsMediaFile(mediaFile)) {\n startHlsPlayback(mediaFile);\n } else {\n startNativePlayback(mediaFile);\n }\n }\n async function playAd(bids) {\n if (destroyed) {\n return Promise.reject(new Error(\"Layer has been destroyed\"));\n }\n if (bids.length === 0) {\n return Promise.reject(new Error(\"No bids provided\"));\n }\n const winner = bids[0];\n if (debug) {\n console.log(`${LOG} Winning bid: ${winner.bidder} $${winner.cpm.toFixed(2)} ${winner.currency}`);\n }\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad) {\n if (debug) console.warn(`${LOG} Winning bid has no VAST URL or XML`);\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No VAST from bid\"));\n }\n if (debug) {\n console.log(`${LOG} Ad parsed: ${ad.title}, duration: ${ad.duration}s, mediaFiles: ${ad.mediaFiles.length}`);\n }\n sessionId = generateSessionId();\n currentAd = ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels2(ad.trackingUrls.impression);\n trackingFired.impression = true;\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 (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n setupAdEventListeners();\n } else {\n teardownCurrentPlayback();\n }\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume = originalMutedState ? 1 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (debug) console.log(`${LOG} Loading ad from: ${mediaFile.url}`);\n startPlayback(mediaFile);\n }\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n updateOptions(opts) {\n if (opts.continueLiveStreamDuringAds !== void 0) {\n continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;\n }\n if (opts.mainHlsInstance !== void 0) {\n mainHlsInstance = opts.mainHlsInstance ?? void 0;\n }\n },\n playAd,\n pause() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (!adVideoElement.paused) adVideoElement.pause();\n } catch (error) {\n if (debug) console.warn(`${LOG} Error pausing ad:`, error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (adVideoElement.paused) adVideoElement.play().catch(() => {\n });\n } catch (error) {\n if (debug) console.warn(`${LOG} Error resuming ad:`, error);\n }\n },\n async stop() {\n tornDown = true;\n if (debug) console.log(`${LOG} Stopping ad`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {\n });\n }\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n currentAd = void 0;\n tornDown = false;\n },\n destroy() {\n tornDown = true;\n if (debug) console.log(`${LOG} Destroying`);\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"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 },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, 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 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 TRACK_URL = \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\nasync function sendTrackRequest(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_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 sendInitialTracking(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = {\n browserId,\n ...clientInfo\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData)\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 sendAdDetectTracking(licenseKey, adDetectInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adDetectInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n error\n );\n }\n}\nasync function sendAdLoadedTracking(licenseKey, adLoadedInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adLoadedInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n error\n );\n }\n}\nasync function sendAdImpressionTracking(licenseKey, adImpressionInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adImpressionInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\nasync function sendHeartbeat(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const heartbeatData = {\n browserId,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\n\n// src/utils/polyfills.ts\nfunction polyfillURLSearchParams() {\n if (typeof URLSearchParams !== \"undefined\") {\n return;\n }\n class URLSearchParamsPolyfill {\n constructor(init) {\n this.params = /* @__PURE__ */ new Map();\n if (typeof init === \"string\") {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n parseQueryString(query) {\n const cleanQuery = query.startsWith(\"?\") ? query.slice(1) : query;\n if (!cleanQuery) return;\n cleanQuery.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : \"\";\n this.append(decodedKey, decodedValue);\n }\n });\n }\n safeDecodeURIComponent(str) {\n try {\n return decodeURIComponent(str.replace(/\\+/g, \" \"));\n } catch (e) {\n return str;\n }\n }\n append(name, value) {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n delete(name) {\n this.params.delete(name);\n }\n get(name) {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;\n }\n getAll(name) {\n return this.params.get(name) || [];\n }\n has(name) {\n return this.params.has(name);\n }\n set(name, value) {\n this.params.set(name, [String(value)]);\n }\n forEach(callback) {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n toString() {\n const parts = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join(\"&\");\n }\n }\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\nfunction polyfillTextEncoder() {\n if (typeof TextEncoder !== \"undefined\") {\n return;\n }\n class TextEncoderPolyfill {\n constructor() {\n this.encoding = \"utf-8\";\n }\n encode(str) {\n const utf8 = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 128) {\n utf8.push(charcode);\n } else if (charcode < 2048) {\n utf8.push(192 | charcode >> 6, 128 | charcode & 63);\n } else if (charcode < 55296 || charcode >= 57344) {\n utf8.push(\n 224 | charcode >> 12,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n } else {\n i++;\n charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);\n utf8.push(\n 240 | charcode >> 18,\n 128 | charcode >> 12 & 63,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n window.TextEncoder = TextEncoderPolyfill;\n}\nfunction polyfillPromiseFinally() {\n if (typeof Promise !== \"undefined\" && !Promise.prototype.finally) {\n Promise.prototype.finally = function(callback) {\n const constructor = this.constructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) => constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\nfunction polyfillObjectAssign() {\n if (typeof Object.assign !== \"function\") {\n Object.assign = function(target, ...sources) {\n if (target == null) {\n throw new TypeError(\"Cannot convert undefined or null to object\");\n }\n const to = Object(target);\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n }\n}\nfunction polyfillArrayFrom() {\n if (!Array.from) {\n Array.from = function(arrayLike, mapFn, thisArg) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError(\"Array.from requires an array-like object\");\n }\n const len = items.length >>> 0;\n const result = new Array(len);\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n return result;\n };\n }\n}\nfunction polyfillStringStartsWith() {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function(search, pos) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\nfunction polyfillStringEndsWith() {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function(search, length) {\n if (length === void 0 || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\nfunction polyfillStringIncludes() {\n if (!String.prototype.includes) {\n String.prototype.includes = function(search, start) {\n if (typeof start !== \"number\") {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\nfunction initializePolyfills() {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n// src/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.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.pendingNextAdBids = null;\n this.continuousFetchLoopPromise = null;\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.adPodQueue = [];\n this.lastHeartbeatTime = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.showAds = false;\n this.isLiveStream = false;\n this.nativeHlsMode = false;\n this.videoSrcProtection = null;\n this.bufferedSegmentsCount = 0;\n this.shouldAutoplayAfterBuffering = false;\n this.hasInitialBufferCompleted = false;\n this.activeAdRequestToken = null;\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.continuousFetchingActive = false;\n this.isInAdTransition = false;\n this.maxPlaceholderDurationMs = 5e3;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n this.maxTotalAdRequestsPerBreak = 20;\n this.pendingAdBreak = null;\n this.savedMutedStateBeforeScte = null;\n this.consecutiveFailures = 0;\n this.maxConsecutiveFailures = 5;\n this.lastAdRequestTime = 0;\n this.minAdRequestIntervalMs = 2500;\n this.backoffBaseMs = 1e3;\n this.maxBackoffMs = 15e3;\n this.adTransitionGapMs = 1500;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.prebidManager = createPrebidManager(\n config.debugAdTiming !== void 0 ? { debug: !!config.debugAdTiming } : {}\n );\n this.adLayer = createPrebidAdLayer(this.video, {\n continueLiveStreamDuringAds: false,\n debug: !!config.debugAdTiming\n });\n }\n async adRequest() {\n await this.prebidManager.initialize();\n return this.prebidManager.requestBidsUntilResponse();\n }\n async load() {\n if (!this.attached) {\n this.attach();\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.adLayer.updateOptions({ continueLiveStreamDuringAds: false, mainHlsInstance: null });\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.adLayer.updateOptions({\n continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds(),\n mainHlsInstance: this.hls ?? null\n });\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.startAdPrefetch(marker, frag?.sn);\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.inAdBreak || this.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Ad break active \\u2014 deferring play() to handleAdPodComplete().`\n );\n }\n } else {\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(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_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n const marker = {\n type: \"progress\",\n ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},\n ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { tag, value, attrs }\n };\n this.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n this.hls.on(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 getAdSource() {\n return \"prebid\";\n }\n attachAdLayerEventListeners() {\n this.adLayer.on(\"ad_impression\", () => {\n if (this.config.licenseKey) {\n sendAdImpressionTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n adIndex: this.currentAdIndex,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n });\n this.adLayer.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.adLayer.stop().catch(() => {\n });\n this.handleAdFailure();\n });\n this.adLayer.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\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 this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.hidePlaceholderLayer();\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.adLayer.on(\"content_resume\", () => {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, pendingNext=%s\",\n this.inAdBreak,\n remaining,\n !!this.pendingNextAdBids\n );\n }\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n this.video.style.visibility = \"visible\";\n this.video.style.opacity = \"1\";\n this.syncMainContentAudioWhenVisible();\n return;\n }\n this.consecutiveFailures = 0;\n if (this.pendingNextAdBids && this.pendingNextAdBids.length > 0) {\n const bids = [...this.pendingNextAdBids];\n this.pendingNextAdBids = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n this.isInAdTransition = true;\n setTimeout(() => {\n this.isInAdTransition = false;\n if (!this.inAdBreak || bids.length === 0) return;\n const freshBids = this.pendingNextAdBids ?? bids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(freshBids).catch((err) => {\n if (this.config.debugAdTiming) console.warn(\"[StormcloudVideoPlayer] playAd(pending) failed:\", err);\n this.handleAdFailure();\n });\n }, this.adTransitionGapMs);\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] content_resume: no more ads, ending ad pod and restoring main content sound\");\n }\n this.handleAdPodComplete();\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\");\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.adLayer.initialize();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachAdLayerEventListeners();\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.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {\n });\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n shouldUseNativeHls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n parseScte35FromId3(tag) {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return void 0;\n const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) || text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...dur !== void 0 ? { durationSeconds: dur } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker = {\n type: \"progress\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n if (hasScteIn) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text, attrs }\n };\n return marker;\n }\n }\n if (/SCTE35-OUT/i.test(text)) {\n const marker = {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker = {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n return marker;\n }\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n }\n decodeId3ValueToText(value) {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]);\n return out;\n } catch {\n return void 0;\n }\n }\n onScte35Marker(marker) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n hasPendingAdBreak: !!this.pendingAdBreak\n });\n }\n if (marker.type === \"start\") {\n if (this.savedMutedStateBeforeScte == null) {\n this.savedMutedStateBeforeScte = {\n muted: this.video.muted,\n volume: this.video.volume\n };\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\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 SCTE start marker\");\n }\n }\n if (this.inAdBreak) {\n if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n if (this.config.debugAdTiming) {\n console.log(`[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${this.expectedAdBreakDurationMs}ms`);\n }\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.pendingAdBreak?.marker.durationSeconds != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n if (this.config.licenseKey) {\n const adDetectInfo = {\n source: \"scte35\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n ...marker.durationSeconds != null && { durationSeconds: marker.durationSeconds },\n ...marker.ptsSeconds != null && { ptsSeconds: marker.ptsSeconds },\n ...this.pendingAdBreak?.detectedAtFragmentSn != null && {\n detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn\n }\n };\n sendAdDetectTracking(this.config.licenseKey, adDetectInfo);\n }\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\"\n });\n }\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1e3;\n const nowMs = this.video.currentTime * 1e3;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1e3,\n deltaMs,\n tolerance: tol\n });\n }\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch(() => this.handleAdFailure());\n }\n return;\n }\n if (marker.type === \"end\") {\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.adLayer.isAdPlaying();\n const hasQueuedAds = this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n inAdBreak: this.inAdBreak,\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null\n });\n }\n if (!this.inAdBreak) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end marker - not in ad break\");\n }\n return;\n }\n if (adPlaying || remaining > 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining\");\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.adLayer.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n return;\n }\n }\n parseCueOutDuration(value) {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match = value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) || value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? void 0 : d;\n }\n return void 0;\n }\n parseCueOutCont(value) {\n const 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 parseScte35Binary(data) {\n class BitReader {\n constructor(buf) {\n this.buf = buf;\n this.bytePos = 0;\n this.bitPos = 0;\n }\n readBits(numBits) {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos];\n const shift = remainingInByte - toRead;\n const mask = (1 << toRead) - 1 & 255;\n const bits = currentByte >> shift & mask;\n result = result << toRead | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n) {\n this.readBits(n);\n }\n }\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 252) return void 0;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return void 0;\n }\n r.readBits(32);\n const cancel = r.readBits(1) === 1;\n r.readBits(7);\n if (cancel) return void 0;\n const outOfNetwork = r.readBits(1) === 1;\n const programSpliceFlag = r.readBits(1) === 1;\n const durationFlag = r.readBits(1) === 1;\n const spliceImmediateFlag = r.readBits(1) === 1;\n r.readBits(4);\n if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n } else if (!programSpliceFlag) {\n const componentCount = r.readBits(8);\n for (let i = 0; i < componentCount; i++) {\n r.readBits(8);\n if (!spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds = void 0;\n if (durationFlag) {\n r.readBits(6);\n r.readBits(1);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const durationTicks = high * 4294967296 + low;\n durationSeconds = durationTicks / 9e4;\n }\n r.readBits(16);\n r.readBits(8);\n r.readBits(8);\n if (outOfNetwork) {\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { splice_command_type: 5 }\n };\n return marker;\n }\n return void 0;\n }\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n });\n }\n sendHeartbeatIfNeeded() {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n getCurrentAdIndex() {\n return this.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.totalAdsInBreak;\n }\n isAdPlaying() {\n return this.inAdBreak && this.adLayer.isAdPlaying();\n }\n isShowingAds() {\n return this.showAds;\n }\n syncMainContentAudioWhenVisible() {\n const adLayerShowing = this.showAds || this.adLayer.isAdPlaying();\n if (adLayerShowing) return;\n const muted = this.adLayer.getOriginalMutedState();\n const volume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== muted) this.video.muted = muted;\n if (Math.abs(this.video.volume - volume) > 0.01) this.video.volume = volume;\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) {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n this.pendingAdBreak = {\n marker,\n ...fragmentSn !== void 0 ? { detectedAtFragmentSn: fragmentSn } : {},\n isFetching: false,\n fetchStartTime: Date.now()\n };\n void this.adRequest().then(() => {\n }).catch(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Prebid auction prefetch failed, will request at playback time\");\n }\n });\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Ad break marker registered, auction prefetch started\");\n }\n }\n clearPendingAdBreak() {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = void 0;\n }\n this.pendingAdBreak = null;\n }\n startContinuousFetchLoop() {\n if (this.continuousFetchLoopPromise != null) return;\n this.continuousFetchLoopPromise = this.runContinuousFetchLoop();\n }\n async runContinuousFetchLoop() {\n const backoffMs = () => {\n const mult = Math.pow(2, this.consecutiveFailures);\n return Math.min(this.backoffBaseMs * mult, this.maxBackoffMs);\n };\n while (this.inAdBreak && this.continuousFetchingActive) {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) break;\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) break;\n const delay = this.lastAdRequestTime ? this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;\n const elapsed = Date.now() - this.lastAdRequestTime;\n if (elapsed < delay && this.lastAdRequestTime > 0) {\n await new Promise((r) => setTimeout(r, delay - elapsed));\n }\n if (!this.inAdBreak || !this.continuousFetchingActive) break;\n try {\n const bids = await this.adRequest();\n this.lastAdRequestTime = Date.now();\n if (!this.inAdBreak) break;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.adLayer.isAdPlaying() || this.isInAdTransition) {\n this.pendingNextAdBids = bids;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] Next ad response stored (ad currently playing or in transition)\");\n }\n } else {\n this.currentAdIndex++;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (err) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] adRequest failed:\", err);\n }\n }\n await new Promise((r) => setTimeout(r, backoffMs()));\n }\n this.continuousFetchLoopPromise = null;\n }\n async handleAdStart(_marker) {\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : void 0;\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.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.continuousFetchLoopPromise = null;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n if (this.savedMutedStateBeforeScte == null && !this.video.muted) {\n this.savedMutedStateBeforeScte = {\n muted: false,\n volume: this.video.volume\n };\n }\n const state = this.savedMutedStateBeforeScte ?? {\n muted: this.video.muted,\n volume: this.video.volume\n };\n this.adLayer.updateOriginalMutedState(state.muted, state.volume);\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.adLayer.showPlaceholder();\n if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n this.clearPendingAdBreak();\n const adBreakToken = Date.now();\n this.activeAdRequestToken = adBreakToken;\n this.startAdFailsafeTimer(adBreakToken);\n this.startAdRequestWatchdog(adBreakToken);\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 First ad request successful, starting playback\");\n }\n this.currentAdIndex++;\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = state.muted ? 1 : state.volume;\n this.adLayer.setAdVolume(adVolume);\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F First ad request failed:\", error);\n }\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n this.startContinuousFetchLoop();\n }\n stopContinuousFetching() {\n this.continuousFetchingActive = 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 if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Max ad requests per break (${this.maxTotalAdRequestsPerBreak}) reached`);\n }\n this.handleAdPodComplete();\n return;\n }\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\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.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 try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n if (this.adLayer.isAdPlaying() || this.isInAdTransition) {\n this.pendingNextAdBids = bids;\n } else {\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] tryNextAvailableAd request failed:\", error);\n }\n await this.showPlaceholderAndWaitForAds();\n }\n }\n async showPlaceholderAndWaitForAds() {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\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 response`);\n }\n this.isShowingPlaceholder = true;\n this.adLayer.showPlaceholder();\n const checkInterval = 300;\n const maxChecks = Math.floor(waitTime / checkInterval);\n for (let i = 0; i < maxChecks; i++) {\n await new Promise((resolve) => setTimeout(resolve, checkInterval));\n if (!this.inAdBreak) return;\n if (this.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 if (this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.currentAdIndex++;\n try {\n await this.adLayer.playAd(bids);\n this.consecutiveFailures = 0;\n } catch {\n this.consecutiveFailures++;\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (this.adLayer.isAdPlaying()) {\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\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.adLayer.hidePlaceholder();\n this.handleAdPodComplete();\n }\n onTimeUpdate(_currentTimeSec) {\n if (this.adLayer.isAdPlaying()) return;\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.adLayer.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.adLayer.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n }\n scheduleAdStartIn(delayMs) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\n updatePtsDrift(ptsSecondsSample) {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n 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.isInAdTransition = false;\n this.stopContinuousFetching();\n this.clearPendingAdBreak();\n this.pendingNextAdBids = null;\n if (this.isShowingPlaceholder) {\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.totalAdRequestsInBreak = 0;\n this.consecutiveFailures = 0;\n const restoredMuted = this.savedMutedStateBeforeScte?.muted ?? this.adLayer.getOriginalMutedState();\n const restoredVolume = this.savedMutedStateBeforeScte?.volume ?? this.adLayer.getOriginalVolume();\n this.adLayer.updateOriginalMutedState(restoredMuted, restoredVolume);\n this.adLayer.stop().catch(() => {\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 const browser = detectBrowser();\n const isSmartTV = browser.tizenVersion !== void 0 || browser.webOSVersion !== void 0;\n if (isSmartTV && this.hls) {\n if (!restoredMuted) {\n const hlsRef = this.hls;\n const savedMuted = restoredMuted;\n const savedVolume = restoredVolume;\n const onManifestParsedRestore = () => {\n hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);\n if (!this.inAdBreak && !this.adLayer.isAdPlaying()) {\n if (this.video.muted !== savedMuted) this.video.muted = savedMuted;\n if (Math.abs(this.video.volume - savedVolume) > 0.01) this.video.volume = savedVolume;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Smart TV: audio state restored on MANIFEST_PARSED after re-attach\");\n }\n }\n };\n hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);\n }\n this.hls.attachMedia(this.video);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline\");\n }\n }\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.config.debugAdTiming) {\n if (this.video.paused) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n } else {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n this.video.play()?.catch(() => {\n });\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n this.syncMainContentAudioWhenVisible();\n if (!restoredMuted) {\n requestAnimationFrame(() => {\n this.syncMainContentAudioWhenVisible();\n });\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 0);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 50);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 100);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 150);\n }\n if (isSmartTV && !restoredMuted) {\n [500, 1e3, 2e3, 3e3, 5e3].forEach((delay) => {\n setTimeout(() => {\n if (!this.inAdBreak && !this.adLayer.isAdPlaying()) {\n if (this.video.muted !== restoredMuted) this.video.muted = restoredMuted;\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) this.video.volume = restoredVolume;\n }\n }, delay);\n });\n }\n this.savedMutedStateBeforeScte = null;\n }\n handleAdFailure() {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: consecutiveFailures=${this.consecutiveFailures}`\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 }\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.adLayer.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 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.adLayer.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n getRemainingAdMs() {\n if (this.currentAdBreakStartWallClockMs == null) return 0;\n if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n toggleMute() {\n if (this.adLayer.isAdPlaying()) {\n const isAdCurrentlyMuted = this.adLayer.getAdVolume() === 0;\n if (isAdCurrentlyMuted) {\n const savedVolume = this.adLayer.getOriginalVolume() || 1;\n this.adLayer.setAdVolume(savedVolume);\n this.adLayer.updateOriginalMutedState(false, savedVolume);\n } else {\n const currentAdVolume = this.adLayer.getAdVolume();\n this.adLayer.setAdVolume(0);\n this.adLayer.updateOriginalMutedState(true, currentAdVolume);\n }\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad:\",\n isAdCurrentlyMuted ? \"unmuted\" : \"muted\"\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.adLayer.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.adLayer.isAdPlaying()) {\n const adMuted = this.adLayer.getAdVolume() === 0;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() during ad playback ->\",\n adMuted\n );\n }\n return adMuted;\n }\n return this.video.muted;\n }\n setMuted(muted) {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n const savedVolume = this.adLayer.getOriginalVolume() || 1;\n this.adLayer.setAdVolume(muted ? 0 : savedVolume);\n this.adLayer.updateOriginalMutedState(muted, savedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied to ad layer (content stays muted)\", {\n muted,\n savedVolume\n });\n }\n return;\n }\n this.video.muted = muted;\n if (!this.inAdBreak) {\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n }\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.adLayer.isAdPlaying();\n if (adPlaying) {\n this.adLayer.setAdVolume(clampedVolume);\n const preservedVolume = clampedVolume > 0 ? clampedVolume : this.adLayer.getOriginalVolume();\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, preservedVolume);\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 if (!this.inAdBreak) {\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n getVolume() {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n return this.adLayer.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.adLayer && this.adLayer.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.adLayer.resize(width, height);\n }\n }\n destroy() {\n this.stopContinuousFetching();\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.adLayer?.destroy();\n this.consecutiveFailures = 0;\n }\n};\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n StormcloudVideoPlayer\n});\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n} from \"../types\";\nimport type { PrebidBidResponse } from \"../types\";\nimport { createPrebidManager } from \"../sdk/prebid\";\nimport { createPrebidAdLayer } from \"../sdk/prebidAdLayer\";\nimport type { PrebidAdLayer } from \"../sdk/prebidAdLayer\";\nimport {\n sendInitialTracking,\n sendHeartbeat,\n sendAdDetectTracking,\n sendAdLoadedTracking,\n sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport { logBrowserInfo, getBrowserConfigOverrides, detectBrowser } from \"../utils/browserCompat\";\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private prebidManager: ReturnType<typeof createPrebidManager>;\n private adLayer: PrebidAdLayer;\n private pendingNextAdBids: PrebidBidResponse[] | null = null;\n private continuousFetchLoopPromise: Promise<void> | null = null;\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 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 activeAdRequestToken: number | null = null;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n private continuousFetchingActive: boolean = false;\n private isInAdTransition: boolean = false;\n private maxPlaceholderDurationMs: number = 5000;\n private isShowingPlaceholder: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n \n private totalAdRequestsInBreak: number = 0;\n private readonly maxTotalAdRequestsPerBreak: number = 20;\n \n private pendingAdBreak: {\n marker: Scte35Marker;\n detectedAtFragmentSn?: number;\n isFetching: boolean;\n fetchStartTime?: number;\n } | null = null;\n private prefetchTimerId: number | undefined;\n private savedMutedStateBeforeScte: { muted: boolean; volume: number } | null = null;\n\n private consecutiveFailures: number = 0;\n private readonly maxConsecutiveFailures: number = 5;\n private lastAdRequestTime: number = 0;\n private readonly minAdRequestIntervalMs: number = 2500;\n private readonly backoffBaseMs: number = 1000;\n private readonly maxBackoffMs: number = 15000;\n private readonly adTransitionGapMs: number = 1500;\n private placeholderContainer: HTMLDivElement | undefined;\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.prebidManager = createPrebidManager(\n config.debugAdTiming !== undefined ? { debug: !!config.debugAdTiming } : {}\n );\n this.adLayer = createPrebidAdLayer(this.video, {\n continueLiveStreamDuringAds: false,\n debug: !!config.debugAdTiming,\n });\n }\n\n private async adRequest(): Promise<PrebidBidResponse[]> {\n await this.prebidManager.initialize();\n return this.prebidManager.requestBidsUntilResponse();\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\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.adLayer.updateOptions({ continueLiveStreamDuringAds: false, mainHlsInstance: null });\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.adLayer.updateOptions({\n continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds(),\n mainHlsInstance: this.hls ?? null,\n });\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.startAdPrefetch(marker, frag?.sn);\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.inAdBreak || this.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Ad break active — deferring play() to handleAdPodComplete().`\n );\n }\n } else {\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\n this.hls.on(Hls.Events.FRAG_PARSING_METADATA, (_evt, data: any) => {\n const id3Tags: Id3TagInfo[] = (data?.samples || []).map((s: any) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts,\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n\n this.hls.on(Hls.Events.FRAG_CHANGED, (_evt, data: any) => {\n const frag = data?.frag;\n const tagList: any[] | undefined = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(prog?.duration !== undefined\n ? { durationSeconds: prog.duration }\n : {}),\n ...(prog?.elapsed !== undefined\n ? { ptsSeconds: prog.elapsed }\n : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { tag, value, attrs },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n\n this.hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case Hls.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case Hls.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private getAdSource(): \"prebid\" {\n return \"prebid\";\n }\n\n private attachAdLayerEventListeners(): void {\n this.adLayer.on(\"ad_impression\", () => {\n if (this.config.licenseKey) {\n sendAdImpressionTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n adIndex: this.currentAdIndex,\n timestamp: new Date().toISOString(),\n });\n }\n });\n this.adLayer.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.adLayer.stop().catch(() => {});\n this.handleAdFailure();\n });\n this.adLayer.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\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 this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.hidePlaceholderLayer();\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.adLayer.on(\"content_resume\", () => {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, pendingNext=%s\",\n this.inAdBreak,\n remaining,\n !!this.pendingNextAdBids\n );\n }\n\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n this.video.style.visibility = \"visible\";\n this.video.style.opacity = \"1\";\n this.syncMainContentAudioWhenVisible();\n return;\n }\n\n this.consecutiveFailures = 0;\n\n if (this.pendingNextAdBids && this.pendingNextAdBids.length > 0) {\n const bids = [...this.pendingNextAdBids];\n this.pendingNextAdBids = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n this.isInAdTransition = true;\n setTimeout(() => {\n this.isInAdTransition = false;\n if (!this.inAdBreak || bids.length === 0) return;\n const freshBids = this.pendingNextAdBids ?? bids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(freshBids).catch((err) => {\n if (this.config.debugAdTiming) console.warn(\"[StormcloudVideoPlayer] playAd(pending) failed:\", err);\n this.handleAdFailure();\n });\n }, this.adTransitionGapMs);\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] content_resume: no more ads, ending ad pod and restoring main content sound\");\n }\n this.handleAdPodComplete();\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\");\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.adLayer.initialize();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachAdLayerEventListeners();\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.adLayer.isAdPlaying()\n ) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n\n if (streamType === \"other\") {\n return true;\n }\n\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return undefined;\n\n const cueOutMatch =\n text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) ||\n text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(dur !== undefined ? { durationSeconds: dur } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n const marker: Scte35Marker = {\n type: \"progress\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(cont?.duration !== undefined\n ? { durationSeconds: cont.duration }\n : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n if (daterangeMatch) {\n const attrs = this.parseAttributeList(daterangeMatch[1] ?? \"\");\n const hasScteOut =\n \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n const hasScteIn =\n \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n if (hasScteIn) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined\n ? { ptsSeconds: tag.ptsSeconds }\n : {}),\n raw: { id3: text, attrs },\n } as Scte35Marker;\n return marker;\n }\n }\n\n if (/SCTE35-OUT/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n if (/SCTE35-IN/i.test(text)) {\n const marker: Scte35Marker = {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n } as Scte35Marker;\n return marker;\n }\n\n if (tag.value instanceof Uint8Array) {\n const bin = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n }\n\n private decodeId3ValueToText(value: string | Uint8Array): string | undefined {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++)\n out += String.fromCharCode(value[i]!);\n return out;\n } catch {\n return undefined;\n }\n }\n\n private onScte35Marker(marker: Scte35Marker): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n raw: marker.raw,\n hasPendingAdBreak: !!this.pendingAdBreak,\n });\n }\n\n if (marker.type === \"start\") {\n if (this.savedMutedStateBeforeScte == null) {\n this.savedMutedStateBeforeScte = {\n muted: this.video.muted,\n volume: this.video.volume,\n };\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\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 SCTE start marker\");\n }\n }\n\n if (this.inAdBreak) {\n if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n if (this.config.debugAdTiming) {\n console.log(`[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${this.expectedAdBreakDurationMs}ms`);\n }\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n\n this.inAdBreak = true;\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 this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n\n if (this.config.licenseKey) {\n const adDetectInfo = {\n source: \"scte35\" as const,\n timestamp: new Date().toISOString(),\n ...(marker.durationSeconds != null && { durationSeconds: marker.durationSeconds }),\n ...(marker.ptsSeconds != null && { ptsSeconds: marker.ptsSeconds }),\n ...(this.pendingAdBreak?.detectedAtFragmentSn != null && {\n detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn,\n }),\n };\n sendAdDetectTracking(this.config.licenseKey, adDetectInfo);\n }\n\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n });\n }\n\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1000;\n const nowMs = this.video.currentTime * 1000;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1000 - estCurrentPtsMs);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1000,\n deltaMs,\n tolerance: tol,\n });\n }\n\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n if (\n this.expectedAdBreakDurationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n \n if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch(() => this.handleAdFailure());\n }\n return;\n }\n if (marker.type === \"end\") {\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.adLayer.isAdPlaying();\n const hasQueuedAds = this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0;\n \n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n inAdBreak: this.inAdBreak,\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null,\n });\n }\n\n if (!this.inAdBreak) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end marker - not in ad break\");\n }\n return;\n }\n \n if (adPlaying || remaining > 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining\");\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.adLayer.stop().catch(() => {});\n }\n \n this.handleAdPodComplete();\n return;\n }\n }\n\n private parseCueOutDuration(value: string): number | undefined {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match =\n value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) ||\n value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const dStr = match[1];\n const d = parseFloat(dStr);\n return Number.isNaN(d) ? undefined : d;\n }\n return undefined;\n }\n\n private parseCueOutCont(\n value: string\n ): { elapsed?: number; duration?: number } | undefined {\n const 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 parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\n class BitReader {\n private bytePos = 0;\n private bitPos = 0;\n constructor(private readonly buf: Uint8Array) {}\n readBits(numBits: number): number {\n let result = 0;\n while (numBits > 0) {\n if (this.bytePos >= this.buf.length) return result;\n const remainingInByte = 8 - this.bitPos;\n const toRead = Math.min(numBits, remainingInByte);\n const currentByte = this.buf[this.bytePos]!;\n const shift = remainingInByte - toRead;\n const mask = ((1 << toRead) - 1) & 0xff;\n const bits = (currentByte >> shift) & mask;\n result = (result << toRead) | bits;\n this.bitPos += toRead;\n if (this.bitPos >= 8) {\n this.bitPos = 0;\n this.bytePos += 1;\n }\n numBits -= toRead;\n }\n return result >>> 0;\n }\n skipBits(n: number): void {\n this.readBits(n);\n }\n }\n\n const r = new BitReader(data);\n const tableId = r.readBits(8);\n if (tableId !== 0xfc) return undefined;\n r.readBits(1);\n r.readBits(1);\n r.readBits(2);\n const sectionLength = r.readBits(12);\n r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return undefined;\n }\n r.readBits(32);\n const cancel = r.readBits(1) === 1;\n r.readBits(7);\n if (cancel) return undefined;\n const outOfNetwork = r.readBits(1) === 1;\n const programSpliceFlag = r.readBits(1) === 1;\n const durationFlag = r.readBits(1) === 1;\n const spliceImmediateFlag = r.readBits(1) === 1;\n r.readBits(4);\n if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n } else if (!programSpliceFlag) {\n const componentCount = r.readBits(8);\n for (let i = 0; i < componentCount; i++) {\n r.readBits(8);\n if (!spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds: number | undefined = undefined;\n if (durationFlag) {\n r.readBits(6);\n r.readBits(1);\n const high = r.readBits(1);\n const low = r.readBits(32);\n const durationTicks = high * 0x100000000 + low;\n durationSeconds = durationTicks / 90000;\n }\n r.readBits(16);\n r.readBits(8);\n r.readBits(8);\n\n if (outOfNetwork) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { splice_command_type: 5 },\n } as Scte35Marker;\n return marker;\n }\n return undefined;\n }\n\n private initializeTracking(): void {\n sendInitialTracking(this.config.licenseKey)\n .then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n })\n .catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n error\n );\n }\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5000);\n });\n }\n\n private sendHeartbeatIfNeeded(): void {\n const now = Date.now();\n if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 30000) {\n this.lastHeartbeatTime = now;\n sendHeartbeat(this.config.licenseKey).catch((error) => {\n if (this.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n getCurrentAdIndex(): number {\n return this.currentAdIndex;\n }\n\n getTotalAdsInBreak(): number {\n return this.totalAdsInBreak;\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.adLayer.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.showAds;\n }\n\n private syncMainContentAudioWhenVisible(): void {\n const adLayerShowing = this.showAds || this.adLayer.isAdPlaying();\n if (adLayerShowing) return;\n const muted = this.adLayer.getOriginalMutedState();\n const volume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== muted) this.video.muted = muted;\n if (Math.abs(this.video.volume - volume) > 0.01) this.video.volume = volume;\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(marker: Scte35Marker, fragmentSn?: number): void {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n\n this.pendingAdBreak = {\n marker,\n ...(fragmentSn !== undefined ? { detectedAtFragmentSn: fragmentSn } : {}),\n isFetching: false,\n fetchStartTime: Date.now(),\n };\n\n void this.adRequest().then(() => {}).catch(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Prebid auction prefetch failed, will request at playback time\");\n }\n });\n\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Ad break marker registered, auction prefetch started\");\n }\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 }\n\n private startContinuousFetchLoop(): void {\n if (this.continuousFetchLoopPromise != null) return;\n this.continuousFetchLoopPromise = this.runContinuousFetchLoop();\n }\n\n private async runContinuousFetchLoop(): Promise<void> {\n const backoffMs = () => {\n const mult = Math.pow(2, this.consecutiveFailures);\n return Math.min(this.backoffBaseMs * mult, this.maxBackoffMs);\n };\n while (this.inAdBreak && this.continuousFetchingActive) {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) break;\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) break;\n const delay = this.lastAdRequestTime ? this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;\n const elapsed = Date.now() - this.lastAdRequestTime;\n if (elapsed < delay && this.lastAdRequestTime > 0) {\n await new Promise((r) => setTimeout(r, delay - elapsed));\n }\n if (!this.inAdBreak || !this.continuousFetchingActive) break;\n try {\n const bids = await this.adRequest();\n this.lastAdRequestTime = Date.now();\n if (!this.inAdBreak) break;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.adLayer.isAdPlaying() || this.isInAdTransition) {\n this.pendingNextAdBids = bids;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] Next ad response stored (ad currently playing or in transition)\");\n }\n } else {\n this.currentAdIndex++;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (err) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] adRequest failed:\", err);\n }\n }\n await new Promise((r) => setTimeout(r, backoffMs()));\n }\n this.continuousFetchLoopPromise = null;\n }\n\n private async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const adBreakDurationMs =\n _marker.durationSeconds != null\n ? _marker.durationSeconds * 1000\n : undefined;\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.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.continuousFetchLoopPromise = null;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n\n if (this.savedMutedStateBeforeScte == null && !this.video.muted) {\n this.savedMutedStateBeforeScte = {\n muted: false,\n volume: this.video.volume,\n };\n }\n\n const state = this.savedMutedStateBeforeScte ?? {\n muted: this.video.muted,\n volume: this.video.volume,\n };\n this.adLayer.updateOriginalMutedState(state.muted, state.volume);\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.adLayer.showPlaceholder();\n\n if (\n this.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n\n this.clearPendingAdBreak();\n\n const adBreakToken = Date.now();\n this.activeAdRequestToken = adBreakToken;\n this.startAdFailsafeTimer(adBreakToken);\n this.startAdRequestWatchdog(adBreakToken);\n\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ First ad request successful, starting playback\");\n }\n this.currentAdIndex++;\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = state.muted ? 1 : state.volume;\n this.adLayer.setAdVolume(adVolume);\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ First ad request failed:\", error);\n }\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n\n this.startContinuousFetchLoop();\n }\n\n private stopContinuousFetching(): void {\n this.continuousFetchingActive = 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 if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Max ad requests per break (${this.maxTotalAdRequestsPerBreak}) reached`);\n }\n this.handleAdPodComplete();\n return;\n }\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\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.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 try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n if (this.adLayer.isAdPlaying() || this.isInAdTransition) {\n this.pendingNextAdBids = bids;\n } else {\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 1 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] tryNextAvailableAd request failed:\", error);\n }\n await this.showPlaceholderAndWaitForAds();\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.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 response`);\n }\n\n this.isShowingPlaceholder = true;\n this.adLayer.showPlaceholder();\n\n const checkInterval = 300;\n const maxChecks = Math.floor(waitTime / checkInterval);\n\n for (let i = 0; i < maxChecks; i++) {\n await new Promise((resolve) => setTimeout(resolve, checkInterval));\n\n if (!this.inAdBreak) return;\n\n if (this.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 if (this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.currentAdIndex++;\n try {\n await this.adLayer.playAd(bids);\n this.consecutiveFailures = 0;\n } catch {\n this.consecutiveFailures++;\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n\n if (this.adLayer.isAdPlaying()) {\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\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.adLayer.hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n private onTimeUpdate(_currentTimeSec: number): void {\n if (this.adLayer.isAdPlaying()) return;\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.adLayer.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.adLayer.stop().catch(() => {});\n }\n\n this.handleAdPodComplete();\n }\n\n private scheduleAdStartIn(delayMs: number): void {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n }, ms) as unknown as number;\n }\n\n private clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n private updatePtsDrift(ptsSecondsSample: number): void {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1000;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 60000) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n\n private 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.isInAdTransition = false;\n this.stopContinuousFetching();\n this.clearPendingAdBreak();\n this.pendingNextAdBids = null;\n\n if (this.isShowingPlaceholder) {\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n\n this.inAdBreak = false;\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.totalAdRequestsInBreak = 0;\n this.consecutiveFailures = 0;\n\n const restoredMuted = this.savedMutedStateBeforeScte?.muted ?? this.adLayer.getOriginalMutedState();\n const restoredVolume = this.savedMutedStateBeforeScte?.volume ?? this.adLayer.getOriginalVolume();\n this.adLayer.updateOriginalMutedState(restoredMuted, restoredVolume);\n\n this.adLayer.stop().catch(() => {});\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 const browser = detectBrowser();\n const isSmartTV = browser.tizenVersion !== undefined || browser.webOSVersion !== undefined;\n if (isSmartTV && this.hls) {\n if (!restoredMuted) {\n const hlsRef = this.hls;\n const savedMuted = restoredMuted;\n const savedVolume = restoredVolume;\n const onManifestParsedRestore = () => {\n hlsRef.off(Hls.Events.MANIFEST_PARSED, onManifestParsedRestore);\n if (!this.inAdBreak && !this.adLayer.isAdPlaying()) {\n if (this.video.muted !== savedMuted) this.video.muted = savedMuted;\n if (Math.abs(this.video.volume - savedVolume) > 0.01) this.video.volume = savedVolume;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Smart TV: audio state restored on MANIFEST_PARSED after re-attach\");\n }\n }\n };\n hlsRef.on(Hls.Events.MANIFEST_PARSED, onManifestParsedRestore);\n }\n this.hls.attachMedia(this.video);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline\");\n }\n }\n\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.config.debugAdTiming) {\n if (this.video.paused) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n } else {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n this.video.play()?.catch(() => {});\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n\n this.syncMainContentAudioWhenVisible();\n\n if (!restoredMuted) {\n requestAnimationFrame(() => {\n this.syncMainContentAudioWhenVisible();\n });\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 0);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 50);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 100);\n setTimeout(() => {\n this.syncMainContentAudioWhenVisible();\n }, 150);\n }\n\n if (isSmartTV && !restoredMuted) {\n [500, 1000, 2000, 3000, 5000].forEach(delay => {\n setTimeout(() => {\n if (!this.inAdBreak && !this.adLayer.isAdPlaying()) {\n if (this.video.muted !== restoredMuted) this.video.muted = restoredMuted;\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) this.video.volume = restoredVolume;\n }\n }, delay);\n });\n }\n\n this.savedMutedStateBeforeScte = null;\n }\n\n private handleAdFailure(): void {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: consecutiveFailures=${this.consecutiveFailures}`\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 }\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.adLayer.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 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.adLayer.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n private getRemainingAdMs(): number {\n if (this.currentAdBreakStartWallClockMs == null) return 0;\n if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n\n toggleMute(): void {\n if (this.adLayer.isAdPlaying()) {\n const isAdCurrentlyMuted = this.adLayer.getAdVolume() === 0;\n if (isAdCurrentlyMuted) {\n const savedVolume = this.adLayer.getOriginalVolume() || 1;\n this.adLayer.setAdVolume(savedVolume);\n this.adLayer.updateOriginalMutedState(false, savedVolume);\n } else {\n const currentAdVolume = this.adLayer.getAdVolume();\n this.adLayer.setAdVolume(0);\n this.adLayer.updateOriginalMutedState(true, currentAdVolume);\n }\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad:\", isAdCurrentlyMuted ? \"unmuted\" : \"muted\"\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.adLayer.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.adLayer.isAdPlaying()) {\n const adMuted = this.adLayer.getAdVolume() === 0;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() during ad playback ->\", adMuted\n );\n }\n return adMuted;\n }\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n const adPlaying = this.adLayer.isAdPlaying();\n\n if (adPlaying) {\n const savedVolume = this.adLayer.getOriginalVolume() || 1;\n this.adLayer.setAdVolume(muted ? 0 : savedVolume);\n this.adLayer.updateOriginalMutedState(muted, savedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied to ad layer (content stays muted)\", {\n muted, savedVolume,\n });\n }\n return;\n }\n\n this.video.muted = muted;\n\n if (!this.inAdBreak) {\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n }\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.adLayer.isAdPlaying();\n\n if (adPlaying) {\n this.adLayer.setAdVolume(clampedVolume);\n const preservedVolume = clampedVolume > 0 ? clampedVolume : this.adLayer.getOriginalVolume();\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, preservedVolume);\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 if (!this.inAdBreak) {\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n\n getVolume(): number {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n return this.adLayer.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.adLayer && this.adLayer.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.adLayer.resize(width, height);\n }\n }\n\n destroy(): void {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n 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.adLayer?.destroy();\n this.consecutiveFailures = 0;\n }\n}\n","import type { PrebidBidResponse, PrebidManager } from \"../types\";\n\nconst DEFAULT_TIMEOUT_MS = 3000;\nconst AUCTION_URL = \"https://sspproxy.adstorm.co/openrtb2/auction/adstorm\";\n\nexport interface PrebidManagerOptions {\n debug?: boolean;\n}\n\nexport function createPrebidManager(\n options: PrebidManagerOptions = {}\n): PrebidManager {\n let initialized = false;\n const debug = options.debug ?? false;\n\n function log(...args: any[]): void {\n if (debug) {\n console.log(\"[Prebid]\", ...args);\n }\n }\n\n function warn(...args: any[]): void {\n console.warn(\"[Prebid]\", ...args);\n }\n\n function parseResponse(data: any): PrebidBidResponse[] {\n const bids: PrebidBidResponse[] = [];\n const seatbids: any[] = data?.seatbid || [];\n const currency: string = data?.cur || \"USD\";\n\n for (const seatbid of seatbids) {\n const seat: string = seatbid.seat || \"unknown\";\n const bidArray: any[] = seatbid.bid || [];\n\n for (const bid of bidArray) {\n const cacheUrl: string | undefined =\n bid.ext?.prebid?.cache?.vastXml?.url;\n const vastXml: string | undefined = bid.adm || undefined;\n\n const bidResponse: PrebidBidResponse = {\n bidder: seat,\n cpm: bid.price || 0,\n width: bid.w || 0,\n height: bid.h || 0,\n adId: bid.id || \"\",\n impId: bid.impid || \"\",\n creativeId: bid.crid || \"\",\n currency,\n };\n if (cacheUrl) bidResponse.vastUrl = cacheUrl;\n if (vastXml) bidResponse.vastXml = vastXml;\n if (bid.adomain) bidResponse.adomain = bid.adomain;\n\n bids.push(bidResponse);\n }\n }\n\n bids.sort((a, b) => b.cpm - a.cpm);\n return bids;\n }\n\n async function initialize(): Promise<void> {\n if (initialized) return;\n initialized = true;\n log(\"Initialized, auction URL:\", AUCTION_URL);\n }\n\n async function requestBids(): Promise<PrebidBidResponse[]> {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n\n const timeout = DEFAULT_TIMEOUT_MS;\n\n log(\"Fetching auction response from:\", AUCTION_URL);\n\n const controller =\n typeof AbortController !== \"undefined\"\n ? new AbortController()\n : null;\n const timeoutId = setTimeout(() => {\n controller?.abort();\n }, timeout + 2000);\n\n try {\n const fetchOptions: RequestInit = {\n method: \"POST\",\n };\n if (controller) {\n fetchOptions.signal = controller.signal;\n }\n\n const response = await fetch(AUCTION_URL, fetchOptions);\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new Error(\n `Prebid Server returned HTTP ${response.status}: ${body.slice(0, 200)}`\n );\n }\n\n const data = await response.json();\n\n if (debug && data?.ext?.responsetimemillis) {\n log(\"Bidder response times:\", data.ext.responsetimemillis);\n }\n if (debug && data?.ext?.errors) {\n warn(\"Auction errors:\", data.ext.errors);\n }\n\n const bids = parseResponse(data);\n log(`Received ${bids.length} bid(s)`);\n\n if (debug) {\n for (const b of bids) {\n log(\n ` ${b.bidder}: $${b.cpm.toFixed(2)} ${b.currency}` +\n ` ${b.width}x${b.height}` +\n (b.vastUrl ? \" [cached VAST]\" : \"\") +\n (b.vastXml && !b.vastUrl ? \" [VAST XML]\" : \"\")\n );\n }\n }\n\n return bids;\n } catch (error: any) {\n clearTimeout(timeoutId);\n\n if (error?.name === \"AbortError\") {\n warn(`Auction request timed out after ${timeout + 2000}ms`);\n return [];\n }\n\n throw error;\n }\n }\n\n const REQUEST_BIDS_MAX_RETRIES = 3;\n const REQUEST_BIDS_BACKOFF_MS = 1500;\n\n async function requestBidsUntilResponse(): Promise<PrebidBidResponse[]> {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n let lastError: unknown;\n for (let attempt = 1; attempt <= REQUEST_BIDS_MAX_RETRIES; attempt++) {\n try {\n const bids = await requestBids();\n if (bids.length > 0) {\n log(`requestBidsUntilResponse: got ${bids.length} bid(s) on attempt ${attempt}`);\n return bids;\n }\n log(`requestBidsUntilResponse: no bids on attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES}`);\n } catch (err) {\n lastError = err;\n warn(`requestBidsUntilResponse: attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES} failed:`, err);\n }\n if (attempt < REQUEST_BIDS_MAX_RETRIES) {\n const delay = REQUEST_BIDS_BACKOFF_MS * attempt;\n log(`requestBidsUntilResponse: waiting ${delay}ms before retry`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n return [];\n }\n\n function destroy(): void {\n initialized = false;\n log(\"Destroyed\");\n }\n\n return {\n initialize,\n requestBids,\n requestBidsUntilResponse,\n destroy,\n get isInitialized() {\n return initialized;\n },\n };\n}\n","export interface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\nexport interface 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\nexport interface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport type MediaFileFilter = \"hls-only\" | \"mp4-first\" | \"all\";\n\nfunction isHlsType(type: string): boolean {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\n\nfunction isMp4Type(type: string): boolean {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\n\nexport function parseVastXml(\n xmlString: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): 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 `${logPrefix} 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(`${logPrefix} 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 Math.round(parseFloat(durationParts[2] || \"0\"));\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : undefined;\n\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible 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(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\n\nexport async function fetchAndParseVastAd(\n vastTagUrl: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\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(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml, filter, logPrefix);\n}\n\nexport function createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n}\n\nexport function fireTrackingPixels(\n urls: string[],\n sessionId?: string,\n logPrefix = \"[VastParser]\"\n): 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 const img = new Image(1, 1);\n img.onerror = () => {\n // 502 or other network errors are fire-and-forget; do not affect playback\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n","import type { PrebidBidResponse } from \"../types\";\nimport type { VastAd, VastMediaFile } from \"./vastParser\";\nimport {\n parseVastXml,\n fetchAndParseVastAd,\n fireTrackingPixels as fireTrackingPixelsShared,\n createEmptyTrackingState,\n} from \"./vastParser\";\nimport Hls from \"hls.js\";\n\nconst LOG = \"[PrebidAdLayer]\";\n\nexport interface PrebidAdLayerOptions {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls;\n debug?: boolean;\n}\n\nexport interface PrebidAdLayerOptionsUpdate {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls | null;\n}\n\nexport interface PrebidAdLayer {\n initialize: () => void;\n updateOptions: (opts: PrebidAdLayerOptionsUpdate) => void;\n playAd: (bids: PrebidBidResponse[]) => Promise<void>;\n pause: () => void;\n resume: () => void;\n stop: () => Promise<void>;\n destroy: () => void;\n isAdPlaying: () => boolean;\n resize: (width: number, height: number) => void;\n on: (event: string, listener: (payload?: any) => void) => void;\n off: (event: string, listener: (payload?: any) => void) => void;\n updateOriginalMutedState: (muted: boolean, volume?: number) => void;\n getOriginalMutedState: () => boolean;\n getOriginalVolume: () => number;\n setAdVolume: (volume: number) => void;\n getAdVolume: () => number;\n showPlaceholder: () => void;\n hidePlaceholder: () => void;\n}\n\nfunction resolveBidToVastAd(winner: PrebidBidResponse, logPrefix: string): Promise<VastAd | null> {\n if (winner.vastXml) {\n const ad = parseVastXml(winner.vastXml, \"mp4-first\", logPrefix);\n return Promise.resolve(ad);\n }\n if (winner.vastUrl) {\n return fetchAndParseVastAd(winner.vastUrl, \"mp4-first\", logPrefix);\n }\n return Promise.resolve(null);\n}\n\nexport function createPrebidAdLayer(\n contentVideo: HTMLVideoElement,\n options?: PrebidAdLayerOptions\n): PrebidAdLayer {\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 let mainHlsInstance: Hls | undefined = options?.mainHlsInstance;\n let continueLiveStreamDuringAds = options?.continueLiveStreamDuringAds ?? false;\n const debug = options?.debug ?? false;\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 let destroyed = false;\n let tornDown = false;\n let trackingFired = createEmptyTrackingState();\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(`${LOG} Error in event listener for ${event}:`, error);\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 fireTrackingPixelsShared(urls, sessionId, LOG);\n }\n\n function getMainStreamQuality(): { width: number; height: number; bitrate: number } | null {\n if (!mainHlsInstance?.levels) return null;\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 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) throw new Error(\"No media files available\");\n const firstFile = mediaFiles[0]!;\n if (mediaFiles.length === 1) return firstFile;\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n if (debug) console.log(`${LOG} No main stream quality info, using first media file`);\n return firstFile;\n }\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 const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n return { file, score };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n return scoredFiles[0]?.file ?? firstFile;\n }\n\n function isHlsMediaFile(file: VastMediaFile): boolean {\n return file.type === \"application/x-mpegURL\" || file.type.includes(\"m3u8\");\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 video.volume = 1.0;\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n const ad = currentAd;\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(ad.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n const ad = currentAd;\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(ad.trackingUrls.start);\n if (debug) console.log(`${LOG} Ad started playing`);\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (tornDown || !currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n if (debug) console.log(`${LOG} Ad completed`);\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels(currentAd.trackingUrls.error);\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd || !adVideoElement) 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 && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement && 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 if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad completion`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n emit(\"ad_impression\");\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad error`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n emit(\"ad_error\");\n }\n\n function teardownCurrentPlayback(): void {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n }\n\n function startNativePlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting native MP4 playback: ${mediaFile.url}`);\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native ad playback:`, error);\n handleAdError();\n });\n }\n\n function startHlsPlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting HLS playback: ${mediaFile.url}`);\n\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n adHls = new Hls({ enableWorker: true, lowLatencyMode: false });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n adVideoElement!.play().catch((error) => {\n console.error(`${LOG} Error starting HLS ad playback:`, error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (_event, data) => {\n if (data.fatal) handleAdError();\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native HLS ad playback:`, error);\n handleAdError();\n });\n } else {\n console.error(`${LOG} HLS not supported on this platform`);\n handleAdError();\n }\n }\n\n function startPlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (isHlsMediaFile(mediaFile)) {\n startHlsPlayback(mediaFile);\n } else {\n startNativePlayback(mediaFile);\n }\n }\n\n async function playAd(bids: PrebidBidResponse[]): Promise<void> {\n if (destroyed) {\n return Promise.reject(new Error(\"Layer has been destroyed\"));\n }\n if (bids.length === 0) {\n return Promise.reject(new Error(\"No bids provided\"));\n }\n\n const winner = bids[0]!;\n if (debug) {\n console.log(`${LOG} Winning bid: ${winner.bidder} $${winner.cpm.toFixed(2)} ${winner.currency}`);\n }\n\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad) {\n if (debug) console.warn(`${LOG} Winning bid has no VAST URL or XML`);\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No VAST from bid\"));\n }\n\n if (debug) {\n console.log(`${LOG} Ad parsed: ${ad.title}, duration: ${ad.duration}s, mediaFiles: ${ad.mediaFiles.length}`);\n }\n\n sessionId = generateSessionId();\n currentAd = ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\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 contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n setupAdEventListeners();\n } else {\n teardownCurrentPlayback();\n }\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n const adVolume = originalMutedState ? 1 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\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(ad.mediaFiles);\n if (debug) console.log(`${LOG} Loading ad from: ${mediaFile.url}`);\n startPlayback(mediaFile);\n }\n\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n\n updateOptions(opts: PrebidAdLayerOptionsUpdate) {\n if (opts.continueLiveStreamDuringAds !== undefined) {\n continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;\n }\n if (opts.mainHlsInstance !== undefined) {\n mainHlsInstance = opts.mainHlsInstance ?? undefined;\n }\n },\n\n playAd,\n\n pause() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (!adVideoElement.paused) adVideoElement.pause();\n } catch (error) {\n if (debug) console.warn(`${LOG} Error pausing ad:`, error);\n }\n },\n\n resume() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (adVideoElement.paused) adVideoElement.play().catch(() => {});\n } catch (error) {\n if (debug) console.warn(`${LOG} Error resuming ad:`, error);\n }\n },\n\n async stop() {\n tornDown = true;\n if (debug) console.log(`${LOG} Stopping ad`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n }\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n currentAd = undefined;\n tornDown = false;\n },\n\n destroy() {\n tornDown = true;\n if (debug) console.log(`${LOG} Destroying`);\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\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\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 originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\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\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\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","import type {\n ClientInfo,\n TrackingData,\n HeartbeatData,\n AdDetectInfo,\n AdLoadedInfo,\n AdImpressionInfo,\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 TRACK_URL =\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\n\nasync function sendTrackRequest(\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_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 sendInitialTracking(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const trackingData: TrackingData = {\n browserId,\n ...clientInfo,\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(TRACK_URL, {\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\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 sendAdDetectTracking(\n licenseKey: string | undefined,\n adDetectInfo: AdDetectInfo\n): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adDetectInfo,\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adLoadedInfo,\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adImpressionInfo,\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\n\nexport async function sendHeartbeat(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const heartbeatData: HeartbeatData = {\n browserId,\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\n } catch (error) {\n console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n }\n}\n","export function polyfillURLSearchParams(): void {\n if (typeof URLSearchParams !== 'undefined') {\n return;\n }\n\n class URLSearchParamsPolyfill {\n private params: Map<string, string[]>;\n\n constructor(init?: string | URLSearchParamsPolyfill) {\n this.params = new Map();\n\n if (typeof init === 'string') {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n\n private parseQueryString(query: string): void {\n const cleanQuery = query.startsWith('?') ? query.slice(1) : query;\n if (!cleanQuery) return;\n\n cleanQuery.split('&').forEach((param) => {\n const [key, value] = param.split('=');\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : '';\n this.append(decodedKey, decodedValue);\n }\n });\n }\n\n private safeDecodeURIComponent(str: string): string {\n try {\n return decodeURIComponent(str.replace(/\\+/g, ' '));\n } catch (e) {\n return str;\n }\n }\n\n append(name: string, value: string): void {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n\n delete(name: string): void {\n this.params.delete(name);\n }\n\n get(name: string): string | null {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== undefined ? values[0] : null;\n }\n\n getAll(name: string): string[] {\n return this.params.get(name) || [];\n }\n\n has(name: string): boolean {\n return this.params.has(name);\n }\n\n set(name: string, value: string): void {\n this.params.set(name, [String(value)]);\n }\n\n forEach(callback: (value: string, key: string, parent: URLSearchParamsPolyfill) => void): void {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n\n toString(): string {\n const parts: string[] = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join('&');\n }\n }\n\n // @ts-ignore\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\n\nexport function polyfillTextEncoder(): void {\n if (typeof TextEncoder !== 'undefined') {\n return;\n }\n\n class TextEncoderPolyfill {\n encoding = 'utf-8';\n\n encode(str: string): Uint8Array {\n const utf8: number[] = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 0x80) {\n utf8.push(charcode);\n } else if (charcode < 0x800) {\n utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));\n } else if (charcode < 0xd800 || charcode >= 0xe000) {\n utf8.push(\n 0xe0 | (charcode >> 12),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n } else {\n i++;\n charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));\n utf8.push(\n 0xf0 | (charcode >> 18),\n 0x80 | ((charcode >> 12) & 0x3f),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n\n // @ts-ignore\n window.TextEncoder = TextEncoderPolyfill;\n}\n\nexport function polyfillPromiseFinally(): void {\n if (typeof Promise !== 'undefined' && !Promise.prototype.finally) {\n Promise.prototype.finally = function (callback: () => void) {\n const constructor = this.constructor as PromiseConstructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) =>\n constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\n\nexport function polyfillObjectAssign(): void {\n if (typeof Object.assign !== 'function') {\n Object.assign = function (target: any, ...sources: any[]) {\n if (target == null) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n const to = Object(target);\n\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n\n return to;\n };\n }\n}\n\nexport function polyfillArrayFrom(): void {\n if (!Array.from) {\n Array.from = function (arrayLike: any, mapFn?: any, thisArg?: any) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object');\n }\n\n const len = items.length >>> 0;\n const result = new Array(len);\n\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n\n return result;\n };\n }\n}\n\nexport function polyfillStringStartsWith(): void {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function (search: string, pos?: number) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\n\nexport function polyfillStringEndsWith(): void {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function (search: string, length?: number) {\n if (length === undefined || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\n\nexport function polyfillStringIncludes(): void {\n if (!String.prototype.includes) {\n String.prototype.includes = function (search: string, start?: number) {\n if (typeof start !== 'number') {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\n\nexport function initializePolyfills(): void {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n","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 allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: { allowNativeHls?: boolean } = {};\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function 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"]}
|