stormcloud-video-player 0.2.16 → 0.2.18
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 -56
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +6 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +387 -56
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +266 -23
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +5 -1
- package/lib/players/HlsPlayer.cjs +268 -23
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +268 -23
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +76 -12
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/sdk/ima.cjs +73 -2
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-mVgmKmzM.d.cts → types-J6-Dpcvw.d.cts} +1 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +383 -56
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/utils/tracking.d.cts +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Component } from 'react';
|
|
2
|
-
import { S as StormcloudVideoPlayerConfig } from '../types-
|
|
2
|
+
import { S as StormcloudVideoPlayerConfig } from '../types-J6-Dpcvw.cjs';
|
|
3
3
|
|
|
4
4
|
interface HlsPlayerProps extends StormcloudVideoPlayerConfig {
|
|
5
5
|
onMount?: (player: any) => void;
|
package/lib/players/index.cjs
CHANGED
|
@@ -242,6 +242,13 @@ function createImaController(video, options) {
|
|
|
242
242
|
let adPlaying = false;
|
|
243
243
|
let originalMutedState = false;
|
|
244
244
|
const listeners = /* @__PURE__ */ new Map();
|
|
245
|
+
function setAdPlayingFlag(isPlaying) {
|
|
246
|
+
if (isPlaying) {
|
|
247
|
+
video.dataset.stormcloudAdPlaying = "true";
|
|
248
|
+
} else {
|
|
249
|
+
delete video.dataset.stormcloudAdPlaying;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
245
252
|
function emit(event, payload) {
|
|
246
253
|
const set = listeners.get(event);
|
|
247
254
|
if (!set) return;
|
|
@@ -326,6 +333,14 @@ function createImaController(video, options) {
|
|
|
326
333
|
function makeAdsRequest(google, vastTagUrl) {
|
|
327
334
|
const adsRequest = new google.ima.AdsRequest();
|
|
328
335
|
adsRequest.adTagUrl = vastTagUrl;
|
|
336
|
+
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
337
|
+
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
338
|
+
adsRequest.linearAdSlotWidth = videoWidth;
|
|
339
|
+
adsRequest.linearAdSlotHeight = videoHeight;
|
|
340
|
+
adsRequest.nonLinearAdSlotWidth = videoWidth;
|
|
341
|
+
adsRequest.nonLinearAdSlotHeight = videoHeight;
|
|
342
|
+
adsRequest.vastLoadTimeout = 5e3;
|
|
343
|
+
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
329
344
|
adsLoader.requestAds(adsRequest);
|
|
330
345
|
}
|
|
331
346
|
function destroyAdsManager() {
|
|
@@ -372,6 +387,18 @@ function createImaController(video, options) {
|
|
|
372
387
|
},
|
|
373
388
|
async requestAds(vastTagUrl) {
|
|
374
389
|
console.log("[IMA] Requesting ads:", vastTagUrl);
|
|
390
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
391
|
+
const error = new Error("VAST tag URL is empty or undefined");
|
|
392
|
+
console.warn("[IMA]", error.message);
|
|
393
|
+
return Promise.reject(error);
|
|
394
|
+
}
|
|
395
|
+
try {
|
|
396
|
+
new URL(vastTagUrl);
|
|
397
|
+
} catch (e) {
|
|
398
|
+
const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);
|
|
399
|
+
console.warn("[IMA]", error.message);
|
|
400
|
+
return Promise.reject(error);
|
|
401
|
+
}
|
|
375
402
|
if (adPlaying) {
|
|
376
403
|
console.warn(
|
|
377
404
|
"[IMA] Cannot request new ads while an ad is playing. Call stop() first."
|
|
@@ -433,6 +460,18 @@ function createImaController(video, options) {
|
|
|
433
460
|
);
|
|
434
461
|
}
|
|
435
462
|
}
|
|
463
|
+
const videoWidth = video.offsetWidth || video.clientWidth;
|
|
464
|
+
const videoHeight = video.offsetHeight || video.clientHeight;
|
|
465
|
+
if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {
|
|
466
|
+
const error = new Error(
|
|
467
|
+
`Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`
|
|
468
|
+
);
|
|
469
|
+
console.warn("[IMA]", error.message);
|
|
470
|
+
currentReject == null ? void 0 : currentReject(error);
|
|
471
|
+
adsLoadedReject = void 0;
|
|
472
|
+
adsLoadedResolve = void 0;
|
|
473
|
+
return Promise.reject(error);
|
|
474
|
+
}
|
|
436
475
|
if (!adsLoader) {
|
|
437
476
|
console.log("[IMA] Creating ads loader");
|
|
438
477
|
const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
|
|
@@ -452,7 +491,12 @@ function createImaController(video, options) {
|
|
|
452
491
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
453
492
|
destroyAdsManager();
|
|
454
493
|
adPlaying = false;
|
|
494
|
+
const previousMutedState = video.muted;
|
|
455
495
|
video.muted = originalMutedState;
|
|
496
|
+
setAdPlayingFlag(false);
|
|
497
|
+
console.log(
|
|
498
|
+
`[IMA] Restored mute state after ad error: ${previousMutedState} -> ${originalMutedState}`
|
|
499
|
+
);
|
|
456
500
|
if (adContainerEl) {
|
|
457
501
|
adContainerEl.style.pointerEvents = "none";
|
|
458
502
|
adContainerEl.style.display = "none";
|
|
@@ -481,7 +525,9 @@ function createImaController(video, options) {
|
|
|
481
525
|
emit("ad_error");
|
|
482
526
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
483
527
|
if (video.paused) {
|
|
484
|
-
console.log(
|
|
528
|
+
console.log(
|
|
529
|
+
"[IMA] Resuming paused video after ad error"
|
|
530
|
+
);
|
|
485
531
|
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
486
532
|
});
|
|
487
533
|
}
|
|
@@ -503,11 +549,13 @@ function createImaController(video, options) {
|
|
|
503
549
|
}
|
|
504
550
|
video.muted = true;
|
|
505
551
|
adPlaying = true;
|
|
552
|
+
setAdPlayingFlag(true);
|
|
506
553
|
emit("content_pause");
|
|
507
554
|
}
|
|
508
555
|
);
|
|
509
556
|
adsManager.addEventListener(AdEvent.STARTED, () => {
|
|
510
557
|
console.log("[IMA] Ad started playing");
|
|
558
|
+
setAdPlayingFlag(true);
|
|
511
559
|
if (adContainerEl) {
|
|
512
560
|
adContainerEl.style.pointerEvents = "auto";
|
|
513
561
|
adContainerEl.style.display = "flex";
|
|
@@ -523,6 +571,7 @@ function createImaController(video, options) {
|
|
|
523
571
|
console.log("[IMA] Content resume requested");
|
|
524
572
|
adPlaying = false;
|
|
525
573
|
video.muted = originalMutedState;
|
|
574
|
+
setAdPlayingFlag(false);
|
|
526
575
|
if (adContainerEl) {
|
|
527
576
|
adContainerEl.style.pointerEvents = "none";
|
|
528
577
|
adContainerEl.style.display = "none";
|
|
@@ -546,6 +595,7 @@ function createImaController(video, options) {
|
|
|
546
595
|
console.log("[IMA] All ads completed");
|
|
547
596
|
adPlaying = false;
|
|
548
597
|
video.muted = originalMutedState;
|
|
598
|
+
setAdPlayingFlag(false);
|
|
549
599
|
if (adContainerEl) {
|
|
550
600
|
adContainerEl.style.pointerEvents = "none";
|
|
551
601
|
adContainerEl.style.display = "none";
|
|
@@ -576,6 +626,7 @@ function createImaController(video, options) {
|
|
|
576
626
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
577
627
|
adPlaying = false;
|
|
578
628
|
video.muted = originalMutedState;
|
|
629
|
+
setAdPlayingFlag(false);
|
|
579
630
|
if (adContainerEl) {
|
|
580
631
|
adContainerEl.style.pointerEvents = "none";
|
|
581
632
|
adContainerEl.style.display = "none";
|
|
@@ -583,7 +634,9 @@ function createImaController(video, options) {
|
|
|
583
634
|
}
|
|
584
635
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
585
636
|
if (video.paused) {
|
|
586
|
-
console.log(
|
|
637
|
+
console.log(
|
|
638
|
+
"[IMA] Resuming paused video after setup error"
|
|
639
|
+
);
|
|
587
640
|
video.play().catch(() => {
|
|
588
641
|
});
|
|
589
642
|
}
|
|
@@ -603,7 +656,12 @@ function createImaController(video, options) {
|
|
|
603
656
|
(adErrorEvent) => {
|
|
604
657
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
605
658
|
adPlaying = false;
|
|
659
|
+
const previousMutedState = video.muted;
|
|
606
660
|
video.muted = originalMutedState;
|
|
661
|
+
setAdPlayingFlag(false);
|
|
662
|
+
console.log(
|
|
663
|
+
`[IMA] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
664
|
+
);
|
|
607
665
|
if (adContainerEl) {
|
|
608
666
|
adContainerEl.style.pointerEvents = "none";
|
|
609
667
|
adContainerEl.style.display = "none";
|
|
@@ -655,12 +713,20 @@ function createImaController(video, options) {
|
|
|
655
713
|
console.log(`[IMA] Initializing ads manager (${width}x${height})`);
|
|
656
714
|
adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
|
|
657
715
|
adPlaying = true;
|
|
716
|
+
const adVolume = originalMutedState ? 0 : video.volume;
|
|
717
|
+
try {
|
|
718
|
+
adsManager.setVolume(adVolume);
|
|
719
|
+
console.log(`[IMA] Set ad volume to ${adVolume}`);
|
|
720
|
+
} catch (error) {
|
|
721
|
+
console.warn("[IMA] Failed to set ad volume:", error);
|
|
722
|
+
}
|
|
658
723
|
console.log("[IMA] Starting ad playback");
|
|
659
724
|
adsManager.start();
|
|
660
725
|
return Promise.resolve();
|
|
661
726
|
} catch (error) {
|
|
662
727
|
console.error("[IMA] Error starting ad playback:", error);
|
|
663
728
|
adPlaying = false;
|
|
729
|
+
setAdPlayingFlag(false);
|
|
664
730
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
665
731
|
(_b = video.play()) == null ? void 0 : _b.catch(() => {
|
|
666
732
|
});
|
|
@@ -672,6 +738,7 @@ function createImaController(video, options) {
|
|
|
672
738
|
var _a;
|
|
673
739
|
adPlaying = false;
|
|
674
740
|
video.muted = originalMutedState;
|
|
741
|
+
setAdPlayingFlag(false);
|
|
675
742
|
if (adContainerEl) {
|
|
676
743
|
adContainerEl.style.pointerEvents = "none";
|
|
677
744
|
adContainerEl.style.display = "none";
|
|
@@ -695,6 +762,7 @@ function createImaController(video, options) {
|
|
|
695
762
|
destroyAdsManager();
|
|
696
763
|
adPlaying = false;
|
|
697
764
|
video.muted = originalMutedState;
|
|
765
|
+
setAdPlayingFlag(false);
|
|
698
766
|
if (adContainerEl) {
|
|
699
767
|
adContainerEl.style.pointerEvents = "none";
|
|
700
768
|
adContainerEl.style.display = "none";
|
|
@@ -737,6 +805,9 @@ function createImaController(video, options) {
|
|
|
737
805
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
738
806
|
},
|
|
739
807
|
updateOriginalMutedState(muted) {
|
|
808
|
+
console.log(
|
|
809
|
+
`[IMA] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
810
|
+
);
|
|
740
811
|
originalMutedState = muted;
|
|
741
812
|
},
|
|
742
813
|
getOriginalMutedState() {
|
|
@@ -793,7 +864,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
793
864
|
try {
|
|
794
865
|
fn(payload);
|
|
795
866
|
} catch (error) {
|
|
796
|
-
console.warn(
|
|
867
|
+
console.warn(
|
|
868
|
+
`[HlsAdPlayer] Error in event listener for ${event}:`,
|
|
869
|
+
error
|
|
870
|
+
);
|
|
797
871
|
}
|
|
798
872
|
}
|
|
799
873
|
}
|
|
@@ -856,7 +930,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
856
930
|
}
|
|
857
931
|
const mainQuality = getMainStreamQuality();
|
|
858
932
|
if (!mainQuality) {
|
|
859
|
-
console.log(
|
|
933
|
+
console.log(
|
|
934
|
+
"[HlsAdPlayer] No main stream quality info, using first media file"
|
|
935
|
+
);
|
|
860
936
|
return firstFile;
|
|
861
937
|
}
|
|
862
938
|
console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
|
|
@@ -892,7 +968,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
892
968
|
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
893
969
|
const parserError = xmlDoc.querySelector("parsererror");
|
|
894
970
|
if (parserError) {
|
|
895
|
-
console.error(
|
|
971
|
+
console.error(
|
|
972
|
+
"[HlsAdPlayer] XML parsing error (malformed VAST XML):",
|
|
973
|
+
parserError.textContent
|
|
974
|
+
);
|
|
896
975
|
return null;
|
|
897
976
|
}
|
|
898
977
|
const adElement = xmlDoc.querySelector("Ad");
|
|
@@ -908,17 +987,23 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
908
987
|
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
909
988
|
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
910
989
|
const mediaFiles = [];
|
|
911
|
-
console.log(
|
|
990
|
+
console.log(
|
|
991
|
+
`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`
|
|
992
|
+
);
|
|
912
993
|
mediaFileElements.forEach((mf, index) => {
|
|
913
994
|
var _a2;
|
|
914
995
|
const type = mf.getAttribute("type") || "";
|
|
915
996
|
const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
|
|
916
997
|
const width = mf.getAttribute("width") || "";
|
|
917
998
|
const height = mf.getAttribute("height") || "";
|
|
918
|
-
console.log(
|
|
999
|
+
console.log(
|
|
1000
|
+
`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`
|
|
1001
|
+
);
|
|
919
1002
|
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
920
1003
|
if (!url) {
|
|
921
|
-
console.warn(
|
|
1004
|
+
console.warn(
|
|
1005
|
+
`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`
|
|
1006
|
+
);
|
|
922
1007
|
return;
|
|
923
1008
|
}
|
|
924
1009
|
const bitrateAttr = mf.getAttribute("bitrate");
|
|
@@ -932,12 +1017,16 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
932
1017
|
});
|
|
933
1018
|
console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
|
|
934
1019
|
} else {
|
|
935
|
-
console.log(
|
|
1020
|
+
console.log(
|
|
1021
|
+
`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`
|
|
1022
|
+
);
|
|
936
1023
|
}
|
|
937
1024
|
});
|
|
938
1025
|
if (mediaFiles.length === 0) {
|
|
939
1026
|
if (isNoAdAvailable) {
|
|
940
|
-
console.warn(
|
|
1027
|
+
console.warn(
|
|
1028
|
+
"[HlsAdPlayer] No ads available (VAST response indicates no ads)"
|
|
1029
|
+
);
|
|
941
1030
|
} else {
|
|
942
1031
|
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
943
1032
|
}
|
|
@@ -1000,6 +1089,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1000
1089
|
video.style.backgroundColor = "#000";
|
|
1001
1090
|
video.playsInline = true;
|
|
1002
1091
|
video.muted = false;
|
|
1092
|
+
video.volume = 1;
|
|
1093
|
+
console.log(
|
|
1094
|
+
`[HlsAdPlayer] Created ad video element with volume ${video.volume}`
|
|
1095
|
+
);
|
|
1003
1096
|
return video;
|
|
1004
1097
|
}
|
|
1005
1098
|
function setupAdEventListeners() {
|
|
@@ -1059,10 +1152,22 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1059
1152
|
}
|
|
1060
1153
|
});
|
|
1061
1154
|
}
|
|
1155
|
+
function setAdPlayingFlag(isPlaying) {
|
|
1156
|
+
if (isPlaying) {
|
|
1157
|
+
contentVideo.dataset.stormcloudAdPlaying = "true";
|
|
1158
|
+
} else {
|
|
1159
|
+
delete contentVideo.dataset.stormcloudAdPlaying;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1062
1162
|
function handleAdComplete() {
|
|
1063
1163
|
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1064
1164
|
adPlaying = false;
|
|
1165
|
+
setAdPlayingFlag(false);
|
|
1166
|
+
const previousMutedState = contentVideo.muted;
|
|
1065
1167
|
contentVideo.muted = originalMutedState;
|
|
1168
|
+
console.log(
|
|
1169
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1170
|
+
);
|
|
1066
1171
|
if (adContainerEl) {
|
|
1067
1172
|
adContainerEl.style.display = "none";
|
|
1068
1173
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -1080,7 +1185,12 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1080
1185
|
function handleAdError() {
|
|
1081
1186
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
1082
1187
|
adPlaying = false;
|
|
1188
|
+
setAdPlayingFlag(false);
|
|
1189
|
+
const previousMutedState = contentVideo.muted;
|
|
1083
1190
|
contentVideo.muted = originalMutedState;
|
|
1191
|
+
console.log(
|
|
1192
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1193
|
+
);
|
|
1084
1194
|
if (adContainerEl) {
|
|
1085
1195
|
adContainerEl.style.display = "none";
|
|
1086
1196
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -1117,7 +1227,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1117
1227
|
async requestAds(vastTagUrl) {
|
|
1118
1228
|
console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
|
|
1119
1229
|
if (adPlaying) {
|
|
1120
|
-
console.warn(
|
|
1230
|
+
console.warn(
|
|
1231
|
+
"[HlsAdPlayer] Cannot request new ads while an ad is playing"
|
|
1232
|
+
);
|
|
1121
1233
|
return Promise.reject(new Error("Ad already playing"));
|
|
1122
1234
|
}
|
|
1123
1235
|
try {
|
|
@@ -1128,14 +1240,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1128
1240
|
}
|
|
1129
1241
|
const vastXml = await response.text();
|
|
1130
1242
|
console.log("[HlsAdPlayer] VAST XML received");
|
|
1131
|
-
console.log(
|
|
1243
|
+
console.log(
|
|
1244
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1245
|
+
vastXml.substring(0, 2e3)
|
|
1246
|
+
);
|
|
1132
1247
|
const ad = parseVastXml(vastXml);
|
|
1133
1248
|
if (!ad) {
|
|
1134
1249
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1250
|
+
emit("ad_error");
|
|
1135
1251
|
return Promise.resolve();
|
|
1136
1252
|
}
|
|
1137
1253
|
currentAd = ad;
|
|
1138
|
-
console.log(
|
|
1254
|
+
console.log(
|
|
1255
|
+
`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`
|
|
1256
|
+
);
|
|
1139
1257
|
fireTrackingPixels(ad.trackingUrls.impression);
|
|
1140
1258
|
trackingFired.impression = true;
|
|
1141
1259
|
return Promise.resolve();
|
|
@@ -1147,7 +1265,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1147
1265
|
},
|
|
1148
1266
|
async play() {
|
|
1149
1267
|
if (!currentAd) {
|
|
1150
|
-
console.warn(
|
|
1268
|
+
console.warn(
|
|
1269
|
+
"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)"
|
|
1270
|
+
);
|
|
1151
1271
|
return Promise.reject(new Error("No ad loaded"));
|
|
1152
1272
|
}
|
|
1153
1273
|
console.log("[HlsAdPlayer] Starting ad playback");
|
|
@@ -1165,6 +1285,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1165
1285
|
thirdQuartile: false,
|
|
1166
1286
|
complete: false
|
|
1167
1287
|
};
|
|
1288
|
+
const contentVolume = contentVideo.volume;
|
|
1168
1289
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1169
1290
|
contentVideo.pause();
|
|
1170
1291
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
@@ -1173,6 +1294,15 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1173
1294
|
}
|
|
1174
1295
|
contentVideo.muted = true;
|
|
1175
1296
|
adPlaying = true;
|
|
1297
|
+
setAdPlayingFlag(true);
|
|
1298
|
+
if (adVideoElement) {
|
|
1299
|
+
const adVolume = originalMutedState ? 0 : contentVolume;
|
|
1300
|
+
adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
|
|
1301
|
+
adVideoElement.muted = false;
|
|
1302
|
+
console.log(
|
|
1303
|
+
`[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`
|
|
1304
|
+
);
|
|
1305
|
+
}
|
|
1176
1306
|
if (adContainerEl) {
|
|
1177
1307
|
adContainerEl.style.display = "flex";
|
|
1178
1308
|
adContainerEl.style.pointerEvents = "auto";
|
|
@@ -1225,6 +1355,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1225
1355
|
async stop() {
|
|
1226
1356
|
console.log("[HlsAdPlayer] Stopping ad");
|
|
1227
1357
|
adPlaying = false;
|
|
1358
|
+
setAdPlayingFlag(false);
|
|
1228
1359
|
contentVideo.muted = originalMutedState;
|
|
1229
1360
|
if (adContainerEl) {
|
|
1230
1361
|
adContainerEl.style.display = "none";
|
|
@@ -1247,6 +1378,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1247
1378
|
destroy() {
|
|
1248
1379
|
console.log("[HlsAdPlayer] Destroying");
|
|
1249
1380
|
adPlaying = false;
|
|
1381
|
+
setAdPlayingFlag(false);
|
|
1250
1382
|
contentVideo.muted = originalMutedState;
|
|
1251
1383
|
if (adHls) {
|
|
1252
1384
|
adHls.destroy();
|
|
@@ -1288,6 +1420,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1288
1420
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1289
1421
|
},
|
|
1290
1422
|
updateOriginalMutedState(muted) {
|
|
1423
|
+
console.log(
|
|
1424
|
+
`[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
1425
|
+
);
|
|
1291
1426
|
originalMutedState = muted;
|
|
1292
1427
|
},
|
|
1293
1428
|
getOriginalMutedState() {
|
|
@@ -1780,6 +1915,9 @@ var StormcloudVideoPlayer = class {
|
|
|
1780
1915
|
this.isLiveStream = false;
|
|
1781
1916
|
this.nativeHlsMode = false;
|
|
1782
1917
|
this.videoSrcProtection = null;
|
|
1918
|
+
this.bufferedSegmentsCount = 0;
|
|
1919
|
+
this.shouldAutoplayAfterBuffering = false;
|
|
1920
|
+
this.hasInitialBufferCompleted = false;
|
|
1783
1921
|
initializePolyfills();
|
|
1784
1922
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1785
1923
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -1866,14 +2004,22 @@ var StormcloudVideoPlayer = class {
|
|
|
1866
2004
|
liveDurationInfinity: true,
|
|
1867
2005
|
lowLatencyMode: !!this.config.lowLatencyMode,
|
|
1868
2006
|
maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,
|
|
1869
|
-
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
|
|
2007
|
+
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {},
|
|
2008
|
+
maxBufferLength: 30,
|
|
2009
|
+
maxMaxBufferLength: 600,
|
|
2010
|
+
maxBufferSize: 60 * 1e3 * 1e3,
|
|
2011
|
+
maxBufferHole: 0.5,
|
|
2012
|
+
highBufferWatchdogPeriod: 2,
|
|
2013
|
+
nudgeOffset: 0.1,
|
|
2014
|
+
nudgeMaxRetry: 3,
|
|
2015
|
+
startPosition: -1
|
|
1870
2016
|
});
|
|
1871
2017
|
this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {
|
|
1872
2018
|
var _a2;
|
|
1873
2019
|
(_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
|
|
1874
2020
|
});
|
|
1875
2021
|
this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, data) => {
|
|
1876
|
-
var _a2, _b2, _c, _d;
|
|
2022
|
+
var _a2, _b2, _c, _d, _e;
|
|
1877
2023
|
this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
|
|
1878
2024
|
(level) => {
|
|
1879
2025
|
var _a3, _b3;
|
|
@@ -1891,9 +2037,51 @@ var StormcloudVideoPlayer = class {
|
|
|
1891
2037
|
this.ima.destroy();
|
|
1892
2038
|
this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
|
|
1893
2039
|
this.ima.initialize();
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
2040
|
+
this.bufferedSegmentsCount = 0;
|
|
2041
|
+
this.hasInitialBufferCompleted = false;
|
|
2042
|
+
this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
|
|
2043
|
+
const minSegments = (_d = this.config.minSegmentsBeforePlay) != null ? _d : 2;
|
|
2044
|
+
if (this.config.debugAdTiming) {
|
|
2045
|
+
console.log(
|
|
2046
|
+
"[StormcloudVideoPlayer] Waiting for",
|
|
2047
|
+
minSegments,
|
|
2048
|
+
"segments to buffer before playback"
|
|
2049
|
+
);
|
|
2050
|
+
}
|
|
2051
|
+
if (minSegments === 0 || !this.config.autoplay) {
|
|
2052
|
+
this.hasInitialBufferCompleted = true;
|
|
2053
|
+
if (this.config.autoplay) {
|
|
2054
|
+
await ((_e = this.video.play()) == null ? void 0 : _e.catch(() => {
|
|
2055
|
+
}));
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
});
|
|
2059
|
+
this.hls.on(import_hls2.default.Events.FRAG_BUFFERED, async (_evt, data) => {
|
|
2060
|
+
var _a2, _b2;
|
|
2061
|
+
if (this.hasInitialBufferCompleted) {
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
this.bufferedSegmentsCount++;
|
|
2065
|
+
const minSegments = (_a2 = this.config.minSegmentsBeforePlay) != null ? _a2 : 2;
|
|
2066
|
+
if (this.config.debugAdTiming) {
|
|
2067
|
+
console.log(
|
|
2068
|
+
`[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`
|
|
2069
|
+
);
|
|
2070
|
+
}
|
|
2071
|
+
if (this.bufferedSegmentsCount >= minSegments) {
|
|
2072
|
+
this.hasInitialBufferCompleted = true;
|
|
2073
|
+
if (this.shouldAutoplayAfterBuffering) {
|
|
2074
|
+
if (this.config.debugAdTiming) {
|
|
2075
|
+
console.log(
|
|
2076
|
+
`[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`
|
|
2077
|
+
);
|
|
2078
|
+
}
|
|
2079
|
+
await ((_b2 = this.video.play()) == null ? void 0 : _b2.catch((err) => {
|
|
2080
|
+
if (this.config.debugAdTiming) {
|
|
2081
|
+
console.warn("[StormcloudVideoPlayer] Autoplay failed:", err);
|
|
2082
|
+
}
|
|
2083
|
+
}));
|
|
2084
|
+
}
|
|
1897
2085
|
}
|
|
1898
2086
|
});
|
|
1899
2087
|
this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {
|
|
@@ -1989,6 +2177,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1989
2177
|
this.video.autoplay = !!this.config.autoplay;
|
|
1990
2178
|
this.video.muted = !!this.config.muted;
|
|
1991
2179
|
this.ima.initialize();
|
|
2180
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
1992
2181
|
this.ima.on("all_ads_completed", () => {
|
|
1993
2182
|
if (this.config.debugAdTiming) {
|
|
1994
2183
|
console.log(
|
|
@@ -2773,7 +2962,23 @@ var StormcloudVideoPlayer = class {
|
|
|
2773
2962
|
}
|
|
2774
2963
|
return;
|
|
2775
2964
|
}
|
|
2776
|
-
|
|
2965
|
+
if (!this.showAds) {
|
|
2966
|
+
if (this.config.debugAdTiming) {
|
|
2967
|
+
console.log(
|
|
2968
|
+
`[StormcloudVideoPlayer] Capturing original state before ad request:`,
|
|
2969
|
+
{
|
|
2970
|
+
videoMuted: this.video.muted,
|
|
2971
|
+
videoVolume: this.video.volume,
|
|
2972
|
+
showAds: this.showAds
|
|
2973
|
+
}
|
|
2974
|
+
);
|
|
2975
|
+
}
|
|
2976
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2977
|
+
} else if (this.config.debugAdTiming) {
|
|
2978
|
+
console.log(
|
|
2979
|
+
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
2980
|
+
);
|
|
2981
|
+
}
|
|
2777
2982
|
this.startAdFailsafeTimer();
|
|
2778
2983
|
try {
|
|
2779
2984
|
await this.ima.requestAds(vastTagUrl);
|
|
@@ -2828,11 +3033,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2828
3033
|
this.showAds = false;
|
|
2829
3034
|
this.currentAdIndex = 0;
|
|
2830
3035
|
this.totalAdsInBreak = 0;
|
|
3036
|
+
const currentMutedState = this.video.muted;
|
|
2831
3037
|
const originalMutedState = this.ima.getOriginalMutedState();
|
|
2832
3038
|
this.video.muted = originalMutedState;
|
|
2833
3039
|
if (this.config.debugAdTiming) {
|
|
2834
3040
|
console.log(
|
|
2835
|
-
`[StormcloudVideoPlayer] Restored mute state
|
|
3041
|
+
`[StormcloudVideoPlayer] Restored mute state: ${currentMutedState} -> ${originalMutedState}`
|
|
2836
3042
|
);
|
|
2837
3043
|
}
|
|
2838
3044
|
if (this.video.paused) {
|
|
@@ -2924,6 +3130,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2924
3130
|
}
|
|
2925
3131
|
} else {
|
|
2926
3132
|
this.video.muted = !this.video.muted;
|
|
3133
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2927
3134
|
if (this.config.debugAdTiming) {
|
|
2928
3135
|
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
2929
3136
|
}
|
|
@@ -2968,11 +3175,47 @@ var StormcloudVideoPlayer = class {
|
|
|
2968
3175
|
}
|
|
2969
3176
|
isMuted() {
|
|
2970
3177
|
if (this.ima.isAdPlaying()) {
|
|
2971
|
-
|
|
2972
|
-
|
|
3178
|
+
if (this.config.debugAdTiming) {
|
|
3179
|
+
console.log(
|
|
3180
|
+
"[StormcloudVideoPlayer] isMuted() override during ad playback -> false"
|
|
3181
|
+
);
|
|
3182
|
+
}
|
|
3183
|
+
return false;
|
|
3184
|
+
}
|
|
3185
|
+
if (this.config.debugAdTiming) {
|
|
3186
|
+
console.log(
|
|
3187
|
+
`[StormcloudVideoPlayer] isMuted() no ad playing: video.muted=${this.video.muted}`
|
|
3188
|
+
);
|
|
2973
3189
|
}
|
|
2974
3190
|
return this.video.muted;
|
|
2975
3191
|
}
|
|
3192
|
+
setMuted(muted) {
|
|
3193
|
+
const adPlaying = this.ima.isAdPlaying();
|
|
3194
|
+
if (adPlaying && muted === this.video.muted) {
|
|
3195
|
+
if (this.config.debugAdTiming) {
|
|
3196
|
+
console.log(
|
|
3197
|
+
"[StormcloudVideoPlayer] setMuted reflective update during ad ignored",
|
|
3198
|
+
{ muted }
|
|
3199
|
+
);
|
|
3200
|
+
}
|
|
3201
|
+
return;
|
|
3202
|
+
}
|
|
3203
|
+
this.video.muted = muted;
|
|
3204
|
+
if (adPlaying) {
|
|
3205
|
+
this.ima.updateOriginalMutedState(muted);
|
|
3206
|
+
this.ima.setAdVolume(muted ? 0 : 1);
|
|
3207
|
+
if (this.config.debugAdTiming) {
|
|
3208
|
+
console.log("[StormcloudVideoPlayer] setMuted applied during ad", {
|
|
3209
|
+
muted
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3212
|
+
return;
|
|
3213
|
+
}
|
|
3214
|
+
this.ima.updateOriginalMutedState(muted);
|
|
3215
|
+
if (this.config.debugAdTiming) {
|
|
3216
|
+
console.log("[StormcloudVideoPlayer] setMuted called:", muted);
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
2976
3219
|
isFullscreen() {
|
|
2977
3220
|
return !!document.fullscreenElement;
|
|
2978
3221
|
}
|
|
@@ -3054,6 +3297,8 @@ var HlsPlayer = class extends import_react2.Component {
|
|
|
3054
3297
|
config.licenseKey = this.props.licenseKey;
|
|
3055
3298
|
if (this.props.adFailsafeTimeoutMs !== void 0)
|
|
3056
3299
|
config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;
|
|
3300
|
+
if (this.props.minSegmentsBeforePlay !== void 0)
|
|
3301
|
+
config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;
|
|
3057
3302
|
this.player = new StormcloudVideoPlayer(config);
|
|
3058
3303
|
(_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
|
|
3059
3304
|
await this.player.load();
|