stormcloud-video-player 0.2.5 → 0.2.7

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/lib/sdk/ima.cjs CHANGED
@@ -217,7 +217,7 @@ function createImaController(video, options) {
217
217
  );
218
218
  emit("ad_error");
219
219
  if (!options?.continueLiveStreamDuringAds) {
220
- video.play().catch(() => {
220
+ video.play()?.catch(() => {
221
221
  });
222
222
  }
223
223
  }
@@ -252,7 +252,7 @@ function createImaController(video, options) {
252
252
  if (adContainerEl)
253
253
  adContainerEl.style.pointerEvents = "none";
254
254
  if (!options?.continueLiveStreamDuringAds) {
255
- video.play().catch(() => {
255
+ video.play()?.catch(() => {
256
256
  });
257
257
  console.log("[IMA] Video resumed (VOD mode)");
258
258
  } else {
@@ -365,7 +365,7 @@ function createImaController(video, options) {
365
365
  console.error("[IMA] Error starting ad playback:", error);
366
366
  adPlaying = false;
367
367
  if (!options?.continueLiveStreamDuringAds) {
368
- video.play().catch(() => {
368
+ video.play()?.catch(() => {
369
369
  });
370
370
  }
371
371
  return Promise.reject(error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/sdk/ima.ts"],"sourcesContent":["import type { ImaController } from \"../types\";\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 originalMutedState = false;\n const listeners = new Map<string, Set<(payload?: any) => void>>();\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 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 return new Promise((resolve) =>\n existing.addEventListener(\"load\", () => resolve())\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 adsRequest.adTagUrl = vastTagUrl;\n adsLoader.requestAds(adsRequest);\n }\n\n return {\n initialize() {\n ensureImaLoaded()\n .then(() => {\n const google = window.google;\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 = \"flex\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"2\";\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n video\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {}\n }\n })\n .catch(() => {});\n },\n async requestAds(vastTagUrl: string) {\n console.log(\"[IMA] Requesting ads:\", vastTagUrl);\n\n adsLoadedPromise = new Promise<void>((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = 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 console.log(\"[IMA] Creating ad display container\");\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 = \"flex\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"2\";\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 adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n video\n );\n\n try {\n adDisplayContainer.initialize();\n console.log(\"[IMA] Ad display container initialized\");\n } catch (error) {\n console.warn(\n \"[IMA] Failed to initialize ad display container:\",\n error\n );\n }\n }\n\n if (!adsLoader) {\n console.log(\"[IMA] Creating ads loader\");\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 console.log(\"[IMA] Ads manager loaded\");\n try {\n adsManager = evt.getAdsManager(video);\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 console.error(\"[IMA] Ad error:\", errorEvent.getError());\n try {\n adsManager?.destroy?.();\n } catch {}\n adPlaying = false;\n video.muted = originalMutedState;\n if (adContainerEl)\n adContainerEl.style.pointerEvents = \"none\";\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 console.log(\n `[IMA] Retrying ad request in ${delay}ms (attempt ${retryAttempts})`\n );\n window.setTimeout(() => {\n try {\n makeAdsRequest(google, lastAdTagUrl!);\n } catch {}\n }, delay);\n } else {\n console.log(\n \"[IMA] Max retries reached, emitting ad_error\"\n );\n emit(\"ad_error\");\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play().catch(() => {});\n }\n }\n }\n );\n\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n console.log(\"[IMA] Content pause requested\");\n originalMutedState = video.muted;\n video.muted = true;\n\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n console.log(\"[IMA] Video paused (VOD mode)\");\n } else {\n console.log(\n \"[IMA] Video continues playing but muted (Live mode)\"\n );\n }\n\n adPlaying = true;\n if (adContainerEl)\n adContainerEl.style.pointerEvents = \"auto\";\n emit(\"content_pause\");\n }\n );\n\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n console.log(\"[IMA] Content resume requested\");\n adPlaying = false;\n video.muted = originalMutedState;\n if (adContainerEl)\n adContainerEl.style.pointerEvents = \"none\";\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play().catch(() => {});\n console.log(\"[IMA] Video resumed (VOD mode)\");\n } else {\n console.log(\n \"[IMA] Video unmuted (Live mode - was never paused)\"\n );\n }\n\n emit(\"content_resume\");\n }\n );\n\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n console.log(\"[IMA] All ads completed\");\n adPlaying = false;\n video.muted = originalMutedState;\n if (adContainerEl) adContainerEl.style.pointerEvents = \"none\";\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play().catch(() => {});\n console.log(\n \"[IMA] Video resumed after all ads completed (VOD mode)\"\n );\n } else {\n console.log(\n \"[IMA] Video unmuted after all ads completed (Live mode)\"\n );\n }\n\n emit(\"all_ads_completed\");\n });\n\n console.log(\"[IMA] Ads manager event listeners attached\");\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 video.muted = originalMutedState;\n if (adContainerEl) adContainerEl.style.pointerEvents = \"none\";\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play().catch(() => {});\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 console.error(\"[IMA] Ads loader error:\", adErrorEvent.getError());\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 console.log(\"[IMA] Making ads request\");\n makeAdsRequest(google, vastTagUrl);\n\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n if (adsLoadedReject) {\n adsLoadedReject(error as Error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n return Promise.reject(error);\n }\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n console.warn(\n \"[IMA] Cannot play ad: IMA SDK or ad container not available\"\n );\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n\n if (!adsManager) {\n console.warn(\"[IMA] Cannot play ad: No ads manager available\");\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 console.log(`[IMA] Initializing ads manager (${width}x${height})`);\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n\n if (!options?.continueLiveStreamDuringAds) {\n console.log(\"[IMA] Pausing video for ad playback (VOD mode)\");\n video.pause();\n } else {\n console.log(\n \"[IMA] Keeping video playing but muted for ad playback (Live mode)\"\n );\n }\n adPlaying = true;\n\n console.log(\"[IMA] Starting ad playback\");\n adsManager.start();\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[IMA] Error starting ad playback:\", error);\n adPlaying = 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 video.muted = originalMutedState;\n try {\n adsManager?.stop?.();\n } catch {}\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play().catch(() => {});\n console.log(\"[IMA] Video resumed after stop (VOD mode)\");\n } else {\n console.log(\"[IMA] Video unmuted after stop (Live mode)\");\n }\n },\n destroy() {\n try {\n adsManager?.destroy?.();\n } catch {}\n adPlaying = false;\n video.muted = originalMutedState;\n try {\n adsLoader?.destroy?.();\n } catch {}\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\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) {\n originalMutedState = muted;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n setAdVolume(volume: number) {\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(Math.max(0, Math.min(1, volume)));\n } catch (error) {\n console.warn(\"[IMA] Failed to set ad volume:\", error);\n }\n }\n },\n getAdVolume(): number {\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 };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/sdk/ima.ts"],"sourcesContent":["import type { ImaController } from \"../types\";\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 originalMutedState = false;\n const listeners = new Map<string, Set<(payload?: any) => void>>();\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 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 return new Promise((resolve) =>\n existing.addEventListener(\"load\", () => resolve())\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 adsRequest.adTagUrl = vastTagUrl;\n adsLoader.requestAds(adsRequest);\n }\n\n return {\n initialize() {\n ensureImaLoaded()\n .then(() => {\n const google = window.google;\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 = \"flex\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"2\";\n video.parentElement?.appendChild(container);\n adContainerEl = container;\n adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n video\n );\n try {\n adDisplayContainer.initialize?.();\n } catch {}\n }\n })\n .catch(() => {});\n },\n async requestAds(vastTagUrl: string) {\n console.log(\"[IMA] Requesting ads:\", vastTagUrl);\n\n adsLoadedPromise = new Promise<void>((resolve, reject) => {\n adsLoadedResolve = resolve;\n adsLoadedReject = 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 console.log(\"[IMA] Creating ad display container\");\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 = \"flex\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"2\";\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 adDisplayContainer = new google.ima.AdDisplayContainer(\n container,\n video\n );\n\n try {\n adDisplayContainer.initialize();\n console.log(\"[IMA] Ad display container initialized\");\n } catch (error) {\n console.warn(\n \"[IMA] Failed to initialize ad display container:\",\n error\n );\n }\n }\n\n if (!adsLoader) {\n console.log(\"[IMA] Creating ads loader\");\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 console.log(\"[IMA] Ads manager loaded\");\n try {\n adsManager = evt.getAdsManager(video);\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 console.error(\"[IMA] Ad error:\", errorEvent.getError());\n try {\n adsManager?.destroy?.();\n } catch {}\n adPlaying = false;\n video.muted = originalMutedState;\n if (adContainerEl)\n adContainerEl.style.pointerEvents = \"none\";\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 console.log(\n `[IMA] Retrying ad request in ${delay}ms (attempt ${retryAttempts})`\n );\n window.setTimeout(() => {\n try {\n makeAdsRequest(google, lastAdTagUrl!);\n } catch {}\n }, delay);\n } else {\n console.log(\n \"[IMA] Max retries reached, emitting ad_error\"\n );\n emit(\"ad_error\");\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {});\n }\n }\n }\n );\n\n adsManager.addEventListener(\n AdEvent.CONTENT_PAUSE_REQUESTED,\n () => {\n console.log(\"[IMA] Content pause requested\");\n originalMutedState = video.muted;\n video.muted = true;\n\n if (!options?.continueLiveStreamDuringAds) {\n video.pause();\n console.log(\"[IMA] Video paused (VOD mode)\");\n } else {\n console.log(\n \"[IMA] Video continues playing but muted (Live mode)\"\n );\n }\n\n adPlaying = true;\n if (adContainerEl)\n adContainerEl.style.pointerEvents = \"auto\";\n emit(\"content_pause\");\n }\n );\n\n adsManager.addEventListener(\n AdEvent.CONTENT_RESUME_REQUESTED,\n () => {\n console.log(\"[IMA] Content resume requested\");\n adPlaying = false;\n video.muted = originalMutedState;\n if (adContainerEl)\n adContainerEl.style.pointerEvents = \"none\";\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play()?.catch(() => {});\n console.log(\"[IMA] Video resumed (VOD mode)\");\n } else {\n console.log(\n \"[IMA] Video unmuted (Live mode - was never paused)\"\n );\n }\n\n emit(\"content_resume\");\n }\n );\n\n adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {\n console.log(\"[IMA] All ads completed\");\n adPlaying = false;\n video.muted = originalMutedState;\n if (adContainerEl) adContainerEl.style.pointerEvents = \"none\";\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play().catch(() => {});\n console.log(\n \"[IMA] Video resumed after all ads completed (VOD mode)\"\n );\n } else {\n console.log(\n \"[IMA] Video unmuted after all ads completed (Live mode)\"\n );\n }\n\n emit(\"all_ads_completed\");\n });\n\n console.log(\"[IMA] Ads manager event listeners attached\");\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 video.muted = originalMutedState;\n if (adContainerEl) adContainerEl.style.pointerEvents = \"none\";\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play().catch(() => {});\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 console.error(\"[IMA] Ads loader error:\", adErrorEvent.getError());\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 console.log(\"[IMA] Making ads request\");\n makeAdsRequest(google, vastTagUrl);\n\n return adsLoadedPromise;\n } catch (error) {\n console.error(\"[IMA] Failed to request ads:\", error);\n if (adsLoadedReject) {\n adsLoadedReject(error as Error);\n adsLoadedReject = undefined;\n adsLoadedResolve = undefined;\n }\n return Promise.reject(error);\n }\n },\n async play() {\n if (!window.google?.ima || !adDisplayContainer) {\n console.warn(\n \"[IMA] Cannot play ad: IMA SDK or ad container not available\"\n );\n return Promise.reject(new Error(\"IMA SDK not available\"));\n }\n\n if (!adsManager) {\n console.warn(\"[IMA] Cannot play ad: No ads manager available\");\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 console.log(`[IMA] Initializing ads manager (${width}x${height})`);\n adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);\n\n if (!options?.continueLiveStreamDuringAds) {\n console.log(\"[IMA] Pausing video for ad playback (VOD mode)\");\n video.pause();\n } else {\n console.log(\n \"[IMA] Keeping video playing but muted for ad playback (Live mode)\"\n );\n }\n adPlaying = true;\n\n console.log(\"[IMA] Starting ad playback\");\n adsManager.start();\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[IMA] Error starting ad playback:\", error);\n adPlaying = 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 video.muted = originalMutedState;\n try {\n adsManager?.stop?.();\n } catch {}\n\n if (!options?.continueLiveStreamDuringAds) {\n video.play().catch(() => {});\n console.log(\"[IMA] Video resumed after stop (VOD mode)\");\n } else {\n console.log(\"[IMA] Video unmuted after stop (Live mode)\");\n }\n },\n destroy() {\n try {\n adsManager?.destroy?.();\n } catch {}\n adPlaying = false;\n video.muted = originalMutedState;\n try {\n adsLoader?.destroy?.();\n } catch {}\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\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) {\n originalMutedState = muted;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n setAdVolume(volume: number) {\n if (adsManager && adPlaying) {\n try {\n adsManager.setVolume(Math.max(0, Math.min(1, volume)));\n } catch (error) {\n console.warn(\"[IMA] Failed to set ad volume:\", error);\n }\n }\n },\n getAdVolume(): number {\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 };\n}\n"],"mappings":"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","names":[]}
@@ -233,7 +233,7 @@ function createImaController(video, options) {
233
233
  );
234
234
  emit("ad_error");
235
235
  if (!options?.continueLiveStreamDuringAds) {
236
- video.play().catch(() => {
236
+ video.play()?.catch(() => {
237
237
  });
238
238
  }
239
239
  }
@@ -268,7 +268,7 @@ function createImaController(video, options) {
268
268
  if (adContainerEl)
269
269
  adContainerEl.style.pointerEvents = "none";
270
270
  if (!options?.continueLiveStreamDuringAds) {
271
- video.play().catch(() => {
271
+ video.play()?.catch(() => {
272
272
  });
273
273
  console.log("[IMA] Video resumed (VOD mode)");
274
274
  } else {
@@ -381,7 +381,7 @@ function createImaController(video, options) {
381
381
  console.error("[IMA] Error starting ad playback:", error);
382
382
  adPlaying = false;
383
383
  if (!options?.continueLiveStreamDuringAds) {
384
- video.play().catch(() => {
384
+ video.play()?.catch(() => {
385
385
  });
386
386
  }
387
387
  return Promise.reject(error);
@@ -614,13 +614,32 @@ function getClientInfo() {
614
614
  }
615
615
  async function getBrowserID(clientInfo) {
616
616
  const fingerprintString = JSON.stringify(clientInfo);
617
- const hashBuffer = await crypto.subtle.digest(
618
- "SHA-256",
619
- new TextEncoder().encode(fingerprintString)
620
- );
621
- const hashArray = Array.from(new Uint8Array(hashBuffer));
622
- const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
623
- return hashHex;
617
+ if (typeof crypto !== "undefined" && crypto.subtle && crypto.subtle.digest) {
618
+ try {
619
+ const hashBuffer = await crypto.subtle.digest(
620
+ "SHA-256",
621
+ new TextEncoder().encode(fingerprintString)
622
+ );
623
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
624
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
625
+ return hashHex;
626
+ } catch (error) {
627
+ console.warn(
628
+ "[StormcloudVideoPlayer] crypto.subtle.digest failed, using fallback hash:",
629
+ error
630
+ );
631
+ }
632
+ }
633
+ let hash = 0;
634
+ for (let i = 0; i < fingerprintString.length; i++) {
635
+ const char = fingerprintString.charCodeAt(i);
636
+ hash = (hash << 5) - hash + char;
637
+ hash = hash & hash;
638
+ }
639
+ const fallbackHash = Math.abs(hash).toString(16).padStart(8, "0");
640
+ const timestamp = Date.now().toString(16).padStart(12, "0");
641
+ const random = Math.random().toString(16).substring(2, 14).padStart(12, "0");
642
+ return (fallbackHash + timestamp + random).padEnd(64, "0");
624
643
  }
625
644
  async function sendInitialTracking(licenseKey) {
626
645
  try {
@@ -738,7 +757,7 @@ var StormcloudVideoPlayer = class {
738
757
  });
739
758
  this.ima.initialize();
740
759
  if (this.config.autoplay) {
741
- await this.video.play().catch(() => {
760
+ await this.video.play()?.catch(() => {
742
761
  });
743
762
  }
744
763
  return;
@@ -772,7 +791,7 @@ var StormcloudVideoPlayer = class {
772
791
  });
773
792
  this.ima.initialize();
774
793
  if (this.config.autoplay) {
775
- await this.video.play().catch(() => {
794
+ await this.video.play()?.catch(() => {
776
795
  });
777
796
  }
778
797
  });
@@ -1405,17 +1424,6 @@ var StormcloudVideoPlayer = class {
1405
1424
  }
1406
1425
  return true;
1407
1426
  }
1408
- async loadDefaultVastFromAdstorm(adstormApiUrl, params) {
1409
- const usp = new URLSearchParams(params || {});
1410
- const url = `${adstormApiUrl}?${usp.toString()}`;
1411
- const res = await fetch(url);
1412
- if (!res.ok) throw new Error(`Failed to fetch adstorm ads: ${res.status}`);
1413
- const data = await res.json();
1414
- const tag = data?.adTagUrl || data?.vastTagUrl || data?.tagUrl;
1415
- if (typeof tag === "string" && tag.length > 0) {
1416
- this.apiVastTagUrl = tag;
1417
- }
1418
- }
1419
1427
  async handleAdStart(_marker) {
1420
1428
  const scheduled = this.findCurrentOrNextBreak(
1421
1429
  this.video.currentTime * 1e3
@@ -1596,7 +1604,7 @@ var StormcloudVideoPlayer = class {
1596
1604
  this.currentAdIndex = 0;
1597
1605
  this.totalAdsInBreak = 0;
1598
1606
  if (this.video.paused) {
1599
- this.video.play().catch(() => {
1607
+ this.video.play()?.catch(() => {
1600
1608
  if (this.config.debugAdTiming) {
1601
1609
  console.error(
1602
1610
  "[StormcloudVideoPlayer] Failed to resume video after ad failure"