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.
@@ -222,7 +222,6 @@ function createImaController(video, options) {
222
222
  video.muted = true;
223
223
  video.volume = 0;
224
224
  contentVideoHidden = true;
225
- console.log("[DEBUG-LAYER] \u{1F534} Content video HIDDEN | muted=true, volume=0");
226
225
  }
227
226
  }
228
227
  function showContentVideo() {
@@ -234,9 +233,6 @@ function createImaController(video, options) {
234
233
  video.muted = originalMutedState;
235
234
  video.volume = originalVolume;
236
235
  contentVideoHidden = false;
237
- console.log(
238
- `[DEBUG-LAYER] \u{1F7E2} Content video RESTORED | muted=${originalMutedState}, volume=${originalVolume}`
239
- );
240
236
  }
241
237
  }
242
238
  function createAdVideoElement() {
@@ -257,13 +253,9 @@ function createImaController(video, options) {
257
253
  "canplay",
258
254
  () => {
259
255
  adVideo.style.opacity = "1";
260
- console.log("[DEBUG-LAYER] \u{1F4FA} Ad video element ready (canplay fired)");
261
256
  },
262
257
  { once: true }
263
258
  );
264
- console.log(
265
- `[DEBUG-AUDIO] \u{1F50A} Ad video created | volume=${adVideo.volume}, muted=${adVideo.muted}`
266
- );
267
259
  return adVideo;
268
260
  }
