stormcloud-video-player 0.2.24 → 0.2.25

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.
@@ -45,6 +45,8 @@ function createHlsAdPlayer(contentVideo, options) {
45
45
  let adContainerEl;
46
46
  let currentAd;
47
47
  let sessionId;
48
+ const preloadedAds = /* @__PURE__ */ new Map();
49
+ const preloadingAds = /* @__PURE__ */ new Map();
48
50
  let trackingFired = {
49
51
  impression: false,
50
52
  start: false,
@@ -274,6 +276,19 @@ function createHlsAdPlayer(contentVideo, options) {
274
276
  return null;
275
277
  }
276
278
  }
279
+ async function fetchAndParseVastAd(vastTagUrl) {
280
+ const response = await fetch(vastTagUrl);
281
+ if (!response.ok) {
282
+ throw new Error(`Failed to fetch VAST: ${response.statusText}`);
283
+ }
284
+ const vastXml = await response.text();
285
+ console.log("[HlsAdPlayer] VAST XML received");
286
+ console.log(
287
+ "[HlsAdPlayer] VAST XML content (first 2000 chars):",
288
+ vastXml.substring(0, 2e3)
289
+ );
290
+ return parseVastXml(vastXml);
291
+ }
277
292
  function createAdVideoElement() {
278
293
  const video = document.createElement("video");
279
294
  video.style.position = "absolute";
@@ -425,17 +440,17 @@ function createHlsAdPlayer(contentVideo, options) {
425
440
  }
426
441
  try {
427
442
  sessionId = generateSessionId();
428
- const response = await fetch(vastTagUrl);
429
- if (!response.ok) {
430
- throw new Error(`Failed to fetch VAST: ${response.statusText}`);
443
+ let ad;
444
+ if (preloadedAds.has(vastTagUrl)) {
445
+ ad = preloadedAds.get(vastTagUrl);
446
+ preloadedAds.delete(vastTagUrl);
447
+ console.log(
448
+ "[HlsAdPlayer] Using preloaded VAST response:",
449
+ vastTagUrl
450
+ );
451
+ } else {
452
+ ad = await fetchAndParseVastAd(vastTagUrl);
431
453
  }
432
- const vastXml = await response.text();
433
- console.log("[HlsAdPlayer] VAST XML received");
434
- console.log(
435
- "[HlsAdPlayer] VAST XML content (first 2000 chars):",
436
- vastXml.substring(0, 2e3)
437
- );
438
- const ad = parseVastXml(vastXml);
439
454
  if (!ad) {
440
455
  console.warn("[HlsAdPlayer] No ads available from VAST response");
441
456
  emit("ad_error");
@@ -454,6 +469,37 @@ function createHlsAdPlayer(contentVideo, options) {
454
469
  return Promise.reject(error);
455
470
  }
456
471
  },
472
+ async preloadAds(vastTagUrl) {
473
+ if (!vastTagUrl || vastTagUrl.trim() === "") {
474
+ return Promise.resolve();
475
+ }
476
+ if (preloadedAds.has(vastTagUrl)) {
477
+ return Promise.resolve();
478
+ }
479
+ const inflight = preloadingAds.get(vastTagUrl);
480
+ if (inflight) {
481
+ return inflight;
482
+ }
483
+ const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {
484
+ if (ad) {
485
+ preloadedAds.set(vastTagUrl, ad);
486
+ console.log(
487
+ "[HlsAdPlayer] Cached VAST response for preloading:",
488
+ vastTagUrl
489
+ );
490
+ }
491
+ }).catch((error) => {
492
+ console.warn("[HlsAdPlayer] Failed to preload VAST response:", error);
493
+ preloadedAds.delete(vastTagUrl);
494
+ }).finally(() => {
495
+ preloadingAds.delete(vastTagUrl);
496
+ });
497
+ preloadingAds.set(vastTagUrl, preloadPromise);
498
+ return preloadPromise;
499
+ },
500
+ hasPreloadedAd(vastTagUrl) {
501
+ return preloadedAds.has(vastTagUrl);
502
+ },
457
503
  async play() {
458
504
  if (!currentAd) {
459
505
  console.warn(
@@ -584,6 +630,8 @@ function createHlsAdPlayer(contentVideo, options) {
584
630
  adContainerEl = void 0;
585
631
  currentAd = void 0;
586
632
  listeners.clear();
633
+ preloadedAds.clear();
634
+ preloadingAds.clear();
587
635
  },
588
636
  isAdPlaying() {
589
637
  return adPlaying;
@@ -626,6 +674,35 @@ function createHlsAdPlayer(contentVideo, options) {
626
674
  return adVideoElement.volume;
627
675
  }
628
676
  return 1;
677
+ },
678
+ showPlaceholder() {
679
+ var _a;
680
+ if (!adContainerEl) {
681
+ const container = document.createElement("div");
682
+ container.style.position = "absolute";
683
+ container.style.left = "0";
684
+ container.style.top = "0";
685
+ container.style.right = "0";
686
+ container.style.bottom = "0";
687
+ container.style.display = "none";
688
+ container.style.alignItems = "center";
689
+ container.style.justifyContent = "center";
690
+ container.style.pointerEvents = "none";
691
+ container.style.zIndex = "10";
692
+ container.style.backgroundColor = "#000";
693
+ (_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
694
+ adContainerEl = container;
695
+ }
696
+ if (adContainerEl) {
697
+ adContainerEl.style.display = "flex";
698
+ adContainerEl.style.pointerEvents = "auto";
699
+ }
700
+ },
701
+ hidePlaceholder() {
702
+ if (adContainerEl) {
703
+ adContainerEl.style.display = "none";
704
+ adContainerEl.style.pointerEvents = "none";
705
+ }
629
706
  }
630
707
  };
631
708
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/sdk/hlsAdPlayer.ts"],"sourcesContent":["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 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\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 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 setTimeout(() => {\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 }, 50);\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 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\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 const ad = parseVastXml(vastXml);\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\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\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 : contentVolume;\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 adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\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 },\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) {\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`\n );\n originalMutedState = muted;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n };\n}\n"],"mappings":"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","names":["level","_a","Hls"]}
1
+ {"version":3,"sources":["../../src/sdk/hlsAdPlayer.ts"],"sourcesContent":["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 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\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 setTimeout(() => {\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 }, 50);\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 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\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 : contentVolume;\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 adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\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) {\n console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`\n );\n originalMutedState = muted;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\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"],"mappings":"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","names":["level","_a","Hls"]}
@@ -1,4 +1,4 @@
1
- import { I as ImaController } from '../types-D1xfSdLP.cjs';
1
+ import { I as ImaController } from '../types-9_2sbHCg.cjs';
2
2
  import Hls from 'hls.js';
3
3
 
4
4
  declare function createHlsAdPlayer(contentVideo: HTMLVideoElement, options?: {
package/lib/sdk/ima.cjs CHANGED
@@ -163,6 +163,8 @@ function createImaController(video, options) {
163
163
  let adPlaying = false;
164
164
  let originalMutedState = false;
165
165
  const listeners = /* @__PURE__ */ new Map();
166
+ const preloadedVast = /* @__PURE__ */ new Map();
167
+ const preloadingVast = /* @__PURE__ */ new Map();
166
168
  function setAdPlayingFlag(isPlaying) {
167
169
  if (isPlaying) {
168
170
  video.dataset.stormcloudAdPlaying = "true";
@@ -253,7 +255,15 @@ function createImaController(video, options) {
253
255
  let adsLoadedReject;
254
256
  function makeAdsRequest(google, vastTagUrl) {
255
257
  const adsRequest = new google.ima.AdsRequest();
256
- adsRequest.adTagUrl = vastTagUrl;
258
+ const preloadedResponse = preloadedVast.get(vastTagUrl);
259
+ if (preloadedResponse) {
260
+ adsRequest.adsResponse = preloadedResponse;
261
+ console.log(
262
+ "[IMA] Using preloaded VAST response for immediate ad request"
263
+ );
264
+ } else {
265
+ adsRequest.adTagUrl = vastTagUrl;
266
+ }
257
267
  const videoWidth = video.offsetWidth || video.clientWidth || 640;
258
268
  const videoHeight = video.offsetHeight || video.clientHeight || 360;
259
269
  adsRequest.linearAdSlotWidth = videoWidth;
@@ -263,6 +273,36 @@ function createImaController(video, options) {
263
273
  adsRequest.vastLoadTimeout = 5e3;
264
274
  console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
265
275
  adsLoader.requestAds(adsRequest);
276
+ if (preloadedResponse) {
277
+ preloadedVast.delete(vastTagUrl);
278
+ }
279
+ }
280
+ function ensurePlaceholderContainer() {
281
+ var _a;
282
+ if (adContainerEl) {
283
+ return;
284
+ }
285
+ const container = document.createElement("div");
286
+ container.style.position = "absolute";
287
+ container.style.left = "0";
288
+ container.style.top = "0";
289
+ container.style.right = "0";
290
+ container.style.bottom = "0";
291
+ container.style.display = "none";
292
+ container.style.alignItems = "center";
293
+ container.style.justifyContent = "center";
294
+ container.style.pointerEvents = "none";
295
+ container.style.zIndex = "10";
296
+ container.style.backgroundColor = "#000";
297
+ (_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
298
+ adContainerEl = container;
299
+ }
300
+ async function fetchVastDocument(vastTagUrl) {
301
+ const response = await fetch(vastTagUrl, { mode: "cors" });
302
+ if (!response.ok) {
303
+ throw new Error(`Failed to preload VAST: ${response.status}`);
304
+ }
305
+ return response.text();
266
306
  }
267
307
  function destroyAdsManager() {
268
308
  if (adsManager) {
@@ -278,29 +318,16 @@ function createImaController(video, options) {
278
318
  return {
279
319
  initialize() {
280
320
  ensureImaLoaded().then(() => {
281
- var _a, _b;
321
+ var _a;
282
322
  const google = window.google;
283
- if (!adDisplayContainer) {
284
- const container = document.createElement("div");
285
- container.style.position = "absolute";
286
- container.style.left = "0";
287
- container.style.top = "0";
288
- container.style.right = "0";
289
- container.style.bottom = "0";
290
- container.style.display = "none";
291
- container.style.alignItems = "center";
292
- container.style.justifyContent = "center";
293
- container.style.pointerEvents = "none";
294
- container.style.zIndex = "10";
295
- container.style.backgroundColor = "#000";
296
- (_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
297
- adContainerEl = container;
323
+ ensurePlaceholderContainer();
324
+ if (!adDisplayContainer && adContainerEl) {
298
325
  adDisplayContainer = new google.ima.AdDisplayContainer(
299
- container,
326
+ adContainerEl,
300
327
  video
301
328
  );
302
329
  try {
303
- (_b = adDisplayContainer.initialize) == null ? void 0 : _b.call(adDisplayContainer);
330
+ (_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
304
331
  } catch {
305
332
  }
306
333
  }
@@ -604,6 +631,32 @@ function createImaController(video, options) {
604
631
  return Promise.reject(error);
605
632
  }
606
633
  },
634
+ async preloadAds(vastTagUrl) {
635
+ if (!vastTagUrl || vastTagUrl.trim() === "") {
636
+ return Promise.resolve();
637
+ }
638
+ if (preloadedVast.has(vastTagUrl)) {
639
+ return Promise.resolve();
640
+ }
641
+ const inflight = preloadingVast.get(vastTagUrl);
642
+ if (inflight) {
643
+ return inflight;
644
+ }
645
+ const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
646
+ preloadedVast.set(vastTagUrl, xml);
647
+ console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
648
+ }).catch((error) => {
649
+ console.warn("[IMA] Failed to preload VAST response:", error);
650
+ preloadedVast.delete(vastTagUrl);
651
+ }).finally(() => {
652
+ preloadingVast.delete(vastTagUrl);
653
+ });
654
+ preloadingVast.set(vastTagUrl, preloadPromise);
655
+ return preloadPromise;
656
+ },
657
+ hasPreloadedAd(vastTagUrl) {
658
+ return preloadedVast.has(vastTagUrl);
659
+ },
607
660
  async play() {
608
661
  var _a, _b;
609
662
  if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
@@ -679,6 +732,8 @@ function createImaController(video, options) {
679
732
  adContainerEl = void 0;
680
733
  adDisplayContainer = void 0;
681
734
  adsLoader = void 0;
735
+ preloadedVast.clear();
736
+ preloadingVast.clear();
682
737
  },
683
738
  isAdPlaying() {
684
739
  return adPlaying;
@@ -734,6 +789,19 @@ function createImaController(video, options) {
734
789
  }
735
790
  }
736
791
  return 1;
792
+ },
793
+ showPlaceholder() {
794
+ ensurePlaceholderContainer();
795
+ if (adContainerEl) {
796
+ adContainerEl.style.display = "flex";
797
+ adContainerEl.style.pointerEvents = "auto";
798
+ }
799
+ },
800
+ hidePlaceholder() {
801
+ if (adContainerEl) {
802
+ adContainerEl.style.display = "none";
803
+ adContainerEl.style.pointerEvents = "none";
804
+ }
737
805
  }
738
806
  };
739
807
  }