stormcloud-video-player 0.2.32 → 0.2.34

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/index.js CHANGED
@@ -220,7 +220,7 @@ function createImaController(video, options) {
220
220
  video.muted = true;
221
221
  video.volume = 0;
222
222
  contentVideoHidden = true;
223
- console.log("[IMA] Content video hidden and muted");
223
+ console.log("[DEBUG-LAYER] \u{1F534} Content video HIDDEN | muted=true, volume=0");
224
224
  }
225
225
  }
226
226
  function showContentVideo() {
@@ -233,7 +233,7 @@ function createImaController(video, options) {
233
233
  video.volume = originalVolume;
234
234
  contentVideoHidden = false;
235
235
  console.log(
236
- `[IMA] Content video restored (muted: ${originalMutedState}, volume: ${originalVolume})`
236
+ `[DEBUG-LAYER] \u{1F7E2} Content video RESTORED | muted=${originalMutedState}, volume=${originalVolume}`
237
237
  );
238
238
  }
239
239
  }
@@ -255,12 +255,12 @@ function createImaController(video, options) {
255
255
  "canplay",
256
256
  () => {
257
257
  adVideo.style.opacity = "1";
258
- console.log("[IMA] Ad video ready to play");
258
+ console.log("[DEBUG-LAYER] \u{1F4FA} Ad video element ready (canplay fired)");
259
259
  },
260
260
  { once: true }
261
261
  );
262
262
  console.log(
263
- `[IMA] Created dedicated ad video element with volume: ${adVideo.volume}, muted: ${adVideo.muted}`
263
+ `[DEBUG-AUDIO] \u{1F50A} Ad video created | volume=${adVideo.volume}, muted=${adVideo.muted}`
264
264
  );
265
265
  return adVideo;
266
266
  }
@@ -350,9 +350,6 @@ function createImaController(video, options) {
350
350
  const preloadedResponse = preloadedVast.get(vastTagUrl);
351
351
  if (preloadedResponse) {
352
352
  adsRequest.adsResponse = preloadedResponse;
353
- console.log(
354
- "[IMA] Using preloaded VAST response for immediate ad request"
355
- );
356
353
  } else {
357
354
  adsRequest.adTagUrl = vastTagUrl;
358
355
  }
@@ -379,7 +376,6 @@ function createImaController(video, options) {
379
376
  }
380
377
  }
381
378
  adsRequest.vastLoadTimeout = 5e3;
382
- console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
383
379
  adsLoader.requestAds(adsRequest);
384
380
  if (preloadedResponse) {
385
381
  preloadedVast.delete(vastTagUrl);
@@ -458,22 +454,24 @@ function createImaController(video, options) {
458
454
  });
459
455
  },
460
456
  async requestAds(vastTagUrl) {
461
- console.log("[IMA] Requesting ads:", vastTagUrl);
457
+ console.log("[IMA] \u{1F4E1} === requestAds() called ===");
458
+ console.log("[IMA] VAST URL:", vastTagUrl);
459
+ console.log("[IMA] This will fetch the ad from the server - no visual change yet");
462
460
  if (!vastTagUrl || vastTagUrl.trim() === "") {
463
461
  const error = new Error("VAST tag URL is empty or undefined");
464
- console.warn("[IMA]", error.message);
462
+ console.warn("[IMA] \u274C", error.message);
465
463
  return Promise.reject(error);
466
464
  }
467
465
  try {
468
466
  new URL(vastTagUrl);
469
467
  } catch (e) {
470
468
  const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);
471
- console.warn("[IMA]", error.message);
469
+ console.warn("[IMA] \u274C", error.message);
472
470
  return Promise.reject(error);
473
471
  }
