stormcloud-video-player 0.6.1 → 0.6.2

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.
@@ -599,7 +599,7 @@ function resolveBidToVastAd(winner, logPrefix) {
599
599
  return Promise.resolve(null);
600
600
  }
601
601
  function createVastAdLayer(contentVideo, options) {
602
- var _ref, _ref1, _ref2, _ref3;
602
+ var _ref, _ref1, _ref2, _ref3, _ref4;
603
603
  var adPlaying = false;
604
604
  var originalMutedState = false;
605
605
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
@@ -608,7 +608,8 @@ function createVastAdLayer(contentVideo, options) {
608
608
  var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
609
609
  var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
610
610
  var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
611
- var debug = (_ref3 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref3 !== void 0 ? _ref3 : false;
611
+ var forceMP4Ads = (_ref3 = options === null || options === void 0 ? void 0 : options.forceMP4Ads) !== null && _ref3 !== void 0 ? _ref3 : smartTVMode || singleElementMode;
612
+ var debug = (_ref4 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref4 !== void 0 ? _ref4 : false;
612
613
  var adVideoElement;
613
614
  var adHls;
614
615
  var adContainerEl;
@@ -679,14 +680,26 @@ function createVastAdLayer(contentVideo, options) {
679
680
  var _ref;
680
681
  var _scoredFiles_;
681
682
  if (mediaFiles.length === 0) throw new Error("No media files available");
682
- var firstFile = mediaFiles[0];
683
- if (mediaFiles.length === 1) return firstFile;
683
+ var candidates = mediaFiles;
684
+ if (forceMP4Ads) {
685
+ var mp4Only = candidates.filter(function(f) {
686
+ return !isHlsMediaFile(f);
687
+ });
688
+ if (mp4Only.length > 0) {
689
+ candidates = mp4Only;
690
+ if (debug) console.log("".concat(LOG, " forceMP4Ads: filtered to ").concat(mp4Only.length, " MP4-only file(s)"));
691
+ } else if (debug) {
692
+ console.warn("".concat(LOG, " forceMP4Ads: no MP4 files available, falling back to all media files"));
693
+ }
694
+ }
695
+ var firstFile = candidates[0];
696
+ if (candidates.length === 1) return firstFile;
684
697
  var mainQuality = getMainStreamQuality();
685
698
  if (!mainQuality) {
686
699
  if (debug) console.log("".concat(LOG, " No main stream quality info, using first media file"));
687
700
  return firstFile;
688
701
  }
689
- var scoredFiles = mediaFiles.map(function(file) {
702
+ var scoredFiles = candidates.map(function(file) {
690
703
  var widthDiff = Math.abs(file.width - mainQuality.width);
691
704
  var heightDiff = Math.abs(file.height - mainQuality.height);
692
705
  var resolutionDiff = widthDiff + heightDiff;
@@ -903,6 +916,16 @@ function createVastAdLayer(contentVideo, options) {
903
916
  }
904
917
  function startPlayback(mediaFile) {
905
918
  if (!adVideoElement) return;
919
+ if (singleElementMode && isHlsMediaFile(mediaFile)) {
920
+ var mp4Fallback = currentAd === null || currentAd === void 0 ? void 0 : currentAd.mediaFiles.find(function(f) {
921
+ return !isHlsMediaFile(f);
922
+ });
923
+ if (mp4Fallback) {
924
+ if (debug) console.log("".concat(LOG, " singleElementMode: HLS ad blocked, using MP4 fallback"));
925
+ startNativePlayback(mp4Fallback);
926
+ return;
927
+ }
928
+ }
906
929
  if (isHlsMediaFile(mediaFile)) {
907
930
  startHlsPlayback(mediaFile);
908
931
  } else {
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/sdk/vastAdLayer.cjs","../../src/sdk/vastAdLayer.ts","../../src/sdk/vastParser.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","hasOwnProperty","prototype","__export","target","all","name","get","enumerable","__copyProps","from","to","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","vastAdLayer_exports","createVastAdLayer","module","exports","isHlsType","type","includes","isMp4Type","parseVastXml","xmlString","filter","logPrefix","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","console","error","textContent","adElement","warn","adId","getAttribute","title","isNoAdAvailable","toLowerCase","durationText","durationParts","split","duration","parseInt","Math","round","parseFloat","mediaFileElements","querySelectorAll","mediaFiles","log","length","forEach","mf","index","url","trim","width","height","substring","isHls","isMp4","accepted","bitrateAttr","bitrateValue","push","bitrate","sort","a","b","aIsMp4","bIsMp4","trackingUrls","impression","start","firstQuartile","midpoint","thirdQuartile","complete","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","el","event","eventKey","clickThrough","id","fetchAndParseVastAd","vastTagUrl","response","vastXml","fetch","mode","credentials","headers","Accept","referrerPolicy","ok","Error","statusText","text","createEmptyTrackingState","firePixelWithRetry","retries","delayMs","attempt","method","cache","keepalive","Promise","r","setTimeout","pow","fireTrackingPixels","listeners","adContainerEl","urls","sessionId","trackingUrl","catch","img","Image","onerror","src","import_hls","require","LOG","resolveBidToVastAd","winner","ad","resolve","vastUrl","contentVideo","options","adPlaying","originalMutedState","originalVolume","max","min","volume","Map","mainHlsInstance","continueLiveStreamDuringAds","smartTVMode","singleElementMode","debug","adVideoElement","adHls","currentAd","destroyed","tornDown","trackingFired","currentAdEventHandlers","preloadSlots","emit","payload","set","Array","fn","getMainStreamQuality","currentLevel","scoredFiles","generateSessionId","Date","now","random","toString","substr","levels","autoLevel","loadLevel","level","selectBestMediaFile","firstFile","mainQuality","map","file","widthDiff","abs","video","muted","progress","volumechange","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","isHlsMediaFile","createAdVideoElement","document","createElement","style","position","left","top","objectFit","backgroundColor","playsInline","removeAdEventListeners","removeEventListener","timeupdate","playing","ended","play","setupAdEventListeners","handlers","currentTime","handleAdComplete","e","handleAdError","addEventListener","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","teardownCurrentPlayback","destroy","removeAttribute","load","startNativePlayback","mediaFile","startHlsPlayback","Hls","isSupported","enableWorker","lowLatencyMode","loadSource","attachMedia","on","Events","MANIFEST_PARSED","nonFatalNetworkErrors","ERROR","_event","data","fatal","ErrorTypes","NETWORK_ERROR","canPlayType","startPlayback","playAd","bids","contentVolume","container","adVolume","reject","bidder","cpm","toFixed","currency","detachMedia","right","bottom","alignItems","justifyContent","zIndex","parentElement","appendChild"],"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/sdk/vastAdLayer.ts\nvar vastAdLayer_exports = {};\n__export(vastAdLayer_exports, {\n createVastAdLayer: () => createVastAdLayer\n});\nmodule.exports = __toCommonJS(vastAdLayer_exports);\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}\nasync function firePixelWithRetry(url, retries = 2, delayMs = 500, logPrefix = \"[VastParser]\") {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n await fetch(url, {\n method: \"GET\",\n mode: \"no-cors\",\n cache: \"no-cache\",\n keepalive: true\n });\n return;\n } catch {\n if (attempt < retries) {\n await new Promise((r) => setTimeout(r, delayMs * Math.pow(2, attempt)));\n } else {\n console.warn(`${logPrefix} Tracking pixel failed after ${retries + 1} attempts: ${url}`);\n }\n }\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 if (typeof fetch !== \"undefined\") {\n firePixelWithRetry(trackingUrl, 2, 500, logPrefix).catch(() => {\n });\n } else {\n const img = new Image(1, 1);\n img.onerror = () => {\n };\n img.src = trackingUrl;\n }\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/vastAdLayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar LOG = \"[VastAdLayer]\";\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 createVastAdLayer(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 smartTVMode = options?.smartTVMode ?? false;\n const singleElementMode = options?.singleElementMode ?? 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 let currentAdEventHandlers;\n const preloadSlots = /* @__PURE__ */ new Map();\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 removeAdEventListeners() {\n if (!currentAdEventHandlers || !adVideoElement) return;\n const el = adVideoElement;\n el.removeEventListener(\"timeupdate\", currentAdEventHandlers.timeupdate);\n el.removeEventListener(\"playing\", currentAdEventHandlers.playing);\n el.removeEventListener(\"ended\", currentAdEventHandlers.ended);\n el.removeEventListener(\"error\", currentAdEventHandlers.error);\n el.removeEventListener(\"volumechange\", currentAdEventHandlers.volumechange);\n el.removeEventListener(\"pause\", currentAdEventHandlers.pause);\n el.removeEventListener(\"play\", currentAdEventHandlers.play);\n currentAdEventHandlers = void 0;\n }\n function setupAdEventListeners() {\n if (!adVideoElement) return;\n removeAdEventListeners();\n const handlers = {\n 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 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 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 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 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 pause: () => {\n if (currentAd && adVideoElement && !adVideoElement.ended) {\n fireTrackingPixels2(currentAd.trackingUrls.pause);\n }\n },\n play: () => {\n if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {\n fireTrackingPixels2(currentAd.trackingUrls.resume);\n }\n }\n };\n adVideoElement.addEventListener(\"timeupdate\", handlers.timeupdate);\n adVideoElement.addEventListener(\"playing\", handlers.playing);\n adVideoElement.addEventListener(\"ended\", handlers.ended);\n adVideoElement.addEventListener(\"error\", handlers.error);\n adVideoElement.addEventListener(\"volumechange\", handlers.volumechange);\n adVideoElement.addEventListener(\"pause\", handlers.pause);\n adVideoElement.addEventListener(\"play\", handlers.play);\n currentAdEventHandlers = handlers;\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 (!adPlaying) 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 removeAdEventListeners();\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n if (singleElementMode && adVideoElement === contentVideo) {\n contentVideo.pause();\n } else {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\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 let nonFatalNetworkErrors = 0;\n adHls.on(import_hls.default.Events.ERROR, (_event, data) => {\n if (data.fatal) {\n handleAdError();\n } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {\n nonFatalNetworkErrors++;\n if (nonFatalNetworkErrors >= 3) {\n if (debug) console.warn(`${LOG} Too many non-fatal HLS network errors (${nonFatalNetworkErrors}), treating as fatal`);\n handleAdError();\n }\n }\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 const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n if (singleElementMode) {\n mainHlsInstance?.detachMedia();\n teardownCurrentPlayback();\n adVideoElement = contentVideo;\n adHls = void 0;\n setupAdEventListeners();\n } else {\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 }\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 (!singleElementMode && 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 function ensureAdContainer() {\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 return adContainerEl;\n }\n async function preloadAd(bids, token) {\n if (destroyed) return;\n const winner = bids[0];\n if (!winner) return;\n if (debug) console.log(`${LOG} [preload] Resolving VAST for token=${token}`);\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad || destroyed) return;\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (!mediaFile) return;\n if (smartTVMode || singleElementMode) {\n const slot = { bids, ad, mediaFile, videoEl: null, ready: true };\n preloadSlots.set(token, slot);\n if (debug) console.log(`${LOG} [preload] Metadata-only preload (smartTV/singleElement), token=${token}, url=${mediaFile.url}`);\n return;\n }\n const videoEl = createAdVideoElement();\n videoEl.style.visibility = \"hidden\";\n videoEl.style.pointerEvents = \"none\";\n videoEl.preload = \"auto\";\n const container = ensureAdContainer();\n container.appendChild(videoEl);\n if (isHlsMediaFile(mediaFile) && import_hls.default.isSupported()) {\n const hls = new import_hls.default({ enableWorker: true, lowLatencyMode: false });\n hls.loadSource(mediaFile.url);\n hls.attachMedia(videoEl);\n const slot = { bids, ad, mediaFile, videoEl, hlsInstance: hls, ready: false };\n preloadSlots.set(token, slot);\n hls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n const s = preloadSlots.get(token);\n if (s) s.ready = true;\n if (debug) console.log(`${LOG} [preload] HLS manifest parsed, token=${token}`);\n });\n hls.on(import_hls.default.Events.ERROR, (_evt, data) => {\n if (data.fatal) {\n if (debug) console.warn(`${LOG} [preload] HLS error for token=${token}`);\n preloadSlots.delete(token);\n hls.destroy();\n videoEl.remove();\n }\n });\n } else {\n videoEl.src = mediaFile.url;\n videoEl.load();\n const slot = { bids, ad, mediaFile, videoEl, ready: false };\n preloadSlots.set(token, slot);\n videoEl.addEventListener(\"canplay\", () => {\n const s = preloadSlots.get(token);\n if (s) s.ready = true;\n if (debug) console.log(`${LOG} [preload] canplay fired, token=${token}`);\n }, { once: true });\n }\n if (debug) console.log(`${LOG} [preload] Started buffering token=${token}, url=${mediaFile.url}`);\n }\n async function playPreloaded(token) {\n if (destroyed) return Promise.reject(new Error(\"Layer has been destroyed\"));\n const slot = preloadSlots.get(token);\n if (!slot) {\n if (debug) console.warn(`${LOG} [preload] No slot found for token=${token}, nothing to play`);\n return;\n }\n preloadSlots.delete(token);\n if (debug) console.log(`${LOG} [preload] Playing preloaded ad, token=${token}, ready=${slot.ready}`);\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n sessionId = generateSessionId();\n currentAd = slot.ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels2(slot.ad.trackingUrls.impression);\n trackingFired.impression = true;\n if (singleElementMode) {\n mainHlsInstance?.detachMedia();\n teardownCurrentPlayback();\n adVideoElement = contentVideo;\n adHls = void 0;\n setupAdEventListeners();\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume2 = originalMutedState ? 1 : originalVolume;\n contentVideo.volume = Math.max(0, Math.min(1, adVolume2));\n contentVideo.muted = false;\n emit(\"content_pause\");\n if (debug) console.log(`${LOG} [preload] singleElementMode: attaching ad to contentVideo, url=${slot.mediaFile.url}`);\n startPlayback(slot.mediaFile);\n return;\n }\n if (smartTVMode && !slot.videoEl) {\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n const videoEl = createAdVideoElement();\n videoEl.style.visibility = \"visible\";\n videoEl.style.pointerEvents = \"none\";\n const container2 = ensureAdContainer();\n container2.appendChild(videoEl);\n adVideoElement = videoEl;\n setupAdEventListeners();\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume2 = originalMutedState ? 1 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume2));\n adVideoElement.muted = false;\n container2.style.display = \"flex\";\n container2.style.pointerEvents = \"auto\";\n emit(\"content_pause\");\n if (debug) console.log(`${LOG} [preload] smartTVMode deferred: creating video element and loading, url=${slot.mediaFile.url}`);\n startPlayback(slot.mediaFile);\n return;\n }\n teardownCurrentPlayback();\n if (adVideoElement && adVideoElement !== slot.videoEl) {\n adVideoElement.remove();\n }\n slot.videoEl.style.visibility = \"visible\";\n slot.videoEl.style.pointerEvents = \"none\";\n adVideoElement = slot.videoEl;\n adHls = slot.hlsInstance;\n setupAdEventListeners();\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 const container = ensureAdContainer();\n container.style.display = \"flex\";\n container.style.pointerEvents = \"auto\";\n emit(\"content_pause\");\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} [preload] Error playing preloaded ad:`, error);\n handleAdError();\n });\n }\n function cancelPreload(token) {\n const slot = preloadSlots.get(token);\n if (!slot) return;\n preloadSlots.delete(token);\n if (slot.hlsInstance) {\n slot.hlsInstance.destroy();\n }\n if (slot.videoEl) {\n slot.videoEl.pause();\n slot.videoEl.removeAttribute(\"src\");\n slot.videoEl.load();\n slot.videoEl.remove();\n }\n if (debug) console.log(`${LOG} [preload] Cancelled and cleaned up token=${token}`);\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 preloadAd,\n playPreloaded,\n hasPreloaded(token) {\n return preloadSlots.has(token);\n },\n cancelPreload,\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 contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (singleElementMode) {\n teardownCurrentPlayback();\n contentVideo.removeAttribute(\"src\");\n contentVideo.load();\n adVideoElement = void 0;\n } else {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\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 }\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 for (const [token] of Array.from(preloadSlots.entries())) {\n cancelPreload(token);\n }\n teardownCurrentPlayback();\n if (adVideoElement) {\n if (singleElementMode && adVideoElement === contentVideo) {\n contentVideo.removeAttribute(\"src\");\n contentVideo.load();\n } else {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.remove();\n }\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// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createVastAdLayer\n});\n","import type { VastBidResponse } 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 = \"[VastAdLayer]\";\n\nexport interface VastAdLayerOptions {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls;\n smartTVMode?: boolean;\n singleElementMode?: boolean;\n debug?: boolean;\n}\n\nexport interface VastAdLayerOptionsUpdate {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls | null;\n}\n\nexport interface VastAdLayer {\n initialize: () => void;\n updateOptions: (opts: VastAdLayerOptionsUpdate) => void;\n playAd: (bids: VastBidResponse[]) => Promise<void>;\n preloadAd: (bids: VastBidResponse[], token: string) => Promise<void>;\n playPreloaded: (token: string) => Promise<void>;\n hasPreloaded: (token: string) => boolean;\n cancelPreload: (token: string) => 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: VastBidResponse, 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 createVastAdLayer(\n contentVideo: HTMLVideoElement,\n options?: VastAdLayerOptions\n): VastAdLayer {\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 smartTVMode = options?.smartTVMode ?? false;\n const singleElementMode = options?.singleElementMode ?? 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 type AdEventHandlers = {\n timeupdate: () => void;\n playing: () => void;\n ended: () => void;\n error: (e: Event) => void;\n volumechange: () => void;\n pause: () => void;\n play: () => void;\n };\n let currentAdEventHandlers: AdEventHandlers | undefined;\n\n interface PreloadSlot {\n bids: VastBidResponse[];\n ad: VastAd;\n mediaFile: VastMediaFile;\n videoEl: HTMLVideoElement | null;\n hlsInstance?: Hls;\n ready: boolean;\n }\n const preloadSlots = new Map<string, PreloadSlot>();\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 removeAdEventListeners(): void {\n if (!currentAdEventHandlers || !adVideoElement) return;\n const el = adVideoElement;\n el.removeEventListener(\"timeupdate\", currentAdEventHandlers.timeupdate);\n el.removeEventListener(\"playing\", currentAdEventHandlers.playing);\n el.removeEventListener(\"ended\", currentAdEventHandlers.ended);\n el.removeEventListener(\"error\", currentAdEventHandlers.error);\n el.removeEventListener(\"volumechange\", currentAdEventHandlers.volumechange);\n el.removeEventListener(\"pause\", currentAdEventHandlers.pause);\n el.removeEventListener(\"play\", currentAdEventHandlers.play);\n currentAdEventHandlers = undefined;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement) return;\n\n removeAdEventListeners();\n\n const handlers: AdEventHandlers = {\n 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 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 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 error: (e: Event) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels(currentAd.trackingUrls.error);\n handleAdError();\n },\n 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 pause: () => {\n if (currentAd && adVideoElement && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n },\n play: () => {\n if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n },\n };\n\n adVideoElement.addEventListener(\"timeupdate\", handlers.timeupdate);\n adVideoElement.addEventListener(\"playing\", handlers.playing);\n adVideoElement.addEventListener(\"ended\", handlers.ended);\n adVideoElement.addEventListener(\"error\", handlers.error);\n adVideoElement.addEventListener(\"volumechange\", handlers.volumechange);\n adVideoElement.addEventListener(\"pause\", handlers.pause);\n adVideoElement.addEventListener(\"play\", handlers.play);\n\n currentAdEventHandlers = handlers;\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 (!adPlaying) 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 removeAdEventListeners();\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n if (singleElementMode && adVideoElement === contentVideo) {\n contentVideo.pause();\n } else {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\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 let nonFatalNetworkErrors = 0;\n adHls.on(Hls.Events.ERROR, (_event, data) => {\n if (data.fatal) {\n handleAdError();\n } else if (data.type === Hls.ErrorTypes.NETWORK_ERROR) {\n nonFatalNetworkErrors++;\n if (nonFatalNetworkErrors >= 3) {\n if (debug) console.warn(`${LOG} Too many non-fatal HLS network errors (${nonFatalNetworkErrors}), treating as fatal`);\n handleAdError();\n }\n }\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: VastBidResponse[]): 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 const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n\n if (singleElementMode) {\n mainHlsInstance?.detachMedia();\n\n teardownCurrentPlayback();\n\n adVideoElement = contentVideo;\n adHls = undefined;\n setupAdEventListeners();\n } else {\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\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 (!singleElementMode && 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 function ensureAdContainer(): HTMLDivElement {\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 return adContainerEl;\n }\n\n async function preloadAd(bids: VastBidResponse[], token: string): Promise<void> {\n if (destroyed) return;\n const winner = bids[0];\n if (!winner) return;\n\n if (debug) console.log(`${LOG} [preload] Resolving VAST for token=${token}`);\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad || destroyed) return;\n\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (!mediaFile) return;\n\n if (smartTVMode || singleElementMode) {\n const slot: PreloadSlot = { bids, ad, mediaFile, videoEl: null, ready: true };\n preloadSlots.set(token, slot);\n if (debug) console.log(`${LOG} [preload] Metadata-only preload (smartTV/singleElement), token=${token}, url=${mediaFile.url}`);\n return;\n }\n\n const videoEl = createAdVideoElement();\n videoEl.style.visibility = \"hidden\";\n videoEl.style.pointerEvents = \"none\";\n videoEl.preload = \"auto\";\n\n const container = ensureAdContainer();\n container.appendChild(videoEl);\n\n if (isHlsMediaFile(mediaFile) && Hls.isSupported()) {\n const hls = new Hls({ enableWorker: true, lowLatencyMode: false });\n hls.loadSource(mediaFile.url);\n hls.attachMedia(videoEl);\n const slot: PreloadSlot = { bids, ad, mediaFile, videoEl, hlsInstance: hls, ready: false };\n preloadSlots.set(token, slot);\n hls.on(Hls.Events.MANIFEST_PARSED, () => {\n const s = preloadSlots.get(token);\n if (s) s.ready = true;\n if (debug) console.log(`${LOG} [preload] HLS manifest parsed, token=${token}`);\n });\n hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data.fatal) {\n if (debug) console.warn(`${LOG} [preload] HLS error for token=${token}`);\n preloadSlots.delete(token);\n hls.destroy();\n videoEl.remove();\n }\n });\n } else {\n videoEl.src = mediaFile.url;\n videoEl.load();\n const slot: PreloadSlot = { bids, ad, mediaFile, videoEl, ready: false };\n preloadSlots.set(token, slot);\n videoEl.addEventListener(\"canplay\", () => {\n const s = preloadSlots.get(token);\n if (s) s.ready = true;\n if (debug) console.log(`${LOG} [preload] canplay fired, token=${token}`);\n }, { once: true });\n }\n\n if (debug) console.log(`${LOG} [preload] Started buffering token=${token}, url=${mediaFile.url}`);\n }\n\n async function playPreloaded(token: string): Promise<void> {\n if (destroyed) return Promise.reject(new Error(\"Layer has been destroyed\"));\n\n const slot = preloadSlots.get(token);\n if (!slot) {\n if (debug) console.warn(`${LOG} [preload] No slot found for token=${token}, nothing to play`);\n return;\n }\n preloadSlots.delete(token);\n\n if (debug) console.log(`${LOG} [preload] Playing preloaded ad, token=${token}, ready=${slot.ready}`);\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n\n sessionId = generateSessionId();\n currentAd = slot.ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels(slot.ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n if (singleElementMode) {\n mainHlsInstance?.detachMedia();\n\n teardownCurrentPlayback();\n\n adVideoElement = contentVideo;\n adHls = undefined;\n setupAdEventListeners();\n\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n const adVolume = originalMutedState ? 1 : originalVolume;\n contentVideo.volume = Math.max(0, Math.min(1, adVolume));\n contentVideo.muted = false;\n\n emit(\"content_pause\");\n\n if (debug) console.log(`${LOG} [preload] singleElementMode: attaching ad to contentVideo, url=${slot.mediaFile.url}`);\n startPlayback(slot.mediaFile);\n return;\n }\n\n if (smartTVMode && !slot.videoEl) {\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n const videoEl = createAdVideoElement();\n videoEl.style.visibility = \"visible\";\n videoEl.style.pointerEvents = \"none\";\n\n const container = ensureAdContainer();\n container.appendChild(videoEl);\n adVideoElement = videoEl;\n\n setupAdEventListeners();\n\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\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 container.style.display = \"flex\";\n container.style.pointerEvents = \"auto\";\n\n emit(\"content_pause\");\n\n if (debug) console.log(`${LOG} [preload] smartTVMode deferred: creating video element and loading, url=${slot.mediaFile.url}`);\n startPlayback(slot.mediaFile);\n return;\n }\n\n teardownCurrentPlayback();\n\n if (adVideoElement && adVideoElement !== slot.videoEl) {\n adVideoElement.remove();\n }\n\n slot.videoEl!.style.visibility = \"visible\";\n slot.videoEl!.style.pointerEvents = \"none\";\n adVideoElement = slot.videoEl!;\n adHls = slot.hlsInstance;\n\n setupAdEventListeners();\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 const container = ensureAdContainer();\n container.style.display = \"flex\";\n container.style.pointerEvents = \"auto\";\n\n emit(\"content_pause\");\n\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} [preload] Error playing preloaded ad:`, error);\n handleAdError();\n });\n }\n\n function cancelPreload(token: string): void {\n const slot = preloadSlots.get(token);\n if (!slot) return;\n preloadSlots.delete(token);\n if (slot.hlsInstance) {\n slot.hlsInstance.destroy();\n }\n if (slot.videoEl) {\n slot.videoEl.pause();\n slot.videoEl.removeAttribute(\"src\");\n slot.videoEl.load();\n slot.videoEl.remove();\n }\n if (debug) console.log(`${LOG} [preload] Cancelled and cleaned up token=${token}`);\n }\n\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n\n updateOptions(opts: VastAdLayerOptionsUpdate) {\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 preloadAd,\n playPreloaded,\n hasPreloaded(token: string): boolean {\n return preloadSlots.has(token);\n },\n cancelPreload,\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 contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n\n if (singleElementMode) {\n // In singleElementMode the ad was playing on contentVideo. Tear down the\n // ad HLS and clear contentVideo so it is ready for main HLS re-attachment\n // in handleAdPodComplete (hls.attachMedia → MANIFEST_PARSED → play).\n // Do NOT call contentVideo.play() here — playback is restored by the player.\n teardownCurrentPlayback();\n contentVideo.removeAttribute(\"src\");\n contentVideo.load();\n adVideoElement = undefined;\n } else {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\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 }\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 for (const [token] of Array.from(preloadSlots.entries())) {\n cancelPreload(token);\n }\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n if (singleElementMode && adVideoElement === contentVideo) {\n // contentVideo belongs to the host page — do not remove it from the DOM.\n contentVideo.removeAttribute(\"src\");\n contentVideo.load();\n } else {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.remove();\n }\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","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\nasync function firePixelWithRetry(\n url: string,\n retries = 2,\n delayMs = 500,\n logPrefix = \"[VastParser]\"\n): Promise<void> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n await fetch(url, {\n method: \"GET\",\n mode: \"no-cors\",\n cache: \"no-cache\",\n keepalive: true,\n });\n return;\n } catch {\n if (attempt < retries) {\n await new Promise((r) => setTimeout(r, delayMs * Math.pow(2, attempt)));\n } else {\n console.warn(`${logPrefix} Tracking pixel failed after ${retries + 1} attempts: ${url}`);\n }\n }\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 if (typeof fetch !== \"undefined\") {\n firePixelWithRetry(trackingUrl, 2, 500, logPrefix).catch(() => {});\n } else {\n const img = new Image(1, 1);\n img.onerror = () => {};\n img.src = trackingUrl;\n }\n\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n"]}
1
+ {"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/sdk/vastAdLayer.cjs","../../src/sdk/vastAdLayer.ts","../../src/sdk/vastParser.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","hasOwnProperty","prototype","__export","target","all","name","get","enumerable","__copyProps","from","to","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","vastAdLayer_exports","createVastAdLayer","module","exports","isHlsType","type","includes","isMp4Type","parseVastXml","xmlString","filter","logPrefix","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","console","error","textContent","adElement","warn","adId","getAttribute","title","isNoAdAvailable","toLowerCase","durationText","durationParts","split","duration","parseInt","Math","round","parseFloat","mediaFileElements","querySelectorAll","mediaFiles","log","length","forEach","mf","index","url","trim","width","height","substring","isHls","isMp4","accepted","bitrateAttr","bitrateValue","push","bitrate","sort","a","b","aIsMp4","bIsMp4","trackingUrls","impression","start","firstQuartile","midpoint","thirdQuartile","complete","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","el","event","eventKey","clickThrough","id","fetchAndParseVastAd","vastTagUrl","response","vastXml","fetch","mode","credentials","headers","Accept","referrerPolicy","ok","Error","statusText","text","createEmptyTrackingState","firePixelWithRetry","retries","delayMs","attempt","method","cache","keepalive","Promise","r","setTimeout","pow","mainHlsInstance","set","fireTrackingPixels","urls","sessionId","trackingUrl","catch","img","Image","onerror","src","import_hls","require","LOG","resolveBidToVastAd","winner","ad","resolve","vastUrl","contentVideo","options","adPlaying","originalMutedState","originalVolume","max","min","volume","listeners","Map","continueLiveStreamDuringAds","smartTVMode","singleElementMode","forceMP4Ads","debug","adVideoElement","adHls","adContainerEl","currentAd","destroyed","tornDown","trackingFired","currentAdEventHandlers","preloadSlots","emit","payload","Array","fn","generateSessionId","Date","now","random","toString","substr","level","scoredFiles","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","selectBestMediaFile","candidates","mp4Only","f","isHlsMediaFile","firstFile","mainQuality","map","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","timeupdate","progress","createAdVideoElement","video","document","createElement","style","position","left","top","objectFit","backgroundColor","playsInline","muted","removeAdEventListeners","removeEventListener","playing","ended","volumechange","play","setupAdEventListeners","handlers","currentTime","handleAdComplete","e","handleAdError","addEventListener","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","teardownCurrentPlayback","destroy","removeAttribute","load","startNativePlayback","mediaFile","startHlsPlayback","Hls","isSupported","enableWorker","lowLatencyMode","loadSource","attachMedia","on","Events","MANIFEST_PARSED","nonFatalNetworkErrors","ERROR","_event","data","fatal","ErrorTypes","NETWORK_ERROR","canPlayType","startPlayback","mp4Fallback","find","playAd","bids","contentVolume","container","adVolume","reject","bidder","cpm","toFixed","currency","detachMedia","right","bottom","alignItems","justifyContent"],"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/sdk/vastAdLayer.ts\nvar vastAdLayer_exports = {};\n__export(vastAdLayer_exports, {\n createVastAdLayer: () => createVastAdLayer\n});\nmodule.exports = __toCommonJS(vastAdLayer_exports);\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}\nasync function firePixelWithRetry(url, retries = 2, delayMs = 500, logPrefix = \"[VastParser]\") {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n await fetch(url, {\n method: \"GET\",\n mode: \"no-cors\",\n cache: \"no-cache\",\n keepalive: true\n });\n return;\n } catch {\n if (attempt < retries) {\n await new Promise((r) => setTimeout(r, delayMs * Math.pow(2, attempt)));\n } else {\n console.warn(`${logPrefix} Tracking pixel failed after ${retries + 1} attempts: ${url}`);\n }\n }\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 if (typeof fetch !== \"undefined\") {\n firePixelWithRetry(trackingUrl, 2, 500, logPrefix).catch(() => {\n });\n } else {\n const img = new Image(1, 1);\n img.onerror = () => {\n };\n img.src = trackingUrl;\n }\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/vastAdLayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar LOG = \"[VastAdLayer]\";\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 createVastAdLayer(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 smartTVMode = options?.smartTVMode ?? false;\n const singleElementMode = options?.singleElementMode ?? false;\n const forceMP4Ads = options?.forceMP4Ads ?? (smartTVMode || singleElementMode);\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 let currentAdEventHandlers;\n const preloadSlots = /* @__PURE__ */ new Map();\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 let candidates = mediaFiles;\n if (forceMP4Ads) {\n const mp4Only = candidates.filter((f) => !isHlsMediaFile(f));\n if (mp4Only.length > 0) {\n candidates = mp4Only;\n if (debug) console.log(`${LOG} forceMP4Ads: filtered to ${mp4Only.length} MP4-only file(s)`);\n } else if (debug) {\n console.warn(`${LOG} forceMP4Ads: no MP4 files available, falling back to all media files`);\n }\n }\n const firstFile = candidates[0];\n if (candidates.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 = candidates.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 removeAdEventListeners() {\n if (!currentAdEventHandlers || !adVideoElement) return;\n const el = adVideoElement;\n el.removeEventListener(\"timeupdate\", currentAdEventHandlers.timeupdate);\n el.removeEventListener(\"playing\", currentAdEventHandlers.playing);\n el.removeEventListener(\"ended\", currentAdEventHandlers.ended);\n el.removeEventListener(\"error\", currentAdEventHandlers.error);\n el.removeEventListener(\"volumechange\", currentAdEventHandlers.volumechange);\n el.removeEventListener(\"pause\", currentAdEventHandlers.pause);\n el.removeEventListener(\"play\", currentAdEventHandlers.play);\n currentAdEventHandlers = void 0;\n }\n function setupAdEventListeners() {\n if (!adVideoElement) return;\n removeAdEventListeners();\n const handlers = {\n 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 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 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 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 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 pause: () => {\n if (currentAd && adVideoElement && !adVideoElement.ended) {\n fireTrackingPixels2(currentAd.trackingUrls.pause);\n }\n },\n play: () => {\n if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {\n fireTrackingPixels2(currentAd.trackingUrls.resume);\n }\n }\n };\n adVideoElement.addEventListener(\"timeupdate\", handlers.timeupdate);\n adVideoElement.addEventListener(\"playing\", handlers.playing);\n adVideoElement.addEventListener(\"ended\", handlers.ended);\n adVideoElement.addEventListener(\"error\", handlers.error);\n adVideoElement.addEventListener(\"volumechange\", handlers.volumechange);\n adVideoElement.addEventListener(\"pause\", handlers.pause);\n adVideoElement.addEventListener(\"play\", handlers.play);\n currentAdEventHandlers = handlers;\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 (!adPlaying) 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 removeAdEventListeners();\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n if (singleElementMode && adVideoElement === contentVideo) {\n contentVideo.pause();\n } else {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\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 let nonFatalNetworkErrors = 0;\n adHls.on(import_hls.default.Events.ERROR, (_event, data) => {\n if (data.fatal) {\n handleAdError();\n } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {\n nonFatalNetworkErrors++;\n if (nonFatalNetworkErrors >= 3) {\n if (debug) console.warn(`${LOG} Too many non-fatal HLS network errors (${nonFatalNetworkErrors}), treating as fatal`);\n handleAdError();\n }\n }\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 (singleElementMode && isHlsMediaFile(mediaFile)) {\n const mp4Fallback = currentAd?.mediaFiles.find((f) => !isHlsMediaFile(f));\n if (mp4Fallback) {\n if (debug) console.log(`${LOG} singleElementMode: HLS ad blocked, using MP4 fallback`);\n startNativePlayback(mp4Fallback);\n return;\n }\n }\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 const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n if (singleElementMode) {\n mainHlsInstance?.detachMedia();\n teardownCurrentPlayback();\n adVideoElement = contentVideo;\n adHls = void 0;\n setupAdEventListeners();\n } else {\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 }\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 (!singleElementMode && 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 function ensureAdContainer() {\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 return adContainerEl;\n }\n async function preloadAd(bids, token) {\n if (destroyed) return;\n const winner = bids[0];\n if (!winner) return;\n if (debug) console.log(`${LOG} [preload] Resolving VAST for token=${token}`);\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad || destroyed) return;\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (!mediaFile) return;\n if (smartTVMode || singleElementMode) {\n const slot = { bids, ad, mediaFile, videoEl: null, ready: true };\n preloadSlots.set(token, slot);\n if (debug) console.log(`${LOG} [preload] Metadata-only preload (smartTV/singleElement), token=${token}, url=${mediaFile.url}`);\n return;\n }\n const videoEl = createAdVideoElement();\n videoEl.style.visibility = \"hidden\";\n videoEl.style.pointerEvents = \"none\";\n videoEl.preload = \"auto\";\n const container = ensureAdContainer();\n container.appendChild(videoEl);\n if (isHlsMediaFile(mediaFile) && import_hls.default.isSupported()) {\n const hls = new import_hls.default({ enableWorker: true, lowLatencyMode: false });\n hls.loadSource(mediaFile.url);\n hls.attachMedia(videoEl);\n const slot = { bids, ad, mediaFile, videoEl, hlsInstance: hls, ready: false };\n preloadSlots.set(token, slot);\n hls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n const s = preloadSlots.get(token);\n if (s) s.ready = true;\n if (debug) console.log(`${LOG} [preload] HLS manifest parsed, token=${token}`);\n });\n hls.on(import_hls.default.Events.ERROR, (_evt, data) => {\n if (data.fatal) {\n if (debug) console.warn(`${LOG} [preload] HLS error for token=${token}`);\n preloadSlots.delete(token);\n hls.destroy();\n videoEl.remove();\n }\n });\n } else {\n videoEl.src = mediaFile.url;\n videoEl.load();\n const slot = { bids, ad, mediaFile, videoEl, ready: false };\n preloadSlots.set(token, slot);\n videoEl.addEventListener(\"canplay\", () => {\n const s = preloadSlots.get(token);\n if (s) s.ready = true;\n if (debug) console.log(`${LOG} [preload] canplay fired, token=${token}`);\n }, { once: true });\n }\n if (debug) console.log(`${LOG} [preload] Started buffering token=${token}, url=${mediaFile.url}`);\n }\n async function playPreloaded(token) {\n if (destroyed) return Promise.reject(new Error(\"Layer has been destroyed\"));\n const slot = preloadSlots.get(token);\n if (!slot) {\n if (debug) console.warn(`${LOG} [preload] No slot found for token=${token}, nothing to play`);\n return;\n }\n preloadSlots.delete(token);\n if (debug) console.log(`${LOG} [preload] Playing preloaded ad, token=${token}, ready=${slot.ready}`);\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n sessionId = generateSessionId();\n currentAd = slot.ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels2(slot.ad.trackingUrls.impression);\n trackingFired.impression = true;\n if (singleElementMode) {\n mainHlsInstance?.detachMedia();\n teardownCurrentPlayback();\n adVideoElement = contentVideo;\n adHls = void 0;\n setupAdEventListeners();\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume2 = originalMutedState ? 1 : originalVolume;\n contentVideo.volume = Math.max(0, Math.min(1, adVolume2));\n contentVideo.muted = false;\n emit(\"content_pause\");\n if (debug) console.log(`${LOG} [preload] singleElementMode: attaching ad to contentVideo, url=${slot.mediaFile.url}`);\n startPlayback(slot.mediaFile);\n return;\n }\n if (smartTVMode && !slot.videoEl) {\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n const videoEl = createAdVideoElement();\n videoEl.style.visibility = \"visible\";\n videoEl.style.pointerEvents = \"none\";\n const container2 = ensureAdContainer();\n container2.appendChild(videoEl);\n adVideoElement = videoEl;\n setupAdEventListeners();\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume2 = originalMutedState ? 1 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume2));\n adVideoElement.muted = false;\n container2.style.display = \"flex\";\n container2.style.pointerEvents = \"auto\";\n emit(\"content_pause\");\n if (debug) console.log(`${LOG} [preload] smartTVMode deferred: creating video element and loading, url=${slot.mediaFile.url}`);\n startPlayback(slot.mediaFile);\n return;\n }\n teardownCurrentPlayback();\n if (adVideoElement && adVideoElement !== slot.videoEl) {\n adVideoElement.remove();\n }\n slot.videoEl.style.visibility = \"visible\";\n slot.videoEl.style.pointerEvents = \"none\";\n adVideoElement = slot.videoEl;\n adHls = slot.hlsInstance;\n setupAdEventListeners();\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 const container = ensureAdContainer();\n container.style.display = \"flex\";\n container.style.pointerEvents = \"auto\";\n emit(\"content_pause\");\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} [preload] Error playing preloaded ad:`, error);\n handleAdError();\n });\n }\n function cancelPreload(token) {\n const slot = preloadSlots.get(token);\n if (!slot) return;\n preloadSlots.delete(token);\n if (slot.hlsInstance) {\n slot.hlsInstance.destroy();\n }\n if (slot.videoEl) {\n slot.videoEl.pause();\n slot.videoEl.removeAttribute(\"src\");\n slot.videoEl.load();\n slot.videoEl.remove();\n }\n if (debug) console.log(`${LOG} [preload] Cancelled and cleaned up token=${token}`);\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 preloadAd,\n playPreloaded,\n hasPreloaded(token) {\n return preloadSlots.has(token);\n },\n cancelPreload,\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 contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (singleElementMode) {\n teardownCurrentPlayback();\n contentVideo.removeAttribute(\"src\");\n contentVideo.load();\n adVideoElement = void 0;\n } else {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\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 }\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 for (const [token] of Array.from(preloadSlots.entries())) {\n cancelPreload(token);\n }\n teardownCurrentPlayback();\n if (adVideoElement) {\n if (singleElementMode && adVideoElement === contentVideo) {\n contentVideo.removeAttribute(\"src\");\n contentVideo.load();\n } else {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.remove();\n }\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// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createVastAdLayer\n});\n","import type { VastBidResponse } 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 = \"[VastAdLayer]\";\n\nexport interface VastAdLayerOptions {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls;\n smartTVMode?: boolean;\n singleElementMode?: boolean;\n forceMP4Ads?: boolean;\n debug?: boolean;\n}\n\nexport interface VastAdLayerOptionsUpdate {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls | null;\n}\n\nexport interface VastAdLayer {\n initialize: () => void;\n updateOptions: (opts: VastAdLayerOptionsUpdate) => void;\n playAd: (bids: VastBidResponse[]) => Promise<void>;\n preloadAd: (bids: VastBidResponse[], token: string) => Promise<void>;\n playPreloaded: (token: string) => Promise<void>;\n hasPreloaded: (token: string) => boolean;\n cancelPreload: (token: string) => 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: VastBidResponse, 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 createVastAdLayer(\n contentVideo: HTMLVideoElement,\n options?: VastAdLayerOptions\n): VastAdLayer {\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 smartTVMode = options?.smartTVMode ?? false;\n const singleElementMode = options?.singleElementMode ?? false;\n const forceMP4Ads = options?.forceMP4Ads ?? (smartTVMode || singleElementMode);\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 type AdEventHandlers = {\n timeupdate: () => void;\n playing: () => void;\n ended: () => void;\n error: (e: Event) => void;\n volumechange: () => void;\n pause: () => void;\n play: () => void;\n };\n let currentAdEventHandlers: AdEventHandlers | undefined;\n\n interface PreloadSlot {\n bids: VastBidResponse[];\n ad: VastAd;\n mediaFile: VastMediaFile;\n videoEl: HTMLVideoElement | null;\n hlsInstance?: Hls;\n ready: boolean;\n }\n const preloadSlots = new Map<string, PreloadSlot>();\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\n let candidates = mediaFiles;\n if (forceMP4Ads) {\n const mp4Only = candidates.filter(f => !isHlsMediaFile(f));\n if (mp4Only.length > 0) {\n candidates = mp4Only;\n if (debug) console.log(`${LOG} forceMP4Ads: filtered to ${mp4Only.length} MP4-only file(s)`);\n } else if (debug) {\n console.warn(`${LOG} forceMP4Ads: no MP4 files available, falling back to all media files`);\n }\n }\n\n const firstFile = candidates[0]!;\n if (candidates.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 = candidates.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 removeAdEventListeners(): void {\n if (!currentAdEventHandlers || !adVideoElement) return;\n const el = adVideoElement;\n el.removeEventListener(\"timeupdate\", currentAdEventHandlers.timeupdate);\n el.removeEventListener(\"playing\", currentAdEventHandlers.playing);\n el.removeEventListener(\"ended\", currentAdEventHandlers.ended);\n el.removeEventListener(\"error\", currentAdEventHandlers.error);\n el.removeEventListener(\"volumechange\", currentAdEventHandlers.volumechange);\n el.removeEventListener(\"pause\", currentAdEventHandlers.pause);\n el.removeEventListener(\"play\", currentAdEventHandlers.play);\n currentAdEventHandlers = undefined;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement) return;\n\n removeAdEventListeners();\n\n const handlers: AdEventHandlers = {\n 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 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 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 error: (e: Event) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels(currentAd.trackingUrls.error);\n handleAdError();\n },\n 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 pause: () => {\n if (currentAd && adVideoElement && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n },\n play: () => {\n if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n },\n };\n\n adVideoElement.addEventListener(\"timeupdate\", handlers.timeupdate);\n adVideoElement.addEventListener(\"playing\", handlers.playing);\n adVideoElement.addEventListener(\"ended\", handlers.ended);\n adVideoElement.addEventListener(\"error\", handlers.error);\n adVideoElement.addEventListener(\"volumechange\", handlers.volumechange);\n adVideoElement.addEventListener(\"pause\", handlers.pause);\n adVideoElement.addEventListener(\"play\", handlers.play);\n\n currentAdEventHandlers = handlers;\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 (!adPlaying) 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 removeAdEventListeners();\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n if (singleElementMode && adVideoElement === contentVideo) {\n contentVideo.pause();\n } else {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\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 let nonFatalNetworkErrors = 0;\n adHls.on(Hls.Events.ERROR, (_event, data) => {\n if (data.fatal) {\n handleAdError();\n } else if (data.type === Hls.ErrorTypes.NETWORK_ERROR) {\n nonFatalNetworkErrors++;\n if (nonFatalNetworkErrors >= 3) {\n if (debug) console.warn(`${LOG} Too many non-fatal HLS network errors (${nonFatalNetworkErrors}), treating as fatal`);\n handleAdError();\n }\n }\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 (singleElementMode && isHlsMediaFile(mediaFile)) {\n const mp4Fallback = currentAd?.mediaFiles.find(f => !isHlsMediaFile(f));\n if (mp4Fallback) {\n if (debug) console.log(`${LOG} singleElementMode: HLS ad blocked, using MP4 fallback`);\n startNativePlayback(mp4Fallback);\n return;\n }\n }\n if (isHlsMediaFile(mediaFile)) {\n startHlsPlayback(mediaFile);\n } else {\n startNativePlayback(mediaFile);\n }\n }\n\n async function playAd(bids: VastBidResponse[]): 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 const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n\n if (singleElementMode) {\n mainHlsInstance?.detachMedia();\n\n teardownCurrentPlayback();\n\n adVideoElement = contentVideo;\n adHls = undefined;\n setupAdEventListeners();\n } else {\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\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 (!singleElementMode && 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 function ensureAdContainer(): HTMLDivElement {\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 return adContainerEl;\n }\n\n async function preloadAd(bids: VastBidResponse[], token: string): Promise<void> {\n if (destroyed) return;\n const winner = bids[0];\n if (!winner) return;\n\n if (debug) console.log(`${LOG} [preload] Resolving VAST for token=${token}`);\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad || destroyed) return;\n\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (!mediaFile) return;\n\n if (smartTVMode || singleElementMode) {\n const slot: PreloadSlot = { bids, ad, mediaFile, videoEl: null, ready: true };\n preloadSlots.set(token, slot);\n if (debug) console.log(`${LOG} [preload] Metadata-only preload (smartTV/singleElement), token=${token}, url=${mediaFile.url}`);\n return;\n }\n\n const videoEl = createAdVideoElement();\n videoEl.style.visibility = \"hidden\";\n videoEl.style.pointerEvents = \"none\";\n videoEl.preload = \"auto\";\n\n const container = ensureAdContainer();\n container.appendChild(videoEl);\n\n if (isHlsMediaFile(mediaFile) && Hls.isSupported()) {\n const hls = new Hls({ enableWorker: true, lowLatencyMode: false });\n hls.loadSource(mediaFile.url);\n hls.attachMedia(videoEl);\n const slot: PreloadSlot = { bids, ad, mediaFile, videoEl, hlsInstance: hls, ready: false };\n preloadSlots.set(token, slot);\n hls.on(Hls.Events.MANIFEST_PARSED, () => {\n const s = preloadSlots.get(token);\n if (s) s.ready = true;\n if (debug) console.log(`${LOG} [preload] HLS manifest parsed, token=${token}`);\n });\n hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data.fatal) {\n if (debug) console.warn(`${LOG} [preload] HLS error for token=${token}`);\n preloadSlots.delete(token);\n hls.destroy();\n videoEl.remove();\n }\n });\n } else {\n videoEl.src = mediaFile.url;\n videoEl.load();\n const slot: PreloadSlot = { bids, ad, mediaFile, videoEl, ready: false };\n preloadSlots.set(token, slot);\n videoEl.addEventListener(\"canplay\", () => {\n const s = preloadSlots.get(token);\n if (s) s.ready = true;\n if (debug) console.log(`${LOG} [preload] canplay fired, token=${token}`);\n }, { once: true });\n }\n\n if (debug) console.log(`${LOG} [preload] Started buffering token=${token}, url=${mediaFile.url}`);\n }\n\n async function playPreloaded(token: string): Promise<void> {\n if (destroyed) return Promise.reject(new Error(\"Layer has been destroyed\"));\n\n const slot = preloadSlots.get(token);\n if (!slot) {\n if (debug) console.warn(`${LOG} [preload] No slot found for token=${token}, nothing to play`);\n return;\n }\n preloadSlots.delete(token);\n\n if (debug) console.log(`${LOG} [preload] Playing preloaded ad, token=${token}, ready=${slot.ready}`);\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n\n sessionId = generateSessionId();\n currentAd = slot.ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels(slot.ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n if (singleElementMode) {\n mainHlsInstance?.detachMedia();\n\n teardownCurrentPlayback();\n\n adVideoElement = contentVideo;\n adHls = undefined;\n setupAdEventListeners();\n\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n const adVolume = originalMutedState ? 1 : originalVolume;\n contentVideo.volume = Math.max(0, Math.min(1, adVolume));\n contentVideo.muted = false;\n\n emit(\"content_pause\");\n\n if (debug) console.log(`${LOG} [preload] singleElementMode: attaching ad to contentVideo, url=${slot.mediaFile.url}`);\n startPlayback(slot.mediaFile);\n return;\n }\n\n if (smartTVMode && !slot.videoEl) {\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n const videoEl = createAdVideoElement();\n videoEl.style.visibility = \"visible\";\n videoEl.style.pointerEvents = \"none\";\n\n const container = ensureAdContainer();\n container.appendChild(videoEl);\n adVideoElement = videoEl;\n\n setupAdEventListeners();\n\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\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 container.style.display = \"flex\";\n container.style.pointerEvents = \"auto\";\n\n emit(\"content_pause\");\n\n if (debug) console.log(`${LOG} [preload] smartTVMode deferred: creating video element and loading, url=${slot.mediaFile.url}`);\n startPlayback(slot.mediaFile);\n return;\n }\n\n teardownCurrentPlayback();\n\n if (adVideoElement && adVideoElement !== slot.videoEl) {\n adVideoElement.remove();\n }\n\n slot.videoEl!.style.visibility = \"visible\";\n slot.videoEl!.style.pointerEvents = \"none\";\n adVideoElement = slot.videoEl!;\n adHls = slot.hlsInstance;\n\n setupAdEventListeners();\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 const container = ensureAdContainer();\n container.style.display = \"flex\";\n container.style.pointerEvents = \"auto\";\n\n emit(\"content_pause\");\n\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} [preload] Error playing preloaded ad:`, error);\n handleAdError();\n });\n }\n\n function cancelPreload(token: string): void {\n const slot = preloadSlots.get(token);\n if (!slot) return;\n preloadSlots.delete(token);\n if (slot.hlsInstance) {\n slot.hlsInstance.destroy();\n }\n if (slot.videoEl) {\n slot.videoEl.pause();\n slot.videoEl.removeAttribute(\"src\");\n slot.videoEl.load();\n slot.videoEl.remove();\n }\n if (debug) console.log(`${LOG} [preload] Cancelled and cleaned up token=${token}`);\n }\n\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n\n updateOptions(opts: VastAdLayerOptionsUpdate) {\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 preloadAd,\n playPreloaded,\n hasPreloaded(token: string): boolean {\n return preloadSlots.has(token);\n },\n cancelPreload,\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 contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n\n if (singleElementMode) {\n // In singleElementMode the ad was playing on contentVideo. Tear down the\n // ad HLS and clear contentVideo so it is ready for main HLS re-attachment\n // in handleAdPodComplete (hls.attachMedia → MANIFEST_PARSED → play).\n // Do NOT call contentVideo.play() here — playback is restored by the player.\n teardownCurrentPlayback();\n contentVideo.removeAttribute(\"src\");\n contentVideo.load();\n adVideoElement = undefined;\n } else {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\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 }\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 for (const [token] of Array.from(preloadSlots.entries())) {\n cancelPreload(token);\n }\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n if (singleElementMode && adVideoElement === contentVideo) {\n // contentVideo belongs to the host page — do not remove it from the DOM.\n contentVideo.removeAttribute(\"src\");\n contentVideo.load();\n } else {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.remove();\n }\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","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\nasync function firePixelWithRetry(\n url: string,\n retries = 2,\n delayMs = 500,\n logPrefix = \"[VastParser]\"\n): Promise<void> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n await fetch(url, {\n method: \"GET\",\n mode: \"no-cors\",\n cache: \"no-cache\",\n keepalive: true,\n });\n return;\n } catch {\n if (attempt < retries) {\n await new Promise((r) => setTimeout(r, delayMs * Math.pow(2, attempt)));\n } else {\n console.warn(`${logPrefix} Tracking pixel failed after ${retries + 1} attempts: ${url}`);\n }\n }\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 if (typeof fetch !== \"undefined\") {\n firePixelWithRetry(trackingUrl, 2, 500, logPrefix).catch(() => {});\n } else {\n const img = new Image(1, 1);\n img.onerror = () => {};\n img.src = trackingUrl;\n }\n\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n"]}