stormcloud-video-player 0.3.6 → 0.3.8

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.
@@ -264,7 +264,6 @@ function createImaController(video, options) {
264
264
  video.muted = true;
265
265
  video.volume = 0;
266
266
  contentVideoHidden = true;
267
- console.log("[DEBUG-LAYER] \u{1F534} Content video HIDDEN | muted=true, volume=0");
268
267
  }
269
268
  }
270
269
  function showContentVideo() {
@@ -276,9 +275,6 @@ function createImaController(video, options) {
276
275
  video.muted = originalMutedState;
277
276
  video.volume = originalVolume;
278
277
  contentVideoHidden = false;
279
- console.log(
280
- `[DEBUG-LAYER] \u{1F7E2} Content video RESTORED | muted=${originalMutedState}, volume=${originalVolume}`
281
- );
282
278
  }
283
279
  }
284
280
  function createAdVideoElement() {
@@ -299,13 +295,9 @@ function createImaController(video, options) {
299
295
  "canplay",
300
296
  () => {
301
297
  adVideo.style.opacity = "1";
302
- console.log("[DEBUG-LAYER] \u{1F4FA} Ad video element ready (canplay fired)");
303
298
  },
304
299
  { once: true }
305
300
  );
306
- console.log(
307
- `[DEBUG-AUDIO] \u{1F50A} Ad video created | volume=${adVideo.volume}, muted=${adVideo.muted}`
308
- );
309
301
  return adVideo;
310
302
  }
