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/players/index.cjs
CHANGED
|
@@ -256,7 +256,11 @@ function createImaController(video, options) {
|
|
|
256
256
|
}
|
|
257
257
|
function hideContentVideo() {
|
|
258
258
|
if (!contentVideoHidden) {
|
|
259
|
-
video.style.
|
|
259
|
+
video.style.transition = "opacity 0.3s ease-in-out";
|
|
260
|
+
video.style.opacity = "0";
|
|
261
|
+
setTimeout(() => {
|
|
262
|
+
video.style.visibility = "hidden";
|
|
263
|
+
}, 300);
|
|
260
264
|
video.muted = true;
|
|
261
265
|
video.volume = 0;
|
|
262
266
|
contentVideoHidden = true;
|
|
@@ -266,6 +270,9 @@ function createImaController(video, options) {
|
|
|
266
270
|
function showContentVideo() {
|
|
267
271
|
if (contentVideoHidden) {
|
|
268
272
|
video.style.visibility = "visible";
|
|
273
|
+
video.style.transition = "opacity 0.3s ease-in-out";
|
|
274
|
+
video.offsetHeight;
|
|
275
|
+
video.style.opacity = "1";
|
|
269
276
|
video.muted = originalMutedState;
|
|
270
277
|
video.volume = originalVolume;
|
|
271
278
|
contentVideoHidden = false;
|
|
@@ -438,7 +445,9 @@ function createImaController(video, options) {
|
|
|
438
445
|
container.style.justifyContent = "center";
|
|
439
446
|
container.style.pointerEvents = "none";
|
|
440
447
|
container.style.zIndex = "10";
|
|
441
|
-
container.style.backgroundColor = "
|
|
448
|
+
container.style.backgroundColor = "transparent";
|
|
449
|
+
container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
|
|
450
|
+
container.style.opacity = "0";
|
|
442
451
|
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
443
452
|
adContainerEl = container;
|
|
444
453
|
}
|
|
@@ -548,7 +557,9 @@ function createImaController(video, options) {
|
|
|
548
557
|
container.style.justifyContent = "center";
|
|
549
558
|
container.style.pointerEvents = "none";
|
|
550
559
|
container.style.zIndex = "10";
|
|
551
|
-
container.style.backgroundColor = "
|
|
560
|
+
container.style.backgroundColor = "transparent";
|
|
561
|
+
container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
|
|
562
|
+
container.style.opacity = "0";
|
|
552
563
|
if (!video.parentElement) {
|
|
553
564
|
throw new Error("Video element has no parent for ad container");
|
|
554
565
|
}
|
|
@@ -612,13 +623,19 @@ function createImaController(video, options) {
|
|
|
612
623
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
613
624
|
destroyAdsManager();
|
|
614
625
|
adPlaying = false;
|
|
615
|
-
showContentVideo();
|
|
616
626
|
setAdPlayingFlag(false);
|
|
617
627
|
if (adContainerEl) {
|
|
618
|
-
adContainerEl.style.
|
|
619
|
-
adContainerEl.style.
|
|
620
|
-
|
|
628
|
+
adContainerEl.style.opacity = "0";
|
|
629
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
630
|
+
setTimeout(() => {
|
|
631
|
+
if (adContainerEl) {
|
|
632
|
+
adContainerEl.style.pointerEvents = "none";
|
|
633
|
+
adContainerEl.style.display = "none";
|
|
634
|
+
console.log("[IMA] Ad container hidden after error");
|
|
635
|
+
}
|
|
636
|
+
}, 300);
|
|
621
637
|
}
|
|
638
|
+
showContentVideo();
|
|
622
639
|
if (adsLoadedReject) {
|
|
623
640
|
adsLoadedReject(new Error("Ad playback error"));
|
|
624
641
|
adsLoadedReject = void 0;
|
|
@@ -664,6 +681,15 @@ function createImaController(video, options) {
|
|
|
664
681
|
"[IMA] Content video continues in background (Live mode)"
|
|
665
682
|
);
|
|
666
683
|
}
|
|
684
|
+
hideContentVideo();
|
|
685
|
+
if (adContainerEl) {
|
|
686
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
687
|
+
adContainerEl.style.display = "flex";
|
|
688
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
689
|
+
adContainerEl.offsetHeight;
|
|
690
|
+
adContainerEl.style.opacity = "1";
|
|
691
|
+
console.log("[IMA] Ad container shown on content pause");
|
|
692
|
+
}
|
|
667
693
|
adPlaying = true;
|
|
668
694
|
setAdPlayingFlag(true);
|
|
669
695
|
emit("content_pause");
|
|
@@ -683,6 +709,9 @@ function createImaController(video, options) {
|
|
|
683
709
|
if (adContainerEl) {
|
|
684
710
|
adContainerEl.style.pointerEvents = "auto";
|
|
685
711
|
adContainerEl.style.display = "flex";
|
|
712
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
713
|
+
adContainerEl.offsetHeight;
|
|
714
|
+
adContainerEl.style.opacity = "1";
|
|
686
715
|
console.log("[IMA] Ad container now visible");
|
|
687
716
|
}
|
|
688
717
|
});
|
|
@@ -699,12 +728,18 @@ function createImaController(video, options) {
|
|
|
699
728
|
console.log("[IMA] All ads completed - restoring content");
|
|
700
729
|
adPlaying = false;
|
|
701
730
|
setAdPlayingFlag(false);
|
|
702
|
-
showContentVideo();
|
|
703
731
|
if (adContainerEl) {
|
|
704
|
-
adContainerEl.style.
|
|
705
|
-
adContainerEl.style.
|
|
706
|
-
|
|
732
|
+
adContainerEl.style.opacity = "0";
|
|
733
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
734
|
+
setTimeout(() => {
|
|
735
|
+
if (adContainerEl) {
|
|
736
|
+
adContainerEl.style.pointerEvents = "none";
|
|
737
|
+
adContainerEl.style.display = "none";
|
|
738
|
+
console.log("[IMA] Ad container hidden");
|
|
739
|
+
}
|
|
740
|
+
}, 300);
|
|
707
741
|
}
|
|
742
|
+
showContentVideo();
|
|
708
743
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds) && video.paused) {
|
|
709
744
|
console.log("[IMA] Resuming content video playback");
|
|
710
745
|
video.play().catch((e) => {
|
|
@@ -722,13 +757,21 @@ function createImaController(video, options) {
|
|
|
722
757
|
} catch (e) {
|
|
723
758
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
724
759
|
adPlaying = false;
|
|
725
|
-
showContentVideo();
|
|
726
760
|
setAdPlayingFlag(false);
|
|
727
761
|
if (adContainerEl) {
|
|
728
|
-
adContainerEl.style.
|
|
729
|
-
adContainerEl.style.
|
|
730
|
-
|
|
762
|
+
adContainerEl.style.opacity = "0";
|
|
763
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
764
|
+
setTimeout(() => {
|
|
765
|
+
if (adContainerEl) {
|
|
766
|
+
adContainerEl.style.pointerEvents = "none";
|
|
767
|
+
adContainerEl.style.display = "none";
|
|
768
|
+
console.log(
|
|
769
|
+
"[IMA] Ad container hidden after setup error"
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
}, 300);
|
|
731
773
|
}
|
|
774
|
+
showContentVideo();
|
|
732
775
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
733
776
|
if (video.paused) {
|
|
734
777
|
console.log(
|
|
@@ -753,13 +796,19 @@ function createImaController(video, options) {
|
|
|
753
796
|
(adErrorEvent) => {
|
|
754
797
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
755
798
|
adPlaying = false;
|
|
756
|
-
showContentVideo();
|
|
757
799
|
setAdPlayingFlag(false);
|
|
758
800
|
if (adContainerEl) {
|
|
759
|
-
adContainerEl.style.
|
|
760
|
-
adContainerEl.style.
|
|
761
|
-
|
|
801
|
+
adContainerEl.style.opacity = "0";
|
|
802
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
803
|
+
setTimeout(() => {
|
|
804
|
+
if (adContainerEl) {
|
|
805
|
+
adContainerEl.style.pointerEvents = "none";
|
|
806
|
+
adContainerEl.style.display = "none";
|
|
807
|
+
console.log("[IMA] Ad container hidden after loader error");
|
|
808
|
+
}
|
|
809
|
+
}, 300);
|
|
762
810
|
}
|
|
811
|
+
showContentVideo();
|
|
763
812
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
764
813
|
if (video.paused) {
|
|
765
814
|
console.log("[IMA] Resuming paused video after loader error");
|
|
@@ -865,12 +914,18 @@ function createImaController(video, options) {
|
|
|
865
914
|
console.log("[IMA] Stopping ad playback");
|
|
866
915
|
adPlaying = false;
|
|
867
916
|
setAdPlayingFlag(false);
|
|
868
|
-
showContentVideo();
|
|
869
917
|
if (adContainerEl) {
|
|
870
|
-
adContainerEl.style.
|
|
871
|
-
adContainerEl.style.
|
|
872
|
-
|
|
918
|
+
adContainerEl.style.opacity = "0";
|
|
919
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
920
|
+
setTimeout(() => {
|
|
921
|
+
if (adContainerEl) {
|
|
922
|
+
adContainerEl.style.pointerEvents = "none";
|
|
923
|
+
adContainerEl.style.display = "none";
|
|
924
|
+
console.log("[IMA] Ad container hidden after stop");
|
|
925
|
+
}
|
|
926
|
+
}, 300);
|
|
873
927
|
}
|
|
928
|
+
showContentVideo();
|
|
874
929
|
try {
|
|
875
930
|
(_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
|
|
876
931
|
} catch {
|
|
@@ -881,23 +936,29 @@ function createImaController(video, options) {
|
|
|
881
936
|
var _a;
|
|
882
937
|
destroyAdsManager();
|
|
883
938
|
adPlaying = false;
|
|
884
|
-
showContentVideo();
|
|
885
939
|
setAdPlayingFlag(false);
|
|
886
940
|
if (adContainerEl) {
|
|
887
|
-
adContainerEl.style.
|
|
888
|
-
adContainerEl.style.
|
|
941
|
+
adContainerEl.style.opacity = "0";
|
|
942
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
943
|
+
setTimeout(() => {
|
|
944
|
+
if (adContainerEl) {
|
|
945
|
+
adContainerEl.style.pointerEvents = "none";
|
|
946
|
+
adContainerEl.style.display = "none";
|
|
947
|
+
if (adContainerEl.parentElement) {
|
|
948
|
+
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
949
|
+
}
|
|
950
|
+
adContainerEl = void 0;
|
|
951
|
+
adVideoElement = void 0;
|
|
952
|
+
}
|
|
953
|
+
}, 300);
|
|
889
954
|
}
|
|
955
|
+
showContentVideo();
|
|
890
956
|
try {
|
|
891
957
|
(_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
|
|
892
958
|
} catch {
|
|
893
959
|
}
|
|
894
|
-
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
895
|
-
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
896
|
-
}
|
|
897
|
-
adContainerEl = void 0;
|
|
898
960
|
adDisplayContainer = void 0;
|
|
899
961
|
adsLoader = void 0;
|
|
900
|
-
adVideoElement = void 0;
|
|
901
962
|
contentVideoHidden = false;
|
|
902
963
|
preloadedVast.clear();
|
|
903
964
|
preloadingVast.clear();
|
|
@@ -977,13 +1038,22 @@ function createImaController(video, options) {
|
|
|
977
1038
|
ensurePlaceholderContainer();
|
|
978
1039
|
if (adContainerEl) {
|
|
979
1040
|
adContainerEl.style.display = "flex";
|
|
1041
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
1042
|
+
adContainerEl.offsetHeight;
|
|
1043
|
+
adContainerEl.style.opacity = "1";
|
|
980
1044
|
adContainerEl.style.pointerEvents = "auto";
|
|
981
1045
|
}
|
|
982
1046
|
},
|
|
983
1047
|
hidePlaceholder() {
|
|
984
1048
|
if (adContainerEl) {
|
|
985
|
-
adContainerEl.style.
|
|
986
|
-
adContainerEl.style.
|
|
1049
|
+
adContainerEl.style.opacity = "0";
|
|
1050
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
1051
|
+
setTimeout(() => {
|
|
1052
|
+
if (adContainerEl) {
|
|
1053
|
+
adContainerEl.style.display = "none";
|
|
1054
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1055
|
+
}
|
|
1056
|
+
}, 300);
|
|
987
1057
|
}
|
|
988
1058
|
}
|
|
989
1059
|
};
|
|
@@ -2154,6 +2224,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2154
2224
|
this.hasInitialBufferCompleted = false;
|
|
2155
2225
|
this.adPodAllUrls = [];
|
|
2156
2226
|
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
2227
|
+
this.vastToMediaUrlMap = /* @__PURE__ */ new Map();
|
|
2228
|
+
this.preloadedMediaUrls = /* @__PURE__ */ new Set();
|
|
2229
|
+
this.preloadingMediaUrls = /* @__PURE__ */ new Set();
|
|
2157
2230
|
initializePolyfills();
|
|
2158
2231
|
const browserOverrides = getBrowserConfigOverrides();
|
|
2159
2232
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2426,27 +2499,44 @@ var StormcloudVideoPlayer = class {
|
|
|
2426
2499
|
});
|
|
2427
2500
|
this.ima.on("ad_error", () => {
|
|
2428
2501
|
if (this.config.debugAdTiming) {
|
|
2429
|
-
console.log("[StormcloudVideoPlayer] IMA ad_error event received"
|
|
2502
|
+
console.log("[StormcloudVideoPlayer] IMA ad_error event received", {
|
|
2503
|
+
showAds: this.showAds,
|
|
2504
|
+
inAdBreak: this.inAdBreak,
|
|
2505
|
+
remainingAds: this.adPodQueue.length
|
|
2506
|
+
});
|
|
2430
2507
|
}
|
|
2431
|
-
if (this.
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2508
|
+
if (this.inAdBreak) {
|
|
2509
|
+
const remaining = this.getRemainingAdMs();
|
|
2510
|
+
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2511
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2512
|
+
if (nextPreloaded) {
|
|
2436
2513
|
this.currentAdIndex++;
|
|
2437
|
-
this.
|
|
2514
|
+
if (this.config.debugAdTiming) {
|
|
2515
|
+
console.log(
|
|
2516
|
+
`[StormcloudVideoPlayer] Skipping to next preloaded ad after error`
|
|
2517
|
+
);
|
|
2518
|
+
}
|
|
2519
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2520
|
+
this.handleAdFailure();
|
|
2438
2521
|
});
|
|
2439
2522
|
} else {
|
|
2523
|
+
if (this.config.debugAdTiming) {
|
|
2524
|
+
console.log(
|
|
2525
|
+
"[StormcloudVideoPlayer] No preloaded ads available, ending ad break"
|
|
2526
|
+
);
|
|
2527
|
+
}
|
|
2440
2528
|
this.handleAdFailure();
|
|
2441
2529
|
}
|
|
2442
2530
|
} else {
|
|
2443
|
-
if (this.config.debugAdTiming) {
|
|
2444
|
-
console.log(
|
|
2445
|
-
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2446
|
-
);
|
|
2447
|
-
}
|
|
2448
2531
|
this.handleAdFailure();
|
|
2449
2532
|
}
|
|
2533
|
+
} else {
|
|
2534
|
+
if (this.config.debugAdTiming) {
|
|
2535
|
+
console.log(
|
|
2536
|
+
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2537
|
+
);
|
|
2538
|
+
}
|
|
2539
|
+
this.handleAdFailure();
|
|
2450
2540
|
}
|
|
2451
2541
|
});
|
|
2452
2542
|
this.ima.on("content_pause", () => {
|
|
@@ -2477,22 +2567,31 @@ var StormcloudVideoPlayer = class {
|
|
|
2477
2567
|
}
|
|
2478
2568
|
const remaining = this.getRemainingAdMs();
|
|
2479
2569
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2480
|
-
const
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
console.log(
|
|
2485
|
-
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
2486
|
-
);
|
|
2487
|
-
}
|
|
2488
|
-
this.playSingleAd(next).catch(() => {
|
|
2570
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2571
|
+
if (nextPreloaded) {
|
|
2572
|
+
this.currentAdIndex++;
|
|
2573
|
+
this.enforceAdHoldState();
|
|
2489
2574
|
if (this.config.debugAdTiming) {
|
|
2490
|
-
console.
|
|
2491
|
-
|
|
2575
|
+
console.log(
|
|
2576
|
+
`[StormcloudVideoPlayer] Playing next preloaded ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak})`
|
|
2577
|
+
);
|
|
2578
|
+
}
|
|
2579
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2580
|
+
if (this.config.debugAdTiming) {
|
|
2581
|
+
console.error(
|
|
2582
|
+
"[StormcloudVideoPlayer] Failed to play next ad in pod"
|
|
2583
|
+
);
|
|
2584
|
+
}
|
|
2585
|
+
this.handleAdPodComplete();
|
|
2586
|
+
});
|
|
2587
|
+
} else {
|
|
2588
|
+
if (this.config.debugAdTiming) {
|
|
2589
|
+
console.log(
|
|
2590
|
+
"[StormcloudVideoPlayer] No preloaded ads available - completing ad break"
|
|
2492
2591
|
);
|
|
2493
2592
|
}
|
|
2494
2593
|
this.handleAdPodComplete();
|
|
2495
|
-
}
|
|
2594
|
+
}
|
|
2496
2595
|
} else {
|
|
2497
2596
|
if (this.config.debugAdTiming) {
|
|
2498
2597
|
console.log(
|
|
@@ -2737,6 +2836,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2737
2836
|
const first = tags[0];
|
|
2738
2837
|
const rest = tags.slice(1);
|
|
2739
2838
|
this.adPodQueue = rest;
|
|
2839
|
+
if (!this.showAds) {
|
|
2840
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2841
|
+
}
|
|
2740
2842
|
this.playSingleAd(first).catch(() => {
|
|
2741
2843
|
});
|
|
2742
2844
|
}
|
|
@@ -3093,19 +3195,38 @@ var StormcloudVideoPlayer = class {
|
|
|
3093
3195
|
if (vastTagUrls.length > 0) {
|
|
3094
3196
|
this.adPodAllUrls = [...vastTagUrls];
|
|
3095
3197
|
this.preloadingAdUrls.clear();
|
|
3198
|
+
this.vastToMediaUrlMap.clear();
|
|
3199
|
+
this.preloadedMediaUrls.clear();
|
|
3200
|
+
this.preloadingMediaUrls.clear();
|
|
3096
3201
|
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
3202
|
+
if (this.config.debugAdTiming) {
|
|
3203
|
+
console.log(
|
|
3204
|
+
`[StormcloudVideoPlayer] Capturing original audio state before ad break:`,
|
|
3205
|
+
{
|
|
3206
|
+
videoMuted: this.video.muted,
|
|
3207
|
+
videoVolume: this.video.volume
|
|
3208
|
+
}
|
|
3209
|
+
);
|
|
3210
|
+
}
|
|
3211
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3097
3212
|
this.inAdBreak = true;
|
|
3098
|
-
this.showAds = true;
|
|
3099
3213
|
this.currentAdIndex = 0;
|
|
3100
3214
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
3101
3215
|
this.adPodQueue = [...vastTagUrls];
|
|
3102
3216
|
this.enforceAdHoldState();
|
|
3103
|
-
this.preloadUpcomingAds();
|
|
3104
3217
|
if (this.config.debugAdTiming) {
|
|
3105
3218
|
console.log(
|
|
3106
|
-
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads -
|
|
3219
|
+
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - preloading all ads in parallel`
|
|
3107
3220
|
);
|
|
3108
3221
|
}
|
|
3222
|
+
this.preloadAllAdsInBackground().catch((error) => {
|
|
3223
|
+
if (this.config.debugAdTiming) {
|
|
3224
|
+
console.warn(
|
|
3225
|
+
"[StormcloudVideoPlayer] Error in background preloading:",
|
|
3226
|
+
error
|
|
3227
|
+
);
|
|
3228
|
+
}
|
|
3229
|
+
});
|
|
3109
3230
|
try {
|
|
3110
3231
|
await this.playAdPod();
|
|
3111
3232
|
} catch (error) {
|
|
@@ -3131,14 +3252,28 @@ var StormcloudVideoPlayer = class {
|
|
|
3131
3252
|
}
|
|
3132
3253
|
return;
|
|
3133
3254
|
}
|
|
3134
|
-
|
|
3255
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3256
|
+
const firstPreloaded = this.findNextPreloadedAd();
|
|
3257
|
+
if (!firstPreloaded) {
|
|
3258
|
+
if (this.config.debugAdTiming) {
|
|
3259
|
+
console.log(
|
|
3260
|
+
"[StormcloudVideoPlayer] No preloaded ads available after waiting, trying first ad anyway"
|
|
3261
|
+
);
|
|
3262
|
+
}
|
|
3263
|
+
const firstAd = this.adPodQueue.shift();
|
|
3264
|
+
if (firstAd) {
|
|
3265
|
+
this.currentAdIndex++;
|
|
3266
|
+
await this.playSingleAd(firstAd);
|
|
3267
|
+
}
|
|
3268
|
+
return;
|
|
3269
|
+
}
|
|
3135
3270
|
this.currentAdIndex++;
|
|
3136
3271
|
if (this.config.debugAdTiming) {
|
|
3137
3272
|
console.log(
|
|
3138
|
-
`[StormcloudVideoPlayer] Playing ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3273
|
+
`[StormcloudVideoPlayer] Playing first preloaded ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3139
3274
|
);
|
|
3140
3275
|
}
|
|
3141
|
-
await this.playSingleAd(
|
|
3276
|
+
await this.playSingleAd(firstPreloaded);
|
|
3142
3277
|
}
|
|
3143
3278
|
findCurrentOrNextBreak(nowMs) {
|
|
3144
3279
|
var _a;
|
|
@@ -3171,6 +3306,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3171
3306
|
const first = tags[0];
|
|
3172
3307
|
const rest = tags.slice(1);
|
|
3173
3308
|
this.adPodQueue = rest;
|
|
3309
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3174
3310
|
this.enforceAdHoldState();
|
|
3175
3311
|
await this.playSingleAd(first);
|
|
3176
3312
|
this.inAdBreak = true;
|
|
@@ -3291,27 +3427,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3291
3427
|
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3292
3428
|
);
|
|
3293
3429
|
}
|
|
3294
|
-
if (!this.showAds) {
|
|
3295
|
-
if (this.config.debugAdTiming) {
|
|
3296
|
-
console.log(
|
|
3297
|
-
`[StormcloudVideoPlayer] Capturing original state before ad request:`,
|
|
3298
|
-
{
|
|
3299
|
-
videoMuted: this.video.muted,
|
|
3300
|
-
videoVolume: this.video.volume,
|
|
3301
|
-
showAds: this.showAds
|
|
3302
|
-
}
|
|
3303
|
-
);
|
|
3304
|
-
}
|
|
3305
|
-
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3306
|
-
} else if (this.config.debugAdTiming) {
|
|
3307
|
-
console.log(
|
|
3308
|
-
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
3309
|
-
);
|
|
3310
|
-
}
|
|
3311
3430
|
this.startAdFailsafeTimer();
|
|
3312
3431
|
try {
|
|
3313
3432
|
await this.ima.requestAds(vastTagUrl);
|
|
3314
|
-
this.preloadUpcomingAds();
|
|
3315
3433
|
try {
|
|
3316
3434
|
if (this.config.debugAdTiming) {
|
|
3317
3435
|
console.log(
|
|
@@ -3320,9 +3438,10 @@ var StormcloudVideoPlayer = class {
|
|
|
3320
3438
|
}
|
|
3321
3439
|
this.enforceAdHoldState();
|
|
3322
3440
|
await this.ima.play();
|
|
3441
|
+
this.showAds = true;
|
|
3323
3442
|
if (this.config.debugAdTiming) {
|
|
3324
3443
|
console.log(
|
|
3325
|
-
"[StormcloudVideoPlayer] Ad playback started successfully"
|
|
3444
|
+
"[StormcloudVideoPlayer] Ad playback started successfully, showAds = true"
|
|
3326
3445
|
);
|
|
3327
3446
|
}
|
|
3328
3447
|
} catch (playError) {
|
|
@@ -3350,6 +3469,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3350
3469
|
}
|
|
3351
3470
|
this.releaseAdHoldState();
|
|
3352
3471
|
this.preloadingAdUrls.clear();
|
|
3472
|
+
this.vastToMediaUrlMap.clear();
|
|
3473
|
+
this.preloadedMediaUrls.clear();
|
|
3474
|
+
this.preloadingMediaUrls.clear();
|
|
3353
3475
|
this.inAdBreak = false;
|
|
3354
3476
|
this.expectedAdBreakDurationMs = void 0;
|
|
3355
3477
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3459,44 +3581,204 @@ var StormcloudVideoPlayer = class {
|
|
|
3459
3581
|
this.ima.hidePlaceholder();
|
|
3460
3582
|
}
|
|
3461
3583
|
}
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3584
|
+
async fetchAndParseVastXml(vastTagUrl) {
|
|
3585
|
+
try {
|
|
3586
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
3587
|
+
if (!response.ok) {
|
|
3588
|
+
throw new Error(`Failed to fetch VAST: ${response.status}`);
|
|
3589
|
+
}
|
|
3590
|
+
const xmlText = await response.text();
|
|
3591
|
+
return this.extractMediaUrlsFromVast(xmlText);
|
|
3592
|
+
} catch (error) {
|
|
3593
|
+
if (this.config.debugAdTiming) {
|
|
3594
|
+
console.warn(
|
|
3595
|
+
`[StormcloudVideoPlayer] Failed to fetch/parse VAST XML: ${vastTagUrl}`,
|
|
3596
|
+
error
|
|
3597
|
+
);
|
|
3598
|
+
}
|
|
3599
|
+
return [];
|
|
3465
3600
|
}
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3601
|
+
}
|
|
3602
|
+
extractMediaUrlsFromVast(xmlText) {
|
|
3603
|
+
var _a;
|
|
3604
|
+
const mediaUrls = [];
|
|
3605
|
+
try {
|
|
3606
|
+
const parser = new DOMParser();
|
|
3607
|
+
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
|
|
3608
|
+
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
3609
|
+
for (const mediaFile of Array.from(mediaFileElements)) {
|
|
3610
|
+
const url = (_a = mediaFile.textContent) == null ? void 0 : _a.trim();
|
|
3611
|
+
if (url) {
|
|
3612
|
+
const lowerUrl = url.toLowerCase();
|
|
3613
|
+
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")) {
|
|
3614
|
+
mediaUrls.push(url);
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3472
3617
|
}
|
|
3473
|
-
if (this.
|
|
3474
|
-
|
|
3618
|
+
if (this.config.debugAdTiming && mediaUrls.length > 0) {
|
|
3619
|
+
console.log(
|
|
3620
|
+
`[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs from VAST:`,
|
|
3621
|
+
mediaUrls
|
|
3622
|
+
);
|
|
3623
|
+
}
|
|
3624
|
+
} catch (error) {
|
|
3625
|
+
if (this.config.debugAdTiming) {
|
|
3626
|
+
console.warn(
|
|
3627
|
+
"[StormcloudVideoPlayer] Failed to parse VAST XML:",
|
|
3628
|
+
error
|
|
3629
|
+
);
|
|
3475
3630
|
}
|
|
3631
|
+
}
|
|
3632
|
+
return mediaUrls;
|
|
3633
|
+
}
|
|
3634
|
+
async preloadMediaFile(mediaUrl) {
|
|
3635
|
+
if (this.preloadedMediaUrls.has(mediaUrl)) {
|
|
3636
|
+
return;
|
|
3637
|
+
}
|
|
3638
|
+
if (this.preloadingMediaUrls.has(mediaUrl)) {
|
|
3639
|
+
return;
|
|
3640
|
+
}
|
|
3641
|
+
this.preloadingMediaUrls.add(mediaUrl);
|
|
3642
|
+
try {
|
|
3476
3643
|
if (this.config.debugAdTiming) {
|
|
3477
3644
|
console.log(
|
|
3478
|
-
`[StormcloudVideoPlayer]
|
|
3645
|
+
`[StormcloudVideoPlayer] Preloading video file: ${mediaUrl}`
|
|
3479
3646
|
);
|
|
3480
3647
|
}
|
|
3481
|
-
|
|
3482
|
-
|
|
3648
|
+
const response = await fetch(mediaUrl, {
|
|
3649
|
+
mode: "cors",
|
|
3650
|
+
method: "GET",
|
|
3651
|
+
headers: {
|
|
3652
|
+
Range: "bytes=0-1048576"
|
|
3653
|
+
}
|
|
3654
|
+
});
|
|
3655
|
+
if (response.ok || response.status === 206) {
|
|
3656
|
+
this.preloadedMediaUrls.add(mediaUrl);
|
|
3483
3657
|
if (this.config.debugAdTiming) {
|
|
3484
3658
|
console.log(
|
|
3485
|
-
`[StormcloudVideoPlayer]
|
|
3659
|
+
`[StormcloudVideoPlayer] Successfully preloaded video file: ${mediaUrl}`
|
|
3486
3660
|
);
|
|
3487
3661
|
}
|
|
3488
|
-
}
|
|
3662
|
+
}
|
|
3663
|
+
} catch (error) {
|
|
3664
|
+
if (this.config.debugAdTiming) {
|
|
3665
|
+
console.warn(
|
|
3666
|
+
`[StormcloudVideoPlayer] Failed to preload video file: ${mediaUrl}`,
|
|
3667
|
+
error
|
|
3668
|
+
);
|
|
3669
|
+
}
|
|
3670
|
+
} finally {
|
|
3671
|
+
this.preloadingMediaUrls.delete(mediaUrl);
|
|
3672
|
+
}
|
|
3673
|
+
}
|
|
3674
|
+
async preloadAllAdsInBackground() {
|
|
3675
|
+
if (this.adPodAllUrls.length === 0) {
|
|
3676
|
+
return;
|
|
3677
|
+
}
|
|
3678
|
+
if (this.config.debugAdTiming) {
|
|
3679
|
+
console.log(
|
|
3680
|
+
`[StormcloudVideoPlayer] Starting parallel preload of ${this.adPodAllUrls.length} ads`
|
|
3681
|
+
);
|
|
3682
|
+
}
|
|
3683
|
+
const preloadPromises = this.adPodAllUrls.map(
|
|
3684
|
+
(vastTagUrl) => this.preloadSingleAd(vastTagUrl).catch((error) => {
|
|
3489
3685
|
if (this.config.debugAdTiming) {
|
|
3490
3686
|
console.warn(
|
|
3491
|
-
`[StormcloudVideoPlayer]
|
|
3687
|
+
`[StormcloudVideoPlayer] Preload failed for ${vastTagUrl}:`,
|
|
3492
3688
|
error
|
|
3493
3689
|
);
|
|
3494
3690
|
}
|
|
3495
|
-
})
|
|
3496
|
-
|
|
3497
|
-
|
|
3691
|
+
})
|
|
3692
|
+
);
|
|
3693
|
+
await Promise.all(preloadPromises);
|
|
3694
|
+
if (this.config.debugAdTiming) {
|
|
3695
|
+
console.log(
|
|
3696
|
+
`[StormcloudVideoPlayer] Background preloading completed for all ads`
|
|
3697
|
+
);
|
|
3498
3698
|
}
|
|
3499
3699
|
}
|
|
3700
|
+
async preloadSingleAd(vastTagUrl) {
|
|
3701
|
+
if (!vastTagUrl) return;
|
|
3702
|
+
try {
|
|
3703
|
+
if (this.ima.preloadAds && !this.ima.hasPreloadedAd(vastTagUrl)) {
|
|
3704
|
+
if (!this.preloadingAdUrls.has(vastTagUrl)) {
|
|
3705
|
+
if (this.config.debugAdTiming) {
|
|
3706
|
+
console.log(
|
|
3707
|
+
`[StormcloudVideoPlayer] Preloading VAST: ${vastTagUrl}`
|
|
3708
|
+
);
|
|
3709
|
+
}
|
|
3710
|
+
this.preloadingAdUrls.add(vastTagUrl);
|
|
3711
|
+
await this.ima.preloadAds(vastTagUrl).then(() => {
|
|
3712
|
+
if (this.config.debugAdTiming) {
|
|
3713
|
+
console.log(
|
|
3714
|
+
`[StormcloudVideoPlayer] IMA VAST preload complete: ${vastTagUrl}`
|
|
3715
|
+
);
|
|
3716
|
+
}
|
|
3717
|
+
}).catch((error) => {
|
|
3718
|
+
if (this.config.debugAdTiming) {
|
|
3719
|
+
console.warn(
|
|
3720
|
+
`[StormcloudVideoPlayer] IMA VAST preload failed: ${vastTagUrl}`,
|
|
3721
|
+
error
|
|
3722
|
+
);
|
|
3723
|
+
}
|
|
3724
|
+
}).finally(() => {
|
|
3725
|
+
this.preloadingAdUrls.delete(vastTagUrl);
|
|
3726
|
+
});
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
let mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3730
|
+
if (!mediaUrls) {
|
|
3731
|
+
if (this.config.debugAdTiming) {
|
|
3732
|
+
console.log(
|
|
3733
|
+
`[StormcloudVideoPlayer] Fetching and parsing VAST to extract media URLs: ${vastTagUrl}`
|
|
3734
|
+
);
|
|
3735
|
+
}
|
|
3736
|
+
mediaUrls = await this.fetchAndParseVastXml(vastTagUrl);
|
|
3737
|
+
if (mediaUrls.length > 0) {
|
|
3738
|
+
this.vastToMediaUrlMap.set(vastTagUrl, mediaUrls);
|
|
3739
|
+
}
|
|
3740
|
+
}
|
|
3741
|
+
if (mediaUrls && mediaUrls.length > 0) {
|
|
3742
|
+
const primaryMediaUrl = mediaUrls[0];
|
|
3743
|
+
if (primaryMediaUrl && !this.preloadedMediaUrls.has(primaryMediaUrl)) {
|
|
3744
|
+
await this.preloadMediaFile(primaryMediaUrl);
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
} catch (error) {
|
|
3748
|
+
if (this.config.debugAdTiming) {
|
|
3749
|
+
console.warn(
|
|
3750
|
+
`[StormcloudVideoPlayer] Failed to preload ad: ${vastTagUrl}`,
|
|
3751
|
+
error
|
|
3752
|
+
);
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
}
|
|
3756
|
+
findNextPreloadedAd() {
|
|
3757
|
+
var _a, _b, _c;
|
|
3758
|
+
for (let i = 0; i < this.adPodQueue.length; i++) {
|
|
3759
|
+
const vastTagUrl = this.adPodQueue[i];
|
|
3760
|
+
if (!vastTagUrl) continue;
|
|
3761
|
+
const hasImaPreload = (_c = (_b = (_a = this.ima).hasPreloadedAd) == null ? void 0 : _b.call(_a, vastTagUrl)) != null ? _c : false;
|
|
3762
|
+
const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3763
|
+
const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;
|
|
3764
|
+
if (hasImaPreload || hasMediaPreload) {
|
|
3765
|
+
if (this.config.debugAdTiming) {
|
|
3766
|
+
console.log(
|
|
3767
|
+
`[StormcloudVideoPlayer] Found preloaded ad at index ${i}: ${vastTagUrl}`,
|
|
3768
|
+
{ hasImaPreload, hasMediaPreload }
|
|
3769
|
+
);
|
|
3770
|
+
}
|
|
3771
|
+
this.adPodQueue.splice(0, i + 1);
|
|
3772
|
+
return vastTagUrl;
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
if (this.config.debugAdTiming) {
|
|
3776
|
+
console.log(
|
|
3777
|
+
"[StormcloudVideoPlayer] No preloaded ads found in queue"
|
|
3778
|
+
);
|
|
3779
|
+
}
|
|
3780
|
+
return void 0;
|
|
3781
|
+
}
|
|
3500
3782
|
getRemainingAdMs() {
|
|
3501
3783
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
3502
3784
|
return 0;
|
|
@@ -3665,6 +3947,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3665
3947
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3666
3948
|
this.releaseAdHoldState();
|
|
3667
3949
|
this.preloadingAdUrls.clear();
|
|
3950
|
+
this.vastToMediaUrlMap.clear();
|
|
3951
|
+
this.preloadedMediaUrls.clear();
|
|
3952
|
+
this.preloadingMediaUrls.clear();
|
|
3668
3953
|
this.adPodAllUrls = [];
|
|
3669
3954
|
}
|
|
3670
3955
|
};
|