stormcloud-video-player 0.3.16 → 0.3.17
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 -10
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/FilePlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/utils/browserCompat.cjs.map +1 -1
- package/lib/utils/polyfills.cjs.map +1 -1
- package/lib/utils/tracking.cjs.map +1 -1
- package/package.json +5 -1
- package/rollup.config.js +22 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24/Dev/stormcloud-vp/lib/sdk/hlsAdPlayer.cjs"],"names":[],"mappings":"AAAA","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 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 if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n if (!url) {\n console.warn(\n `[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0\n });\n console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not HLS)`\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 HLS 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 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 emit(\"content_resume\");\n const timeoutId = window.setTimeout(() => {\n if (destroyed) {\n console.log(\"[HlsAdPlayer] Player destroyed, skipping post-completion check\");\n return;\n }\n const stillInPod = contentVideo.dataset.stormcloudAdPlaying === \"true\";\n if (stillInPod) {\n console.log(\n \"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)\"\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n }\n const idx = pendingTimeouts.indexOf(timeoutId);\n if (idx !== -1) {\n pendingTimeouts.splice(idx, 1);\n }\n }, 50);\n pendingTimeouts.push(timeoutId);\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\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: ${previousMutedState} -> ${originalMutedState}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n contentVideo.play().catch(() => {\n });\n }\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 = \"10\";\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.resolve();\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 preloadAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n if (preloadedAds.has(vastTagUrl)) {\n return Promise.resolve();\n }\n const inflight = preloadingAds.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {\n if (ad) {\n preloadedAds.set(vastTagUrl, ad);\n console.log(\n \"[HlsAdPlayer] Cached VAST response for preloading:\",\n vastTagUrl\n );\n }\n }).catch((error) => {\n console.warn(\"[HlsAdPlayer] Failed to preload VAST response:\", error);\n preloadedAds.delete(vastTagUrl);\n }).finally(() => {\n preloadingAds.delete(vastTagUrl);\n });\n preloadingAds.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl) {\n return preloadedAds.has(vastTagUrl);\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 console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);\n if (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 (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 {\n throw new Error(\"HLS not supported\");\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 async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\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 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 }\n };\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createHlsAdPlayer\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24/Dev/stormcloud-vp/lib/sdk/hlsAdPlayer.cjs","../../src/sdk/hlsAdPlayer.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","value","__toCommonJS","hlsAdPlayer_exports","createHlsAdPlayer","exports","contentVideo","options","originalMutedState","adPlaying","originalVolume","Math","max","min","volume","listeners","Map","licenseKey","mainHlsInstance","adHls","adContainerEl","currentAd","sessionId","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","img","Image","src","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","parseVastXml","xmlString","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","textContent","adElement","adId","getAttribute","title","isNoAdAvailable","toLowerCase","durationText","durationParts","split","duration","parseInt","mediaFileElements","querySelectorAll","mf","index","type","trim","bitrateAttr","bitrateValue","push","trackingUrls","mute","unmute","pause","fullscreen","exitFullscreen","skip","el","eventKey","clickThrough","id","fetchAndParseVastAd","vastTagUrl","fetch","response","ok","statusText","vastXml","substring","createAdVideoElement","video","document","createElement","style","position","top","adVideoElement","objectFit","backgroundColor","playsInline","muted","setupAdEventListeners","addEventListener","progress","currentTime","handleAdComplete","e","handleAdError","resume","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","timeoutId","window","setTimeout","stillInPod","display","pointerEvents","idx","indexOf","splice","previousMutedState","continueLiveStreamDuringAds","paused","play","catch","initialize","container","left","right","bottom","alignItems","justifyContent","zIndex","parentElement","appendChild","requestAds","ad","Promise","reject","preloadedAds","has","delete","resolve","preloadAds","inflight","preloadPromise","then","finally"],"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 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 if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n if (!url) {\n console.warn(\n `[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0\n });\n console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not HLS)`\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 HLS 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 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 emit(\"content_resume\");\n const timeoutId = window.setTimeout(() => {\n if (destroyed) {\n console.log(\"[HlsAdPlayer] Player destroyed, skipping post-completion check\");\n return;\n }\n const stillInPod = contentVideo.dataset.stormcloudAdPlaying === \"true\";\n if (stillInPod) {\n console.log(\n \"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)\"\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n }\n const idx = pendingTimeouts.indexOf(timeoutId);\n if (idx !== -1) {\n pendingTimeouts.splice(idx, 1);\n }\n }, 50);\n pendingTimeouts.push(timeoutId);\n }\n function handleAdError() {\n console.log(\"[HlsAdPlayer] Handling ad error\");\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: ${previousMutedState} -> ${originalMutedState}`\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n if (!options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n contentVideo.play().catch(() => {\n });\n }\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 = \"10\";\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.resolve();\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 preloadAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n if (preloadedAds.has(vastTagUrl)) {\n return Promise.resolve();\n }\n const inflight = preloadingAds.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {\n if (ad) {\n preloadedAds.set(vastTagUrl, ad);\n console.log(\n \"[HlsAdPlayer] Cached VAST response for preloading:\",\n vastTagUrl\n );\n }\n }).catch((error) => {\n console.warn(\"[HlsAdPlayer] Failed to preload VAST response:\", error);\n preloadedAds.delete(vastTagUrl);\n }).finally(() => {\n preloadingAds.delete(vastTagUrl);\n });\n preloadingAds.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl) {\n return preloadedAds.has(vastTagUrl);\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 console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);\n if (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 (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 {\n throw new Error(\"HLS not supported\");\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 async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\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 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 }\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 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 if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n if (!url) {\n console.warn(\n `[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`\n );\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate:\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n\n console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not HLS)`\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 HLS 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 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 emit(\"content_resume\");\n\n const timeoutId = window.setTimeout(() => {\n if (destroyed) {\n console.log(\"[HlsAdPlayer] Player destroyed, skipping post-completion check\");\n return;\n }\n \n const stillInPod = contentVideo.dataset.stormcloudAdPlaying === \"true\";\n if (stillInPod) {\n console.log(\n \"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)\"\n );\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n }\n \n const idx = pendingTimeouts.indexOf(timeoutId);\n if (idx !== -1) {\n pendingTimeouts.splice(idx, 1);\n }\n }, 50);\n \n pendingTimeouts.push(timeoutId);\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\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: ${previousMutedState} -> ${originalMutedState}`\n );\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 contentVideo.play().catch(() => {});\n }\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 = \"10\";\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.resolve();\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 preloadAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n\n if (preloadedAds.has(vastTagUrl)) {\n return Promise.resolve();\n }\n\n const inflight = preloadingAds.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n\n const preloadPromise = fetchAndParseVastAd(vastTagUrl)\n .then((ad) => {\n if (ad) {\n preloadedAds.set(vastTagUrl, ad);\n console.log(\n \"[HlsAdPlayer] Cached VAST response for preloading:\",\n vastTagUrl\n );\n }\n })\n .catch((error) => {\n console.warn(\"[HlsAdPlayer] Failed to preload VAST response:\", error);\n preloadedAds.delete(vastTagUrl);\n })\n .finally(() => {\n preloadingAds.delete(vastTagUrl);\n });\n\n preloadingAds.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl: string) {\n return preloadedAds.has(vastTagUrl);\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 // Capture content volume BEFORE muting\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 console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);\n\n if (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 (\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 {\n throw new Error(\"HLS not supported\");\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\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\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 // Clear all pending timeouts\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 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 };\n}\n"]}
|
package/lib/sdk/ima.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24/Dev/stormcloud-vp/lib/sdk/ima.cjs","../../src/utils/browserCompat.ts"],"names":["from","__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","except","desc","key","call"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\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 __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/sdk/ima.ts\nvar ima_exports = {};\n__export(ima_exports, {\n createImaController: () => createImaController\n});\nmodule.exports = __toCommonJS(ima_exports);\n\n// src/utils/browserCompat.ts\nfunction getChromeVersion(ua) {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getWebKitVersion(ua) {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getPlatform() {\n if (\"userAgentData\" in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? \"iPhone\" : \"MacIntel\";\n }\n if (/Win/i.test(ua)) {\n return \"Win32\";\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? \"Linux armv8l\" : \"Linux x86_64\";\n }\n if (/CrOS/i.test(ua)) {\n return \"CrOS\";\n }\n return navigator.platform || \"Unknown\";\n}\nfunction detectBrowser() {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n let name = \"Unknown\";\n let version = \"0\";\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer = \"ima\";\n if (/Web0S|webOS/i.test(ua)) {\n name = \"LG WebOS\";\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = \"Samsung Tizen\";\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n }\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n isLegacyTV = true;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n if (typeof URLSearchParams === \"undefined\") {\n supportsModernJS = false;\n }\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS,\n recommendedAdPlayer\n };\n}\nfunction supportsGoogleIMA() {\n const browser = detectBrowser();\n if (browser.isLegacyTV) {\n return false;\n }\n if (typeof document === \"undefined\" || typeof document.createElement !== \"function\") {\n return false;\n }\n try {\n const video = document.createElement(\"video\");\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n if (typeof Promise === \"undefined\") {\n return false;\n }\n return browser.supportsIMA;\n}\n\n// src/sdk/ima.ts\nfunction createImaController(video, options) {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume = typeof video.volume === \"number\" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;\n const listeners = /* @__PURE__ */ new Map();\n const preloadedVast = /* @__PURE__ */ new Map();\n const preloadingVast = /* @__PURE__ */ new Map();\n let adVideoElement;\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n function hideContentVideo() {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n function showContentVideo() {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n function createAdVideoElement() {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"15\";\n adVideo.playsInline = true;\n adVideo.muted = false;\n adVideo.volume = originalMutedState ? 0 : originalVolume;\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n return adVideo;\n }\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {\n }\n }\n }\n function ensureImaLoaded() {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n try {\n const frameEl = window.frameElement;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr.split(/\\s+/).map((t) => t.trim()).filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {\n }\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n );\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 1e4);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n let adsManager;\n let adsLoader;\n let adDisplayContainer;\n let adContainerEl;\n let lastAdTagUrl;\n let retryAttempts = 0;\n const maxRetries = 2;\n const backoffBaseMs = 500;\n let adsLoadedPromise;\n let adsLoadedResolve;\n let adsLoadedReject;\n function makeAdsRequest(google, vastTagUrl) {\n const adsRequest = new google.ima.AdsRequest();\n console.log(\"[IMA] \\u{1F4E1} Requesting VAST from URL (letting IMA fetch fresh)\");\n adsRequest.adTagUrl = vastTagUrl;\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 360;\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n adsRequest.vastLoadTimeout = 1e4;\n adsLoader.requestAds(adsRequest);\n }\n function ensurePlaceholderContainer() {\n if (adContainerEl) {\n return;\n }\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n async function fetchVastDocument(vastTagUrl) {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to preload VAST: ${response.status}`);\n }\n return response.text();\n }\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {\n }\n adsManager = void 0;\n }\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n return {\n initialize() {\n ensureImaLoaded().then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {\n }\n }\n }).catch(() => {\n });\n },\n async requestAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n console.warn(\"[IMA] \\u274C\", error.message);\n return Promise.reject(error);\n }\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n console.warn(\"[IMA] \\u274C\", error.message);\n return Promise.reject(error);\n }\n if (adPlaying) {\n console.warn(\n \"[IMA] \\u26A0\\uFE0F Cannot request new ads while an ad is playing. Call stop() first.\"\n );\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n destroyAdsManager();\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n let currentReject;\n adsLoadedPromise = new Promise((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n }, 1e4);\n });\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n retryAttempts = 0;\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n video.parentElement.appendChild(container);\n adContainerEl = container;\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n }\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n console.warn(\"[IMA]\", error.message);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt) => {\n try {\n const adsRenderingSettings = new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent) => {\n const error = errorEvent.getError();\n console.error(\"[DEBUG-ERROR] \\u274C AD_ERROR:\", error.getMessage?.());\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n if (lastAdTagUrl && retryAttempts < maxRetries) {\n const delay = backoffBaseMs * Math.pow(2, retryAttempts++);\n window.setTimeout(() => {\n try {\n makeAdsRequest(google, lastAdTagUrl);\n } catch {\n }\n }, delay);\n } else {\n emit(\"ad_error\");\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {\n });\n }\n }\n }\n }\n );\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n adPlaying = true;\n setAdPlayingFlag(true);\n emit(\"content_pause\");\n }\n );\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n hideContentVideo();\n if (adVideoElement) {\n adVideoElement.volume = originalMutedState ? 0 : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n emit(\"content_resume\");\n }\n );\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds && video.paused) {\n video.play().catch(() => {\n });\n }\n emit(\"all_ads_completed\");\n });\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = void 0;\n adsLoadedReject = void 0;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {\n });\n }\n }\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent) => {\n const error = adErrorEvent.getError();\n console.error(\"[DEBUG-ERROR] \\u274C ADS_LOADER ERROR:\", error.getMessage?.());\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {\n });\n }\n }\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ads loader error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n },\n false\n );\n }\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n if (preloadedVast.has(vastTagUrl)) {\n return Promise.resolve();\n }\n const inflight = preloadingVast.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {\n preloadedVast.set(vastTagUrl, xml);\n }).catch(() => {\n preloadedVast.delete(vastTagUrl);\n }).finally(() => {\n preloadingVast.delete(vastTagUrl);\n });\n preloadingVast.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl) {\n return preloadedVast.has(vastTagUrl);\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 360;\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n adPlaying = true;\n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n try {\n adsManager.setVolume(adVolume);\n } catch {\n }\n adsManager.start();\n return Promise.resolve();\n } catch (error) {\n console.error(\"[IMA] \\u274C Error starting ad:\", error);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {\n });\n }\n return Promise.reject(error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n try {\n adsManager?.stop?.();\n } catch {\n }\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n adVideoElement = void 0;\n }\n }, 300);\n }\n showContentVideo();\n try {\n adsLoader?.destroy?.();\n } catch {\n }\n adDisplayContainer = void 0;\n adsLoader = void 0;\n contentVideoHidden = false;\n preloadedVast.clear();\n preloadingVast.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {\n }\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n }\n };\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createImaController\n});\n","interface NavigatorUAData {\n platform?: string;\n brands?: Array<{ brand: string; version: string }>;\n mobile?: boolean;\n}\n\ndeclare global {\n interface Navigator {\n userAgentData?: NavigatorUAData;\n }\n}\n\nexport interface BrowserInfo {\n name: string;\n version: string;\n majorVersion: number;\n isSmartTV: boolean;\n isLegacyTV: boolean;\n platform: string;\n supportsIMA: boolean;\n supportsModernJS: boolean;\n recommendedAdPlayer: 'ima' | 'hls';\n}\n\nfunction getChromeVersion(ua: string): number {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getWebKitVersion(ua: string): number {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getPlatform(): string {\n if ('userAgentData' in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? 'iPhone' : 'MacIntel';\n }\n if (/Win/i.test(ua)) {\n return 'Win32';\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? 'Linux armv8l' : 'Linux x86_64';\n }\n if (/CrOS/i.test(ua)) {\n return 'CrOS';\n }\n\n // eslint-disable-next-line deprecation/deprecation\n return (navigator as any).platform || 'Unknown';\n}\n\nexport function detectBrowser(): BrowserInfo {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n\n let name = 'Unknown';\n let version = '0';\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer: 'ima' | 'hls' = 'ima';\n\n if (/Web0S|webOS/i.test(ua)) {\n name = 'LG WebOS';\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = 'Samsung Tizen';\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n }\n\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n isLegacyTV = true;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n\n if (typeof URLSearchParams === 'undefined') {\n supportsModernJS = false;\n }\n\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n };\n}\n\nexport function supportsGoogleIMA(): boolean {\n const browser = detectBrowser();\n\n if (browser.isLegacyTV) {\n return false;\n }\n\n if (typeof document === 'undefined' ||\n typeof document.createElement !== 'function') {\n return false;\n }\n\n try {\n const video = document.createElement('video');\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n\n if (typeof Promise === 'undefined') {\n return false;\n }\n\n return browser.supportsIMA;\n}\n\nexport function getRecommendedAdPlayer(): 'ima' | 'hls' {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\n}\n\nexport function supportsModernJS(): boolean {\n try {\n return (\n typeof Promise !== 'undefined' &&\n typeof Map !== 'undefined' &&\n typeof Set !== 'undefined' &&\n typeof Array.from !== 'undefined' &&\n typeof Object.assign !== 'undefined' &&\n typeof Array.prototype.forEach !== 'undefined' &&\n typeof String.prototype.includes !== 'undefined'\n );\n } catch (e) {\n return false;\n }\n}\n\nexport function logBrowserInfo(debug: boolean = false): void {\n if (!debug) return;\n\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n\n console.log('[StormcloudVideoPlayer] Browser Compatibility Info:', {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n userAgent: navigator.userAgent,\n });\n}\n\nexport function getBrowserConfigOverrides(): {\n adPlayerType?: 'ima' | 'hls';\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: any = {};\n\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = 'hls';\n }\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'ima':\n return supportsGoogleIMA();\n case 'urlsearchparams':\n return typeof URLSearchParams !== 'undefined';\n case 'textencoder':\n return typeof TextEncoder !== 'undefined';\n case 'promises':\n return typeof Promise !== 'undefined';\n case 'fetch':\n return typeof fetch !== 'undefined';\n case 'crypto':\n return typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined';\n default:\n return false;\n }\n}\n\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24/Dev/stormcloud-vp/lib/sdk/ima.cjs","../../src/sdk/ima.ts","../../src/utils/browserCompat.ts"],"names":["__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toCommonJS","mod","value","ima_exports","createImaController","module","exports","getChromeVersion","ua","match","parseInt","getWebKitVersion","getPlatform","navigator","userAgentData","platform","userAgent","test","detectBrowser","version","majorVersion","isSmartTV","isLegacyTV","supportsIMA","supportsModernJS","recommendedAdPlayer","parts","split","chromeVersion","webkitVersion","toString","Promise","Map","Set","URLSearchParams","supportsGoogleIMA","browser","document","createElement","video","e","options","adPlaying","contentVideoHidden","originalMutedState","originalVolume","volume","Number","isNaN","Math","max","min","listeners","preloadedVast","preloadingVast","adVideoElement","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","hideContentVideo","style","transition","opacity","setTimeout","visibility","muted","showContentVideo","offsetHeight","createAdVideoElement","adVideo","position","top","left","width","height","objectFit","backgroundColor","zIndex","playsInline","addEventListener","once","emit","event","payload","set","Array","fn","console","warn","existing","error","backoffBaseMs","adsLoadedPromise","adsLoadedReject","adsRequest","nonLinearAdSlotHeight","ensureImaLoaded","window","reject","Error","frameEl","sandboxAttr","frameElement","getAttribute","tokens","t","trim","map","length","allowsScripts","has","google","ima","resolve","querySelector","timeout","clearTimeout","script","src","async","defer","setAttribute","onload","onerror","head","appendChild","adsManager","adsLoader","adDisplayContainer","adContainerEl","lastAdTagUrl","maxRetries","adsLoadedResolve","makeAdsRequest","vastTagUrl","log","adTagUrl","videoWidth","offsetWidth","clientWidth","videoHeight","clientHeight","linearAdSlotWidth","linearAdSlotHeight","nonLinearAdSlotWidth","setAdWillAutoPlay","willAutoPlay","paused","autoplay","setAdWillPlayMuted","willPlayMuted","vastLoadTimeout","requestAds","ensurePlaceholderContainer","right","bottom","display","alignItems","justifyContent","pointerEvents","parentElement","container","fetchVastDocument","response","fetch","mode","ok","status","text","destroyAdsManager","destroy","initialize","then","AdDisplayContainer","currentReject","adsLoaderCls","message","URL","retryAttempts","AdsLoader","AdsManagerLoadedEvent","Type","ADS_MANAGER_LOADED","evt","adsRenderingSettings","AdsRenderingSettings","enablePreloading","getAdsManager","AdEvent","AdErrorEvent","AD_ERROR","errorEvent","getError","getMessage","delay","pow","continueLiveStreamDuringAds","play","catch","CONTENT_PAUSE_REQUESTED","pause","STARTED","CONTENT_RESUME_REQUESTED","ALL_ADS_COMPLETED","adErrorEvent","preloadAds","inflight","preloadPromise"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\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 __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/sdk/ima.ts\nvar ima_exports = {};\n__export(ima_exports, {\n createImaController: () => createImaController\n});\nmodule.exports = __toCommonJS(ima_exports);\n\n// src/utils/browserCompat.ts\nfunction getChromeVersion(ua) {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getWebKitVersion(ua) {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getPlatform() {\n if (\"userAgentData\" in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? \"iPhone\" : \"MacIntel\";\n }\n if (/Win/i.test(ua)) {\n return \"Win32\";\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? \"Linux armv8l\" : \"Linux x86_64\";\n }\n if (/CrOS/i.test(ua)) {\n return \"CrOS\";\n }\n return navigator.platform || \"Unknown\";\n}\nfunction detectBrowser() {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n let name = \"Unknown\";\n let version = \"0\";\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer = \"ima\";\n if (/Web0S|webOS/i.test(ua)) {\n name = \"LG WebOS\";\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = \"Samsung Tizen\";\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n }\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n isLegacyTV = true;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n if (typeof URLSearchParams === \"undefined\") {\n supportsModernJS = false;\n }\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS,\n recommendedAdPlayer\n };\n}\nfunction supportsGoogleIMA() {\n const browser = detectBrowser();\n if (browser.isLegacyTV) {\n return false;\n }\n if (typeof document === \"undefined\" || typeof document.createElement !== \"function\") {\n return false;\n }\n try {\n const video = document.createElement(\"video\");\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n if (typeof Promise === \"undefined\") {\n return false;\n }\n return browser.supportsIMA;\n}\n\n// src/sdk/ima.ts\nfunction createImaController(video, options) {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume = typeof video.volume === \"number\" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;\n const listeners = /* @__PURE__ */ new Map();\n const preloadedVast = /* @__PURE__ */ new Map();\n const preloadingVast = /* @__PURE__ */ new Map();\n let adVideoElement;\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n function hideContentVideo() {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n function showContentVideo() {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n function createAdVideoElement() {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"15\";\n adVideo.playsInline = true;\n adVideo.muted = false;\n adVideo.volume = originalMutedState ? 0 : originalVolume;\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n return adVideo;\n }\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {\n }\n }\n }\n function ensureImaLoaded() {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n try {\n const frameEl = window.frameElement;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr.split(/\\s+/).map((t) => t.trim()).filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {\n }\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n );\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 1e4);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n let adsManager;\n let adsLoader;\n let adDisplayContainer;\n let adContainerEl;\n let lastAdTagUrl;\n let retryAttempts = 0;\n const maxRetries = 2;\n const backoffBaseMs = 500;\n let adsLoadedPromise;\n let adsLoadedResolve;\n let adsLoadedReject;\n function makeAdsRequest(google, vastTagUrl) {\n const adsRequest = new google.ima.AdsRequest();\n console.log(\"[IMA] \\u{1F4E1} Requesting VAST from URL (letting IMA fetch fresh)\");\n adsRequest.adTagUrl = vastTagUrl;\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 360;\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n adsRequest.vastLoadTimeout = 1e4;\n adsLoader.requestAds(adsRequest);\n }\n function ensurePlaceholderContainer() {\n if (adContainerEl) {\n return;\n }\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n async function fetchVastDocument(vastTagUrl) {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to preload VAST: ${response.status}`);\n }\n return response.text();\n }\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {\n }\n adsManager = void 0;\n }\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n return {\n initialize() {\n ensureImaLoaded().then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {\n }\n }\n }).catch(() => {\n });\n },\n async requestAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n console.warn(\"[IMA] \\u274C\", error.message);\n return Promise.reject(error);\n }\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n console.warn(\"[IMA] \\u274C\", error.message);\n return Promise.reject(error);\n }\n if (adPlaying) {\n console.warn(\n \"[IMA] \\u26A0\\uFE0F Cannot request new ads while an ad is playing. Call stop() first.\"\n );\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n destroyAdsManager();\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n let currentReject;\n adsLoadedPromise = new Promise((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n }, 1e4);\n });\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n retryAttempts = 0;\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition = \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n video.parentElement.appendChild(container);\n adContainerEl = container;\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n }\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n console.warn(\"[IMA]\", error.message);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt) => {\n try {\n const adsRenderingSettings = new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent) => {\n const error = errorEvent.getError();\n console.error(\"[DEBUG-ERROR] \\u274C AD_ERROR:\", error.getMessage?.());\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n if (lastAdTagUrl && retryAttempts < maxRetries) {\n const delay = backoffBaseMs * Math.pow(2, retryAttempts++);\n window.setTimeout(() => {\n try {\n makeAdsRequest(google, lastAdTagUrl);\n } catch {\n }\n }, delay);\n } else {\n emit(\"ad_error\");\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {\n });\n }\n }\n }\n }\n );\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n adPlaying = true;\n setAdPlayingFlag(true);\n emit(\"content_pause\");\n }\n );\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n hideContentVideo();\n if (adVideoElement) {\n adVideoElement.volume = originalMutedState ? 0 : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n emit(\"content_resume\");\n }\n );\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds && video.paused) {\n video.play().catch(() => {\n });\n }\n emit(\"all_ads_completed\");\n });\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = void 0;\n adsLoadedReject = void 0;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {\n });\n }\n }\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent) => {\n const error = adErrorEvent.getError();\n console.error(\"[DEBUG-ERROR] \\u274C ADS_LOADER ERROR:\", error.getMessage?.());\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {\n });\n }\n }\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ads loader error\"));\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n }\n emit(\"ad_error\");\n },\n false\n );\n }\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n currentReject?.(error);\n adsLoadedReject = void 0;\n adsLoadedResolve = void 0;\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n if (preloadedVast.has(vastTagUrl)) {\n return Promise.resolve();\n }\n const inflight = preloadingVast.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {\n preloadedVast.set(vastTagUrl, xml);\n }).catch(() => {\n preloadedVast.delete(vastTagUrl);\n }).finally(() => {\n preloadingVast.delete(vastTagUrl);\n });\n preloadingVast.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl) {\n return preloadedVast.has(vastTagUrl);\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 360;\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n adPlaying = true;\n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n try {\n adsManager.setVolume(adVolume);\n } catch {\n }\n adsManager.start();\n return Promise.resolve();\n } catch (error) {\n console.error(\"[IMA] \\u274C Error starting ad:\", error);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {\n });\n }\n return Promise.reject(error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n try {\n adsManager?.stop?.();\n } catch {\n }\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n adVideoElement = void 0;\n }\n }, 300);\n }\n showContentVideo();\n try {\n adsLoader?.destroy?.();\n } catch {\n }\n adDisplayContainer = void 0;\n adsLoader = void 0;\n contentVideoHidden = false;\n preloadedVast.clear();\n preloadingVast.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {\n }\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n }\n };\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createImaController\n});\n","import type { ImaController } from \"../types\";\nimport { supportsGoogleIMA } from \"../utils/browserCompat\";\n\ndeclare global {\n interface Window {\n google?: any;\n }\n}\n\nexport function createImaController(\n video: HTMLVideoElement,\n options?: { continueLiveStreamDuringAds?: boolean }\n): ImaController {\n let adPlaying = false;\n let contentVideoHidden = false;\n let originalMutedState = false;\n let originalVolume =\n typeof video.volume === \"number\" && !Number.isNaN(video.volume)\n ? Math.max(0, Math.min(1, video.volume))\n : 1;\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const preloadedVast = new Map<string, string>();\n const preloadingVast = new Map<string, Promise<void>>();\n let adVideoElement: HTMLVideoElement | undefined;\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n video.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete video.dataset.stormcloudAdPlaying;\n }\n }\n\n function hideContentVideo(): void {\n if (!contentVideoHidden) {\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.style.opacity = \"0\";\n setTimeout(() => {\n video.style.visibility = \"hidden\";\n }, 300);\n video.muted = true;\n video.volume = 0;\n contentVideoHidden = true;\n }\n }\n\n function showContentVideo(): void {\n if (contentVideoHidden) {\n video.style.visibility = \"visible\";\n video.style.transition = \"opacity 0.3s ease-in-out\";\n video.offsetHeight;\n video.style.opacity = \"1\";\n video.muted = originalMutedState;\n video.volume = originalVolume;\n contentVideoHidden = false;\n }\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const adVideo = document.createElement(\"video\");\n adVideo.style.position = \"absolute\";\n adVideo.style.top = \"0\";\n adVideo.style.left = \"0\";\n adVideo.style.width = \"100%\";\n adVideo.style.height = \"100%\";\n adVideo.style.objectFit = \"contain\";\n adVideo.style.backgroundColor = \"transparent\";\n adVideo.style.zIndex = \"15\";\n adVideo.playsInline = true;\n adVideo.muted = false;\n adVideo.volume = originalMutedState ? 0 : originalVolume;\n\n adVideo.style.opacity = \"0\";\n adVideo.addEventListener(\n \"canplay\",\n () => {\n adVideo.style.opacity = \"1\";\n },\n { once: true }\n );\n\n return adVideo;\n }\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch {}\n }\n }\n\n function ensureImaLoaded(): Promise<void> {\n if (!supportsGoogleIMA()) {\n console.warn(\n \"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead.\"\n );\n return Promise.reject(\n new Error(\"Google IMA SDK not supported on this browser\")\n );\n }\n\n try {\n const frameEl = window.frameElement as HTMLIFrameElement | null;\n const sandboxAttr = frameEl?.getAttribute?.(\"sandbox\") || \"\";\n if (sandboxAttr) {\n const tokens = new Set(\n sandboxAttr\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0)\n );\n const allowsScripts = tokens.has(\"allow-scripts\");\n if (!allowsScripts) {\n // eslint-disable-next-line no-console\n console.error(\n \"StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.\"\n );\n }\n }\n } catch {}\n\n if (typeof window !== \"undefined\" && window.google?.ima)\n return Promise.resolve();\n const existing = document.querySelector(\n 'script[data-ima=\"true\"]'\n ) as HTMLScriptElement | null;\n if (existing) {\n if (window.google?.ima) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"IMA SDK load timeout\"));\n }, 10000);\n existing.addEventListener(\"load\", () => {\n clearTimeout(timeout);\n resolve();\n });\n existing.addEventListener(\"error\", () => {\n clearTimeout(timeout);\n reject(new Error(\"IMA SDK load failed\"));\n });\n });\n }\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = \"https://imasdk.googleapis.com/js/sdkloader/ima3.js\";\n script.async = true;\n script.defer = true;\n script.setAttribute(\"data-ima\", \"true\");\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(\"IMA SDK load failed\"));\n document.head.appendChild(script);\n });\n }\n\n let adsManager: any | undefined;\n let adsLoader: any | undefined;\n let adDisplayContainer: any | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let lastAdTagUrl: string | undefined;\n let retryAttempts = 0;\n const maxRetries = 2;\n const backoffBaseMs = 500;\n let adsLoadedPromise: Promise<void> | undefined;\n let adsLoadedResolve: (() => void) | undefined;\n let adsLoadedReject: ((error: Error) => void) | undefined;\n\n function makeAdsRequest(google: any, vastTagUrl: string) {\n const adsRequest = new google.ima.AdsRequest();\n \n console.log(\"[IMA] 📡 Requesting VAST from URL (letting IMA fetch fresh)\");\n adsRequest.adTagUrl = vastTagUrl;\n\n const videoWidth = video.offsetWidth || video.clientWidth || 640;\n const videoHeight = video.offsetHeight || video.clientHeight || 360;\n\n adsRequest.linearAdSlotWidth = videoWidth;\n adsRequest.linearAdSlotHeight = videoHeight;\n adsRequest.nonLinearAdSlotWidth = videoWidth;\n adsRequest.nonLinearAdSlotHeight = videoHeight;\n\n if (typeof adsRequest.setAdWillAutoPlay === \"function\") {\n try {\n const willAutoPlay = !video.paused || video.autoplay;\n adsRequest.setAdWillAutoPlay(willAutoPlay);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillAutoPlay:\", error);\n }\n }\n\n if (typeof adsRequest.setAdWillPlayMuted === \"function\") {\n try {\n const willPlayMuted = video.muted || video.volume === 0;\n adsRequest.setAdWillPlayMuted(willPlayMuted);\n } catch (error) {\n console.warn(\"[IMA] Failed to call setAdWillPlayMuted:\", error);\n }\n }\n\n adsRequest.vastLoadTimeout = 10000;\n\n adsLoader.requestAds(adsRequest);\n }\n\n function ensurePlaceholderContainer(): void {\n if (adContainerEl) {\n return;\n }\n\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition =\n \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n async function fetchVastDocument(vastTagUrl: string): Promise<string> {\n const response = await fetch(vastTagUrl, { mode: \"cors\" });\n if (!response.ok) {\n throw new Error(`Failed to preload VAST: ${response.status}`);\n }\n return response.text();\n }\n\n function destroyAdsManager() {\n if (adsManager) {\n try {\n adsManager.destroy();\n } catch {}\n adsManager = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.style.opacity = \"0\";\n }\n }\n\n return {\n initialize() {\n ensureImaLoaded()\n .then(() => {\n const google = window.google;\n ensurePlaceholderContainer();\n\n if (!adDisplayContainer && adContainerEl) {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n adContainerEl,\n adVideoElement\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {}\n }\n })\n .catch(() => {});\n },\n async requestAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n const error = new Error(\"VAST tag URL is empty or undefined\");\n console.warn(\"[IMA] ❌\", error.message);\n return Promise.reject(error);\n }\n\n try {\n new URL(vastTagUrl);\n } catch (e) {\n const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);\n console.warn(\"[IMA] ❌\", error.message);\n return Promise.reject(error);\n }\n\n if (adPlaying) {\n console.warn(\n \"[IMA] ⚠️ Cannot request new ads while an ad is playing. Call stop() first.\"\n );\n return Promise.reject(\n new Error(\"Ad already playing - cannot request new ads\")\n );\n }\n\n destroyAdsManager();\n\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n\n let currentReject: ((error: Error) => void) | undefined;\n adsLoadedPromise = new Promise<void>((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = reject;\n currentReject = reject;\n\n setTimeout(() => {\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad request timeout\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n }, 10000);\n });\n\n try {\n await ensureImaLoaded();\n const google = window.google;\n lastAdTagUrl = vastTagUrl;\n retryAttempts = 0;\n\n if (!adDisplayContainer) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"transparent\";\n container.style.transition =\n \"opacity 0.3s ease-in-out, background-color 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n if (!video.parentElement) {\n throw new Error(\"Video element has no parent for ad container\");\n }\n\n video.parentElement.appendChild(container);\n adContainerEl = container;\n\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n }\n\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n adVideoElement\n );\n\n }\n\n const videoWidth = video.offsetWidth || video.clientWidth;\n const videoHeight = video.offsetHeight || video.clientHeight;\n\n if (\n !videoWidth ||\n !videoHeight ||\n videoWidth === 0 ||\n videoHeight === 0\n ) {\n const error = new Error(\n `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`\n );\n console.warn(\"[IMA]\", error.message);\n currentReject?.(error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n\n if (!adsLoader) {\n const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);\n adsLoader = adsLoaderCls;\n\n adsLoader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (evt: any) => {\n try {\n const adsRenderingSettings =\n new google.ima.AdsRenderingSettings();\n adsRenderingSettings.enablePreloading = true;\n adsManager = evt.getAdsManager(video, adsRenderingSettings);\n const AdEvent = google.ima.AdEvent.Type;\n const AdErrorEvent = google.ima.AdErrorEvent.Type;\n\n adsManager.addEventListener(\n AdErrorEvent.AD_ERROR,\n (errorEvent: any) => {\n const error = errorEvent.getError();\n console.error(\"[DEBUG-ERROR] ❌ AD_ERROR:\", error.getMessage?.());\n\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ad playback error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n\n if (lastAdTagUrl && retryAttempts < maxRetries) {\n const delay =\n backoffBaseMs * Math.pow(2, retryAttempts++);\n window.setTimeout(() => {\n try {\n makeAdsRequest(google, lastAdTagUrl!);\n } catch {}\n }, delay);\n } else {\n emit(\"ad_error\");\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play()?.catch(() => {});\n }\n }\n }\n }\n );\n\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n }\n\n adPlaying = true;\n setAdPlayingFlag(true);\n \n emit(\"content_pause\");\n }\n );\n\n adsManager.addEventListener(AdEvent.STARTED, () => {\n setAdPlayingFlag(true);\n\n hideContentVideo();\n\n if (adVideoElement) {\n adVideoElement.volume = originalMutedState\n ? 0\n : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n });\n\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n \n emit(\"content_resume\");\n }\n );\n\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (!options?.continueLiveStreamDuringAds && video.paused) {\n video.play().catch(() => {});\n }\n\n emit(\"all_ads_completed\");\n });\n\n if (adsLoadedResolve) {\n adsLoadedResolve();\n adsLoadedResolve = undefined;\n adsLoadedReject = undefined;\n }\n } catch (e) {\n console.error(\"[IMA] Error setting up ads manager:\", e);\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n showContentVideo();\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {});\n }\n }\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Failed to setup ads manager\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\");\n }\n },\n false\n );\n\n adsLoader.addEventListener(\n google.ima.AdErrorEvent.Type.AD_ERROR,\n (adErrorEvent: any) => {\n const error = adErrorEvent.getError();\n console.error(\"[DEBUG-ERROR] ❌ ADS_LOADER ERROR:\", error.getMessage?.());\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n if (!options?.continueLiveStreamDuringAds) {\n if (video.paused) {\n video.play().catch(() => {});\n }\n }\n\n if (adsLoadedReject) {\n adsLoadedReject(new Error(\"Ads loader error\"));\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n emit(\"ad_error\");\n },\n false\n );\n }\n\n makeAdsRequest(google, vastTagUrl);\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n\n currentReject?.(error as Error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n return Promise.reject(error);\n }\n },\n async preloadAds(vastTagUrl: string) {\n if (!vastTagUrl || vastTagUrl.trim() === \"\") {\n return Promise.resolve();\n }\n\n if (preloadedVast.has(vastTagUrl)) {\n return Promise.resolve();\n }\n\n const inflight = preloadingVast.get(vastTagUrl);\n if (inflight) {\n return inflight;\n }\n\n const preloadPromise = fetchVastDocument(vastTagUrl)\n .then((xml) => {\n preloadedVast.set(vastTagUrl, xml);\n })\n .catch(() => {\n preloadedVast.delete(vastTagUrl);\n })\n .finally(() => {\n preloadingVast.delete(vastTagUrl);\n });\n\n preloadingVast.set(vastTagUrl, preloadPromise);\n return preloadPromise;\n },\n hasPreloadedAd(vastTagUrl: string) {\n return preloadedVast.has(vastTagUrl);\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n\n if (!adsManager) {\n return Promise.reject(new Error(\"No ads manager\"));\n }\n\n try {\n const width = video.clientWidth || 640;\n const height = video.clientHeight || 360;\n\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n\n adPlaying = true;\n\n const adVolume = originalMutedState ? 0 : originalVolume;\n if (adVideoElement) {\n adVideoElement.volume = adVolume;\n adVideoElement.muted = originalMutedState;\n }\n\n try {\n adsManager.setVolume(adVolume);\n } catch {}\n\n adsManager.start();\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[IMA] ❌ Error starting ad:\", error);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {});\n }\n return Promise.reject(error);\n }\n },\n async stop() {\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n }\n }, 300);\n }\n\n showContentVideo();\n\n try {\n adsManager?.stop?.();\n } catch {}\n\n destroyAdsManager();\n },\n destroy() {\n destroyAdsManager();\n\n adPlaying = false;\n setAdPlayingFlag(false);\n\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.pointerEvents = \"none\";\n adContainerEl.style.display = \"none\";\n\n if (adContainerEl.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n adVideoElement = undefined;\n }\n }, 300);\n }\n\n showContentVideo();\n\n try {\n adsLoader?.destroy?.();\n } catch {}\n\n adDisplayContainer = undefined;\n adsLoader = undefined;\n contentVideoHidden = false;\n preloadedVast.clear();\n preloadingVast.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width: number, height: number) {\n if (!adsManager || !window.google?.ima) {\n console.warn(\n \"[IMA] Cannot resize: No ads manager or IMA SDK available\"\n );\n return;\n }\n\n try {\n console.log(`[IMA] Resizing ads manager to ${width}x${height}`);\n adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);\n } catch (error) {\n console.warn(\"[IMA] Error resizing ads manager:\", error);\n }\n },\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume: number) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = clampedVolume;\n adVideoElement.muted = clampedVolume === 0;\n }\n\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(clampedVolume);\n } catch {}\n }\n },\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n\n if (adsManager && adPlaying) {\n try {\n return adsManager.getVolume();\n } catch (error) {\n console.warn(\"[IMA] Failed to get ad volume:\", error);\n return 1;\n }\n }\n return 1;\n },\n showPlaceholder() {\n ensurePlaceholderContainer();\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.backgroundColor = \"#000\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n adContainerEl.style.backgroundColor = \"transparent\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n },\n };\n}\n","interface NavigatorUAData {\n platform?: string;\n brands?: Array<{ brand: string; version: string }>;\n mobile?: boolean;\n}\n\ndeclare global {\n interface Navigator {\n userAgentData?: NavigatorUAData;\n }\n}\n\nexport interface BrowserInfo {\n name: string;\n version: string;\n majorVersion: number;\n isSmartTV: boolean;\n isLegacyTV: boolean;\n platform: string;\n supportsIMA: boolean;\n supportsModernJS: boolean;\n recommendedAdPlayer: 'ima' | 'hls';\n}\n\nfunction getChromeVersion(ua: string): number {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getWebKitVersion(ua: string): number {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getPlatform(): string {\n if ('userAgentData' in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? 'iPhone' : 'MacIntel';\n }\n if (/Win/i.test(ua)) {\n return 'Win32';\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? 'Linux armv8l' : 'Linux x86_64';\n }\n if (/CrOS/i.test(ua)) {\n return 'CrOS';\n }\n\n // eslint-disable-next-line deprecation/deprecation\n return (navigator as any).platform || 'Unknown';\n}\n\nexport function detectBrowser(): BrowserInfo {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n\n let name = 'Unknown';\n let version = '0';\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer: 'ima' | 'hls' = 'ima';\n\n if (/Web0S|webOS/i.test(ua)) {\n name = 'LG WebOS';\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = 'Samsung Tizen';\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n }\n\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n isLegacyTV = true;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n\n if (typeof URLSearchParams === 'undefined') {\n supportsModernJS = false;\n }\n\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n };\n}\n\nexport function supportsGoogleIMA(): boolean {\n const browser = detectBrowser();\n\n if (browser.isLegacyTV) {\n return false;\n }\n\n if (typeof document === 'undefined' ||\n typeof document.createElement !== 'function') {\n return false;\n }\n\n try {\n const video = document.createElement('video');\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n\n if (typeof Promise === 'undefined') {\n return false;\n }\n\n return browser.supportsIMA;\n}\n\nexport function getRecommendedAdPlayer(): 'ima' | 'hls' {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\n}\n\nexport function supportsModernJS(): boolean {\n try {\n return (\n typeof Promise !== 'undefined' &&\n typeof Map !== 'undefined' &&\n typeof Set !== 'undefined' &&\n typeof Array.from !== 'undefined' &&\n typeof Object.assign !== 'undefined' &&\n typeof Array.prototype.forEach !== 'undefined' &&\n typeof String.prototype.includes !== 'undefined'\n );\n } catch (e) {\n return false;\n }\n}\n\nexport function logBrowserInfo(debug: boolean = false): void {\n if (!debug) return;\n\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\n\n console.log('[StormcloudVideoPlayer] Browser Compatibility Info:', {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\n userAgent: navigator.userAgent,\n });\n}\n\nexport function getBrowserConfigOverrides(): {\n adPlayerType?: 'ima' | 'hls';\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: any = {};\n\n if (browser.isLegacyTV || !browser.supportsIMA) {\n overrides.adPlayerType = 'hls';\n }\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'ima':\n return supportsGoogleIMA();\n case 'urlsearchparams':\n return typeof URLSearchParams !== 'undefined';\n case 'textencoder':\n return typeof TextEncoder !== 'undefined';\n case 'promises':\n return typeof Promise !== 'undefined';\n case 'fetch':\n return typeof fetch !== 'undefined';\n case 'crypto':\n return typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined';\n default:\n return false;\n }\n}\n\n"]}
|