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