stormcloud-video-player 0.8.7 → 0.8.8

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.
@@ -662,7 +662,6 @@ function createHlsAdPlayer(contentVideo, options) {
662
662
  adPlaying = false;
663
663
  setAdPlayingFlag(false);
664
664
  contentVideo.muted = true;
665
- contentVideo.volume = 0;
666
665
  if (adContainerEl) {
667
666
  adContainerEl.style.display = "none";
668
667
  adContainerEl.style.pointerEvents = "none";
@@ -682,7 +681,6 @@ function createHlsAdPlayer(contentVideo, options) {
682
681
  adPlaying = false;
683
682
  setAdPlayingFlag(false);
684
683
  contentVideo.muted = true;
685
- contentVideo.volume = 0;
686
684
  if (adContainerEl) {
687
685
  adContainerEl.style.display = "none";
688
686
  adContainerEl.style.pointerEvents = "none";
@@ -787,7 +785,7 @@ function createHlsAdPlayer(contentVideo, options) {
787
785
  },
788
786
  play: function play() {
789
787
  return _async_to_generator(function() {
790
- var contentVolume, adVolume, mediaFile, isHlsAd;
788
+ var contentVolume, mediaFile, isHlsAd;
791
789
  return _ts_generator(this, function(_state) {
792
790
  if (!currentAd) {
793
791
  console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
@@ -821,13 +819,11 @@ function createHlsAdPlayer(contentVideo, options) {
821
819
  }
822
820
  console.log("[HlsAdPlayer] FORCE MUTING main video");
823
821
  contentVideo.muted = true;
824
- contentVideo.volume = 0;
825
822
  adPlaying = true;
826
823
  setAdPlayingFlag(true);
827
824
  if (adVideoElement) {
828
- adVolume = originalMutedState ? 0 : originalVolume;
829
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
830
- adVideoElement.muted = false;
825
+ adVideoElement.volume = Math.max(0, Math.min(1, originalVolume));
826
+ adVideoElement.muted = originalMutedState;
831
827
  console.log("[HlsAdPlayer] Set ad video volume to ".concat(adVideoElement.volume, ", muted: ").concat(adVideoElement.muted, ", originalMutedState: ").concat(originalMutedState, ", contentVolume: ").concat(contentVolume));
832
828
  }
833
829
  if (adContainerEl) {
@@ -935,8 +931,8 @@ function createHlsAdPlayer(contentVideo, options) {
935
931
  setAdPlayingFlag(false);
936
932
  previousMutedState = contentVideo.muted;
937
933
  contentVideo.muted = originalMutedState;
938
- contentVideo.volume = originalMutedState ? 0 : originalVolume;
939
- console.log("[HlsAdPlayer] Restored mute state on stop: ".concat(previousMutedState, " -> ").concat(originalMutedState));
934
+ contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
935
+ console.log("[HlsAdPlayer] Restored mute state on stop: ".concat(previousMutedState, " -> ").concat(originalMutedState, ", volume: ").concat(contentVideo.volume));
940
936
  if (adContainerEl) {
941
937
  adContainerEl.style.display = "none";
942
938
  adContainerEl.style.pointerEvents = "none";
@@ -991,7 +987,7 @@ function createHlsAdPlayer(contentVideo, options) {
991
987
  adPlaying = false;
992
988
  setAdPlayingFlag(false);
993
989
  contentVideo.muted = originalMutedState;
994
- contentVideo.volume = originalMutedState ? 0 : originalVolume;
990
+ contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
995
991
  if (adHls) {
996
992
  adHls.destroy();
997
993
  adHls = void 0;
@@ -1047,7 +1043,9 @@ function createHlsAdPlayer(contentVideo, options) {
1047
1043
  },
1048
1044
  setAdVolume: function setAdVolume(volume) {
1049
1045
  if (adVideoElement && adPlaying) {
1050
- adVideoElement.volume = Math.max(0, Math.min(1, volume));
1046
+ var clamped = Math.max(0, Math.min(1, volume));
1047
+ adVideoElement.volume = clamped;
1048
+ adVideoElement.muted = clamped === 0;
1051
1049
  }
1052
1050
  },
1053
1051
  getAdVolume: function getAdVolume() {
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/sdk/hlsAdPlayer.cjs","../../src/sdk/hlsAdPlayer.ts"],"names":["__create","Object","create","__defProp","__getOwnPropDesc","defineProperty","getOwnPropertyDescriptor","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__getOwnPropNames","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","hlsAdPlayer_exports","createHlsAdPlayer","module","exports","import_hls","require","MAX_VAST_WRAPPER_DEPTH","contentVideo","options","adPlaying","originalMutedState","originalVolume","Math","max","min","volume","listeners","Map","licenseKey","mainHlsInstance","adVideoElement","adHls","adContainerEl","currentAd","sessionId","preloadedAds","preloadingAds","destroyed","pendingTimeouts","trackingFired","impression","start","firstQuartile","midpoint","thirdQuartile","complete","fireTrackingPixels","urls","emit","event","payload","set","Array","fn","error","console","warn","generateSessionId","Date","now","random","toString","substr","length","forEach","url","trackingUrl","includes","img","Image","src","log","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","width","height","bitrate","selectBestMediaFile","mediaFiles","firstFile","Error","mainQuality","scoredFiles","map","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","sort","a","b","bestMatch","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","isProgressiveMediaFile","startsWith","endsWith","createEmptyTrackingUrls","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","extractTrackingUrls","xmlDoc","trackingUrls","querySelectorAll","el","textContent","trim","push","getAttribute","eventKey","mergeTrackingUrls","source","keys","concat","parseVastXml","xmlString","parser","DOMParser","parseFromString","parserError","querySelector","adElement","adId","title","clickThrough","wrapperUri","vastAdTagUri","isNoAdAvailable","durationText","durationParts","split","duration","parseInt","mediaFileElements","mf","index","bitrateAttr","bitrateValue","ad","id","response","fetch","vastTagUrl","mode","credentials","headers","referrerPolicy","ok","statusText","fetchAndParseVastAd","playsInline","video","depth","accumulatedTracking","fetchVastXml","vastXml","substring","parsed","createAdVideoElement","document","createElement","style","left","top","objectFit","backgroundColor","muted","setupAdEventListeners","addEventListener","progress","currentTime","handleAdComplete","e","handleAdError","ended","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","continueLiveStreamDuringAds","paused","play","catch","initialize","container","position","right","bottom","alignItems","justifyContent","zIndex","parentElement","appendChild","requestAds","Promise","reject","has","delete","resolve","contentVolume","adVolume","isHlsAd"],"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/hlsAdPlayer.ts\nvar hlsAdPlayer_exports = {};\n__export(hlsAdPlayer_exports, {\n createHlsAdPlayer: () => createHlsAdPlayer\n});\nmodule.exports = __toCommonJS(hlsAdPlayer_exports);\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar MAX_VAST_WRAPPER_DEPTH = 5;\nfunction createHlsAdPlayer(contentVideo, options) {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = /* @__PURE__ */ new Map();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n const preloadedAds = /* @__PURE__ */ new Map();\n const preloadingAds = /* @__PURE__ */ new Map();\n let destroyed = false;\n let pendingTimeouts = [];\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels(urls) {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n }\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level2 = mainHlsInstance.levels[autoLevel];\n return {\n width: level2.width || 1920,\n height: level2.height || 1080,\n bitrate: level2.bitrate || 5e6\n };\n }\n return null;\n }\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5e6\n };\n }\n function selectBestMediaFile(mediaFiles) {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n const fileBitrate = (file.bitrate || 5e3) * 1e3;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1e3;\n return { file, score, resolutionDiff, bitrateDiff };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff\n });\n return bestMatch.file;\n }\n function isHlsMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type === \"application/x-mpegurl\" || type === \"application/vnd.apple.mpegurl\" || type.includes(\"mpegurl\") || url.includes(\".m3u8\");\n }\n function isProgressiveMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type.startsWith(\"video/\") || url.endsWith(\".mp4\") || url.includes(\".mp4?\");\n }\n function createEmptyTrackingUrls() {\n return {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: []\n };\n }\n function extractTrackingUrls(xmlDoc) {\n const trackingUrls = createEmptyTrackingUrls();\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n xmlDoc.querySelectorAll(\"Error\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.error.push(url);\n });\n return trackingUrls;\n }\n function mergeTrackingUrls(target, source) {\n Object.keys(target).forEach((key) => {\n if (source[key] && source[key].length > 0) {\n target[key] = target[key].concat(source[key]);\n }\n });\n return target;\n }\n function parseVastXml(xmlString) {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return { type: \"empty\" };\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return { type: \"empty\" };\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n const wrapperUri = xmlDoc.querySelector(\"VASTAdTagURI\")?.textContent?.trim();\n if (wrapperUri) {\n console.log(\n `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n );\n return {\n type: \"wrapper\",\n vastAdTagUri: wrapperUri,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough\n };\n }\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n const mediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: void 0\n };\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n );\n }\n });\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n }\n return { type: \"empty\" };\n }\n return {\n type: \"inline\",\n ad: {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough\n }\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return { type: \"empty\" };\n }\n }\n async function fetchVastXml(vastTagUrl) {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\"\n },\n referrerPolicy: \"no-referrer-when-downgrade\"\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n return response.text();\n }\n async function fetchAndParseVastAd(vastTagUrl, depth = 0, accumulatedTracking = createEmptyTrackingUrls()) {\n const vastXml = await fetchVastXml(vastTagUrl);\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2e3)\n );\n const parsed = parseVastXml(vastXml);\n if (parsed.type === \"empty\") {\n return null;\n }\n if (parsed.type === \"wrapper\") {\n if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n console.warn(\n `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n );\n return null;\n }\n mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n return fetchAndParseVastAd(\n parsed.vastAdTagUri,\n depth + 1,\n accumulatedTracking\n );\n }\n mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n return parsed.ad;\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n video.volume = 1;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n const progress = adVideoElement.currentTime / currentAd.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function handleAdComplete() {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {\n });\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n emit(\"content_resume\");\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n async requestAds(vastTagUrl) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n try {\n sessionId = generateSessionId();\n let ad;\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No ads available from VAST response\"));\n }\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n if (isHlsAd && import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n adHls = new import_hls.default({\n enableWorker: true,\n lowLatencyMode: false\n });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n adHls.on(import_hls.default.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n }\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {\n });\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {\n });\n }\n }\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n currentAd = void 0;\n },\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n }\n };\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createHlsAdPlayer\n});\n","import type { AdController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\ntype VastParseResult =\n | { type: \"inline\"; ad: VastAd }\n | {\n type: \"wrapper\";\n vastAdTagUri: string;\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n }\n | { type: \"empty\" };\n\nconst MAX_VAST_WRAPPER_DEPTH = 5;\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): AdController {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n const preloadedAds = new Map<string, VastAd>();\n const preloadingAds = new Map<string, Promise<void>>();\n let destroyed = false;\n let pendingTimeouts: number[] = [];\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n if (sessionId) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function getMainStreamQuality(): {\n width: number;\n height: number;\n bitrate: number;\n } | null {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level = mainHlsInstance.levels[autoLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n return null;\n }\n\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n\n const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n return { file, score, resolutionDiff, bitrateDiff };\n });\n\n scoredFiles.sort((a, b) => a.score - b.score);\n\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff,\n });\n\n return bestMatch.file;\n }\n\n function isHlsMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type === \"application/x-mpegurl\" ||\n type === \"application/vnd.apple.mpegurl\" ||\n type.includes(\"mpegurl\") ||\n url.includes(\".m3u8\")\n );\n }\n\n function isProgressiveMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type.startsWith(\"video/\") ||\n url.endsWith(\".mp4\") ||\n url.includes(\".mp4?\")\n );\n }\n\n function createEmptyTrackingUrls(): VastTrackingUrls {\n return {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n }\n\n function extractTrackingUrls(xmlDoc: Document): VastTrackingUrls {\n const trackingUrls = createEmptyTrackingUrls();\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n xmlDoc.querySelectorAll(\"Error\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.error.push(url);\n });\n\n return trackingUrls;\n }\n\n function mergeTrackingUrls(\n target: VastTrackingUrls,\n source: VastTrackingUrls\n ): VastTrackingUrls {\n (Object.keys(target) as Array<keyof VastTrackingUrls>).forEach((key) => {\n if (source[key] && source[key].length > 0) {\n target[key] = target[key].concat(source[key]);\n }\n });\n return target;\n }\n\n function parseVastXml(xmlString: string): VastParseResult {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return { type: \"empty\" };\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return { type: \"empty\" };\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n const wrapperUri = xmlDoc\n .querySelector(\"VASTAdTagURI\")\n ?.textContent?.trim();\n if (wrapperUri) {\n console.log(\n `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n );\n return {\n type: \"wrapper\",\n vastAdTagUri: wrapperUri,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough,\n };\n }\n\n const isNoAdAvailable =\n adId === \"empty\" ||\n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\n\n const durationText =\n xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n\n const mediaFile: VastMediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: undefined,\n };\n\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n mediaFile.bitrate =\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined;\n\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n );\n }\n });\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n }\n return { type: \"empty\" };\n }\n\n return {\n type: \"inline\",\n ad: {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough,\n },\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return { type: \"empty\" };\n }\n }\n\n async function fetchVastXml(vastTagUrl: string): Promise<string> {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\",\n },\n referrerPolicy: \"no-referrer-when-downgrade\",\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n return response.text();\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string,\n depth = 0,\n accumulatedTracking: VastTrackingUrls = createEmptyTrackingUrls()\n ): Promise<VastAd | null> {\n const vastXml = await fetchVastXml(vastTagUrl);\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2000)\n );\n\n const parsed = parseVastXml(vastXml);\n\n if (parsed.type === \"empty\") {\n return null;\n }\n\n if (parsed.type === \"wrapper\") {\n if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n console.warn(\n `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n );\n return null;\n }\n\n mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n return fetchAndParseVastAd(\n parsed.vastAdTagUri,\n depth + 1,\n accumulatedTracking\n );\n }\n\n mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n return parsed.ad;\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n\n video.volume = 1.0;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {});\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n emit(\"ad_error\");\n }\n\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(vastTagUrl: string) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n\n try {\n sessionId = generateSessionId();\n let ad: VastAd | null | undefined;\n\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No ads available from VAST response\"));\n }\n\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n\n if (isHlsAd && Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false,\n });\n\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement!.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && (\n adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")\n )) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n }\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {});\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\n );\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {});\n }\n }\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n\n currentAd = undefined;\n },\n\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n \n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n \n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n \n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/sdk/hlsAdPlayer.cjs","../../src/sdk/hlsAdPlayer.ts"],"names":["__create","Object","create","__defProp","__getOwnPropDesc","defineProperty","getOwnPropertyDescriptor","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__getOwnPropNames","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","hlsAdPlayer_exports","createHlsAdPlayer","module","exports","import_hls","require","MAX_VAST_WRAPPER_DEPTH","contentVideo","options","adPlaying","originalMutedState","originalVolume","Math","max","min","volume","listeners","Map","licenseKey","mainHlsInstance","adVideoElement","adHls","adContainerEl","currentAd","sessionId","preloadedAds","preloadingAds","destroyed","pendingTimeouts","trackingFired","impression","start","firstQuartile","midpoint","thirdQuartile","complete","fireTrackingPixels","urls","emit","event","payload","set","Array","fn","error","console","warn","generateSessionId","Date","now","random","toString","substr","length","forEach","url","trackingUrl","includes","img","Image","src","log","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","width","height","bitrate","selectBestMediaFile","mediaFiles","firstFile","Error","mainQuality","scoredFiles","map","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","sort","a","b","bestMatch","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","isProgressiveMediaFile","startsWith","endsWith","createEmptyTrackingUrls","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","extractTrackingUrls","xmlDoc","trackingUrls","querySelectorAll","el","textContent","trim","push","getAttribute","eventKey","mergeTrackingUrls","source","keys","concat","parseVastXml","xmlString","parser","DOMParser","parseFromString","parserError","querySelector","adElement","adId","title","clickThrough","wrapperUri","vastAdTagUri","isNoAdAvailable","durationText","durationParts","split","duration","parseInt","mediaFileElements","mf","index","bitrateAttr","bitrateValue","ad","id","fetchVastXml","vastTagUrl","response","fetch","mode","referrerPolicy","ok","statusText","text","depth","accumulatedTracking","vastXml","parsed","style","playsInline","substring","fetchAndParseVastAd","createAdVideoElement","video","document","createElement","position","left","top","objectFit","backgroundColor","muted","setupAdEventListeners","addEventListener","progress","currentTime","handleAdComplete","e","handleAdError","ended","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","continueLiveStreamDuringAds","paused","play","catch","initialize","container","right","bottom","alignItems","justifyContent","zIndex","parentElement","appendChild","requestAds","Promise","reject","has","delete","resolve","contentVolume","isHlsAd"],"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/hlsAdPlayer.ts\nvar hlsAdPlayer_exports = {};\n__export(hlsAdPlayer_exports, {\n createHlsAdPlayer: () => createHlsAdPlayer\n});\nmodule.exports = __toCommonJS(hlsAdPlayer_exports);\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar MAX_VAST_WRAPPER_DEPTH = 5;\nfunction createHlsAdPlayer(contentVideo, options) {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = /* @__PURE__ */ new Map();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n const preloadedAds = /* @__PURE__ */ new Map();\n const preloadingAds = /* @__PURE__ */ new Map();\n let destroyed = false;\n let pendingTimeouts = [];\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels(urls) {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n }\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level2 = mainHlsInstance.levels[autoLevel];\n return {\n width: level2.width || 1920,\n height: level2.height || 1080,\n bitrate: level2.bitrate || 5e6\n };\n }\n return null;\n }\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5e6\n };\n }\n function selectBestMediaFile(mediaFiles) {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n const fileBitrate = (file.bitrate || 5e3) * 1e3;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1e3;\n return { file, score, resolutionDiff, bitrateDiff };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff\n });\n return bestMatch.file;\n }\n function isHlsMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type === \"application/x-mpegurl\" || type === \"application/vnd.apple.mpegurl\" || type.includes(\"mpegurl\") || url.includes(\".m3u8\");\n }\n function isProgressiveMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type.startsWith(\"video/\") || url.endsWith(\".mp4\") || url.includes(\".mp4?\");\n }\n function createEmptyTrackingUrls() {\n return {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: []\n };\n }\n function extractTrackingUrls(xmlDoc) {\n const trackingUrls = createEmptyTrackingUrls();\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n xmlDoc.querySelectorAll(\"Error\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.error.push(url);\n });\n return trackingUrls;\n }\n function mergeTrackingUrls(target, source) {\n Object.keys(target).forEach((key) => {\n if (source[key] && source[key].length > 0) {\n target[key] = target[key].concat(source[key]);\n }\n });\n return target;\n }\n function parseVastXml(xmlString) {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return { type: \"empty\" };\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return { type: \"empty\" };\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n const wrapperUri = xmlDoc.querySelector(\"VASTAdTagURI\")?.textContent?.trim();\n if (wrapperUri) {\n console.log(\n `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n );\n return {\n type: \"wrapper\",\n vastAdTagUri: wrapperUri,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough\n };\n }\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n const mediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: void 0\n };\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n );\n }\n });\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n }\n return { type: \"empty\" };\n }\n return {\n type: \"inline\",\n ad: {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough\n }\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return { type: \"empty\" };\n }\n }\n async function fetchVastXml(vastTagUrl) {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\"\n },\n referrerPolicy: \"no-referrer-when-downgrade\"\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n return response.text();\n }\n async function fetchAndParseVastAd(vastTagUrl, depth = 0, accumulatedTracking = createEmptyTrackingUrls()) {\n const vastXml = await fetchVastXml(vastTagUrl);\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2e3)\n );\n const parsed = parseVastXml(vastXml);\n if (parsed.type === \"empty\") {\n return null;\n }\n if (parsed.type === \"wrapper\") {\n if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n console.warn(\n `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n );\n return null;\n }\n mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n return fetchAndParseVastAd(\n parsed.vastAdTagUri,\n depth + 1,\n accumulatedTracking\n );\n }\n mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n return parsed.ad;\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n video.volume = 1;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n const progress = adVideoElement.currentTime / currentAd.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function handleAdComplete() {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {\n });\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n emit(\"content_resume\");\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n async requestAds(vastTagUrl) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n try {\n sessionId = generateSessionId();\n let ad;\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No ads available from VAST response\"));\n }\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n adVideoElement.volume = Math.max(0, Math.min(1, originalVolume));\n adVideoElement.muted = originalMutedState;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n if (isHlsAd && import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n adHls = new import_hls.default({\n enableWorker: true,\n lowLatencyMode: false\n });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n adHls.on(import_hls.default.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n }\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {\n });\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}, volume: ${contentVideo.volume}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {\n });\n }\n }\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n currentAd = void 0;\n },\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n const clamped = Math.max(0, Math.min(1, volume));\n adVideoElement.volume = clamped;\n adVideoElement.muted = clamped === 0;\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n }\n };\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createHlsAdPlayer\n});\n","import type { AdController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\ntype VastParseResult =\n | { type: \"inline\"; ad: VastAd }\n | {\n type: \"wrapper\";\n vastAdTagUri: string;\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n }\n | { type: \"empty\" };\n\nconst MAX_VAST_WRAPPER_DEPTH = 5;\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): AdController {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n const preloadedAds = new Map<string, VastAd>();\n const preloadingAds = new Map<string, Promise<void>>();\n let destroyed = false;\n let pendingTimeouts: number[] = [];\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n if (sessionId) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function getMainStreamQuality(): {\n width: number;\n height: number;\n bitrate: number;\n } | null {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level = mainHlsInstance.levels[autoLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n return null;\n }\n\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n\n const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n return { file, score, resolutionDiff, bitrateDiff };\n });\n\n scoredFiles.sort((a, b) => a.score - b.score);\n\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff,\n });\n\n return bestMatch.file;\n }\n\n function isHlsMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type === \"application/x-mpegurl\" ||\n type === \"application/vnd.apple.mpegurl\" ||\n type.includes(\"mpegurl\") ||\n url.includes(\".m3u8\")\n );\n }\n\n function isProgressiveMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type.startsWith(\"video/\") ||\n url.endsWith(\".mp4\") ||\n url.includes(\".mp4?\")\n );\n }\n\n function createEmptyTrackingUrls(): VastTrackingUrls {\n return {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n }\n\n function extractTrackingUrls(xmlDoc: Document): VastTrackingUrls {\n const trackingUrls = createEmptyTrackingUrls();\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n xmlDoc.querySelectorAll(\"Error\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.error.push(url);\n });\n\n return trackingUrls;\n }\n\n function mergeTrackingUrls(\n target: VastTrackingUrls,\n source: VastTrackingUrls\n ): VastTrackingUrls {\n (Object.keys(target) as Array<keyof VastTrackingUrls>).forEach((key) => {\n if (source[key] && source[key].length > 0) {\n target[key] = target[key].concat(source[key]);\n }\n });\n return target;\n }\n\n function parseVastXml(xmlString: string): VastParseResult {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return { type: \"empty\" };\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return { type: \"empty\" };\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n const wrapperUri = xmlDoc\n .querySelector(\"VASTAdTagURI\")\n ?.textContent?.trim();\n if (wrapperUri) {\n console.log(\n `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n );\n return {\n type: \"wrapper\",\n vastAdTagUri: wrapperUri,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough,\n };\n }\n\n const isNoAdAvailable =\n adId === \"empty\" ||\n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\n\n const durationText =\n xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n\n const mediaFile: VastMediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: undefined,\n };\n\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n mediaFile.bitrate =\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined;\n\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n );\n }\n });\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n }\n return { type: \"empty\" };\n }\n\n return {\n type: \"inline\",\n ad: {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls: extractTrackingUrls(xmlDoc),\n clickThrough,\n },\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return { type: \"empty\" };\n }\n }\n\n async function fetchVastXml(vastTagUrl: string): Promise<string> {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\",\n },\n referrerPolicy: \"no-referrer-when-downgrade\",\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n return response.text();\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string,\n depth = 0,\n accumulatedTracking: VastTrackingUrls = createEmptyTrackingUrls()\n ): Promise<VastAd | null> {\n const vastXml = await fetchVastXml(vastTagUrl);\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2000)\n );\n\n const parsed = parseVastXml(vastXml);\n\n if (parsed.type === \"empty\") {\n return null;\n }\n\n if (parsed.type === \"wrapper\") {\n if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n console.warn(\n `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n );\n return null;\n }\n\n mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n return fetchAndParseVastAd(\n parsed.vastAdTagUri,\n depth + 1,\n accumulatedTracking\n );\n }\n\n mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n return parsed.ad;\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n\n video.volume = 1.0;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {});\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n emit(\"ad_error\");\n }\n\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(vastTagUrl: string) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n\n try {\n sessionId = generateSessionId();\n let ad: VastAd | null | undefined;\n\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No ads available from VAST response\"));\n }\n\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n adVideoElement.volume = Math.max(0, Math.min(1, originalVolume));\n adVideoElement.muted = originalMutedState;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n\n if (isHlsAd && Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false,\n });\n\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement!.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && (\n adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")\n )) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n }\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {});\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}, volume: ${contentVideo.volume}`\n );\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {});\n }\n }\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n\n currentAd = undefined;\n },\n\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n \n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n \n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n const clamped = Math.max(0, Math.min(1, volume));\n adVideoElement.volume = clamped;\n adVideoElement.muted = clamped === 0;\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n \n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n },\n };\n}\n"]}