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