474
472
  if (adPlaying) {
475
473
  console.warn(
476
- "[IMA] Cannot request new ads while an ad is playing. Call stop() first."
474
+ "[IMA] \u26A0\uFE0F Cannot request new ads while an ad is playing. Call stop() first."
477
475
  );
478
476
  return Promise.reject(
479
477
  new Error("Ad already playing - cannot request new ads")
@@ -563,20 +561,29 @@ function createImaController(video, options) {
563
561
  adsLoader.addEventListener(
564
562
  google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
565
563
  (evt) => {
566
- console.log(
567
- "[IMA] Ads manager loaded - enabling preloading for continuous playback"
568
- );
564
+ console.log("[DEBUG-FLOW] \u2705 ADS_MANAGER_LOADED - Setting up manager");
569
565
  try {
570
566
  const adsRenderingSettings = new google.ima.AdsRenderingSettings();
571
567
  adsRenderingSettings.enablePreloading = true;
572
568
  adsManager = evt.getAdsManager(video, adsRenderingSettings);
573
569
  const AdEvent = google.ima.AdEvent.Type;
574
570
  const AdErrorEvent = google.ima.AdErrorEvent.Type;
571
+ const keyEvents = ["STARTED", "COMPLETE", "CONTENT_PAUSE_REQUESTED", "CONTENT_RESUME_REQUESTED", "ALL_ADS_COMPLETED"];
572
+ keyEvents.forEach((eventType) => {
573
+ if (AdEvent[eventType]) {
574
+ adsManager.addEventListener(AdEvent[eventType], (e) => {
575
+ var _a, _b;
576
+ const ad = (_a = e.getAd) == null ? void 0 : _a.call(e);
577
+ console.log(`[DEBUG-FLOW] \u{1F3AC} ${eventType} | title=${((_b = ad == null ? void 0 : ad.getTitle) == null ? void 0 : _b.call(ad)) || "N/A"}`);
578
+ });
579
+ }
580
+ });
575
581
  adsManager.addEventListener(
576
582
  AdErrorEvent.AD_ERROR,
577
583
  (errorEvent) => {
578
- var _a;
579
- console.error("[IMA] Ad error:", errorEvent.getError());
584
+ var _a, _b;
585
+ const error = errorEvent.getError();
586
+ console.error("[DEBUG-ERROR] \u274C AD_ERROR:", (_a = error.getMessage) == null ? void 0 : _a.call(error));
580
587
  destroyAdsManager();
581
588
  adPlaying = false;
582
589
  setAdPlayingFlag(false);
@@ -587,7 +594,7 @@ function createImaController(video, options) {
587
594
  if (adContainerEl) {
588
595
  adContainerEl.style.pointerEvents = "none";
589
596
  adContainerEl.style.display = "none";
590
- console.log("[IMA] Ad container hidden after error");
597
+ console.log("[DEBUG-LAYER] \u274C Ad container HIDDEN (error)");
591
598
  }
592
599
  }, 300);
593
600
  }
@@ -599,9 +606,6 @@ function createImaController(video, options) {
599
606
  }
600
607
  if (lastAdTagUrl && retryAttempts < maxRetries) {
601
608
  const delay = backoffBaseMs * Math.pow(2, retryAttempts++);
602
- console.log(
603
- `[IMA] Retrying ad request in ${delay}ms (attempt ${retryAttempts})`
604
- );
605
609
  window.setTimeout(() => {
606
610
  try {
607
611
  makeAdsRequest(google, lastAdTagUrl);
@@ -609,16 +613,10 @@ function createImaController(video, options) {
609
613
  }
610
614
  }, delay);
611
615
  } else {
612
- console.log(
613
- "[IMA] Max retries reached, emitting ad_error"
614
- );
615
616
  emit("ad_error");
616
617
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
617
618
  if (video.paused) {
618
- console.log(
619
- "[IMA] Resuming paused video after ad error"
620
- );
621
- (_a = video.play()) == null ? void 0 : _a.catch(() => {
619
+ (_b = video.play()) == null ? void 0 : _b.catch(() => {
622
620
  });
623
621
  }
624
622
  }
@@ -628,14 +626,9 @@ function createImaController(video, options) {
628
626
  adsManager.addEventListener(
629
627
  AdEvent.CONTENT_PAUSE_REQUESTED,
630
628
  () => {
631
- console.log("[IMA] Content pause requested");
629
+ console.log("[DEBUG-FLOW] \u{1F3AF} CONTENT_PAUSE_REQUESTED - Ad starting");
632
630
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
633
631
  video.pause();
634
- console.log("[IMA] Content video paused (VOD mode)");
635
- } else {
636
- console.log(
637
- "[IMA] Content video continues in background (Live mode)"
638
- );
639
632
  }
640
633
  hideContentVideo();
641
634
  if (adContainerEl) {
@@ -644,7 +637,7 @@ function createImaController(video, options) {
644
637
  adContainerEl.style.backgroundColor = "#000";
645
638
  adContainerEl.offsetHeight;
646
639
  adContainerEl.style.opacity = "1";
647
- console.log("[IMA] Ad container shown on content pause");
640
+ console.log("[DEBUG-LAYER] \u{1F7E1} Ad container VISIBLE");
648
641
  }
649
642
  adPlaying = true;
650
643
  setAdPlayingFlag(true);
@@ -652,14 +645,14 @@ function createImaController(video, options) {
652
645
  }
653
646
  );
654
647
  adsManager.addEventListener(AdEvent.STARTED, () => {
655
- console.log("[IMA] Ad started - showing ad video");
648
+ console.log("[DEBUG-FLOW] \u25B6\uFE0F STARTED - Ad playing now");
656
649
  setAdPlayingFlag(true);
657
650
  hideContentVideo();
658
651
  if (adVideoElement) {
659
652
  adVideoElement.volume = originalMutedState ? 0 : originalVolume;
660
653
  adVideoElement.muted = originalMutedState;
661
654
  console.log(
662
- `[IMA] Ad video volume: ${adVideoElement.volume}, muted: ${adVideoElement.muted}`
655
+ `[DEBUG-AUDIO] \u{1F50A} Ad audio set | volume=${adVideoElement.volume}, muted=${adVideoElement.muted}`
663
656
  );
664
657
  }
665
658
  if (adContainerEl) {
@@ -668,20 +661,20 @@ function createImaController(video, options) {
668
661
  adContainerEl.style.backgroundColor = "#000";
669
662
  adContainerEl.offsetHeight;
670
663
  adContainerEl.style.opacity = "1";
671
- console.log("[IMA] Ad container now visible");
672
664
  }
673
665
  });
674
666
  adsManager.addEventListener(
675
667
  AdEvent.CONTENT_RESUME_REQUESTED,
676
668
  () => {
677
- console.log("[IMA] Content resume requested");
669
+ console.log("[DEBUG-FLOW] \u23F8\uFE0F CONTENT_RESUME - Single ad done");
678
670
  adPlaying = false;
679
671
  setAdPlayingFlag(false);
672
+ console.log("[DEBUG-LAYER] \u26A0\uFE0F Waiting for pod manager decision (more ads or done)");
680
673
  emit("content_resume");
681
674
  }
682
675
  );
683
676
  adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {
684
- console.log("[IMA] All ads completed - restoring content");
677
+ console.log("[DEBUG-FLOW] \u{1F3C1} ALL_ADS_COMPLETED - Pod finished");
685
678
  adPlaying = false;
686
679
  setAdPlayingFlag(false);
687
680
  if (adContainerEl) {
@@ -691,15 +684,14 @@ function createImaController(video, options) {
691
684
  if (adContainerEl) {
692
685
  adContainerEl.style.pointerEvents = "none";
693
686
  adContainerEl.style.display = "none";
694
- console.log("[IMA] Ad container hidden");
687
+ console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (pod done)");
695
688
  }
696
689
  }, 300);
697
690
  }
698
691
  showContentVideo();
699
692
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds) && video.paused) {
700
- console.log("[IMA] Resuming content video playback");
701
693
  video.play().catch((e) => {
702
- console.warn("[IMA] Failed to resume content video:", e);
694
+ console.warn("[DEBUG-ERROR] Failed to resume video:", e);
703
695
  });
704
696
  }
705
697
  emit("all_ads_completed");
@@ -721,18 +713,12 @@ function createImaController(video, options) {
721
713
  if (adContainerEl) {
722
714
  adContainerEl.style.pointerEvents = "none";
723
715
  adContainerEl.style.display = "none";
724
- console.log(
725
- "[IMA] Ad container hidden after setup error"
726
- );
727
716
  }
728
717
  }, 300);
729
718
  }
730
719
  showContentVideo();
731
720
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
732
721
  if (video.paused) {
733
- console.log(
734
- "[IMA] Resuming paused video after setup error"
735
- );
736
722
  video.play().catch(() => {
737
723
  });
738
724
  }
@@ -750,7 +736,9 @@ function createImaController(video, options) {
750
736
  adsLoader.addEventListener(
751
737
  google.ima.AdErrorEvent.Type.AD_ERROR,
752
738
  (adErrorEvent) => {
753
- console.error("[IMA] Ads loader error:", adErrorEvent.getError());
739
+ var _a;
740
+ const error = adErrorEvent.getError();
741
+ console.error("[DEBUG-ERROR] \u274C ADS_LOADER ERROR:", (_a = error.getMessage) == null ? void 0 : _a.call(error));
754
742
  adPlaying = false;
755
743
  setAdPlayingFlag(false);
756
744
  if (adContainerEl) {
@@ -760,14 +748,12 @@ function createImaController(video, options) {
760
748
  if (adContainerEl) {
761
749
  adContainerEl.style.pointerEvents = "none";
762
750
  adContainerEl.style.display = "none";
763
- console.log("[IMA] Ad container hidden after loader error");
764
751
  }
765
752
  }, 300);
766
753
  }
767
754
  showContentVideo();
768
755
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
769
756
  if (video.paused) {
770
- console.log("[IMA] Resuming paused video after loader error");
771
757
  video.play().catch(() => {
772
758
  });
773
759
  }
@@ -782,7 +768,6 @@ function createImaController(video, options) {
782
768
  false
783
769
  );
784
770
  }
785
- console.log("[IMA] Making ads request");
786
771
  makeAdsRequest(google, vastTagUrl);
787
772
  return adsLoadedPromise;
788
773
  } catch (error) {
@@ -821,20 +806,16 @@ function createImaController(video, options) {
821
806
  },
822
807
  async play() {
823
808
  var _a, _b;
809
+ console.log("[DEBUG-FLOW] \u25B6\uFE0F play() - Starting ad playback");
824
810
  if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
825
- console.warn(
826
- "[IMA] Cannot play ad: IMA SDK or ad container not available"
827
- );
828
811
  return Promise.reject(new Error("IMA SDK not available"));
829
812
  }
830
813
  if (!adsManager) {
831
- console.warn("[IMA] Cannot play ad: No ads manager available");
832
814
  return Promise.reject(new Error("No ads manager"));
833
815
  }
834
816
  try {
835
817
  const width = video.clientWidth || 640;
836
818
  const height = video.clientHeight || 360;
837
- console.log(`[IMA] Initializing ads manager (${width}x${height})`);
838
819
  adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
839
820
  adPlaying = true;
840
821
  const adVolume = originalMutedState ? 0 : originalVolume;
@@ -842,20 +823,18 @@ function createImaController(video, options) {
842
823
  adVideoElement.volume = adVolume;
843
824
  adVideoElement.muted = originalMutedState;
844
825
  console.log(
845
- `[IMA] Set dedicated ad video volume to ${adVolume}, muted: ${originalMutedState}`
826
+ `[DEBUG-AUDIO] \u{1F50A} Pre-start ad audio | volume=${adVolume}, muted=${originalMutedState}`
846
827
  );
847
828
  }
848
829
  try {
849
830
  adsManager.setVolume(adVolume);
850
- console.log(`[IMA] Set IMA manager volume to ${adVolume}`);
851
831
  } catch (error) {
852
- console.warn("[IMA] Failed to set IMA manager volume:", error);
832
+ console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
853
833
  }
854
- console.log("[IMA] Starting ad playback");
855
834
  adsManager.start();
856
835
  return Promise.resolve();
857
836
  } catch (error) {
858
- console.error("[IMA] Error starting ad playback:", error);
837
+ console.error("[DEBUG-ERROR] \u274C Error starting ad:", error);
859
838
  adPlaying = false;
860
839
  setAdPlayingFlag(false);
861
840
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -867,7 +846,7 @@ function createImaController(video, options) {
867
846
  },
868
847
  async stop() {
869
848
  var _a;
870
- console.log("[IMA] Stopping ad playback");
849
+ console.log("[DEBUG-FLOW] \u23F9\uFE0F stop() - Stopping ad playback");
871
850
  adPlaying = false;
872
851
  setAdPlayingFlag(false);
873
852
  if (adContainerEl) {
@@ -877,7 +856,7 @@ function createImaController(video, options) {
877
856
  if (adContainerEl) {
878
857
  adContainerEl.style.pointerEvents = "none";
879
858
  adContainerEl.style.display = "none";
880
- console.log("[IMA] Ad container hidden after stop");
859
+ console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (stop)");
881
860
  }
882
861
  }, 300);
883
862
  }
@@ -948,7 +927,7 @@ function createImaController(video, options) {
948
927
  updateOriginalMutedState(muted, volume) {
949
928
  const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
950
929
  console.log(
951
- `[IMA] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
930
+ `[DEBUG-AUDIO] \u{1F4BE} Saved original state | muted: ${originalMutedState}->${muted}, volume: ${originalVolume}->${nextVolume}`
952
931
  );
953
932
  originalMutedState = muted;
954
933
  originalVolume = nextVolume;
@@ -965,14 +944,14 @@ function createImaController(video, options) {
965
944
  adVideoElement.volume = clampedVolume;
966
945
  adVideoElement.muted = clampedVolume === 0;
967
946
  console.log(
968
- `[IMA] Set dedicated ad video volume to ${clampedVolume}, muted: ${clampedVolume === 0}`
947
+ `[DEBUG-AUDIO] \u{1F50A} Ad volume changed | volume=${clampedVolume}, muted=${clampedVolume === 0}`
969
948
  );
970
949
  }
971
950
  if (adsManager && adPlaying) {
972
951
  try {
973
952
  adsManager.setVolume(clampedVolume);
974
953
  } catch (error) {
975
- console.warn("[IMA] Failed to set IMA manager volume:", error);
954
+ console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
976
955
  }
977
956
  }
978
957
  },
@@ -2183,6 +2162,10 @@ var StormcloudVideoPlayer = class {
2183
2162
  this.vastToMediaUrlMap = /* @__PURE__ */ new Map();
2184
2163
  this.preloadedMediaUrls = /* @__PURE__ */ new Set();
2185
2164
  this.preloadingMediaUrls = /* @__PURE__ */ new Set();
2165
+ this.adRequestTokenCounter = 0;
2166
+ this.activeAdRequestToken = null;
2167
+ this.adRequestWatchdogToken = null;
2168
+ this.adFailsafeToken = null;
2186
2169
  initializePolyfills();
2187
2170
  const browserOverrides = getBrowserConfigOverrides();
2188
2171
  this.config = { ...config, ...browserOverrides };
@@ -2496,29 +2479,21 @@ var StormcloudVideoPlayer = class {
2496
2479
  }
2497
2480
  });
2498
2481
  this.ima.on("content_pause", () => {
2499
- if (this.config.debugAdTiming) {
2500
- console.log("[StormcloudVideoPlayer] IMA content_pause event received");
2501
- }
2482
+ console.log(`[DEBUG-POD] \u{1F3AF} content_pause | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}`);
2502
2483
  this.clearAdFailsafeTimer();
2484
+ this.clearAdRequestWatchdog();
2485
+ this.activeAdRequestToken = null;
2486
+ this.showAds = true;
2503
2487
  this.enforceAdHoldState();
2504
2488
  });
2505
2489
  this.ima.on("content_resume", () => {
2506
- if (this.config.debugAdTiming) {
2507
- console.log(
2508
- "[StormcloudVideoPlayer] IMA content_resume event received",
2509
- {
2510
- inAdBreak: this.inAdBreak,
2511
- pendingAds: this.adPodQueue.length
2512
- }
2513
- );
2514
- }
2490
+ console.log(`[DEBUG-POD] \u23F8\uFE0F content_resume | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}, remaining=${this.getRemainingAdMs()}ms`);
2515
2491
  this.clearAdFailsafeTimer();
2492
+ this.clearAdRequestWatchdog();
2493
+ this.activeAdRequestToken = null;
2494
+ this.showAds = false;
2516
2495
  if (!this.inAdBreak) {
2517
- if (this.config.debugAdTiming) {
2518
- console.log(
2519
- "[StormcloudVideoPlayer] Not in ad break - this shouldn't happen during pod"
2520
- );
2521
- }
2496
+ console.warn("[DEBUG-POD] \u26A0\uFE0F Not in ad break - shouldn't happen");
2522
2497
  return;
2523
2498
  }
2524
2499
  const remaining = this.getRemainingAdMs();
@@ -2526,34 +2501,17 @@ var StormcloudVideoPlayer = class {
2526
2501
  const nextPreloaded = this.findNextPreloadedAd();
2527
2502
  if (nextPreloaded) {
2528
2503
  this.currentAdIndex++;
2529
- this.enforceAdHoldState();
2530
- if (this.config.debugAdTiming) {
2531
- console.log(
2532
- `[StormcloudVideoPlayer] Playing next preloaded ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak})`
2533
- );
2534
- }
2504
+ console.log(`[DEBUG-POD] \u27A1\uFE0F Playing next ad ${this.currentAdIndex}/${this.totalAdsInBreak} (preloaded)`);
2535
2505
  this.playSingleAd(nextPreloaded).catch(() => {
2536
- if (this.config.debugAdTiming) {
2537
- console.error(
2538
- "[StormcloudVideoPlayer] Failed to play next ad in pod"
2539
- );
2540
- }
2506
+ console.error("[DEBUG-POD] \u274C Failed to play next ad");
2541
2507
  this.handleAdPodComplete();
2542
2508
  });
2543
2509
  } else {
2544
- if (this.config.debugAdTiming) {
2545
- console.log(
2546
- "[StormcloudVideoPlayer] No preloaded ads available - completing ad break"
2547
- );
2548
- }
2510
+ console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads - ending pod");
2549
2511
  this.handleAdPodComplete();
2550
2512
  }
2551
2513
  } else {
2552
- if (this.config.debugAdTiming) {
2553
- console.log(
2554
- "[StormcloudVideoPlayer] No more ads in pod - completing ad break"
2555
- );
2556
- }
2514
+ console.log("[DEBUG-POD] \u2705 Pod complete (no more ads or time expired)");
2557
2515
  this.handleAdPodComplete();
2558
2516
  }
2559
2517
  });
@@ -3128,53 +3086,27 @@ var StormcloudVideoPlayer = class {
3128
3086
  let vastTagUrls = [];
3129
3087
  if (this.apiVastTagUrl) {
3130
3088
  vastTagUrls = [this.apiVastTagUrl];
3131
- if (this.config.debugAdTiming) {
3132
- console.log(
3133
- "[StormcloudVideoPlayer] Using VAST endpoint:",
3134
- this.apiVastTagUrl
3135
- );
3136
- }
3137
3089
  } else if (tags && tags.length > 0) {
3138
3090
  vastTagUrls = tags;
3139
- if (this.config.debugAdTiming) {
3140
- console.log(
3141
- "[StormcloudVideoPlayer] Using scheduled VAST tags (count: " + tags.length + "):",
3142
- tags
3143
- );
3144
- }
3145
3091
  } else {
3146
- if (this.config.debugAdTiming) {
3147
- console.log("[StormcloudVideoPlayer] No VAST tag available for ad");
3148
- }
3092
+ console.log("[DEBUG-POD] \u26A0\uFE0F No VAST tag available");
3149
3093
  return;
3150
3094
  }
3151
3095
  if (vastTagUrls.length > 0) {
3096
+ console.log(`[DEBUG-POD] \u{1F3AF} Starting ad break with ${vastTagUrls.length} ads`);
3152
3097
  this.adPodAllUrls = [...vastTagUrls];
3153
3098
  this.preloadingAdUrls.clear();
3154
3099
  this.vastToMediaUrlMap.clear();
3155
3100
  this.preloadedMediaUrls.clear();
3156
3101
  this.preloadingMediaUrls.clear();
3157
- this.logQueuedAdUrls(this.adPodAllUrls);
3158
- if (this.config.debugAdTiming) {
3159
- console.log(
3160
- `[StormcloudVideoPlayer] Capturing original audio state before ad break:`,
3161
- {
3162
- videoMuted: this.video.muted,
3163
- videoVolume: this.video.volume
3164
- }
3165
- );
3166
- }
3102
+ console.log(
3103
+ `[DEBUG-AUDIO] \u{1F4BE} Capturing original state | muted=${this.video.muted}, volume=${this.video.volume}`
3104
+ );
3167
3105
  this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
3168
3106
  this.inAdBreak = true;
3169
3107
  this.currentAdIndex = 0;
3170
3108
  this.totalAdsInBreak = vastTagUrls.length;
3171
3109
  this.adPodQueue = [...vastTagUrls];
3172
- this.enforceAdHoldState();
3173
- if (this.config.debugAdTiming) {
3174
- console.log(
3175
- `[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - preloading all ads in parallel`
3176
- );
3177
- }
3178
3110
  this.preloadAllAdsInBackground().catch((error) => {
3179
3111
  if (this.config.debugAdTiming) {
3180
3112
  console.warn(
@@ -3186,12 +3118,7 @@ var StormcloudVideoPlayer = class {
3186
3118
  try {
3187
3119
  await this.playAdPod();
3188
3120
  } catch (error) {
3189
- if (this.config.debugAdTiming) {
3190
- console.error(
3191
- "[StormcloudVideoPlayer] Ad pod playback failed:",
3192
- error
3193
- );
3194
- }
3121
+ console.error("[DEBUG-POD] \u274C Pod playback failed:", error);
3195
3122
  this.handleAdFailure();
3196
3123
  }
3197
3124
  }
@@ -3203,19 +3130,13 @@ var StormcloudVideoPlayer = class {
3203
3130
  }
3204
3131
  async playAdPod() {
3205
3132
  if (this.adPodQueue.length === 0) {
3206
- if (this.config.debugAdTiming) {
3207
- console.log("[StormcloudVideoPlayer] No ads in pod to play");
3208
- }
3133
+ console.log("[DEBUG-POD] \u26A0\uFE0F No ads in pod");
3209
3134
  return;
3210
3135
  }
3211
3136
  await new Promise((resolve) => setTimeout(resolve, 500));
3212
3137
  const firstPreloaded = this.findNextPreloadedAd();
3213
3138
  if (!firstPreloaded) {
3214
- if (this.config.debugAdTiming) {
3215
- console.log(
3216
- "[StormcloudVideoPlayer] No preloaded ads available after waiting, trying first ad anyway"
3217
- );
3218
- }
3139
+ console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads after wait, trying first ad");
3219
3140
  const firstAd = this.adPodQueue.shift();
3220
3141
  if (firstAd) {
3221
3142
  this.currentAdIndex++;
@@ -3224,11 +3145,7 @@ var StormcloudVideoPlayer = class {
3224
3145
  return;
3225
3146
  }
3226
3147
  this.currentAdIndex++;
3227
- if (this.config.debugAdTiming) {
3228
- console.log(
3229
- `[StormcloudVideoPlayer] Playing first preloaded ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
3230
- );
3231
- }
3148
+ console.log(`[DEBUG-POD] \u{1F680} Starting pod with ad ${this.currentAdIndex}/${this.totalAdsInBreak}`);
3232
3149
  await this.playSingleAd(firstPreloaded);
3233
3150
  }
3234
3151
  findCurrentOrNextBreak(nowMs) {
@@ -3263,7 +3180,6 @@ var StormcloudVideoPlayer = class {
3263
3180
  const rest = tags.slice(1);
3264
3181
  this.adPodQueue = rest;
3265
3182
  this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
3266
- this.enforceAdHoldState();
3267
3183
  await this.playSingleAd(first);
3268
3184
  this.inAdBreak = true;
3269
3185
  this.expectedAdBreakDurationMs = remainingMs;
@@ -3366,63 +3282,56 @@ var StormcloudVideoPlayer = class {
3366
3282
  this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;
3367
3283
  }
3368
3284
  async playSingleAd(vastTagUrl) {
3369
- if (this.config.debugAdTiming) {
3370
- console.log("[StormcloudVideoPlayer] Attempting to play ad:", vastTagUrl);
3371
- }
3285
+ console.log(`[DEBUG-POD] \u{1F3AC} playSingleAd | url=${vastTagUrl.substring(0, 60)}...`);
3372
3286
  if (this.ima.isAdPlaying()) {
3373
- if (this.config.debugAdTiming) {
3374
- console.warn(
3375
- "[StormcloudVideoPlayer] Ad already playing - skipping new ad request"
3376
- );
3377
- }
3287
+ console.warn("[DEBUG-POD] \u26A0\uFE0F Ad already playing - skipping request");
3378
3288
  return;
3379
3289
  }
3290
+ const requestToken = ++this.adRequestTokenCounter;
3380
3291
  const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
3381
- if (wasPreloaded && this.config.debugAdTiming) {
3382
- console.log(
3383
- `[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
3384
- );
3385
- }
3386
- this.startAdFailsafeTimer();
3292
+ this.activeAdRequestToken = requestToken;
3293
+ console.log(`[DEBUG-POD] \u{1F4DD} Request token=${requestToken}, preloaded=${wasPreloaded}`);
3294
+ this.startAdRequestWatchdog(requestToken);
3387
3295
  try {
3388
3296
  await this.ima.requestAds(vastTagUrl);
3297
+ this.clearAdRequestWatchdog();
3298
+ if (this.activeAdRequestToken !== requestToken) {
3299
+ console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after requestAds (stale request)`);
3300
+ return;
3301
+ }
3389
3302
  try {
3390
- if (this.config.debugAdTiming) {
3391
- console.log(
3392
- "[StormcloudVideoPlayer] Ad request completed, attempting playback"
3393
- );
3394
- }
3395
- this.enforceAdHoldState();
3303
+ this.startAdFailsafeTimer(requestToken);
3396
3304
  await this.ima.play();
3397
- this.showAds = true;
3398
- if (this.config.debugAdTiming) {
3399
- console.log(
3400
- "[StormcloudVideoPlayer] Ad playback started successfully, showAds = true"
3401
- );
3305
+ if (this.activeAdRequestToken === requestToken) {
3306
+ console.log(`[DEBUG-POD] \u2705 Ad play initiated (token=${requestToken})`);
3307
+ } else {
3308
+ console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after play (stale request)`);
3402
3309
  }
3403
3310
  } catch (playError) {
3404
- if (this.config.debugAdTiming) {
3405
- console.log(
3406
- "[StormcloudVideoPlayer] No ads available, skipping playback"
3407
- );
3311
+ console.log("[DEBUG-POD] \u26A0\uFE0F No ads available from play()");
3312
+ this.clearAdFailsafeTimer();
3313
+ if (this.activeAdRequestToken === requestToken) {
3314
+ this.activeAdRequestToken = null;
3408
3315
  }
3409
3316
  this.handleAdFailure();
3410
3317
  return;
3411
3318
  }
3412
3319
  } catch (error) {
3413
- if (this.config.debugAdTiming) {
3414
- console.error("[StormcloudVideoPlayer] Ad playback failed:", error);
3320
+ console.error("[DEBUG-POD] \u274C Ad request failed:", error == null ? void 0 : error.message);
3321
+ this.clearAdRequestWatchdog();
3322
+ this.clearAdFailsafeTimer();
3323
+ if (this.activeAdRequestToken === requestToken) {
3324
+ this.activeAdRequestToken = null;
3415
3325
  }
3416
3326
  this.handleAdFailure();
3417
3327
  }
3418
3328
  }
3419
3329
  handleAdPodComplete() {
3420
3330
  var _a;
3421
- if (this.config.debugAdTiming) {
3422
- console.log(
3423
- "[StormcloudVideoPlayer] Handling ad pod completion - resuming content and hiding ad layer"
3424
- );
3425
- }
3331
+ console.log("[DEBUG-POD] \u{1F3C1} handleAdPodComplete - Ending ad break, restoring content");
3332
+ this.clearAdRequestWatchdog();
3333
+ this.clearAdFailsafeTimer();
3334
+ this.activeAdRequestToken = null;
3426
3335
  this.releaseAdHoldState();
3427
3336
  this.preloadingAdUrls.clear();
3428
3337
  this.vastToMediaUrlMap.clear();
@@ -3433,7 +3342,6 @@ var StormcloudVideoPlayer = class {
3433
3342
  this.currentAdBreakStartWallClockMs = void 0;
3434
3343
  this.clearAdStartTimer();
3435
3344
  this.clearAdStopTimer();
3436
- this.clearAdFailsafeTimer();
3437
3345
  this.adPodQueue = [];
3438
3346
  this.adPodAllUrls = [];
3439
3347
  this.showAds = false;
@@ -3445,70 +3353,84 @@ var StormcloudVideoPlayer = class {
3445
3353
  const originalVolume = typeof this.ima.getOriginalVolume === "function" ? this.ima.getOriginalVolume() : this.video.volume;
3446
3354
  this.video.muted = originalMutedState;
3447
3355
  this.video.volume = originalVolume;
3448
- if (this.config.debugAdTiming) {
3449
- console.log(
3450
- `[StormcloudVideoPlayer] Restored main video - muted: ${originalMutedState}, volume: ${this.video.volume}`
3451
- );
3452
- }
3356
+ console.log(
3357
+ `[DEBUG-AUDIO] \u{1F50A} Main video restored | muted=${originalMutedState}, volume=${originalVolume}`
3358
+ );
3453
3359
  if (!this.shouldContinueLiveStreamDuringAds() && this.video.paused) {
3454
- if (this.config.debugAdTiming) {
3455
- console.log("[StormcloudVideoPlayer] Resuming paused video");
3456
- }
3360
+ console.log("[DEBUG-FLOW] \u25B6\uFE0F Resuming main video playback");
3457
3361
  (_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
3458
- if (this.config.debugAdTiming) {
3459
- console.error(
3460
- "[StormcloudVideoPlayer] Failed to resume video:",
3461
- error
3462
- );
3463
- }
3362
+ console.error("[DEBUG-ERROR] Failed to resume video:", error);
3464
3363
  });
3465
3364
  }
3466
3365
  }
3467
3366
  handleAdFailure() {
3468
- if (this.config.debugAdTiming) {
3469
- console.log(
3470
- "[StormcloudVideoPlayer] Handling ad failure - resuming content",
3471
- {
3472
- inAdBreak: this.inAdBreak,
3473
- showAds: this.showAds,
3474
- videoPaused: this.video.paused,
3475
- adPlaying: this.ima.isAdPlaying()
3476
- }
3477
- );
3478
- }
3367
+ console.log(
3368
+ `[DEBUG-POD] \u274C handleAdFailure | inBreak=${this.inAdBreak}, showAds=${this.showAds}, paused=${this.video.paused}`
3369
+ );
3479
3370
  this.handleAdPodComplete();
3480
3371
  }
3481
- startAdFailsafeTimer() {
3372
+ startAdRequestWatchdog(token) {
3373
+ var _a;
3374
+ this.clearAdRequestWatchdog();
3375
+ const timeoutMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
3376
+ this.adRequestWatchdogToken = token;
3377
+ this.adRequestWatchdogId = window.setTimeout(() => {
3378
+ if (this.adRequestWatchdogToken !== token) {
3379
+ return;
3380
+ }
3381
+ this.adRequestWatchdogId = void 0;
3382
+ this.adRequestWatchdogToken = null;
3383
+ if (this.activeAdRequestToken === token) {
3384
+ this.activeAdRequestToken = null;
3385
+ }
3386
+ this.logAdState("ad_request_timeout", { token, timeoutMs });
3387
+ this.handleAdFailure();
3388
+ }, timeoutMs);
3389
+ this.logAdState("ad_request_watchdog_started", { token, timeoutMs });
3390
+ }
3391
+ clearAdRequestWatchdog() {
3392
+ if (this.adRequestWatchdogId != null) {
3393
+ clearTimeout(this.adRequestWatchdogId);
3394
+ this.adRequestWatchdogId = void 0;
3395
+ }
3396
+ if (this.adRequestWatchdogToken != null) {
3397
+ this.logAdState("ad_request_watchdog_cleared", {
3398
+ token: this.adRequestWatchdogToken
3399
+ });
3400
+ this.adRequestWatchdogToken = null;
3401
+ }
3402
+ }
3403
+ startAdFailsafeTimer(token) {
3482
3404
  var _a;
3483
3405
  this.clearAdFailsafeTimer();
3484
3406
  const failsafeMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
3485
- if (this.config.debugAdTiming) {
3486
- console.log(
3487
- `[StormcloudVideoPlayer] Starting failsafe timer (${failsafeMs}ms)`
3488
- );
3489
- }
3407
+ this.adFailsafeToken = token;
3490
3408
  this.adFailsafeTimerId = window.setTimeout(() => {
3491
- const shouldTrigger = this.video.paused || this.showAds && !this.ima.isAdPlaying();
3492
- if (shouldTrigger) {
3493
- if (this.config.debugAdTiming) {
3494
- console.warn(
3495
- "[StormcloudVideoPlayer] Failsafe timer triggered - forcing video resume",
3496
- {
3497
- paused: this.video.paused,
3498
- showAds: this.showAds,
3499
- adPlaying: this.ima.isAdPlaying()
3500
- }
3501
- );
3502
- }
3503
- this.handleAdFailure();
3409
+ if (this.adFailsafeToken !== token) {
3410
+ return;
3504
3411
  }
3412
+ this.adFailsafeTimerId = void 0;
3413
+ this.adFailsafeToken = null;
3414
+ if (this.activeAdRequestToken === token) {
3415
+ this.activeAdRequestToken = null;
3416
+ }
3417
+ this.logAdState("ad_failsafe_triggered", {
3418
+ token,
3419
+ failsafeMs,
3420
+ videoPaused: this.video.paused,
3421
+ imaAdPlaying: this.ima.isAdPlaying()
3422
+ });
3423
+ this.handleAdFailure();
3505
3424
  }, failsafeMs);
3425
+ this.logAdState("ad_failsafe_started", { token, failsafeMs });
3506
3426
  }
3507
3427
  clearAdFailsafeTimer() {
3508
3428
  if (this.adFailsafeTimerId != null) {
3509
3429
  clearTimeout(this.adFailsafeTimerId);
3430
+ this.logAdState("ad_failsafe_cleared", { token: this.adFailsafeToken });
3510
3431
  this.adFailsafeTimerId = void 0;
3511
3432
  }
3433
+ this.adFailsafeToken = null;
3512
3434
  }
3513
3435
  selectVastTagsForBreak(b) {
3514
3436
  if (!b || !b.vastTagUrl) return void 0;
@@ -3523,16 +3445,32 @@ var StormcloudVideoPlayer = class {
3523
3445
  }
3524
3446
  console.log("[StormcloudVideoPlayer] ALL ad URLs queued:", urls);
3525
3447
  }
3448
+ logAdState(event, extra = {}) {
3449
+ if (!this.config.debugAdTiming) {
3450
+ return;
3451
+ }
3452
+ console.log("[StormcloudVideoPlayer][AdState]", {
3453
+ event,
3454
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3455
+ showAds: this.showAds,
3456
+ adPlaying: this.ima.isAdPlaying(),
3457
+ inAdBreak: this.inAdBreak,
3458
+ activeAdRequestToken: this.activeAdRequestToken,
3459
+ ...extra
3460
+ });
3461
+ }
3526
3462
  enforceAdHoldState() {
3527
3463
  this.video.dataset.stormcloudAdPlaying = "true";
3528
3464
  this.video.muted = true;
3529
3465
  this.video.volume = 0;
3466
+ console.log("[DEBUG-LAYER] \u{1F512} Enforced ad hold state (main video muted)");
3530
3467
  if (typeof this.ima.showPlaceholder === "function") {
3531
3468
  this.ima.showPlaceholder();
3532
3469
  }
3533
3470
  }
3534
3471
  releaseAdHoldState() {
3535
3472
  delete this.video.dataset.stormcloudAdPlaying;
3473
+ console.log("[DEBUG-LAYER] \u{1F513} Released ad hold state");
3536
3474
  if (typeof this.ima.hidePlaceholder === "function") {
3537
3475
  this.ima.hidePlaceholder();
3538
3476
  }