269
261
  function emit(event, payload) {
@@ -415,10 +407,8 @@ function createImaController(video, options) {
415
407
  function destroyAdsManager() {
416
408
  if (adsManager) {
417
409
  try {
418
- console.log("[IMA] Destroying existing ads manager");
419
410
  adsManager.destroy();
420
- } catch (error) {
421
- console.warn("[IMA] Error destroying ads manager:", error);
411
+ } catch {
422
412
  }
423
413
  adsManager = void 0;
424
414
  }
@@ -436,9 +426,6 @@ function createImaController(video, options) {
436
426
  if (!adVideoElement) {
437
427
  adVideoElement = createAdVideoElement();
438
428
  adContainerEl.appendChild(adVideoElement);
439
- console.log(
440
- "[IMA] Dedicated ad video element added to container"
441
- );
442
429
  }
443
430
  adDisplayContainer = new google.ima.AdDisplayContainer(
444
431
  adContainerEl,
@@ -446,9 +433,6 @@ function createImaController(video, options) {
446
433
  );
447
434
  try {
448
435
  (_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
449
- console.log(
450
- "[IMA] AdDisplayContainer initialized with dedicated ad video"
451
- );
452
436
  } catch {
453
437
  }
454
438
  }
@@ -456,9 +440,6 @@ function createImaController(video, options) {
456
440
  });
457
441
  },
458
442
  async requestAds(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");
462
443
  if (!vastTagUrl || vastTagUrl.trim() === "") {
463
444
  const error = new Error("VAST tag URL is empty or undefined");
464
445
  console.warn("[IMA] \u274C", error.message);
@@ -501,7 +482,6 @@ function createImaController(video, options) {
501
482
  lastAdTagUrl = vastTagUrl;
502
483
  retryAttempts = 0;
503
484
  if (!adDisplayContainer) {
504
- console.log("[IMA] Creating ad display container");
505
485
  const container = document.createElement("div");
506
486
  container.style.position = "absolute";
507
487
  container.style.left = "0";
@@ -524,25 +504,11 @@ function createImaController(video, options) {
524
504
  if (!adVideoElement) {
525
505
  adVideoElement = createAdVideoElement();
526
506
  adContainerEl.appendChild(adVideoElement);
527
- console.log(
528
- "[IMA] Dedicated ad video element created and added to container"
529
- );
530
507
  }
531
508
  adDisplayContainer = new google.ima.AdDisplayContainer(
532
509
  container,
533
510
  adVideoElement
534
511
  );
535
- try {
536
- adDisplayContainer.initialize();
537
- console.log(
538
- "[IMA] Ad display container initialized with dedicated ad video"
539
- );
540
- } catch (error) {
541
- console.warn(
542
- "[IMA] Failed to initialize ad display container:",
543
- error
544
- );
545
- }
546
512
  }
547
513
  const videoWidth = video.offsetWidth || video.clientWidth;
548
514
  const videoHeight = video.offsetHeight || video.clientHeight;
@@ -557,29 +523,17 @@ function createImaController(video, options) {
557
523
  return Promise.reject(error);
558
524
  }
559
525
  if (!adsLoader) {
560
- console.log("[IMA] Creating ads loader");
561
526
  const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
562
527
  adsLoader = adsLoaderCls;
563
528
  adsLoader.addEventListener(
564
529
  google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
565
530
  (evt) => {
566
- console.log("[DEBUG-FLOW] \u2705 ADS_MANAGER_LOADED - Setting up manager");
567
531
  try {
568
532
  const adsRenderingSettings = new google.ima.AdsRenderingSettings();
569
533
  adsRenderingSettings.enablePreloading = true;
570
534
  adsManager = evt.getAdsManager(video, adsRenderingSettings);
571
535
  const AdEvent = google.ima.AdEvent.Type;
572
536
  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
- });
583
537
  adsManager.addEventListener(
584
538
  AdErrorEvent.AD_ERROR,
585
539
  (errorEvent) => {
@@ -596,7 +550,6 @@ function createImaController(video, options) {
596
550
  if (adContainerEl) {
597
551
  adContainerEl.style.pointerEvents = "none";
598
552
  adContainerEl.style.display = "none";
599
- console.log("[DEBUG-LAYER] \u274C Ad container HIDDEN (error)");
600
553
  }
601
554
  }, 300);
602
555
  }
@@ -628,7 +581,6 @@ function createImaController(video, options) {
628
581
  adsManager.addEventListener(
629
582
  AdEvent.CONTENT_PAUSE_REQUESTED,
630
583
  () => {
631
- console.log("[DEBUG-FLOW] \u{1F3AF} CONTENT_PAUSE_REQUESTED - Ad request accepted");
632
584
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
633
585
  video.pause();
634
586
  }
@@ -638,15 +590,11 @@ function createImaController(video, options) {
638
590
  }
639
591
  );
640
592
  adsManager.addEventListener(AdEvent.STARTED, () => {
641
- console.log("[DEBUG-FLOW] \u25B6\uFE0F STARTED - Ad playing now");
642
593
  setAdPlayingFlag(true);
643
594
  hideContentVideo();
644
595
  if (adVideoElement) {
645
596
  adVideoElement.volume = originalMutedState ? 0 : originalVolume;
646
597
  adVideoElement.muted = originalMutedState;
647
- console.log(
648
- `[DEBUG-AUDIO] \u{1F50A} Ad audio set | volume=${adVideoElement.volume}, muted=${adVideoElement.muted}`
649
- );
650
598
  }
651
599
  if (adContainerEl) {
652
600
  adContainerEl.style.pointerEvents = "auto";
@@ -659,15 +607,12 @@ function createImaController(video, options) {
659
607
  adsManager.addEventListener(
660
608
  AdEvent.CONTENT_RESUME_REQUESTED,
661
609
  () => {
662
- console.log("[DEBUG-FLOW] \u23F8\uFE0F CONTENT_RESUME - Single ad done");
663
610
  adPlaying = false;
664
611
  setAdPlayingFlag(false);
665
- console.log("[DEBUG-LAYER] \u26A0\uFE0F Waiting for pod manager (more ads, placeholder, or done)");
666
612
  emit("content_resume");
667
613
  }
668
614
  );
669
615
  adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {
670
- console.log("[DEBUG-FLOW] \u{1F3C1} ALL_ADS_COMPLETED - Pod finished");
671
616
  adPlaying = false;
672
617
  setAdPlayingFlag(false);
673
618
  if (adContainerEl) {
@@ -677,19 +622,16 @@ function createImaController(video, options) {
677
622
  if (adContainerEl) {
678
623
  adContainerEl.style.pointerEvents = "none";
679
624
  adContainerEl.style.display = "none";
680
- console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (pod done)");
681
625
  }
682
626
  }, 300);
683
627
  }
684
628
  showContentVideo();
685
629
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds) && video.paused) {
686
- video.play().catch((e) => {
687
- console.warn("[DEBUG-ERROR] Failed to resume video:", e);
630
+ video.play().catch(() => {
688
631
  });
689
632
  }
690
633
  emit("all_ads_completed");
691
634
  });
692
- console.log("[IMA] Ads manager event listeners attached");
693
635
  if (adsLoadedResolve) {
694
636
  adsLoadedResolve();
695
637
  adsLoadedResolve = void 0;
@@ -784,9 +726,7 @@ function createImaController(video, options) {
784
726
  }
785
727
  const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
786
728
  preloadedVast.set(vastTagUrl, xml);
787
- console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
788
- }).catch((error) => {
789
- console.warn("[IMA] Failed to preload VAST response:", error);
729
+ }).catch(() => {
790
730
  preloadedVast.delete(vastTagUrl);
791
731
  }).finally(() => {
792
732
  preloadingVast.delete(vastTagUrl);
@@ -799,7 +739,6 @@ function createImaController(video, options) {
799
739
  },
800
740
  async play() {
801
741
  var _a, _b;
802
- console.log("[DEBUG-FLOW] \u25B6\uFE0F play() - Starting ad playback");
803
742
  if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
804
743
  return Promise.reject(new Error("IMA SDK not available"));
805
744
  }
@@ -815,19 +754,15 @@ function createImaController(video, options) {
815
754
  if (adVideoElement) {
816
755
  adVideoElement.volume = adVolume;
817
756
  adVideoElement.muted = originalMutedState;
818
- console.log(
819
- `[DEBUG-AUDIO] \u{1F50A} Pre-start ad audio | volume=${adVolume}, muted=${originalMutedState}`
820
- );
821
757
  }
822
758
  try {
823
759
  adsManager.setVolume(adVolume);
824
- } catch (error) {
825
- console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
760
+ } catch {
826
761
  }
827
762
  adsManager.start();
828
763
  return Promise.resolve();
829
764
  } catch (error) {
830
- console.error("[DEBUG-ERROR] \u274C Error starting ad:", error);
765
+ console.error("[IMA] \u274C Error starting ad:", error);
831
766
  adPlaying = false;
832
767
  setAdPlayingFlag(false);
833
768
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -839,7 +774,6 @@ function createImaController(video, options) {
839
774
  },
840
775
  async stop() {
841
776
  var _a;
842
- console.log("[DEBUG-FLOW] \u23F9\uFE0F stop() - Stopping ad playback");
843
777
  adPlaying = false;
844
778
  setAdPlayingFlag(false);
845
779
  if (adContainerEl) {
@@ -849,7 +783,6 @@ function createImaController(video, options) {
849
783
  if (adContainerEl) {
850
784
  adContainerEl.style.pointerEvents = "none";
851
785
  adContainerEl.style.display = "none";
852
- console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (stop)");
853
786
  }
854
787
  }, 300);
855
788
  }
@@ -919,9 +852,6 @@ function createImaController(video, options) {
919
852
  },
920
853
  updateOriginalMutedState(muted, volume) {
921
854
  const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
922
- console.log(
923
- `[DEBUG-AUDIO] \u{1F4BE} Saved original state | muted: ${originalMutedState}->${muted}, volume: ${originalVolume}->${nextVolume}`
924
- );
925
855
  originalMutedState = muted;
926
856
  originalVolume = nextVolume;
927
857
  },
@@ -936,15 +866,11 @@ function createImaController(video, options) {
936
866
  if (adVideoElement && adPlaying) {
937
867
  adVideoElement.volume = clampedVolume;
938
868
  adVideoElement.muted = clampedVolume === 0;
939
- console.log(
940
- `[DEBUG-AUDIO] \u{1F50A} Ad volume changed | volume=${clampedVolume}, muted=${clampedVolume === 0}`
941
- );
942
869
  }
943
870
  if (adsManager && adPlaying) {
944
871
  try {
945
872
  adsManager.setVolume(clampedVolume);
946
- } catch (error) {
947
- console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
873
+ } catch {
948
874
  }
949
875
  }
950
876
  },
@@ -2162,6 +2088,7 @@ var StormcloudVideoPlayer = class {
2162
2088
  this.fetchedAdDurations = /* @__PURE__ */ new Map();
2163
2089
  this.targetAdBreakDurationMs = null;
2164
2090
  this.isAdaptiveMode = false;
2091
+ this.failedVastUrls = /* @__PURE__ */ new Set();
2165
2092
  initializePolyfills();
2166
2093
  const browserOverrides = getBrowserConfigOverrides();
2167
2094
  this.config = { ...config, ...browserOverrides };
@@ -2434,51 +2361,37 @@ var StormcloudVideoPlayer = class {
2434
2361
  });
2435
2362
  this.ima.on("ad_error", (errorPayload) => {
2436
2363
  const remaining = this.getRemainingAdMs();
2437
- console.error(
2438
- `[DEBUG-POD] \u274C ad_error event | inBreak=${this.inAdBreak}, queue=${this.adPodQueue.length}, remaining=${remaining}ms`,
2439
- errorPayload ? `
2440
- Error details: ${JSON.stringify(errorPayload)}` : ""
2441
- );
2364
+ console.error("[AD-ERROR] Ad playback failed", errorPayload || "");
2442
2365
  if (this.inAdBreak) {
2443
2366
  if (remaining > 500 && this.adPodQueue.length > 0) {
2444
2367
  const nextPreloaded = this.findNextPreloadedAd();
2445
2368
  if (nextPreloaded) {
2446
2369
  this.currentAdIndex++;
2447
- console.log(
2448
- `[DEBUG-POD] \u27A1\uFE0F Trying next ad after error (${this.currentAdIndex}/${this.totalAdsInBreak})`
2449
- );
2450
2370
  this.playSingleAd(nextPreloaded).catch(() => {
2451
2371
  this.handleAdFailure();
2452
2372
  });
2453
2373
  } else {
2454
- console.log("[DEBUG-POD] \u26A0\uFE0F No more preloaded ads - calling handleAdFailure");
2455
2374
  this.handleAdFailure();
2456
2375
  }
2457
2376
  } else {
2458
- console.log("[DEBUG-POD] \u26A0\uFE0F No more ads or time - calling handleAdFailure");
2459
2377
  this.handleAdFailure();
2460
2378
  }
2461
2379
  } else {
2462
- console.log("[DEBUG-POD] \u26A0\uFE0F Error before ad break established");
2463
2380
  this.handleAdFailure();
2464
2381
  }
2465
2382
  });
2466
2383
  this.ima.on("content_pause", () => {
2467
- console.log(`[DEBUG-POD] \u{1F3AF} content_pause (AD STARTING!) | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}`);
2468
2384
  this.clearAdFailsafeTimer();
2469
2385
  this.clearAdRequestWatchdog();
2470
2386
  this.activeAdRequestToken = null;
2471
2387
  this.showAds = true;
2472
- console.log("[DEBUG-LAYER] \u{1F3AC} Layers: Main=hidden, Ad=visible, Placeholder=no");
2473
2388
  });
2474
2389
  this.ima.on("content_resume", () => {
2475
- console.log(`[DEBUG-POD] \u23F8\uFE0F content_resume | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}, remaining=${this.getRemainingAdMs()}ms`);
2476
2390
  this.clearAdFailsafeTimer();
2477
2391
  this.clearAdRequestWatchdog();
2478
2392
  this.activeAdRequestToken = null;
2479
2393
  this.showAds = false;
2480
2394
  if (!this.inAdBreak) {
2481
- console.warn("[DEBUG-POD] \u26A0\uFE0F Not in ad break - shouldn't happen");
2482
2395
  return;
2483
2396
  }
2484
2397
  const remaining = this.getRemainingAdMs();
@@ -2486,17 +2399,13 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2486
2399
  const nextPreloaded = this.findNextPreloadedAd();
2487
2400
  if (nextPreloaded) {
2488
2401
  this.currentAdIndex++;
2489
- console.log(`[DEBUG-POD] \u27A1\uFE0F Playing next ad ${this.currentAdIndex}/${this.totalAdsInBreak} (preloaded)`);
2490
2402
  this.playSingleAd(nextPreloaded).catch(() => {
2491
- console.error("[DEBUG-POD] \u274C Failed to play next ad");
2492
2403
  this.handleAdPodComplete();
2493
2404
  });
2494
2405
  } else {
2495
- console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads - ending pod");
2496
2406
  this.handleAdPodComplete();
2497
2407
  }
2498
2408
  } else {
2499
- console.log("[DEBUG-POD] \u2705 Pod complete (no more ads or time expired)");
2500
2409
  this.handleAdPodComplete();
2501
2410
  }
2502
2411
  });
@@ -2650,9 +2559,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2650
2559
  }
2651
2560
  if (marker.type === "start") {
2652
2561
  if (this.inAdBreak) {
2653
- console.log(
2654
- `[DEBUG-POD] \u26A0\uFE0F SCTE-35 start marker ignored - already in ad break (currentTime: ${this.video.currentTime})`
2655
- );
2656
2562
  return;
2657
2563
  }
2658
2564
  this.inAdBreak = true;
@@ -2721,9 +2627,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2721
2627
  return;
2722
2628
  }
2723
2629
  if (marker.type === "progress" && this.inAdBreak) {
2724
- console.log(
2725
- `[DEBUG-POD] \u{1F4CA} SCTE-35 progress marker (currentTime: ${this.video.currentTime})`
2726
- );
2727
2630
  if (marker.durationSeconds != null) {
2728
2631
  this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
2729
2632
  }
@@ -2736,7 +2639,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2736
2639
  this.scheduleAdStopCountdown(remainingMs);
2737
2640
  }
2738
2641
  if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null) {
2739
- console.log("[DEBUG-POD] \u{1F4CA} Progress marker: no ad playing, attempting to start");
2740
2642
  const scheduled = this.findCurrentOrNextBreak(
2741
2643
  this.video.currentTime * 1e3
2742
2644
  );
@@ -2748,24 +2650,16 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2748
2650
  this.playSingleAd(first).catch(() => {
2749
2651
  });
2750
2652
  }
2751
- } else {
2752
- console.log(
2753
- `[DEBUG-POD] \u{1F4CA} Progress marker: ad playing or request active (playing=${this.ima.isAdPlaying()}, token=${this.activeAdRequestToken})`
2754
- );
2755
2653
  }
2756
2654
  return;
2757
2655
  }
2758
2656
  if (marker.type === "end") {
2759
- console.log(
2760
- `[DEBUG-POD] \u{1F3C1} SCTE-35 end marker received (currentTime: ${this.video.currentTime})`
2761
- );
2762
2657
  this.inAdBreak = false;
2763
2658
  this.expectedAdBreakDurationMs = void 0;
2764
2659
  this.currentAdBreakStartWallClockMs = void 0;
2765
2660
  this.clearAdStartTimer();
2766
2661
  this.clearAdStopTimer();
2767
2662
  if (this.ima.isAdPlaying()) {
2768
- console.log("[DEBUG-POD] \u{1F6D1} Stopping ad due to SCTE-35 end marker");
2769
2663
  this.ima.stop().catch(() => {
2770
2664
  });
2771
2665
  }
@@ -3166,21 +3060,17 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3166
3060
  } else if (tags && tags.length > 0) {
3167
3061
  vastTagUrls = tags;
3168
3062
  } else {
3169
- console.log("[DEBUG-POD] \u26A0\uFE0F No VAST tag available");
3170
3063
  return;
3171
3064
  }
3172
3065
  if (vastTagUrls.length > 0) {
3173
- console.log(`[DEBUG-POD] \u{1F3AF} Starting ad break with ${vastTagUrls.length} ads`);
3174
3066
  this.adPodAllUrls = [...vastTagUrls];
3175
3067
  this.preloadingAdUrls.clear();
3176
3068
  this.vastToMediaUrlMap.clear();
3177
3069
  this.preloadedMediaUrls.clear();
3178
3070
  this.preloadingMediaUrls.clear();
3071
+ this.failedVastUrls.clear();
3179
3072
  const currentMuted = this.video.muted;
3180
3073
  const currentVolume = this.video.volume;
3181
- console.log(
3182
- `[DEBUG-AUDIO] \u{1F4BE} Capturing ORIGINAL state (once) | muted=${currentMuted}, volume=${currentVolume}`
3183
- );
3184
3074
  this.ima.updateOriginalMutedState(currentMuted, currentVolume);
3185
3075
  this.inAdBreak = true;
3186
3076
  this.currentAdIndex = 0;
@@ -3241,40 +3131,27 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3241
3131
  }
3242
3132
  async playAdPod() {
3243
3133
  if (this.adPodQueue.length === 0) {
3244
- console.log("[DEBUG-POD] \u26A0\uFE0F No ads in pod");
3245
3134
  return;
3246
3135
  }
3247
3136
  const waitTime = this.isAdaptiveMode ? 50 : 500;
3248
3137
  await new Promise((resolve) => setTimeout(resolve, waitTime));
3249
- if (this.config.debugAdTiming) {
3250
- console.log(
3251
- `[DEBUG-POD] \u{1F50D} Looking for preloaded ad in queue of ${this.adPodQueue.length} URLs`
3252
- );
3253
- }
3254
3138
  const firstPreloaded = this.findNextPreloadedAd();
3255
3139
  if (!firstPreloaded) {
3256
- console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads found, trying first ad from queue");
3257
3140
  const firstAd = this.adPodQueue.shift();
3258
3141
  if (firstAd) {
3259
3142
  this.currentAdIndex++;
3260
- console.log(`[DEBUG-POD] \u{1F3AC} Attempting to play first ad (not preloaded): ${firstAd.substring(0, 60)}...`);
3261
3143
  try {
3262
3144
  await this.playSingleAd(firstAd);
3263
3145
  } catch (error) {
3264
- console.log("[DEBUG-POD] \u26A0\uFE0F First ad failed, error handler will retry");
3265
3146
  return;
3266
3147
  }
3267
- } else {
3268
- console.log("[DEBUG-POD] \u274C No ads available in queue");
3269
3148
  }
3270
3149
  return;
3271
3150
  }
3272
3151
  this.currentAdIndex++;
3273
- console.log(`[DEBUG-POD] \u{1F680} Starting pod with ad ${this.currentAdIndex}/${this.totalAdsInBreak}`);
3274
3152
  try {
3275
3153
  await this.playSingleAd(firstPreloaded);
3276
3154
  } catch (error) {
3277
- console.log("[DEBUG-POD] \u26A0\uFE0F First ad failed, error handler will retry");
3278
3155
  }
3279
3156
  }
3280
3157
  findCurrentOrNextBreak(nowMs) {
@@ -3354,15 +3231,9 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3354
3231
  const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
3355
3232
  const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
3356
3233
  if (shouldExtendAdBreak) {
3357
- console.log(
3358
- `[DEBUG-POD] \u23F3 Extending ad break | elapsed=${elapsedSinceStartMs}ms, expected=${expectedDurationMs}ms, overrun=${overrunMs}ms`
3359
- );
3360
3234
  this.scheduleAdStopCountdown(checkIntervalMs);
3361
3235
  return;
3362
3236
  }
3363
- console.log(
3364
- `[DEBUG-POD] \u23F1\uFE0F Ad break duration expired | elapsed=${elapsedSinceStartMs}ms, expected=${expectedDurationMs}ms`
3365
- );
3366
3237
  if (adPlaying) {
3367
3238
  this.ima.stop().catch(() => {
3368
3239
  });
@@ -3395,42 +3266,29 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3395
3266
  this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;
3396
3267
  }
3397
3268
  async playSingleAd(vastTagUrl) {
3398
- console.log(`[DEBUG-POD] \u{1F3AC} playSingleAd | url=${vastTagUrl.substring(0, 60)}...`);
3399
3269
  if (this.ima.isAdPlaying()) {
3400
- console.warn("[DEBUG-POD] \u26A0\uFE0F Ad already playing - skipping request");
3270
+ return;
3271
+ }
3272
+ if (this.failedVastUrls.has(vastTagUrl)) {
3273
+ console.warn("[AD-ERROR] Skipping already-failed VAST URL:", vastTagUrl.substring(0, 60));
3274
+ this.handleAdFailure();
3401
3275
  return;
3402
3276
  }
3403
3277
  const requestToken = ++this.adRequestTokenCounter;
3404
- const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
3405
3278
  this.activeAdRequestToken = requestToken;
3406
- console.log(`[DEBUG-POD] \u{1F4DD} Request token=${requestToken}, preloaded=${wasPreloaded}`);
3407
3279
  this.startAdRequestWatchdog(requestToken);
3408
3280
  try {
3409
- console.log(`[DEBUG-POD] \u{1F4E1} Calling ima.requestAds() for token=${requestToken}...`);
3410
3281
  await this.ima.requestAds(vastTagUrl);
3411
- console.log(`[DEBUG-POD] \u2705 ima.requestAds() completed successfully`);
3412
3282
  this.clearAdRequestWatchdog();
3413
3283
  if (this.activeAdRequestToken !== requestToken) {
3414
- console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after requestAds (stale request)`);
3415
3284
  return;
3416
3285
  }
3417
- console.log(`[DEBUG-POD] \u{1F4FA} Calling ima.play() to start ad playback...`);
3418
- console.log(`[DEBUG-POD] \u{1F4CA} Video element state: paused=${this.video.paused}, muted=${this.video.muted}, readyState=${this.video.readyState}`);
3419
3286
  try {
3420
3287
  this.startAdFailsafeTimer(requestToken);
3421
3288
  await this.ima.play();
3422
- if (this.activeAdRequestToken === requestToken) {
3423
- console.log(`[DEBUG-POD] \u2705 Ad play initiated successfully (token=${requestToken})`);
3424
- } else {
3425
- console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after play (stale request)`);
3426
- }
3427
3289
  } catch (playError) {
3428
- console.error(
3429
- "[DEBUG-POD] \u274C Failed to play ad:",
3430
- playError instanceof Error ? playError.message : playError,
3431
- "\nFull error:",
3432
- playError
3433
- );
3290
+ console.error("[AD-ERROR] Failed to play ad:", playError);
3291
+ this.failedVastUrls.add(vastTagUrl);
3434
3292
  this.clearAdFailsafeTimer();
3435
3293
  if (this.activeAdRequestToken === requestToken) {
3436
3294
  this.activeAdRequestToken = null;
@@ -3439,7 +3297,8 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3439
3297
  return;
3440
3298
  }
3441
3299
  } catch (error) {
3442
- console.error("[DEBUG-POD] \u274C Ad request failed:", error == null ? void 0 : error.message);
3300
+ console.error("[AD-ERROR] Ad request failed:", error == null ? void 0 : error.message);
3301
+ this.failedVastUrls.add(vastTagUrl);
3443
3302
  this.clearAdRequestWatchdog();
3444
3303
  this.clearAdFailsafeTimer();
3445
3304
  if (this.activeAdRequestToken === requestToken) {
@@ -3450,7 +3309,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3450
3309
  }
3451
3310
  handleAdPodComplete() {
3452
3311
  var _a;
3453
- console.log("[DEBUG-POD] \u{1F3C1} handleAdPodComplete - Ending ad break, restoring content");
3454
3312
  this.clearAdRequestWatchdog();
3455
3313
  this.clearAdFailsafeTimer();
3456
3314
  this.activeAdRequestToken = null;
@@ -3472,10 +3330,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3472
3330
  });
3473
3331
  const restoredMuted = this.ima.getOriginalMutedState();
3474
3332
  const restoredVolume = this.ima.getOriginalVolume();
3475
- console.log(
3476
- `[DEBUG-AUDIO] \u{1F50A} Audio restored by IMA | muted=${restoredMuted}, volume=${restoredVolume}`
3477
- );
3478
- console.log("[DEBUG-LAYER] \u{1F3AC} Layers: Main=visible, Ad=hidden, Placeholder=no");
3479
3333
  if (this.video.muted !== restoredMuted) {
3480
3334
  this.video.muted = restoredMuted;
3481
3335
  }
@@ -3483,16 +3337,14 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3483
3337
  this.video.volume = restoredVolume;
3484
3338
  }
3485
3339
  if (!this.shouldContinueLiveStreamDuringAds() && this.video.paused) {
3486
- console.log("[DEBUG-FLOW] \u25B6\uFE0F Resuming main video playback");
3487
- (_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
3488
- console.error("[DEBUG-ERROR] Failed to resume video:", error);
3340
+ (_a = this.video.play()) == null ? void 0 : _a.catch(() => {
3489
3341
  });
3490
3342
  }
3491
3343
  }
3492
3344
  handleAdFailure() {
3493
- console.log("[DEBUG-POD] \u274C handleAdFailure - skipping to next ad or ending break");
3494
3345
  const remaining = this.getRemainingAdMs();
3495
- if (remaining > 500 && this.adPodQueue.length > 0) {
3346
+ const availableAds = this.adPodQueue.filter((url) => !this.failedVastUrls.has(url)).length;
3347
+ if (remaining > 500 && availableAds > 0) {
3496
3348
  if (this.isAdaptiveMode && this.currentAdIndex <= 1) {
3497
3349
  console.log("[ADAPTIVE-POD] \u23F3 First ad failed, waiting for sequential preload to catch up...");
3498
3350
  setTimeout(() => {
@@ -3503,14 +3355,13 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3503
3355
  const nextPreloaded = this.findNextPreloadedAd();
3504
3356
  if (nextPreloaded) {
3505
3357
  this.currentAdIndex++;
3506
- console.log(`[DEBUG-POD] \u27A1\uFE0F Trying next ad after failure (${this.currentAdIndex}/${this.totalAdsInBreak})`);
3507
3358
  this.playSingleAd(nextPreloaded).catch(() => {
3508
3359
  this.handleAdPodComplete();
3509
3360
  });
3510
3361
  return;
3511
3362
  }
3512
3363
  }
3513
- console.log("[DEBUG-POD] \u23F9\uFE0F Ending ad break after failure");
3364
+ console.error("[AD-ERROR] All ads failed or time expired. Failed URLs:", this.failedVastUrls.size);
3514
3365
  this.handleAdPodComplete();
3515
3366
  }
3516
3367
  tryNextAdWithRetry(retryCount) {
@@ -3963,37 +3814,21 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3963
3814
  }
3964
3815
  findNextPreloadedAd() {
3965
3816
  var _a, _b, _c;
3966
- if (this.config.debugAdTiming) {
3967
- console.log(
3968
- `[DEBUG-POD] \u{1F50E} Searching for preloaded ad in queue (${this.adPodQueue.length} URLs, ${this.preloadedMediaUrls.size} media preloaded, ${this.vastToMediaUrlMap.size} VAST mappings)`
3969
- );
3970
- }
3971
3817
  for (let i = 0; i < this.adPodQueue.length; i++) {
3972
3818
  const vastTagUrl = this.adPodQueue[i];
3973
3819
  if (!vastTagUrl) continue;
3820
+ if (this.failedVastUrls.has(vastTagUrl)) {
3821
+ console.warn("[AD-ERROR] Skipping failed URL in queue");
3822
+ continue;
3823
+ }
3974
3824
  const hasImaPreload = (_c = (_b = (_a = this.ima).hasPreloadedAd) == null ? void 0 : _b.call(_a, vastTagUrl)) != null ? _c : false;
3975
3825
  const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
3976
3826
  const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;
3977
- if (this.config.debugAdTiming) {
3978
- console.log(
3979
- `[DEBUG-POD] Ad ${i}: IMA=${hasImaPreload}, Media=${hasMediaPreload}, MediaURLs=${(mediaUrls == null ? void 0 : mediaUrls.length) || 0}, URL=${vastTagUrl.substring(0, 60)}...`
3980
- );
3981
- }
3982
3827
  if (hasImaPreload || hasMediaPreload) {
3983
- if (this.config.debugAdTiming) {
3984
- console.log(
3985
- `[DEBUG-POD] \u2705 Found preloaded ad at index ${i}`
3986
- );
3987
- }
3988
3828
  this.adPodQueue.splice(0, i + 1);
3989
3829
  return vastTagUrl;
3990
3830
  }
3991
3831
  }
3992
- if (this.config.debugAdTiming) {
3993
- console.log(
3994
- `[DEBUG-POD] \u274C No preloaded ads found in queue`
3995
- );
3996
- }
3997
3832
  return void 0;
3998
3833
  }
3999
3834
  getRemainingAdMs() {