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