311
303
  function emit(event, payload) {
@@ -457,10 +449,8 @@ function createImaController(video, options) {
457
449
  function destroyAdsManager() {
458
450
  if (adsManager) {
459
451
  try {
460
- console.log("[IMA] Destroying existing ads manager");
461
452
  adsManager.destroy();
462
- } catch (error) {
463
- console.warn("[IMA] Error destroying ads manager:", error);
453
+ } catch {
464
454
  }
465
455
  adsManager = void 0;
466
456
  }
@@ -478,9 +468,6 @@ function createImaController(video, options) {
478
468
  if (!adVideoElement) {
479
469
  adVideoElement = createAdVideoElement();
480
470
  adContainerEl.appendChild(adVideoElement);
481
- console.log(
482
- "[IMA] Dedicated ad video element added to container"
483
- );
484
471
  }
485
472
  adDisplayContainer = new google.ima.AdDisplayContainer(
486
473
  adContainerEl,
@@ -488,9 +475,6 @@ function createImaController(video, options) {
488
475
  );
489
476
  try {
490
477
  (_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
491
- console.log(
492
- "[IMA] AdDisplayContainer initialized with dedicated ad video"
493
- );
494
478
  } catch {
495
479
  }
496
480
  }
@@ -498,9 +482,6 @@ function createImaController(video, options) {
498
482
  });
499
483
  },
500
484
  async requestAds(vastTagUrl) {
501
- console.log("[IMA] \u{1F4E1} === requestAds() called ===");
502
- console.log("[IMA] VAST URL:", vastTagUrl);
503
- console.log("[IMA] This will fetch the ad from the server - no visual change yet");
504
485
  if (!vastTagUrl || vastTagUrl.trim() === "") {
505
486
  const error = new Error("VAST tag URL is empty or undefined");
506
487
  console.warn("[IMA] \u274C", error.message);
@@ -543,7 +524,6 @@ function createImaController(video, options) {
543
524
  lastAdTagUrl = vastTagUrl;
544
525
  retryAttempts = 0;
545
526
  if (!adDisplayContainer) {
546
- console.log("[IMA] Creating ad display container");
547
527
  const container = document.createElement("div");
548
528
  container.style.position = "absolute";
549
529
  container.style.left = "0";
@@ -566,25 +546,11 @@ function createImaController(video, options) {
566
546
  if (!adVideoElement) {
567
547
  adVideoElement = createAdVideoElement();
568
548
  adContainerEl.appendChild(adVideoElement);
569
- console.log(
570
- "[IMA] Dedicated ad video element created and added to container"
571
- );
572
549
  }
573
550
  adDisplayContainer = new google.ima.AdDisplayContainer(
574
551
  container,
575
552
  adVideoElement
576
553
  );
577
- try {
578
- adDisplayContainer.initialize();
579
- console.log(
580
- "[IMA] Ad display container initialized with dedicated ad video"
581
- );
582
- } catch (error) {
583
- console.warn(
584
- "[IMA] Failed to initialize ad display container:",
585
- error
586
- );
587
- }
588
554
  }
589
555
  const videoWidth = video.offsetWidth || video.clientWidth;
590
556
  const videoHeight = video.offsetHeight || video.clientHeight;
@@ -599,29 +565,17 @@ function createImaController(video, options) {
599
565
  return Promise.reject(error);
600
566
  }
601
567
  if (!adsLoader) {
602
- console.log("[IMA] Creating ads loader");
603
568
  const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
604
569
  adsLoader = adsLoaderCls;
605
570
  adsLoader.addEventListener(
606
571
  google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
607
572
  (evt) => {
608
- console.log("[DEBUG-FLOW] \u2705 ADS_MANAGER_LOADED - Setting up manager");
609
573
  try {
610
574
  const adsRenderingSettings = new google.ima.AdsRenderingSettings();
611
575
  adsRenderingSettings.enablePreloading = true;
612
576
  adsManager = evt.getAdsManager(video, adsRenderingSettings);
613
577
  const AdEvent = google.ima.AdEvent.Type;
614
578
  const AdErrorEvent = google.ima.AdErrorEvent.Type;
615
- const keyEvents = ["STARTED", "COMPLETE", "CONTENT_PAUSE_REQUESTED", "CONTENT_RESUME_REQUESTED", "ALL_ADS_COMPLETED"];
616
- keyEvents.forEach((eventType) => {
617
- if (AdEvent[eventType]) {
618
- adsManager.addEventListener(AdEvent[eventType], (e) => {
619
- var _a, _b;
620
- const ad = (_a = e.getAd) == null ? void 0 : _a.call(e);
621
- console.log(`[DEBUG-FLOW] \u{1F3AC} ${eventType} | title=${((_b = ad == null ? void 0 : ad.getTitle) == null ? void 0 : _b.call(ad)) || "N/A"}`);
622
- });
623
- }
624
- });
625
579
  adsManager.addEventListener(
626
580
  AdErrorEvent.AD_ERROR,
627
581
  (errorEvent) => {
@@ -638,7 +592,6 @@ function createImaController(video, options) {
638
592
  if (adContainerEl) {
639
593
  adContainerEl.style.pointerEvents = "none";
640
594
  adContainerEl.style.display = "none";
641
- console.log("[DEBUG-LAYER] \u274C Ad container HIDDEN (error)");
642
595
  }
643
596
  }, 300);
644
597
  }
@@ -670,7 +623,6 @@ function createImaController(video, options) {
670
623
  adsManager.addEventListener(
671
624
  AdEvent.CONTENT_PAUSE_REQUESTED,
672
625
  () => {
673
- console.log("[DEBUG-FLOW] \u{1F3AF} CONTENT_PAUSE_REQUESTED - Ad request accepted");
674
626
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
675
627
  video.pause();
676
628
  }
@@ -680,15 +632,11 @@ function createImaController(video, options) {
680
632
  }
681
633
  );
682
634
  adsManager.addEventListener(AdEvent.STARTED, () => {
683
- console.log("[DEBUG-FLOW] \u25B6\uFE0F STARTED - Ad playing now");
684
635
  setAdPlayingFlag(true);
685
636
  hideContentVideo();
686
637
  if (adVideoElement) {
687
638
  adVideoElement.volume = originalMutedState ? 0 : originalVolume;
688
639
  adVideoElement.muted = originalMutedState;
689
- console.log(
690
- `[DEBUG-AUDIO] \u{1F50A} Ad audio set | volume=${adVideoElement.volume}, muted=${adVideoElement.muted}`
691
- );
692
640
  }
693
641
  if (adContainerEl) {
694
642
  adContainerEl.style.pointerEvents = "auto";
@@ -701,15 +649,12 @@ function createImaController(video, options) {
701
649
  adsManager.addEventListener(
702
650
  AdEvent.CONTENT_RESUME_REQUESTED,
703
651
  () => {
704
- console.log("[DEBUG-FLOW] \u23F8\uFE0F CONTENT_RESUME - Single ad done");
705
652
  adPlaying = false;
706
653
  setAdPlayingFlag(false);
707
- console.log("[DEBUG-LAYER] \u26A0\uFE0F Waiting for pod manager (more ads, placeholder, or done)");
708
654
  emit("content_resume");
709
655
  }
710
656
  );
711
657
  adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {
712
- console.log("[DEBUG-FLOW] \u{1F3C1} ALL_ADS_COMPLETED - Pod finished");
713
658
  adPlaying = false;
714
659
  setAdPlayingFlag(false);
715
660
  if (adContainerEl) {
@@ -719,19 +664,16 @@ function createImaController(video, options) {
719
664
  if (adContainerEl) {
720
665
  adContainerEl.style.pointerEvents = "none";
721
666
  adContainerEl.style.display = "none";
722
- console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (pod done)");
723
667
  }
724
668
  }, 300);
725
669
  }
726
670
  showContentVideo();
727
671
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds) && video.paused) {
728
- video.play().catch((e) => {
729
- console.warn("[DEBUG-ERROR] Failed to resume video:", e);
672
+ video.play().catch(() => {
730
673
  });
731
674
  }
732
675
  emit("all_ads_completed");
733
676
  });
734
- console.log("[IMA] Ads manager event listeners attached");
735
677
  if (adsLoadedResolve) {
736
678
  adsLoadedResolve();
737
679
  adsLoadedResolve = void 0;
@@ -826,9 +768,7 @@ function createImaController(video, options) {
826
768
  }
827
769
  const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
828
770
  preloadedVast.set(vastTagUrl, xml);
829
- console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
830
- }).catch((error) => {
831
- console.warn("[IMA] Failed to preload VAST response:", error);
771
+ }).catch(() => {
832
772
  preloadedVast.delete(vastTagUrl);
833
773
  }).finally(() => {
834
774
  preloadingVast.delete(vastTagUrl);
@@ -841,7 +781,6 @@ function createImaController(video, options) {
841
781
  },
842
782
  async play() {
843
783
  var _a, _b;
844
- console.log("[DEBUG-FLOW] \u25B6\uFE0F play() - Starting ad playback");
845
784
  if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
846
785
  return Promise.reject(new Error("IMA SDK not available"));
847
786
  }
@@ -857,19 +796,15 @@ function createImaController(video, options) {
857
796
  if (adVideoElement) {
858
797
  adVideoElement.volume = adVolume;
859
798
  adVideoElement.muted = originalMutedState;
860
- console.log(
861
- `[DEBUG-AUDIO] \u{1F50A} Pre-start ad audio | volume=${adVolume}, muted=${originalMutedState}`
862
- );
863
799
  }
864
800
  try {
865
801
  adsManager.setVolume(adVolume);
866
- } catch (error) {
867
- console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
802
+ } catch {
868
803
  }
869
804
  adsManager.start();
870
805
  return Promise.resolve();
871
806
  } catch (error) {
872
- console.error("[DEBUG-ERROR] \u274C Error starting ad:", error);
807
+ console.error("[IMA] \u274C Error starting ad:", error);
873
808
  adPlaying = false;
874
809
  setAdPlayingFlag(false);
875
810
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -881,7 +816,6 @@ function createImaController(video, options) {
881
816
  },
882
817
  async stop() {
883
818
  var _a;
884
- console.log("[DEBUG-FLOW] \u23F9\uFE0F stop() - Stopping ad playback");
885
819
  adPlaying = false;
886
820
  setAdPlayingFlag(false);
887
821
  if (adContainerEl) {
@@ -891,7 +825,6 @@ function createImaController(video, options) {
891
825
  if (adContainerEl) {
892
826
  adContainerEl.style.pointerEvents = "none";
893
827
  adContainerEl.style.display = "none";
894
- console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (stop)");
895
828
  }
896
829
  }, 300);
897
830
  }
@@ -961,9 +894,6 @@ function createImaController(video, options) {
961
894
  },
962
895
  updateOriginalMutedState(muted, volume) {
963
896
  const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
964
- console.log(
965
- `[DEBUG-AUDIO] \u{1F4BE} Saved original state | muted: ${originalMutedState}->${muted}, volume: ${originalVolume}->${nextVolume}`
966
- );
967
897
  originalMutedState = muted;
968
898
  originalVolume = nextVolume;
969
899
  },
@@ -978,15 +908,11 @@ function createImaController(video, options) {
978
908
  if (adVideoElement && adPlaying) {
979
909
  adVideoElement.volume = clampedVolume;
980
910
  adVideoElement.muted = clampedVolume === 0;
981
- console.log(
982
- `[DEBUG-AUDIO] \u{1F50A} Ad volume changed | volume=${clampedVolume}, muted=${clampedVolume === 0}`
983
- );
984
911
  }
985
912
  if (adsManager && adPlaying) {
986
913
  try {
987
914
  adsManager.setVolume(clampedVolume);
988
- } catch (error) {
989
- console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
915
+ } catch {
990
916
  }
991
917
  }
992
918
  },
@@ -2204,6 +2130,7 @@ var StormcloudVideoPlayer = class {
2204
2130
  this.fetchedAdDurations = /* @__PURE__ */ new Map();
2205
2131
  this.targetAdBreakDurationMs = null;
2206
2132
  this.isAdaptiveMode = false;
2133
+ this.failedVastUrls = /* @__PURE__ */ new Set();
2207
2134
  initializePolyfills();
2208
2135
  const browserOverrides = getBrowserConfigOverrides();
2209
2136
  this.config = { ...config, ...browserOverrides };
@@ -2476,51 +2403,37 @@ var StormcloudVideoPlayer = class {
2476
2403
  });
2477
2404
  this.ima.on("ad_error", (errorPayload) => {
2478
2405
  const remaining = this.getRemainingAdMs();
2479
- console.error(
2480
- `[DEBUG-POD] \u274C ad_error event | inBreak=${this.inAdBreak}, queue=${this.adPodQueue.length}, remaining=${remaining}ms`,
2481
- errorPayload ? `
2482
- Error details: ${JSON.stringify(errorPayload)}` : ""
2483
- );
2406
+ console.error("[AD-ERROR] Ad playback failed", errorPayload || "");
2484
2407
  if (this.inAdBreak) {
2485
2408
  if (remaining > 500 && this.adPodQueue.length > 0) {
2486
2409
  const nextPreloaded = this.findNextPreloadedAd();
2487
2410
  if (nextPreloaded) {
2488
2411
  this.currentAdIndex++;
2489
- console.log(
2490
- `[DEBUG-POD] \u27A1\uFE0F Trying next ad after error (${this.currentAdIndex}/${this.totalAdsInBreak})`
2491
- );
2492
2412
  this.playSingleAd(nextPreloaded).catch(() => {
2493
2413
  this.handleAdFailure();
2494
2414
  });
2495
2415
  } else {
2496
- console.log("[DEBUG-POD] \u26A0\uFE0F No more preloaded ads - calling handleAdFailure");
2497
2416
  this.handleAdFailure();
2498
2417
  }
2499
2418
  } else {
2500
- console.log("[DEBUG-POD] \u26A0\uFE0F No more ads or time - calling handleAdFailure");
2501
2419
  this.handleAdFailure();
2502
2420
  }
2503
2421
  } else {
2504
- console.log("[DEBUG-POD] \u26A0\uFE0F Error before ad break established");
2505
2422
  this.handleAdFailure();
2506
2423
  }
2507
2424
  });
2508
2425
  this.ima.on("content_pause", () => {
2509
- console.log(`[DEBUG-POD] \u{1F3AF} content_pause (AD STARTING!) | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}`);
2510
2426
  this.clearAdFailsafeTimer();
2511
2427
  this.clearAdRequestWatchdog();
2512
2428
  this.activeAdRequestToken = null;
2513
2429
  this.showAds = true;
2514
- console.log("[DEBUG-LAYER] \u{1F3AC} Layers: Main=hidden, Ad=visible, Placeholder=no");
2515
2430
  });
2516
2431
  this.ima.on("content_resume", () => {
2517
- console.log(`[DEBUG-POD] \u23F8\uFE0F content_resume | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}, remaining=${this.getRemainingAdMs()}ms`);
2518
2432
  this.clearAdFailsafeTimer();
2519
2433
  this.clearAdRequestWatchdog();
2520
2434
  this.activeAdRequestToken = null;
2521
2435
  this.showAds = false;
2522
2436
  if (!this.inAdBreak) {
2523
- console.warn("[DEBUG-POD] \u26A0\uFE0F Not in ad break - shouldn't happen");
2524
2437
  return;
2525
2438
  }
2526
2439
  const remaining = this.getRemainingAdMs();
@@ -2528,17 +2441,13 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2528
2441
  const nextPreloaded = this.findNextPreloadedAd();
2529
2442
  if (nextPreloaded) {
2530
2443
  this.currentAdIndex++;
2531
- console.log(`[DEBUG-POD] \u27A1\uFE0F Playing next ad ${this.currentAdIndex}/${this.totalAdsInBreak} (preloaded)`);
2532
2444
  this.playSingleAd(nextPreloaded).catch(() => {
2533
- console.error("[DEBUG-POD] \u274C Failed to play next ad");
2534
2445
  this.handleAdPodComplete();
2535
2446
  });
2536
2447
  } else {
2537
- console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads - ending pod");
2538
2448
  this.handleAdPodComplete();
2539
2449
  }
2540
2450
  } else {
2541
- console.log("[DEBUG-POD] \u2705 Pod complete (no more ads or time expired)");
2542
2451
  this.handleAdPodComplete();
2543
2452
  }
2544
2453
  });
@@ -2692,9 +2601,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2692
2601
  }
2693
2602
  if (marker.type === "start") {
2694
2603
  if (this.inAdBreak) {
2695
- console.log(
2696
- `[DEBUG-POD] \u26A0\uFE0F SCTE-35 start marker ignored - already in ad break (currentTime: ${this.video.currentTime})`
2697
- );
2698
2604
  return;
2699
2605
  }
2700
2606
  this.inAdBreak = true;
@@ -2763,9 +2669,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2763
2669
  return;
2764
2670
  }
2765
2671
  if (marker.type === "progress" && this.inAdBreak) {
2766
- console.log(
2767
- `[DEBUG-POD] \u{1F4CA} SCTE-35 progress marker (currentTime: ${this.video.currentTime})`
2768
- );
2769
2672
  if (marker.durationSeconds != null) {
2770
2673
  this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
2771
2674
  }
@@ -2778,7 +2681,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2778
2681
  this.scheduleAdStopCountdown(remainingMs);
2779
2682
  }
2780
2683
  if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null) {
2781
- console.log("[DEBUG-POD] \u{1F4CA} Progress marker: no ad playing, attempting to start");
2782
2684
  const scheduled = this.findCurrentOrNextBreak(
2783
2685
  this.video.currentTime * 1e3
2784
2686
  );
@@ -2790,24 +2692,16 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2790
2692
  this.playSingleAd(first).catch(() => {
2791
2693
  });
2792
2694
  }
2793
- } else {
2794
- console.log(
2795
- `[DEBUG-POD] \u{1F4CA} Progress marker: ad playing or request active (playing=${this.ima.isAdPlaying()}, token=${this.activeAdRequestToken})`
2796
- );
2797
2695
  }
2798
2696
  return;
2799
2697
  }
2800
2698
  if (marker.type === "end") {
2801
- console.log(
2802
- `[DEBUG-POD] \u{1F3C1} SCTE-35 end marker received (currentTime: ${this.video.currentTime})`
2803
- );
2804
2699
  this.inAdBreak = false;
2805
2700
  this.expectedAdBreakDurationMs = void 0;
2806
2701
  this.currentAdBreakStartWallClockMs = void 0;
2807
2702
  this.clearAdStartTimer();
2808
2703
  this.clearAdStopTimer();
2809
2704
  if (this.ima.isAdPlaying()) {
2810
- console.log("[DEBUG-POD] \u{1F6D1} Stopping ad due to SCTE-35 end marker");
2811
2705
  this.ima.stop().catch(() => {
2812
2706
  });
2813
2707
  }
@@ -3208,21 +3102,17 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3208
3102
  } else if (tags && tags.length > 0) {
3209
3103
  vastTagUrls = tags;
3210
3104
  } else {
3211
- console.log("[DEBUG-POD] \u26A0\uFE0F No VAST tag available");
3212
3105
  return;
3213
3106
  }
3214
3107
  if (vastTagUrls.length > 0) {
3215
- console.log(`[DEBUG-POD] \u{1F3AF} Starting ad break with ${vastTagUrls.length} ads`);
3216
3108
  this.adPodAllUrls = [...vastTagUrls];
3217
3109
  this.preloadingAdUrls.clear();
3218
3110
  this.vastToMediaUrlMap.clear();
3219
3111
  this.preloadedMediaUrls.clear();
3220
3112
  this.preloadingMediaUrls.clear();
3113
+ this.failedVastUrls.clear();
3221
3114
  const currentMuted = this.video.muted;
3222
3115
  const currentVolume = this.video.volume;
3223
- console.log(
3224
- `[DEBUG-AUDIO] \u{1F4BE} Capturing ORIGINAL state (once) | muted=${currentMuted}, volume=${currentVolume}`
3225
- );
3226
3116
  this.ima.updateOriginalMutedState(currentMuted, currentVolume);
3227
3117
  this.inAdBreak = true;
3228
3118
  this.currentAdIndex = 0;
@@ -3283,40 +3173,27 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3283
3173
  }
3284
3174
  async playAdPod() {
3285
3175
  if (this.adPodQueue.length === 0) {
3286
- console.log("[DEBUG-POD] \u26A0\uFE0F No ads in pod");
3287
3176
  return;
3288
3177
  }
3289
3178
  const waitTime = this.isAdaptiveMode ? 50 : 500;
3290
3179
  await new Promise((resolve) => setTimeout(resolve, waitTime));
3291
- if (this.config.debugAdTiming) {
3292
- console.log(
3293
- `[DEBUG-POD] \u{1F50D} Looking for preloaded ad in queue of ${this.adPodQueue.length} URLs`
3294
- );
3295
- }
3296
3180
  const firstPreloaded = this.findNextPreloadedAd();
3297
3181
  if (!firstPreloaded) {
3298
- console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads found, trying first ad from queue");
3299
3182
  const firstAd = this.adPodQueue.shift();
3300
3183
  if (firstAd) {
3301
3184
  this.currentAdIndex++;
3302
- console.log(`[DEBUG-POD] \u{1F3AC} Attempting to play first ad (not preloaded): ${firstAd.substring(0, 60)}...`);
3303
3185
  try {
3304
3186
  await this.playSingleAd(firstAd);
3305
3187
  } catch (error) {
3306
- console.log("[DEBUG-POD] \u26A0\uFE0F First ad failed, error handler will retry");
3307
3188
  return;
3308
3189
  }
3309
- } else {
3310
- console.log("[DEBUG-POD] \u274C No ads available in queue");
3311
3190
  }
3312
3191
  return;
3313
3192
  }
3314
3193
  this.currentAdIndex++;
3315
- console.log(`[DEBUG-POD] \u{1F680} Starting pod with ad ${this.currentAdIndex}/${this.totalAdsInBreak}`);
3316
3194
  try {
3317
3195
  await this.playSingleAd(firstPreloaded);
3318
3196
  } catch (error) {
3319
- console.log("[DEBUG-POD] \u26A0\uFE0F First ad failed, error handler will retry");
3320
3197
  }
3321
3198
  }
3322
3199
  findCurrentOrNextBreak(nowMs) {
@@ -3396,15 +3273,9 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3396
3273
  const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
3397
3274
  const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
3398
3275
  if (shouldExtendAdBreak) {
3399
- console.log(
3400
- `[DEBUG-POD] \u23F3 Extending ad break | elapsed=${elapsedSinceStartMs}ms, expected=${expectedDurationMs}ms, overrun=${overrunMs}ms`
3401
- );
3402
3276
  this.scheduleAdStopCountdown(checkIntervalMs);
3403
3277
  return;
3404
3278
  }
3405
- console.log(
3406
- `[DEBUG-POD] \u23F1\uFE0F Ad break duration expired | elapsed=${elapsedSinceStartMs}ms, expected=${expectedDurationMs}ms`
3407
- );
3408
3279
  if (adPlaying) {
3409
3280
  this.ima.stop().catch(() => {
3410
3281
  });
@@ -3437,42 +3308,29 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3437
3308
  this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;
3438
3309
  }
3439
3310
  async playSingleAd(vastTagUrl) {
3440
- console.log(`[DEBUG-POD] \u{1F3AC} playSingleAd | url=${vastTagUrl.substring(0, 60)}...`);
3441
3311
  if (this.ima.isAdPlaying()) {
3442
- console.warn("[DEBUG-POD] \u26A0\uFE0F Ad already playing - skipping request");
3312
+ return;
3313
+ }
3314
+ if (this.failedVastUrls.has(vastTagUrl)) {
3315
+ console.warn("[AD-ERROR] Skipping already-failed VAST URL:", vastTagUrl.substring(0, 60));
3316
+ this.handleAdFailure();
3443
3317
  return;
3444
3318
  }
3445
3319
  const requestToken = ++this.adRequestTokenCounter;
3446
- const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
3447
3320
  this.activeAdRequestToken = requestToken;
3448
- console.log(`[DEBUG-POD] \u{1F4DD} Request token=${requestToken}, preloaded=${wasPreloaded}`);
3449
3321
  this.startAdRequestWatchdog(requestToken);
3450
3322
  try {
3451
- console.log(`[DEBUG-POD] \u{1F4E1} Calling ima.requestAds() for token=${requestToken}...`);
3452
3323
  await this.ima.requestAds(vastTagUrl);
3453
- console.log(`[DEBUG-POD] \u2705 ima.requestAds() completed successfully`);
3454
3324
  this.clearAdRequestWatchdog();
3455
3325
  if (this.activeAdRequestToken !== requestToken) {
3456
- console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after requestAds (stale request)`);
3457
3326
  return;
3458
3327
  }
3459
- console.log(`[DEBUG-POD] \u{1F4FA} Calling ima.play() to start ad playback...`);
3460
- console.log(`[DEBUG-POD] \u{1F4CA} Video element state: paused=${this.video.paused}, muted=${this.video.muted}, readyState=${this.video.readyState}`);
3461
3328
  try {
3462
3329
  this.startAdFailsafeTimer(requestToken);
3463
3330
  await this.ima.play();
3464
- if (this.activeAdRequestToken === requestToken) {
3465
- console.log(`[DEBUG-POD] \u2705 Ad play initiated successfully (token=${requestToken})`);
3466
- } else {
3467
- console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after play (stale request)`);
3468
- }
3469
3331
  } catch (playError) {
3470
- console.error(
3471
- "[DEBUG-POD] \u274C Failed to play ad:",
3472
- playError instanceof Error ? playError.message : playError,
3473
- "\nFull error:",
3474
- playError
3475
- );
3332
+ console.error("[AD-ERROR] Failed to play ad:", playError);
3333
+ this.failedVastUrls.add(vastTagUrl);
3476
3334
  this.clearAdFailsafeTimer();
3477
3335
  if (this.activeAdRequestToken === requestToken) {
3478
3336
  this.activeAdRequestToken = null;
@@ -3481,7 +3339,8 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3481
3339
  return;
3482
3340
  }
3483
3341
  } catch (error) {
3484
- console.error("[DEBUG-POD] \u274C Ad request failed:", error == null ? void 0 : error.message);
3342
+ console.error("[AD-ERROR] Ad request failed:", error == null ? void 0 : error.message);
3343
+ this.failedVastUrls.add(vastTagUrl);
3485
3344
  this.clearAdRequestWatchdog();
3486
3345
  this.clearAdFailsafeTimer();
3487
3346
  if (this.activeAdRequestToken === requestToken) {
@@ -3492,7 +3351,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3492
3351
  }
3493
3352
  handleAdPodComplete() {
3494
3353
  var _a;
3495
- console.log("[DEBUG-POD] \u{1F3C1} handleAdPodComplete - Ending ad break, restoring content");
3496
3354
  this.clearAdRequestWatchdog();
3497
3355
  this.clearAdFailsafeTimer();
3498
3356
  this.activeAdRequestToken = null;
@@ -3514,10 +3372,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3514
3372
  });
3515
3373
  const restoredMuted = this.ima.getOriginalMutedState();
3516
3374
  const restoredVolume = this.ima.getOriginalVolume();
3517
- console.log(
3518
- `[DEBUG-AUDIO] \u{1F50A} Audio restored by IMA | muted=${restoredMuted}, volume=${restoredVolume}`
3519
- );
3520
- console.log("[DEBUG-LAYER] \u{1F3AC} Layers: Main=visible, Ad=hidden, Placeholder=no");
3521
3375
  if (this.video.muted !== restoredMuted) {
3522
3376
  this.video.muted = restoredMuted;
3523
3377
  }
@@ -3525,16 +3379,14 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3525
3379
  this.video.volume = restoredVolume;
3526
3380
  }
3527
3381
  if (!this.shouldContinueLiveStreamDuringAds() && this.video.paused) {
3528
- console.log("[DEBUG-FLOW] \u25B6\uFE0F Resuming main video playback");
3529
- (_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
3530
- console.error("[DEBUG-ERROR] Failed to resume video:", error);
3382
+ (_a = this.video.play()) == null ? void 0 : _a.catch(() => {
3531
3383
  });
3532
3384
  }
3533
3385
  }
3534
3386
  handleAdFailure() {
3535
- console.log("[DEBUG-POD] \u274C handleAdFailure - skipping to next ad or ending break");
3536
3387
  const remaining = this.getRemainingAdMs();
3537
- if (remaining > 500 && this.adPodQueue.length > 0) {
3388
+ const availableAds = this.adPodQueue.filter((url) => !this.failedVastUrls.has(url)).length;
3389
+ if (remaining > 500 && availableAds > 0) {
3538
3390
  if (this.isAdaptiveMode && this.currentAdIndex <= 1) {
3539
3391
  console.log("[ADAPTIVE-POD] \u23F3 First ad failed, waiting for sequential preload to catch up...");
3540
3392
  setTimeout(() => {
@@ -3545,14 +3397,13 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3545
3397
  const nextPreloaded = this.findNextPreloadedAd();
3546
3398
  if (nextPreloaded) {
3547
3399
  this.currentAdIndex++;
3548
- console.log(`[DEBUG-POD] \u27A1\uFE0F Trying next ad after failure (${this.currentAdIndex}/${this.totalAdsInBreak})`);
3549
3400
  this.playSingleAd(nextPreloaded).catch(() => {
3550
3401
  this.handleAdPodComplete();
3551
3402
  });
3552
3403
  return;
3553
3404
  }
3554
3405
  }
3555
- console.log("[DEBUG-POD] \u23F9\uFE0F Ending ad break after failure");
3406
+ console.error("[AD-ERROR] All ads failed or time expired. Failed URLs:", this.failedVastUrls.size);
3556
3407
  this.handleAdPodComplete();
3557
3408
  }
3558
3409
  tryNextAdWithRetry(retryCount) {
@@ -4005,37 +3856,21 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
4005
3856
  }
4006
3857
  findNextPreloadedAd() {
4007
3858
  var _a, _b, _c;
4008
- if (this.config.debugAdTiming) {
4009
- console.log(
4010
- `[DEBUG-POD] \u{1F50E} Searching for preloaded ad in queue (${this.adPodQueue.length} URLs, ${this.preloadedMediaUrls.size} media preloaded, ${this.vastToMediaUrlMap.size} VAST mappings)`
4011
- );
4012
- }
4013
3859
  for (let i = 0; i < this.adPodQueue.length; i++) {
4014
3860
  const vastTagUrl = this.adPodQueue[i];
4015
3861
  if (!vastTagUrl) continue;
3862
+ if (this.failedVastUrls.has(vastTagUrl)) {
3863
+ console.warn("[AD-ERROR] Skipping failed URL in queue");
3864
+ continue;
3865
+ }
4016
3866
  const hasImaPreload = (_c = (_b = (_a = this.ima).hasPreloadedAd) == null ? void 0 : _b.call(_a, vastTagUrl)) != null ? _c : false;
4017
3867
  const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
4018
3868
  const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;
4019
- if (this.config.debugAdTiming) {
4020
- console.log(
4021
- `[DEBUG-POD] Ad ${i}: IMA=${hasImaPreload}, Media=${hasMediaPreload}, MediaURLs=${(mediaUrls == null ? void 0 : mediaUrls.length) || 0}, URL=${vastTagUrl.substring(0, 60)}...`
4022
- );
4023
- }
4024
3869
  if (hasImaPreload || hasMediaPreload) {
4025
- if (this.config.debugAdTiming) {
4026
- console.log(
4027
- `[DEBUG-POD] \u2705 Found preloaded ad at index ${i}`
4028
- );
4029
- }
4030
3870
  this.adPodQueue.splice(0, i + 1);
4031
3871
  return vastTagUrl;
4032
3872
  }
4033
3873
  }
4034
- if (this.config.debugAdTiming) {
4035
- console.log(
4036
- `[DEBUG-POD] \u274C No preloaded ads found in queue`
4037
- );
4038
- }
4039
3874
  return void 0;
4040
3875
  }
4041
3876
  getRemainingAdMs() {