stormcloud-video-player 0.2.30 → 0.2.32
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 +387 -102
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +9 -1
- package/lib/index.d.ts +9 -1
- package/lib/index.js +387 -102
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +387 -102
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +9 -1
- package/lib/players/HlsPlayer.cjs +387 -102
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +387 -102
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/ima.cjs +103 -33
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +387 -102
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -212,7 +212,11 @@ function createImaController(video, options) {
|
|
|
212
212
|
}
|
|
213
213
|
function hideContentVideo() {
|
|
214
214
|
if (!contentVideoHidden) {
|
|
215
|
-
video.style.
|
|
215
|
+
video.style.transition = "opacity 0.3s ease-in-out";
|
|
216
|
+
video.style.opacity = "0";
|
|
217
|
+
setTimeout(() => {
|
|
218
|
+
video.style.visibility = "hidden";
|
|
219
|
+
}, 300);
|
|
216
220
|
video.muted = true;
|
|
217
221
|
video.volume = 0;
|
|
218
222
|
contentVideoHidden = true;
|
|
@@ -222,6 +226,9 @@ function createImaController(video, options) {
|
|
|
222
226
|
function showContentVideo() {
|
|
223
227
|
if (contentVideoHidden) {
|
|
224
228
|
video.style.visibility = "visible";
|
|
229
|
+
video.style.transition = "opacity 0.3s ease-in-out";
|
|
230
|
+
video.offsetHeight;
|
|
231
|
+
video.style.opacity = "1";
|
|
225
232
|
video.muted = originalMutedState;
|
|
226
233
|
video.volume = originalVolume;
|
|
227
234
|
contentVideoHidden = false;
|
|
@@ -394,7 +401,9 @@ function createImaController(video, options) {
|
|
|
394
401
|
container.style.justifyContent = "center";
|
|
395
402
|
container.style.pointerEvents = "none";
|
|
396
403
|
container.style.zIndex = "10";
|
|
397
|
-
container.style.backgroundColor = "
|
|
404
|
+
container.style.backgroundColor = "transparent";
|
|
405
|
+
container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
|
|
406
|
+
container.style.opacity = "0";
|
|
398
407
|
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
399
408
|
adContainerEl = container;
|
|
400
409
|
}
|
|
@@ -504,7 +513,9 @@ function createImaController(video, options) {
|
|
|
504
513
|
container.style.justifyContent = "center";
|
|
505
514
|
container.style.pointerEvents = "none";
|
|
506
515
|
container.style.zIndex = "10";
|
|
507
|
-
container.style.backgroundColor = "
|
|
516
|
+
container.style.backgroundColor = "transparent";
|
|
517
|
+
container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
|
|
518
|
+
container.style.opacity = "0";
|
|
508
519
|
if (!video.parentElement) {
|
|
509
520
|
throw new Error("Video element has no parent for ad container");
|
|
510
521
|
}
|
|
@@ -568,13 +579,19 @@ function createImaController(video, options) {
|
|
|
568
579
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
569
580
|
destroyAdsManager();
|
|
570
581
|
adPlaying = false;
|
|
571
|
-
showContentVideo();
|
|
572
582
|
setAdPlayingFlag(false);
|
|
573
583
|
if (adContainerEl) {
|
|
574
|
-
adContainerEl.style.
|
|
575
|
-
adContainerEl.style.
|
|
576
|
-
|
|
584
|
+
adContainerEl.style.opacity = "0";
|
|
585
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
586
|
+
setTimeout(() => {
|
|
587
|
+
if (adContainerEl) {
|
|
588
|
+
adContainerEl.style.pointerEvents = "none";
|
|
589
|
+
adContainerEl.style.display = "none";
|
|
590
|
+
console.log("[IMA] Ad container hidden after error");
|
|
591
|
+
}
|
|
592
|
+
}, 300);
|
|
577
593
|
}
|
|
594
|
+
showContentVideo();
|
|
578
595
|
if (adsLoadedReject) {
|
|
579
596
|
adsLoadedReject(new Error("Ad playback error"));
|
|
580
597
|
adsLoadedReject = void 0;
|
|
@@ -620,6 +637,15 @@ function createImaController(video, options) {
|
|
|
620
637
|
"[IMA] Content video continues in background (Live mode)"
|
|
621
638
|
);
|
|
622
639
|
}
|
|
640
|
+
hideContentVideo();
|
|
641
|
+
if (adContainerEl) {
|
|
642
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
643
|
+
adContainerEl.style.display = "flex";
|
|
644
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
645
|
+
adContainerEl.offsetHeight;
|
|
646
|
+
adContainerEl.style.opacity = "1";
|
|
647
|
+
console.log("[IMA] Ad container shown on content pause");
|
|
648
|
+
}
|
|
623
649
|
adPlaying = true;
|
|
624
650
|
setAdPlayingFlag(true);
|
|
625
651
|
emit("content_pause");
|
|
@@ -639,6 +665,9 @@ function createImaController(video, options) {
|
|
|
639
665
|
if (adContainerEl) {
|
|
640
666
|
adContainerEl.style.pointerEvents = "auto";
|
|
641
667
|
adContainerEl.style.display = "flex";
|
|
668
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
669
|
+
adContainerEl.offsetHeight;
|
|
670
|
+
adContainerEl.style.opacity = "1";
|
|
642
671
|
console.log("[IMA] Ad container now visible");
|
|
643
672
|
}
|
|
644
673
|
});
|
|
@@ -655,12 +684,18 @@ function createImaController(video, options) {
|
|
|
655
684
|
console.log("[IMA] All ads completed - restoring content");
|
|
656
685
|
adPlaying = false;
|
|
657
686
|
setAdPlayingFlag(false);
|
|
658
|
-
showContentVideo();
|
|
659
687
|
if (adContainerEl) {
|
|
660
|
-
adContainerEl.style.
|
|
661
|
-
adContainerEl.style.
|
|
662
|
-
|
|
688
|
+
adContainerEl.style.opacity = "0";
|
|
689
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
690
|
+
setTimeout(() => {
|
|
691
|
+
if (adContainerEl) {
|
|
692
|
+
adContainerEl.style.pointerEvents = "none";
|
|
693
|
+
adContainerEl.style.display = "none";
|
|
694
|
+
console.log("[IMA] Ad container hidden");
|
|
695
|
+
}
|
|
696
|
+
}, 300);
|
|
663
697
|
}
|
|
698
|
+
showContentVideo();
|
|
664
699
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds) && video.paused) {
|
|
665
700
|
console.log("[IMA] Resuming content video playback");
|
|
666
701
|
video.play().catch((e) => {
|
|
@@ -678,13 +713,21 @@ function createImaController(video, options) {
|
|
|
678
713
|
} catch (e) {
|
|
679
714
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
680
715
|
adPlaying = false;
|
|
681
|
-
showContentVideo();
|
|
682
716
|
setAdPlayingFlag(false);
|
|
683
717
|
if (adContainerEl) {
|
|
684
|
-
adContainerEl.style.
|
|
685
|
-
adContainerEl.style.
|
|
686
|
-
|
|
718
|
+
adContainerEl.style.opacity = "0";
|
|
719
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
720
|
+
setTimeout(() => {
|
|
721
|
+
if (adContainerEl) {
|
|
722
|
+
adContainerEl.style.pointerEvents = "none";
|
|
723
|
+
adContainerEl.style.display = "none";
|
|
724
|
+
console.log(
|
|
725
|
+
"[IMA] Ad container hidden after setup error"
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
}, 300);
|
|
687
729
|
}
|
|
730
|
+
showContentVideo();
|
|
688
731
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
689
732
|
if (video.paused) {
|
|
690
733
|
console.log(
|
|
@@ -709,13 +752,19 @@ function createImaController(video, options) {
|
|
|
709
752
|
(adErrorEvent) => {
|
|
710
753
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
711
754
|
adPlaying = false;
|
|
712
|
-
showContentVideo();
|
|
713
755
|
setAdPlayingFlag(false);
|
|
714
756
|
if (adContainerEl) {
|
|
715
|
-
adContainerEl.style.
|
|
716
|
-
adContainerEl.style.
|
|
717
|
-
|
|
757
|
+
adContainerEl.style.opacity = "0";
|
|
758
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
759
|
+
setTimeout(() => {
|
|
760
|
+
if (adContainerEl) {
|
|
761
|
+
adContainerEl.style.pointerEvents = "none";
|
|
762
|
+
adContainerEl.style.display = "none";
|
|
763
|
+
console.log("[IMA] Ad container hidden after loader error");
|
|
764
|
+
}
|
|
765
|
+
}, 300);
|
|
718
766
|
}
|
|
767
|
+
showContentVideo();
|
|
719
768
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
720
769
|
if (video.paused) {
|
|
721
770
|
console.log("[IMA] Resuming paused video after loader error");
|
|
@@ -821,12 +870,18 @@ function createImaController(video, options) {
|
|
|
821
870
|
console.log("[IMA] Stopping ad playback");
|
|
822
871
|
adPlaying = false;
|
|
823
872
|
setAdPlayingFlag(false);
|
|
824
|
-
showContentVideo();
|
|
825
873
|
if (adContainerEl) {
|
|
826
|
-
adContainerEl.style.
|
|
827
|
-
adContainerEl.style.
|
|
828
|
-
|
|
874
|
+
adContainerEl.style.opacity = "0";
|
|
875
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
876
|
+
setTimeout(() => {
|
|
877
|
+
if (adContainerEl) {
|
|
878
|
+
adContainerEl.style.pointerEvents = "none";
|
|
879
|
+
adContainerEl.style.display = "none";
|
|
880
|
+
console.log("[IMA] Ad container hidden after stop");
|
|
881
|
+
}
|
|
882
|
+
}, 300);
|
|
829
883
|
}
|
|
884
|
+
showContentVideo();
|
|
830
885
|
try {
|
|
831
886
|
(_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
|
|
832
887
|
} catch {
|
|
@@ -837,23 +892,29 @@ function createImaController(video, options) {
|
|
|
837
892
|
var _a;
|
|
838
893
|
destroyAdsManager();
|
|
839
894
|
adPlaying = false;
|
|
840
|
-
showContentVideo();
|
|
841
895
|
setAdPlayingFlag(false);
|
|
842
896
|
if (adContainerEl) {
|
|
843
|
-
adContainerEl.style.
|
|
844
|
-
adContainerEl.style.
|
|
897
|
+
adContainerEl.style.opacity = "0";
|
|
898
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
899
|
+
setTimeout(() => {
|
|
900
|
+
if (adContainerEl) {
|
|
901
|
+
adContainerEl.style.pointerEvents = "none";
|
|
902
|
+
adContainerEl.style.display = "none";
|
|
903
|
+
if (adContainerEl.parentElement) {
|
|
904
|
+
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
905
|
+
}
|
|
906
|
+
adContainerEl = void 0;
|
|
907
|
+
adVideoElement = void 0;
|
|
908
|
+
}
|
|
909
|
+
}, 300);
|
|
845
910
|
}
|
|
911
|
+
showContentVideo();
|
|
846
912
|
try {
|
|
847
913
|
(_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
|
|
848
914
|
} catch {
|
|
849
915
|
}
|
|
850
|
-
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
851
|
-
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
852
|
-
}
|
|
853
|
-
adContainerEl = void 0;
|
|
854
916
|
adDisplayContainer = void 0;
|
|
855
917
|
adsLoader = void 0;
|
|
856
|
-
adVideoElement = void 0;
|
|
857
918
|
contentVideoHidden = false;
|
|
858
919
|
preloadedVast.clear();
|
|
859
920
|
preloadingVast.clear();
|
|
@@ -933,13 +994,22 @@ function createImaController(video, options) {
|
|
|
933
994
|
ensurePlaceholderContainer();
|
|
934
995
|
if (adContainerEl) {
|
|
935
996
|
adContainerEl.style.display = "flex";
|
|
997
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
998
|
+
adContainerEl.offsetHeight;
|
|
999
|
+
adContainerEl.style.opacity = "1";
|
|
936
1000
|
adContainerEl.style.pointerEvents = "auto";
|
|
937
1001
|
}
|
|
938
1002
|
},
|
|
939
1003
|
hidePlaceholder() {
|
|
940
1004
|
if (adContainerEl) {
|
|
941
|
-
adContainerEl.style.
|
|
942
|
-
adContainerEl.style.
|
|
1005
|
+
adContainerEl.style.opacity = "0";
|
|
1006
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
1007
|
+
setTimeout(() => {
|
|
1008
|
+
if (adContainerEl) {
|
|
1009
|
+
adContainerEl.style.display = "none";
|
|
1010
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1011
|
+
}
|
|
1012
|
+
}, 300);
|
|
943
1013
|
}
|
|
944
1014
|
}
|
|
945
1015
|
};
|
|
@@ -2110,6 +2180,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2110
2180
|
this.hasInitialBufferCompleted = false;
|
|
2111
2181
|
this.adPodAllUrls = [];
|
|
2112
2182
|
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
2183
|
+
this.vastToMediaUrlMap = /* @__PURE__ */ new Map();
|
|
2184
|
+
this.preloadedMediaUrls = /* @__PURE__ */ new Set();
|
|
2185
|
+
this.preloadingMediaUrls = /* @__PURE__ */ new Set();
|
|
2113
2186
|
initializePolyfills();
|
|
2114
2187
|
const browserOverrides = getBrowserConfigOverrides();
|
|
2115
2188
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2382,27 +2455,44 @@ var StormcloudVideoPlayer = class {
|
|
|
2382
2455
|
});
|
|
2383
2456
|
this.ima.on("ad_error", () => {
|
|
2384
2457
|
if (this.config.debugAdTiming) {
|
|
2385
|
-
console.log("[StormcloudVideoPlayer] IMA ad_error event received"
|
|
2458
|
+
console.log("[StormcloudVideoPlayer] IMA ad_error event received", {
|
|
2459
|
+
showAds: this.showAds,
|
|
2460
|
+
inAdBreak: this.inAdBreak,
|
|
2461
|
+
remainingAds: this.adPodQueue.length
|
|
2462
|
+
});
|
|
2386
2463
|
}
|
|
2387
|
-
if (this.
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2464
|
+
if (this.inAdBreak) {
|
|
2465
|
+
const remaining = this.getRemainingAdMs();
|
|
2466
|
+
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2467
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2468
|
+
if (nextPreloaded) {
|
|
2392
2469
|
this.currentAdIndex++;
|
|
2393
|
-
this.
|
|
2470
|
+
if (this.config.debugAdTiming) {
|
|
2471
|
+
console.log(
|
|
2472
|
+
`[StormcloudVideoPlayer] Skipping to next preloaded ad after error`
|
|
2473
|
+
);
|
|
2474
|
+
}
|
|
2475
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2476
|
+
this.handleAdFailure();
|
|
2394
2477
|
});
|
|
2395
2478
|
} else {
|
|
2479
|
+
if (this.config.debugAdTiming) {
|
|
2480
|
+
console.log(
|
|
2481
|
+
"[StormcloudVideoPlayer] No preloaded ads available, ending ad break"
|
|
2482
|
+
);
|
|
2483
|
+
}
|
|
2396
2484
|
this.handleAdFailure();
|
|
2397
2485
|
}
|
|
2398
2486
|
} else {
|
|
2399
|
-
if (this.config.debugAdTiming) {
|
|
2400
|
-
console.log(
|
|
2401
|
-
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2402
|
-
);
|
|
2403
|
-
}
|
|
2404
2487
|
this.handleAdFailure();
|
|
2405
2488
|
}
|
|
2489
|
+
} else {
|
|
2490
|
+
if (this.config.debugAdTiming) {
|
|
2491
|
+
console.log(
|
|
2492
|
+
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2495
|
+
this.handleAdFailure();
|
|
2406
2496
|
}
|
|
2407
2497
|
});
|
|
2408
2498
|
this.ima.on("content_pause", () => {
|
|
@@ -2433,22 +2523,31 @@ var StormcloudVideoPlayer = class {
|
|
|
2433
2523
|
}
|
|
2434
2524
|
const remaining = this.getRemainingAdMs();
|
|
2435
2525
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2436
|
-
const
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
console.log(
|
|
2441
|
-
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
2442
|
-
);
|
|
2443
|
-
}
|
|
2444
|
-
this.playSingleAd(next).catch(() => {
|
|
2526
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2527
|
+
if (nextPreloaded) {
|
|
2528
|
+
this.currentAdIndex++;
|
|
2529
|
+
this.enforceAdHoldState();
|
|
2445
2530
|
if (this.config.debugAdTiming) {
|
|
2446
|
-
console.
|
|
2447
|
-
|
|
2531
|
+
console.log(
|
|
2532
|
+
`[StormcloudVideoPlayer] Playing next preloaded ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak})`
|
|
2533
|
+
);
|
|
2534
|
+
}
|
|
2535
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2536
|
+
if (this.config.debugAdTiming) {
|
|
2537
|
+
console.error(
|
|
2538
|
+
"[StormcloudVideoPlayer] Failed to play next ad in pod"
|
|
2539
|
+
);
|
|
2540
|
+
}
|
|
2541
|
+
this.handleAdPodComplete();
|
|
2542
|
+
});
|
|
2543
|
+
} else {
|
|
2544
|
+
if (this.config.debugAdTiming) {
|
|
2545
|
+
console.log(
|
|
2546
|
+
"[StormcloudVideoPlayer] No preloaded ads available - completing ad break"
|
|
2448
2547
|
);
|
|
2449
2548
|
}
|
|
2450
2549
|
this.handleAdPodComplete();
|
|
2451
|
-
}
|
|
2550
|
+
}
|
|
2452
2551
|
} else {
|
|
2453
2552
|
if (this.config.debugAdTiming) {
|
|
2454
2553
|
console.log(
|
|
@@ -2693,6 +2792,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2693
2792
|
const first = tags[0];
|
|
2694
2793
|
const rest = tags.slice(1);
|
|
2695
2794
|
this.adPodQueue = rest;
|
|
2795
|
+
if (!this.showAds) {
|
|
2796
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2797
|
+
}
|
|
2696
2798
|
this.playSingleAd(first).catch(() => {
|
|
2697
2799
|
});
|
|
2698
2800
|
}
|
|
@@ -3049,19 +3151,38 @@ var StormcloudVideoPlayer = class {
|
|
|
3049
3151
|
if (vastTagUrls.length > 0) {
|
|
3050
3152
|
this.adPodAllUrls = [...vastTagUrls];
|
|
3051
3153
|
this.preloadingAdUrls.clear();
|
|
3154
|
+
this.vastToMediaUrlMap.clear();
|
|
3155
|
+
this.preloadedMediaUrls.clear();
|
|
3156
|
+
this.preloadingMediaUrls.clear();
|
|
3052
3157
|
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
3158
|
+
if (this.config.debugAdTiming) {
|
|
3159
|
+
console.log(
|
|
3160
|
+
`[StormcloudVideoPlayer] Capturing original audio state before ad break:`,
|
|
3161
|
+
{
|
|
3162
|
+
videoMuted: this.video.muted,
|
|
3163
|
+
videoVolume: this.video.volume
|
|
3164
|
+
}
|
|
3165
|
+
);
|
|
3166
|
+
}
|
|
3167
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3053
3168
|
this.inAdBreak = true;
|
|
3054
|
-
this.showAds = true;
|
|
3055
3169
|
this.currentAdIndex = 0;
|
|
3056
3170
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
3057
3171
|
this.adPodQueue = [...vastTagUrls];
|
|
3058
3172
|
this.enforceAdHoldState();
|
|
3059
|
-
this.preloadUpcomingAds();
|
|
3060
3173
|
if (this.config.debugAdTiming) {
|
|
3061
3174
|
console.log(
|
|
3062
|
-
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads -
|
|
3175
|
+
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - preloading all ads in parallel`
|
|
3063
3176
|
);
|
|
3064
3177
|
}
|
|
3178
|
+
this.preloadAllAdsInBackground().catch((error) => {
|
|
3179
|
+
if (this.config.debugAdTiming) {
|
|
3180
|
+
console.warn(
|
|
3181
|
+
"[StormcloudVideoPlayer] Error in background preloading:",
|
|
3182
|
+
error
|
|
3183
|
+
);
|
|
3184
|
+
}
|
|
3185
|
+
});
|
|
3065
3186
|
try {
|
|
3066
3187
|
await this.playAdPod();
|
|
3067
3188
|
} catch (error) {
|
|
@@ -3087,14 +3208,28 @@ var StormcloudVideoPlayer = class {
|
|
|
3087
3208
|
}
|
|
3088
3209
|
return;
|
|
3089
3210
|
}
|
|
3090
|
-
|
|
3211
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3212
|
+
const firstPreloaded = this.findNextPreloadedAd();
|
|
3213
|
+
if (!firstPreloaded) {
|
|
3214
|
+
if (this.config.debugAdTiming) {
|
|
3215
|
+
console.log(
|
|
3216
|
+
"[StormcloudVideoPlayer] No preloaded ads available after waiting, trying first ad anyway"
|
|
3217
|
+
);
|
|
3218
|
+
}
|
|
3219
|
+
const firstAd = this.adPodQueue.shift();
|
|
3220
|
+
if (firstAd) {
|
|
3221
|
+
this.currentAdIndex++;
|
|
3222
|
+
await this.playSingleAd(firstAd);
|
|
3223
|
+
}
|
|
3224
|
+
return;
|
|
3225
|
+
}
|
|
3091
3226
|
this.currentAdIndex++;
|
|
3092
3227
|
if (this.config.debugAdTiming) {
|
|
3093
3228
|
console.log(
|
|
3094
|
-
`[StormcloudVideoPlayer] Playing ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3229
|
+
`[StormcloudVideoPlayer] Playing first preloaded ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3095
3230
|
);
|
|
3096
3231
|
}
|
|
3097
|
-
await this.playSingleAd(
|
|
3232
|
+
await this.playSingleAd(firstPreloaded);
|
|
3098
3233
|
}
|
|
3099
3234
|
findCurrentOrNextBreak(nowMs) {
|
|
3100
3235
|
var _a;
|
|
@@ -3127,6 +3262,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3127
3262
|
const first = tags[0];
|
|
3128
3263
|
const rest = tags.slice(1);
|
|
3129
3264
|
this.adPodQueue = rest;
|
|
3265
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3130
3266
|
this.enforceAdHoldState();
|
|
3131
3267
|
await this.playSingleAd(first);
|
|
3132
3268
|
this.inAdBreak = true;
|
|
@@ -3247,27 +3383,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3247
3383
|
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3248
3384
|
);
|
|
3249
3385
|
}
|
|
3250
|
-
if (!this.showAds) {
|
|
3251
|
-
if (this.config.debugAdTiming) {
|
|
3252
|
-
console.log(
|
|
3253
|
-
`[StormcloudVideoPlayer] Capturing original state before ad request:`,
|
|
3254
|
-
{
|
|
3255
|
-
videoMuted: this.video.muted,
|
|
3256
|
-
videoVolume: this.video.volume,
|
|
3257
|
-
showAds: this.showAds
|
|
3258
|
-
}
|
|
3259
|
-
);
|
|
3260
|
-
}
|
|
3261
|
-
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3262
|
-
} else if (this.config.debugAdTiming) {
|
|
3263
|
-
console.log(
|
|
3264
|
-
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
3265
|
-
);
|
|
3266
|
-
}
|
|
3267
3386
|
this.startAdFailsafeTimer();
|
|
3268
3387
|
try {
|
|
3269
3388
|
await this.ima.requestAds(vastTagUrl);
|
|
3270
|
-
this.preloadUpcomingAds();
|
|
3271
3389
|
try {
|
|
3272
3390
|
if (this.config.debugAdTiming) {
|
|
3273
3391
|
console.log(
|
|
@@ -3276,9 +3394,10 @@ var StormcloudVideoPlayer = class {
|
|
|
3276
3394
|
}
|
|
3277
3395
|
this.enforceAdHoldState();
|
|
3278
3396
|
await this.ima.play();
|
|
3397
|
+
this.showAds = true;
|
|
3279
3398
|
if (this.config.debugAdTiming) {
|
|
3280
3399
|
console.log(
|
|
3281
|
-
"[StormcloudVideoPlayer] Ad playback started successfully"
|
|
3400
|
+
"[StormcloudVideoPlayer] Ad playback started successfully, showAds = true"
|
|
3282
3401
|
);
|
|
3283
3402
|
}
|
|
3284
3403
|
} catch (playError) {
|
|
@@ -3306,6 +3425,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3306
3425
|
}
|
|
3307
3426
|
this.releaseAdHoldState();
|
|
3308
3427
|
this.preloadingAdUrls.clear();
|
|
3428
|
+
this.vastToMediaUrlMap.clear();
|
|
3429
|
+
this.preloadedMediaUrls.clear();
|
|
3430
|
+
this.preloadingMediaUrls.clear();
|
|
3309
3431
|
this.inAdBreak = false;
|
|
3310
3432
|
this.expectedAdBreakDurationMs = void 0;
|
|
3311
3433
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3415,43 +3537,203 @@ var StormcloudVideoPlayer = class {
|
|
|
3415
3537
|
this.ima.hidePlaceholder();
|
|
3416
3538
|
}
|
|
3417
3539
|
}
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3540
|
+
async fetchAndParseVastXml(vastTagUrl) {
|
|
3541
|
+
try {
|
|
3542
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
3543
|
+
if (!response.ok) {
|
|
3544
|
+
throw new Error(`Failed to fetch VAST: ${response.status}`);
|
|
3545
|
+
}
|
|
3546
|
+
const xmlText = await response.text();
|
|
3547
|
+
return this.extractMediaUrlsFromVast(xmlText);
|
|
3548
|
+
} catch (error) {
|
|
3549
|
+
if (this.config.debugAdTiming) {
|
|
3550
|
+
console.warn(
|
|
3551
|
+
`[StormcloudVideoPlayer] Failed to fetch/parse VAST XML: ${vastTagUrl}`,
|
|
3552
|
+
error
|
|
3553
|
+
);
|
|
3554
|
+
}
|
|
3555
|
+
return [];
|
|
3421
3556
|
}
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3557
|
+
}
|
|
3558
|
+
extractMediaUrlsFromVast(xmlText) {
|
|
3559
|
+
var _a;
|
|
3560
|
+
const mediaUrls = [];
|
|
3561
|
+
try {
|
|
3562
|
+
const parser = new DOMParser();
|
|
3563
|
+
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
|
|
3564
|
+
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
3565
|
+
for (const mediaFile of Array.from(mediaFileElements)) {
|
|
3566
|
+
const url = (_a = mediaFile.textContent) == null ? void 0 : _a.trim();
|
|
3567
|
+
if (url) {
|
|
3568
|
+
const lowerUrl = url.toLowerCase();
|
|
3569
|
+
if (lowerUrl.endsWith(".mp4") || lowerUrl.endsWith(".webm") || lowerUrl.endsWith(".mov") || lowerUrl.endsWith(".avi") || lowerUrl.includes(".mp4?") || lowerUrl.includes(".webm?") || lowerUrl.includes("/mp4/") || lowerUrl.includes("type=video")) {
|
|
3570
|
+
mediaUrls.push(url);
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
if (this.config.debugAdTiming && mediaUrls.length > 0) {
|
|
3575
|
+
console.log(
|
|
3576
|
+
`[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs from VAST:`,
|
|
3577
|
+
mediaUrls
|
|
3578
|
+
);
|
|
3428
3579
|
}
|
|
3429
|
-
|
|
3430
|
-
|
|
3580
|
+
} catch (error) {
|
|
3581
|
+
if (this.config.debugAdTiming) {
|
|
3582
|
+
console.warn(
|
|
3583
|
+
"[StormcloudVideoPlayer] Failed to parse VAST XML:",
|
|
3584
|
+
error
|
|
3585
|
+
);
|
|
3431
3586
|
}
|
|
3587
|
+
}
|
|
3588
|
+
return mediaUrls;
|
|
3589
|
+
}
|
|
3590
|
+
async preloadMediaFile(mediaUrl) {
|
|
3591
|
+
if (this.preloadedMediaUrls.has(mediaUrl)) {
|
|
3592
|
+
return;
|
|
3593
|
+
}
|
|
3594
|
+
if (this.preloadingMediaUrls.has(mediaUrl)) {
|
|
3595
|
+
return;
|
|
3596
|
+
}
|
|
3597
|
+
this.preloadingMediaUrls.add(mediaUrl);
|
|
3598
|
+
try {
|
|
3432
3599
|
if (this.config.debugAdTiming) {
|
|
3433
3600
|
console.log(
|
|
3434
|
-
`[StormcloudVideoPlayer]
|
|
3601
|
+
`[StormcloudVideoPlayer] Preloading video file: ${mediaUrl}`
|
|
3435
3602
|
);
|
|
3436
3603
|
}
|
|
3437
|
-
|
|
3438
|
-
|
|
3604
|
+
const response = await fetch(mediaUrl, {
|
|
3605
|
+
mode: "cors",
|
|
3606
|
+
method: "GET",
|
|
3607
|
+
headers: {
|
|
3608
|
+
Range: "bytes=0-1048576"
|
|
3609
|
+
}
|
|
3610
|
+
});
|
|
3611
|
+
if (response.ok || response.status === 206) {
|
|
3612
|
+
this.preloadedMediaUrls.add(mediaUrl);
|
|
3439
3613
|
if (this.config.debugAdTiming) {
|
|
3440
3614
|
console.log(
|
|
3441
|
-
`[StormcloudVideoPlayer]
|
|
3615
|
+
`[StormcloudVideoPlayer] Successfully preloaded video file: ${mediaUrl}`
|
|
3442
3616
|
);
|
|
3443
3617
|
}
|
|
3444
|
-
}
|
|
3618
|
+
}
|
|
3619
|
+
} catch (error) {
|
|
3620
|
+
if (this.config.debugAdTiming) {
|
|
3621
|
+
console.warn(
|
|
3622
|
+
`[StormcloudVideoPlayer] Failed to preload video file: ${mediaUrl}`,
|
|
3623
|
+
error
|
|
3624
|
+
);
|
|
3625
|
+
}
|
|
3626
|
+
} finally {
|
|
3627
|
+
this.preloadingMediaUrls.delete(mediaUrl);
|
|
3628
|
+
}
|
|
3629
|
+
}
|
|
3630
|
+
async preloadAllAdsInBackground() {
|
|
3631
|
+
if (this.adPodAllUrls.length === 0) {
|
|
3632
|
+
return;
|
|
3633
|
+
}
|
|
3634
|
+
if (this.config.debugAdTiming) {
|
|
3635
|
+
console.log(
|
|
3636
|
+
`[StormcloudVideoPlayer] Starting parallel preload of ${this.adPodAllUrls.length} ads`
|
|
3637
|
+
);
|
|
3638
|
+
}
|
|
3639
|
+
const preloadPromises = this.adPodAllUrls.map(
|
|
3640
|
+
(vastTagUrl) => this.preloadSingleAd(vastTagUrl).catch((error) => {
|
|
3445
3641
|
if (this.config.debugAdTiming) {
|
|
3446
3642
|
console.warn(
|
|
3447
|
-
`[StormcloudVideoPlayer]
|
|
3643
|
+
`[StormcloudVideoPlayer] Preload failed for ${vastTagUrl}:`,
|
|
3448
3644
|
error
|
|
3449
3645
|
);
|
|
3450
3646
|
}
|
|
3451
|
-
})
|
|
3452
|
-
|
|
3453
|
-
|
|
3647
|
+
})
|
|
3648
|
+
);
|
|
3649
|
+
await Promise.all(preloadPromises);
|
|
3650
|
+
if (this.config.debugAdTiming) {
|
|
3651
|
+
console.log(
|
|
3652
|
+
`[StormcloudVideoPlayer] Background preloading completed for all ads`
|
|
3653
|
+
);
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
async preloadSingleAd(vastTagUrl) {
|
|
3657
|
+
if (!vastTagUrl) return;
|
|
3658
|
+
try {
|
|
3659
|
+
if (this.ima.preloadAds && !this.ima.hasPreloadedAd(vastTagUrl)) {
|
|
3660
|
+
if (!this.preloadingAdUrls.has(vastTagUrl)) {
|
|
3661
|
+
if (this.config.debugAdTiming) {
|
|
3662
|
+
console.log(
|
|
3663
|
+
`[StormcloudVideoPlayer] Preloading VAST: ${vastTagUrl}`
|
|
3664
|
+
);
|
|
3665
|
+
}
|
|
3666
|
+
this.preloadingAdUrls.add(vastTagUrl);
|
|
3667
|
+
await this.ima.preloadAds(vastTagUrl).then(() => {
|
|
3668
|
+
if (this.config.debugAdTiming) {
|
|
3669
|
+
console.log(
|
|
3670
|
+
`[StormcloudVideoPlayer] IMA VAST preload complete: ${vastTagUrl}`
|
|
3671
|
+
);
|
|
3672
|
+
}
|
|
3673
|
+
}).catch((error) => {
|
|
3674
|
+
if (this.config.debugAdTiming) {
|
|
3675
|
+
console.warn(
|
|
3676
|
+
`[StormcloudVideoPlayer] IMA VAST preload failed: ${vastTagUrl}`,
|
|
3677
|
+
error
|
|
3678
|
+
);
|
|
3679
|
+
}
|
|
3680
|
+
}).finally(() => {
|
|
3681
|
+
this.preloadingAdUrls.delete(vastTagUrl);
|
|
3682
|
+
});
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
let mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3686
|
+
if (!mediaUrls) {
|
|
3687
|
+
if (this.config.debugAdTiming) {
|
|
3688
|
+
console.log(
|
|
3689
|
+
`[StormcloudVideoPlayer] Fetching and parsing VAST to extract media URLs: ${vastTagUrl}`
|
|
3690
|
+
);
|
|
3691
|
+
}
|
|
3692
|
+
mediaUrls = await this.fetchAndParseVastXml(vastTagUrl);
|
|
3693
|
+
if (mediaUrls.length > 0) {
|
|
3694
|
+
this.vastToMediaUrlMap.set(vastTagUrl, mediaUrls);
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
if (mediaUrls && mediaUrls.length > 0) {
|
|
3698
|
+
const primaryMediaUrl = mediaUrls[0];
|
|
3699
|
+
if (primaryMediaUrl && !this.preloadedMediaUrls.has(primaryMediaUrl)) {
|
|
3700
|
+
await this.preloadMediaFile(primaryMediaUrl);
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
} catch (error) {
|
|
3704
|
+
if (this.config.debugAdTiming) {
|
|
3705
|
+
console.warn(
|
|
3706
|
+
`[StormcloudVideoPlayer] Failed to preload ad: ${vastTagUrl}`,
|
|
3707
|
+
error
|
|
3708
|
+
);
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
findNextPreloadedAd() {
|
|
3713
|
+
var _a, _b, _c;
|
|
3714
|
+
for (let i = 0; i < this.adPodQueue.length; i++) {
|
|
3715
|
+
const vastTagUrl = this.adPodQueue[i];
|
|
3716
|
+
if (!vastTagUrl) continue;
|
|
3717
|
+
const hasImaPreload = (_c = (_b = (_a = this.ima).hasPreloadedAd) == null ? void 0 : _b.call(_a, vastTagUrl)) != null ? _c : false;
|
|
3718
|
+
const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3719
|
+
const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;
|
|
3720
|
+
if (hasImaPreload || hasMediaPreload) {
|
|
3721
|
+
if (this.config.debugAdTiming) {
|
|
3722
|
+
console.log(
|
|
3723
|
+
`[StormcloudVideoPlayer] Found preloaded ad at index ${i}: ${vastTagUrl}`,
|
|
3724
|
+
{ hasImaPreload, hasMediaPreload }
|
|
3725
|
+
);
|
|
3726
|
+
}
|
|
3727
|
+
this.adPodQueue.splice(0, i + 1);
|
|
3728
|
+
return vastTagUrl;
|
|
3729
|
+
}
|
|
3454
3730
|
}
|
|
3731
|
+
if (this.config.debugAdTiming) {
|
|
3732
|
+
console.log(
|
|
3733
|
+
"[StormcloudVideoPlayer] No preloaded ads found in queue"
|
|
3734
|
+
);
|
|
3735
|
+
}
|
|
3736
|
+
return void 0;
|
|
3455
3737
|
}
|
|
3456
3738
|
getRemainingAdMs() {
|
|
3457
3739
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
@@ -3621,6 +3903,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3621
3903
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3622
3904
|
this.releaseAdHoldState();
|
|
3623
3905
|
this.preloadingAdUrls.clear();
|
|
3906
|
+
this.vastToMediaUrlMap.clear();
|
|
3907
|
+
this.preloadedMediaUrls.clear();
|
|
3908
|
+
this.preloadingMediaUrls.clear();
|
|
3624
3909
|
this.adPodAllUrls = [];
|
|
3625
3910
|
}
|
|
3626
3911
|
};
|