stormcloud-video-player 0.3.67 → 0.3.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/stormcloud-vp.min.js +1 -1
- package/lib/index.cjs +85 -12
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +5 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +85 -12
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +85 -12
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +5 -0
- package/lib/players/HlsPlayer.cjs +85 -12
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +85 -12
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +11 -3
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +85 -12
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
package/lib/sdk/hlsAdPlayer.cjs
CHANGED
|
@@ -367,7 +367,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
367
367
|
}
|
|
368
368
|
var adElement = xmlDoc.querySelector("Ad");
|
|
369
369
|
if (!adElement) {
|
|
370
|
-
console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
|
|
370
|
+
console.warn("[HlsAdPlayer] No Ad element found in VAST XML (no fill). Content (first 2000 chars):", xmlString.substring(0, 2e3));
|
|
371
371
|
return null;
|
|
372
372
|
}
|
|
373
373
|
var adId = adElement.getAttribute("id") || "unknown";
|
|
@@ -463,7 +463,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
463
463
|
}
|
|
464
464
|
function fetchAndParseVastAd(vastTagUrl) {
|
|
465
465
|
return _async_to_generator(function() {
|
|
466
|
-
var response, vastXml;
|
|
466
|
+
var response, vastXml, trimmedXml;
|
|
467
467
|
return _ts_generator(this, function(_state) {
|
|
468
468
|
switch(_state.label){
|
|
469
469
|
case 0:
|
|
@@ -489,8 +489,16 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
489
489
|
];
|
|
490
490
|
case 2:
|
|
491
491
|
vastXml = _state.sent();
|
|
492
|
-
console.log("[HlsAdPlayer] VAST XML received");
|
|
492
|
+
console.log("[HlsAdPlayer] VAST XML received (length=".concat(vastXml.length, ")"));
|
|
493
493
|
console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
|
|
494
|
+
trimmedXml = vastXml.trim();
|
|
495
|
+
if (trimmedXml.length === 0) {
|
|
496
|
+
console.warn("[HlsAdPlayer] VAST response body is empty (no fill)");
|
|
497
|
+
return [
|
|
498
|
+
2,
|
|
499
|
+
null
|
|
500
|
+
];
|
|
501
|
+
}
|
|
494
502
|
return [
|
|
495
503
|
2,
|
|
496
504
|
parseVastXml(vastXml)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/sdk/hlsAdPlayer.cjs","../../src/sdk/hlsAdPlayer.ts"],"names":["__create","Object","__defProp","create","defineProperty","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__getOwnPropDesc","hlsAdPlayer_exports","createHlsAdPlayer","mainHlsInstance","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","module","exports","import_hls","require","contentVideo","options","originalMutedState","originalVolume","Math","max","min","volume","listeners","Map","licenseKey","adVideoElement","adHls","currentAd","sessionId","preloadedAds","preloadingAds","destroyed","pendingTimeouts","trackingFired","impression","start","firstQuartile","midpoint","thirdQuartile","complete","emit","event","payload","set","Array","fn","error","console","warn","generateSessionId","Date","now","random","toString","substr","fireTrackingPixels","urls","length","forEach","url","trackingUrl","includes","src","img","Image","log","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","width","height","bitrate","selectBestMediaFile","mediaFiles","Error","firstFile","mainQuality","scoredFiles","map","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","sort","a","b","bestMatch","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","isProgressiveMediaFile","startsWith","endsWith","parseVastXml","xmlString","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","textContent","adElement","adId","getAttribute","title","isNoAdAvailable","durationText","durationParts","split","duration","parseInt","mediaFileElements","querySelectorAll","mf","index","trim","bitrateAttr","bitrateValue","push","trackingUrls","mute","unmute","pause","el","resume","fullscreen","exitFullscreen","skip","eventKey","clickThrough","response","vastXml","fetch","vastTagUrl","credentials","headers","referrerPolicy","ok","style","left","progress","statusText","text","substring","createAdVideoElement","video","document","createElement","position","top","backgroundColor","playsInline","muted","setupAdEventListeners","addEventListener","currentTime","handleAdComplete","e","handleAdError","ended","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","adPlaying","adContainerEl","display","pointerEvents","continueLiveStreamDuringAds","paused","play","catch","initialize","container","right","bottom","alignItems","zIndex","parentElement","appendChild","requestAds","ad","Promise","reject","has","delete","fetchAndParseVastAd","resolve","contentVolume","adVolume","isHlsAd","Hls","isSupported"],"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);\nfunction createHlsAdPlayer(contentVideo, options) {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = /* @__PURE__ */ new Map();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n const preloadedAds = /* @__PURE__ */ new Map();\n const preloadingAds = /* @__PURE__ */ new Map();\n let destroyed = false;\n let pendingTimeouts = [];\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels(urls) {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n }\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level2 = mainHlsInstance.levels[autoLevel];\n return {\n width: level2.width || 1920,\n height: level2.height || 1080,\n bitrate: level2.bitrate || 5e6\n };\n }\n return null;\n }\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5e6\n };\n }\n function selectBestMediaFile(mediaFiles) {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n const fileBitrate = (file.bitrate || 5e3) * 1e3;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1e3;\n return { file, score, resolutionDiff, bitrateDiff };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff\n });\n return bestMatch.file;\n }\n function isHlsMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type === \"application/x-mpegurl\" || type === \"application/vnd.apple.mpegurl\" || type.includes(\"mpegurl\") || url.includes(\".m3u8\");\n }\n function isProgressiveMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type.startsWith(\"video/\") || url.endsWith(\".mp4\") || url.includes(\".mp4?\");\n }\n function parseVastXml(xmlString) {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n const mediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: void 0\n };\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n );\n }\n });\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n }\n return null;\n }\n const trackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: []\n };\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n async function fetchAndParseVastAd(vastTagUrl) {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\"\n },\n referrerPolicy: \"no-referrer-when-downgrade\"\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml);\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n video.volume = 1;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n const progress = adVideoElement.currentTime / currentAd.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function handleAdComplete() {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {\n });\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n emit(\"content_resume\");\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n async requestAds(vastTagUrl) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n try {\n sessionId = generateSessionId();\n let ad;\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No ads available from VAST response\"));\n }\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n if (isHlsAd && import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n adHls = new import_hls.default({\n enableWorker: true,\n lowLatencyMode: false\n });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n adHls.on(import_hls.default.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n }\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {\n });\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {\n });\n }\n }\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n currentAd = void 0;\n },\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n }\n };\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createHlsAdPlayer\n});\n","import type { ImaController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): ImaController {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n const preloadedAds = new Map<string, VastAd>();\n const preloadingAds = new Map<string, Promise<void>>();\n let destroyed = false;\n let pendingTimeouts: number[] = [];\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n if (sessionId) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function getMainStreamQuality(): {\n width: number;\n height: number;\n bitrate: number;\n } | null {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level = mainHlsInstance.levels[autoLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n return null;\n }\n\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n\n const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n return { file, score, resolutionDiff, bitrateDiff };\n });\n\n scoredFiles.sort((a, b) => a.score - b.score);\n\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff,\n });\n\n return bestMatch.file;\n }\n\n function isHlsMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type === \"application/x-mpegurl\" ||\n type === \"application/vnd.apple.mpegurl\" ||\n type.includes(\"mpegurl\") ||\n url.includes(\".m3u8\")\n );\n }\n\n function isProgressiveMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type.startsWith(\"video/\") ||\n url.endsWith(\".mp4\") ||\n url.includes(\".mp4?\")\n );\n }\n\n function parseVastXml(xmlString: string): VastAd | null {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const isNoAdAvailable =\n adId === \"empty\" ||\n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\n\n const durationText =\n xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n\n const mediaFile: VastMediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: undefined,\n };\n\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n mediaFile.bitrate =\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined;\n\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n );\n }\n });\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n }\n return null;\n }\n\n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string\n ): Promise<VastAd | null> {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\",\n },\n referrerPolicy: \"no-referrer-when-downgrade\",\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml);\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n\n video.volume = 1.0;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {});\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n emit(\"ad_error\");\n }\n\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(vastTagUrl: string) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n\n try {\n sessionId = generateSessionId();\n let ad: VastAd | null | undefined;\n\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No ads available from VAST response\"));\n }\n\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n\n if (isHlsAd && Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false,\n });\n\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement!.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && (\n adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")\n )) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n }\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {});\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\n );\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {});\n }\n }\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n\n currentAd = undefined;\n },\n\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n \n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n \n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n \n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/sdk/hlsAdPlayer.cjs","../../src/sdk/hlsAdPlayer.ts"],"names":["__create","Object","__defProp","create","defineProperty","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__getOwnPropDesc","createHlsAdPlayer","mainHlsInstance","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","hlsAdPlayer_exports","module","exports","import_hls","require","contentVideo","options","adPlaying","originalMutedState","originalVolume","Math","max","volume","min","licenseKey","adVideoElement","adHls","adContainerEl","currentAd","sessionId","preloadingAds","Map","destroyed","pendingTimeouts","trackingFired","impression","start","firstQuartile","midpoint","thirdQuartile","complete","emit","event","payload","set","listeners","fn","Array","error","console","warn","generateSessionId","Date","now","random","toString","substr","fireTrackingPixels","urls","length","forEach","url","trackingUrl","includes","img","Image","src","log","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","width","height","bitrate","firstFile","selectBestMediaFile","mediaFiles","Error","mainQuality","scoredFiles","map","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","sort","a","b","bestMatch","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","isProgressiveMediaFile","startsWith","endsWith","parseVastXml","xmlString","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","textContent","adElement","substring","adId","getAttribute","title","isNoAdAvailable","durationText","durationParts","split","duration","parseInt","mediaFileElements","querySelectorAll","mf","index","trim","bitrateAttr","bitrateValue","push","trackingUrls","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","el","clickThrough","eventKey","id","fetchAndParseVastAd","vastTagUrl","response","vastXml","trimmedXml","mode","headers","referrerPolicy","statusText","text","style","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","parentElement","appendChild","requestAds","ad","Promise","reject","preloadedAds","has","delete","resolve","contentVolume","adVolume","isHlsAd","Hls","isSupported","destroy"],"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);\nfunction createHlsAdPlayer(contentVideo, options) {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = /* @__PURE__ */ new Map();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n const preloadedAds = /* @__PURE__ */ new Map();\n const preloadingAds = /* @__PURE__ */ new Map();\n let destroyed = false;\n let pendingTimeouts = [];\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels(urls) {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n }\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level2 = mainHlsInstance.levels[autoLevel];\n return {\n width: level2.width || 1920,\n height: level2.height || 1080,\n bitrate: level2.bitrate || 5e6\n };\n }\n return null;\n }\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5e6\n };\n }\n function selectBestMediaFile(mediaFiles) {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n const fileBitrate = (file.bitrate || 5e3) * 1e3;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1e3;\n return { file, score, resolutionDiff, bitrateDiff };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff\n });\n return bestMatch.file;\n }\n function isHlsMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type === \"application/x-mpegurl\" || type === \"application/vnd.apple.mpegurl\" || type.includes(\"mpegurl\") || url.includes(\".m3u8\");\n }\n function isProgressiveMediaFile(mediaFile) {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return type.startsWith(\"video/\") || url.endsWith(\".mp4\") || url.includes(\".mp4?\");\n }\n function parseVastXml(xmlString) {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\n \"[HlsAdPlayer] No Ad element found in VAST XML (no fill). Content (first 2000 chars):\",\n xmlString.substring(0, 2e3)\n );\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n const mediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: void 0\n };\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n );\n }\n });\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n }\n return null;\n }\n const trackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: []\n };\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n async function fetchAndParseVastAd(vastTagUrl) {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\"\n },\n referrerPolicy: \"no-referrer-when-downgrade\"\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n const vastXml = await response.text();\n console.log(\n `[HlsAdPlayer] VAST XML received (length=${vastXml.length})`\n );\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2e3)\n );\n const trimmedXml = vastXml.trim();\n if (trimmedXml.length === 0) {\n console.warn(\"[HlsAdPlayer] VAST response body is empty (no fill)\");\n return null;\n }\n return parseVastXml(vastXml);\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n video.volume = 1;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n const progress = adVideoElement.currentTime / currentAd.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function handleAdComplete() {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {\n });\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n emit(\"content_resume\");\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n async requestAds(vastTagUrl) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n try {\n sessionId = generateSessionId();\n let ad;\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No ads available from VAST response\"));\n }\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n if (isHlsAd && import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n adHls = new import_hls.default({\n enableWorker: true,\n lowLatencyMode: false\n });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n adHls.on(import_hls.default.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n }\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {\n });\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {\n });\n }\n }\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n currentAd = void 0;\n },\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n }\n };\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createHlsAdPlayer\n});\n","import type { ImaController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): ImaController {\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n const preloadedAds = new Map<string, VastAd>();\n const preloadingAds = new Map<string, Promise<void>>();\n let destroyed = false;\n let pendingTimeouts: number[] = [];\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n if (sessionId) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function getMainStreamQuality(): {\n width: number;\n height: number;\n bitrate: number;\n } | null {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level = mainHlsInstance.levels[autoLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n return null;\n }\n\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n\n const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n return { file, score, resolutionDiff, bitrateDiff };\n });\n\n scoredFiles.sort((a, b) => a.score - b.score);\n\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff,\n });\n\n return bestMatch.file;\n }\n\n function isHlsMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type === \"application/x-mpegurl\" ||\n type === \"application/vnd.apple.mpegurl\" ||\n type.includes(\"mpegurl\") ||\n url.includes(\".m3u8\")\n );\n }\n\n function isProgressiveMediaFile(mediaFile: VastMediaFile): boolean {\n const type = mediaFile.type.toLowerCase();\n const url = mediaFile.url.toLowerCase();\n return (\n type.startsWith(\"video/\") ||\n url.endsWith(\".mp4\") ||\n url.includes(\".mp4?\")\n );\n }\n\n function parseVastXml(xmlString: string): VastAd | null {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\n \"[HlsAdPlayer] No Ad element found in VAST XML (no fill). Content (first 2000 chars):\",\n xmlString.substring(0, 2000)\n );\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const isNoAdAvailable =\n adId === \"empty\" ||\n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\n\n const durationText =\n xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n\n const mediaFile: VastMediaFile = {\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: undefined,\n };\n\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n mediaFile.bitrate =\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined;\n\n if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n mediaFiles.push(mediaFile);\n console.log(\n `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n );\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n );\n }\n });\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n }\n return null;\n }\n\n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n\n async function fetchAndParseVastAd(\n vastTagUrl: string\n ): Promise<VastAd | null> {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n \"Accept\": \"application/xml, text/xml, */*\",\n },\n referrerPolicy: \"no-referrer-when-downgrade\",\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n\n const vastXml = await response.text();\n console.log(\n `[HlsAdPlayer] VAST XML received (length=${vastXml.length})`\n );\n console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2000)\n );\n\n const trimmedXml = vastXml.trim();\n if (trimmedXml.length === 0) {\n console.warn(\"[HlsAdPlayer] VAST response body is empty (no fill)\");\n return null;\n }\n\n return parseVastXml(vastXml);\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n\n video.volume = 1.0;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n contentVideo.play().catch(() => {});\n } else {\n console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n }\n }\n\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n emit(\"ad_error\");\n }\n\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"30\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(vastTagUrl: string) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n\n if (adPlaying) {\n console.warn(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n\n try {\n sessionId = generateSessionId();\n let ad: VastAd | null | undefined;\n\n if (preloadedAds.has(vastTagUrl)) {\n ad = preloadedAds.get(vastTagUrl);\n preloadedAds.delete(vastTagUrl);\n console.log(\n \"[HlsAdPlayer] Using preloaded VAST response:\",\n vastTagUrl\n );\n } else {\n ad = await fetchAndParseVastAd(vastTagUrl);\n }\n\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No ads available from VAST response\"));\n }\n\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\n\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n console.warn(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(\n 0,\n Math.min(1, contentVolume || originalVolume)\n );\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n\n console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n const isHlsAd = isHlsMediaFile(mediaFile);\n console.log(\n `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad from: ${mediaFile.url}`\n );\n\n if (isHlsAd && Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false,\n });\n\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement!.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (isHlsAd && (\n adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")\n )) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n }\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n pause() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && !adVideoElement.paused) {\n adVideoElement.pause();\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) {\n return;\n }\n\n try {\n if (adVideoElement && adVideoElement.paused) {\n adVideoElement.play().catch(() => {});\n }\n } catch (error) {\n console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n }\n },\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n console.log(\n `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}`\n );\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n\n if (options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n contentVideo.play().catch(() => {});\n }\n }\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n\n currentAd = undefined;\n },\n\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n destroyed = true;\n \n for (const timeoutId of pendingTimeouts) {\n clearTimeout(timeoutId);\n }\n pendingTimeouts = [];\n \n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n preloadedAds.clear();\n preloadingAds.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n );\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n contentVideo.style.opacity = \"0\";\n contentVideo.style.visibility = \"hidden\";\n \n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n if (!adPlaying) {\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n }\n },\n };\n}\n"]}
|
|
@@ -1769,7 +1769,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1769
1769
|
}
|
|
1770
1770
|
var adElement = xmlDoc.querySelector("Ad");
|
|
1771
1771
|
if (!adElement) {
|
|
1772
|
-
console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
|
|
1772
|
+
console.warn("[HlsAdPlayer] No Ad element found in VAST XML (no fill). Content (first 2000 chars):", xmlString.substring(0, 2e3));
|
|
1773
1773
|
return null;
|
|
1774
1774
|
}
|
|
1775
1775
|
var adId = adElement.getAttribute("id") || "unknown";
|
|
@@ -1865,7 +1865,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1865
1865
|
}
|
|
1866
1866
|
function fetchAndParseVastAd(vastTagUrl) {
|
|
1867
1867
|
return _async_to_generator(function() {
|
|
1868
|
-
var response, vastXml;
|
|
1868
|
+
var response, vastXml, trimmedXml;
|
|
1869
1869
|
return _ts_generator(this, function(_state) {
|
|
1870
1870
|
switch(_state.label){
|
|
1871
1871
|
case 0:
|
|
@@ -1891,8 +1891,16 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1891
1891
|
];
|
|
1892
1892
|
case 2:
|
|
1893
1893
|
vastXml = _state.sent();
|
|
1894
|
-
console.log("[HlsAdPlayer] VAST XML received");
|
|
1894
|
+
console.log("[HlsAdPlayer] VAST XML received (length=".concat(vastXml.length, ")"));
|
|
1895
1895
|
console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
|
|
1896
|
+
trimmedXml = vastXml.trim();
|
|
1897
|
+
if (trimmedXml.length === 0) {
|
|
1898
|
+
console.warn("[HlsAdPlayer] VAST response body is empty (no fill)");
|
|
1899
|
+
return [
|
|
1900
|
+
2,
|
|
1901
|
+
null
|
|
1902
|
+
];
|
|
1903
|
+
}
|
|
1896
1904
|
return [
|
|
1897
1905
|
2,
|
|
1898
1906
|
parseVastXml(vastXml)
|
|
@@ -3332,6 +3340,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3332
3340
|
this.preloadPoolActive = false;
|
|
3333
3341
|
this.preloadPoolLoopRunning = false;
|
|
3334
3342
|
this.adDetectSentForCurrentBreak = false;
|
|
3343
|
+
this.latencyProfileApplied = false;
|
|
3335
3344
|
this.continuousFetchLoopRunning = false;
|
|
3336
3345
|
initializePolyfills();
|
|
3337
3346
|
var browserOverrides = getBrowserConfigOverrides();
|
|
@@ -3448,24 +3457,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3448
3457
|
2
|
|
3449
3458
|
];
|
|
3450
3459
|
case 7:
|
|
3451
|
-
this.hls = new import_hls2.default(
|
|
3460
|
+
this.hls = new import_hls2.default({
|
|
3452
3461
|
enableWorker: true,
|
|
3453
3462
|
backBufferLength: 30,
|
|
3454
3463
|
liveDurationInfinity: true,
|
|
3455
3464
|
lowLatencyMode: !!this.config.lowLatencyMode,
|
|
3456
|
-
maxLiveSyncPlaybackRate:
|
|
3457
|
-
}, this.config.lowLatencyMode ? {
|
|
3458
|
-
liveSyncDuration: 2
|
|
3459
|
-
} : {}), {
|
|
3465
|
+
maxLiveSyncPlaybackRate: 1.1,
|
|
3460
3466
|
maxBufferLength: 30,
|
|
3461
3467
|
maxMaxBufferLength: 600,
|
|
3462
3468
|
maxBufferSize: 60 * 1e3 * 1e3,
|
|
3463
|
-
maxBufferHole:
|
|
3469
|
+
maxBufferHole: 1,
|
|
3464
3470
|
highBufferWatchdogPeriod: 2,
|
|
3465
|
-
nudgeOffset: 0.
|
|
3466
|
-
nudgeMaxRetry:
|
|
3471
|
+
nudgeOffset: 0.2,
|
|
3472
|
+
nudgeMaxRetry: 5,
|
|
3467
3473
|
startPosition: -1
|
|
3468
|
-
})
|
|
3474
|
+
});
|
|
3469
3475
|
this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
|
|
3470
3476
|
var _this_hls;
|
|
3471
3477
|
(_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
|
|
@@ -3509,6 +3515,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3509
3515
|
this.bufferedSegmentsCount = 0;
|
|
3510
3516
|
this.hasInitialBufferCompleted = false;
|
|
3511
3517
|
this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
|
|
3518
|
+
this.latencyProfileApplied = false;
|
|
3519
|
+
this.detectedLowLatencyStream = void 0;
|
|
3512
3520
|
minSegments = (_this_config_minSegmentsBeforePlay = this.config.minSegmentsBeforePlay) !== null && _this_config_minSegmentsBeforePlay !== void 0 ? _this_config_minSegmentsBeforePlay : 2;
|
|
3513
3521
|
if (this.config.debugAdTiming) {
|
|
3514
3522
|
console.log("[StormcloudVideoPlayer] Waiting for", minSegments, "segments to buffer before playback");
|
|
@@ -3538,6 +3546,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3538
3546
|
}).call(_this);
|
|
3539
3547
|
});
|
|
3540
3548
|
this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
|
|
3549
|
+
_this.applyStreamLatencyProfile(data === null || data === void 0 ? void 0 : data.details);
|
|
3541
3550
|
if (_this.inAdBreak || _this.pendingAdBreak) {
|
|
3542
3551
|
return;
|
|
3543
3552
|
}
|
|
@@ -3817,6 +3826,64 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3817
3826
|
}).call(this);
|
|
3818
3827
|
}
|
|
3819
3828
|
},
|
|
3829
|
+
{
|
|
3830
|
+
key: "applyStreamLatencyProfile",
|
|
3831
|
+
value: function applyStreamLatencyProfile(details) {
|
|
3832
|
+
if (this.latencyProfileApplied || !this.hls) {
|
|
3833
|
+
return;
|
|
3834
|
+
}
|
|
3835
|
+
if (!details) {
|
|
3836
|
+
return;
|
|
3837
|
+
}
|
|
3838
|
+
if (details.live !== true) {
|
|
3839
|
+
this.latencyProfileApplied = true;
|
|
3840
|
+
this.detectedLowLatencyStream = false;
|
|
3841
|
+
return;
|
|
3842
|
+
}
|
|
3843
|
+
var isLowLatencyManifest = this.isLowLatencyManifest(details);
|
|
3844
|
+
var useLowLatency = isLowLatencyManifest && !!this.config.lowLatencyMode;
|
|
3845
|
+
this.detectedLowLatencyStream = useLowLatency;
|
|
3846
|
+
this.latencyProfileApplied = true;
|
|
3847
|
+
var cfg = this.hls.config;
|
|
3848
|
+
if (useLowLatency) {
|
|
3849
|
+
cfg.maxLiveSyncPlaybackRate = 1.5;
|
|
3850
|
+
cfg.maxBufferHole = 0.5;
|
|
3851
|
+
delete cfg.liveSyncDuration;
|
|
3852
|
+
} else {
|
|
3853
|
+
cfg.maxLiveSyncPlaybackRate = 1.1;
|
|
3854
|
+
cfg.maxBufferHole = 1;
|
|
3855
|
+
delete cfg.liveSyncDuration;
|
|
3856
|
+
cfg.liveSyncDurationCount = 3;
|
|
3857
|
+
}
|
|
3858
|
+
if (this.config.debugAdTiming) {
|
|
3859
|
+
var _details_targetduration;
|
|
3860
|
+
console.log("[StormcloudVideoPlayer] Live latency profile: ".concat(useLowLatency ? "LL-HLS (low latency)" : "standard live (stability)"), {
|
|
3861
|
+
isLowLatencyManifest: isLowLatencyManifest,
|
|
3862
|
+
lowLatencyModeRequested: !!this.config.lowLatencyMode,
|
|
3863
|
+
canBlockReload: details.canBlockReload,
|
|
3864
|
+
partTarget: details.partTarget,
|
|
3865
|
+
partHoldBack: details.partHoldBack,
|
|
3866
|
+
partListLength: Array.isArray(details.partList) ? details.partList.length : 0,
|
|
3867
|
+
targetDuration: (_details_targetduration = details.targetduration) !== null && _details_targetduration !== void 0 ? _details_targetduration : details.targetDuration,
|
|
3868
|
+
maxLiveSyncPlaybackRate: cfg.maxLiveSyncPlaybackRate,
|
|
3869
|
+
maxBufferHole: cfg.maxBufferHole
|
|
3870
|
+
});
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
},
|
|
3874
|
+
{
|
|
3875
|
+
key: "isLowLatencyManifest",
|
|
3876
|
+
value: function isLowLatencyManifest(details) {
|
|
3877
|
+
if (!details) {
|
|
3878
|
+
return false;
|
|
3879
|
+
}
|
|
3880
|
+
var hasParts = Array.isArray(details.partList) && details.partList.length > 0;
|
|
3881
|
+
var hasPartTarget = typeof details.partTarget === "number" && details.partTarget > 0;
|
|
3882
|
+
var hasPartHoldBack = typeof details.partHoldBack === "number" && details.partHoldBack > 0;
|
|
3883
|
+
var canBlockReload = details.canBlockReload === true;
|
|
3884
|
+
return hasParts || hasPartTarget || hasPartHoldBack || canBlockReload;
|
|
3885
|
+
}
|
|
3886
|
+
},
|
|
3820
3887
|
{
|
|
3821
3888
|
key: "attachImaEventListeners",
|
|
3822
3889
|
value: function attachImaEventListeners() {
|
|
@@ -5805,6 +5872,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
5805
5872
|
return !!(this.config.allowNativeHls && !((_this_config_showCustomControls = this.config.showCustomControls) !== null && _this_config_showCustomControls !== void 0 ? _this_config_showCustomControls : false));
|
|
5806
5873
|
}
|
|
5807
5874
|
},
|
|
5875
|
+
{
|
|
5876
|
+
key: "isLowLatencyStream",
|
|
5877
|
+
value: function isLowLatencyStream() {
|
|
5878
|
+
return this.detectedLowLatencyStream;
|
|
5879
|
+
}
|
|
5880
|
+
},
|
|
5808
5881
|
{
|
|
5809
5882
|
key: "shouldContinueLiveStreamDuringAds",
|
|
5810
5883
|
value: function shouldContinueLiveStreamDuringAds() {
|