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
package/lib/index.js
CHANGED
|
@@ -198,6 +198,13 @@ function createImaController(video, options) {
|
|
|
198
198
|
let adPlaying = false;
|
|
199
199
|
let originalMutedState = false;
|
|
200
200
|
const listeners = /* @__PURE__ */ new Map();
|
|
201
|
+
function setAdPlayingFlag(isPlaying) {
|
|
202
|
+
if (isPlaying) {
|
|
203
|
+
video.dataset.stormcloudAdPlaying = "true";
|
|
204
|
+
} else {
|
|
205
|
+
delete video.dataset.stormcloudAdPlaying;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
201
208
|
function emit(event, payload) {
|
|
202
209
|
const set = listeners.get(event);
|
|
203
210
|
if (!set) return;
|
|
@@ -282,6 +289,14 @@ function createImaController(video, options) {
|
|
|
282
289
|
function makeAdsRequest(google, vastTagUrl) {
|
|
283
290
|
const adsRequest = new google.ima.AdsRequest();
|
|
284
291
|
adsRequest.adTagUrl = vastTagUrl;
|
|
292
|
+
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
293
|
+
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
294
|
+
adsRequest.linearAdSlotWidth = videoWidth;
|
|
295
|
+
adsRequest.linearAdSlotHeight = videoHeight;
|
|
296
|
+
adsRequest.nonLinearAdSlotWidth = videoWidth;
|
|
297
|
+
adsRequest.nonLinearAdSlotHeight = videoHeight;
|
|
298
|
+
adsRequest.vastLoadTimeout = 5e3;
|
|
299
|
+
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
285
300
|
adsLoader.requestAds(adsRequest);
|
|
286
301
|
}
|
|
287
302
|
function destroyAdsManager() {
|
|
@@ -328,6 +343,18 @@ function createImaController(video, options) {
|
|
|
328
343
|
},
|
|
329
344
|
async requestAds(vastTagUrl) {
|
|
330
345
|
console.log("[IMA] Requesting ads:", vastTagUrl);
|
|
346
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
347
|
+
const error = new Error("VAST tag URL is empty or undefined");
|
|
348
|
+
console.warn("[IMA]", error.message);
|
|
349
|
+
return Promise.reject(error);
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
new URL(vastTagUrl);
|
|
353
|
+
} catch (e) {
|
|
354
|
+
const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);
|
|
355
|
+
console.warn("[IMA]", error.message);
|
|
356
|
+
return Promise.reject(error);
|
|
357
|
+
}
|
|
331
358
|
if (adPlaying) {
|
|
332
359
|
console.warn(
|
|
333
360
|
"[IMA] Cannot request new ads while an ad is playing. Call stop() first."
|
|
@@ -389,6 +416,18 @@ function createImaController(video, options) {
|
|
|
389
416
|
);
|
|
390
417
|
}
|
|
391
418
|
}
|
|
419
|
+
const videoWidth = video.offsetWidth || video.clientWidth;
|
|
420
|
+
const videoHeight = video.offsetHeight || video.clientHeight;
|
|
421
|
+
if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {
|
|
422
|
+
const error = new Error(
|
|
423
|
+
`Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`
|
|
424
|
+
);
|
|
425
|
+
console.warn("[IMA]", error.message);
|
|
426
|
+
currentReject == null ? void 0 : currentReject(error);
|
|
427
|
+
adsLoadedReject = void 0;
|
|
428
|
+
adsLoadedResolve = void 0;
|
|
429
|
+
return Promise.reject(error);
|
|
430
|
+
}
|
|
392
431
|
if (!adsLoader) {
|
|
393
432
|
console.log("[IMA] Creating ads loader");
|
|
394
433
|
const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
|
|
@@ -408,7 +447,12 @@ function createImaController(video, options) {
|
|
|
408
447
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
409
448
|
destroyAdsManager();
|
|
410
449
|
adPlaying = false;
|
|
450
|
+
const previousMutedState = video.muted;
|
|
411
451
|
video.muted = originalMutedState;
|
|
452
|
+
setAdPlayingFlag(false);
|
|
453
|
+
console.log(
|
|
454
|
+
`[IMA] Restored mute state after ad error: ${previousMutedState} -> ${originalMutedState}`
|
|
455
|
+
);
|
|
412
456
|
if (adContainerEl) {
|
|
413
457
|
adContainerEl.style.pointerEvents = "none";
|
|
414
458
|
adContainerEl.style.display = "none";
|
|
@@ -437,7 +481,9 @@ function createImaController(video, options) {
|
|
|
437
481
|
emit("ad_error");
|
|
438
482
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
439
483
|
if (video.paused) {
|
|
440
|
-
console.log(
|
|
484
|
+
console.log(
|
|
485
|
+
"[IMA] Resuming paused video after ad error"
|
|
486
|
+
);
|
|
441
487
|
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
442
488
|
});
|
|
443
489
|
}
|
|
@@ -459,11 +505,13 @@ function createImaController(video, options) {
|
|
|
459
505
|
}
|
|
460
506
|
video.muted = true;
|
|
461
507
|
adPlaying = true;
|
|
508
|
+
setAdPlayingFlag(true);
|
|
462
509
|
emit("content_pause");
|
|
463
510
|
}
|
|
464
511
|
);
|
|
465
512
|
adsManager.addEventListener(AdEvent.STARTED, () => {
|
|
466
513
|
console.log("[IMA] Ad started playing");
|
|
514
|
+
setAdPlayingFlag(true);
|
|
467
515
|
if (adContainerEl) {
|
|
468
516
|
adContainerEl.style.pointerEvents = "auto";
|
|
469
517
|
adContainerEl.style.display = "flex";
|
|
@@ -479,6 +527,7 @@ function createImaController(video, options) {
|
|
|
479
527
|
console.log("[IMA] Content resume requested");
|
|
480
528
|
adPlaying = false;
|
|
481
529
|
video.muted = originalMutedState;
|
|
530
|
+
setAdPlayingFlag(false);
|
|
482
531
|
if (adContainerEl) {
|
|
483
532
|
adContainerEl.style.pointerEvents = "none";
|
|
484
533
|
adContainerEl.style.display = "none";
|
|
@@ -502,6 +551,7 @@ function createImaController(video, options) {
|
|
|
502
551
|
console.log("[IMA] All ads completed");
|
|
503
552
|
adPlaying = false;
|
|
504
553
|
video.muted = originalMutedState;
|
|
554
|
+
setAdPlayingFlag(false);
|
|
505
555
|
if (adContainerEl) {
|
|
506
556
|
adContainerEl.style.pointerEvents = "none";
|
|
507
557
|
adContainerEl.style.display = "none";
|
|
@@ -532,6 +582,7 @@ function createImaController(video, options) {
|
|
|
532
582
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
533
583
|
adPlaying = false;
|
|
534
584
|
video.muted = originalMutedState;
|
|
585
|
+
setAdPlayingFlag(false);
|
|
535
586
|
if (adContainerEl) {
|
|
536
587
|
adContainerEl.style.pointerEvents = "none";
|
|
537
588
|
adContainerEl.style.display = "none";
|
|
@@ -539,7 +590,9 @@ function createImaController(video, options) {
|
|
|
539
590
|
}
|
|
540
591
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
541
592
|
if (video.paused) {
|
|
542
|
-
console.log(
|
|
593
|
+
console.log(
|
|
594
|
+
"[IMA] Resuming paused video after setup error"
|
|
595
|
+
);
|
|
543
596
|
video.play().catch(() => {
|
|
544
597
|
});
|
|
545
598
|
}
|
|
@@ -559,7 +612,12 @@ function createImaController(video, options) {
|
|
|
559
612
|
(adErrorEvent) => {
|
|
560
613
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
561
614
|
adPlaying = false;
|
|
615
|
+
const previousMutedState = video.muted;
|
|
562
616
|
video.muted = originalMutedState;
|
|
617
|
+
setAdPlayingFlag(false);
|
|
618
|
+
console.log(
|
|
619
|
+
`[IMA] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
620
|
+
);
|
|
563
621
|
if (adContainerEl) {
|
|
564
622
|
adContainerEl.style.pointerEvents = "none";
|
|
565
623
|
adContainerEl.style.display = "none";
|
|
@@ -611,12 +669,20 @@ function createImaController(video, options) {
|
|
|
611
669
|
console.log(`[IMA] Initializing ads manager (${width}x${height})`);
|
|
612
670
|
adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
|
|
613
671
|
adPlaying = true;
|
|
672
|
+
const adVolume = originalMutedState ? 0 : video.volume;
|
|
673
|
+
try {
|
|
674
|
+
adsManager.setVolume(adVolume);
|
|
675
|
+
console.log(`[IMA] Set ad volume to ${adVolume}`);
|
|
676
|
+
} catch (error) {
|
|
677
|
+
console.warn("[IMA] Failed to set ad volume:", error);
|
|
678
|
+
}
|
|
614
679
|
console.log("[IMA] Starting ad playback");
|
|
615
680
|
adsManager.start();
|
|
616
681
|
return Promise.resolve();
|
|
617
682
|
} catch (error) {
|
|
618
683
|
console.error("[IMA] Error starting ad playback:", error);
|
|
619
684
|
adPlaying = false;
|
|
685
|
+
setAdPlayingFlag(false);
|
|
620
686
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
621
687
|
(_b = video.play()) == null ? void 0 : _b.catch(() => {
|
|
622
688
|
});
|
|
@@ -628,6 +694,7 @@ function createImaController(video, options) {
|
|
|
628
694
|
var _a;
|
|
629
695
|
adPlaying = false;
|
|
630
696
|
video.muted = originalMutedState;
|
|
697
|
+
setAdPlayingFlag(false);
|
|
631
698
|
if (adContainerEl) {
|
|
632
699
|
adContainerEl.style.pointerEvents = "none";
|
|
633
700
|
adContainerEl.style.display = "none";
|
|
@@ -651,6 +718,7 @@ function createImaController(video, options) {
|
|
|
651
718
|
destroyAdsManager();
|
|
652
719
|
adPlaying = false;
|
|
653
720
|
video.muted = originalMutedState;
|
|
721
|
+
setAdPlayingFlag(false);
|
|
654
722
|
if (adContainerEl) {
|
|
655
723
|
adContainerEl.style.pointerEvents = "none";
|
|
656
724
|
adContainerEl.style.display = "none";
|
|
@@ -693,6 +761,9 @@ function createImaController(video, options) {
|
|
|
693
761
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
694
762
|
},
|
|
695
763
|
updateOriginalMutedState(muted) {
|
|
764
|
+
console.log(
|
|
765
|
+
`[IMA] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
766
|
+
);
|
|
696
767
|
originalMutedState = muted;
|
|
697
768
|
},
|
|
698
769
|
getOriginalMutedState() {
|
|
@@ -749,7 +820,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
749
820
|
try {
|
|
750
821
|
fn(payload);
|
|
751
822
|
} catch (error) {
|
|
752
|
-
console.warn(
|
|
823
|
+
console.warn(
|
|
824
|
+
`[HlsAdPlayer] Error in event listener for ${event}:`,
|
|
825
|
+
error
|
|
826
|
+
);
|
|
753
827
|
}
|
|
754
828
|
}
|
|
755
829
|
}
|
|
@@ -812,7 +886,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
812
886
|
}
|
|
813
887
|
const mainQuality = getMainStreamQuality();
|
|
814
888
|
if (!mainQuality) {
|
|
815
|
-
console.log(
|
|
889
|
+
console.log(
|
|
890
|
+
"[HlsAdPlayer] No main stream quality info, using first media file"
|
|
891
|
+
);
|
|
816
892
|
return firstFile;
|
|
817
893
|
}
|
|
818
894
|
console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
|
|
@@ -848,7 +924,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
848
924
|
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
849
925
|
const parserError = xmlDoc.querySelector("parsererror");
|
|
850
926
|
if (parserError) {
|
|
851
|
-
console.error(
|
|
927
|
+
console.error(
|
|
928
|
+
"[HlsAdPlayer] XML parsing error (malformed VAST XML):",
|
|
929
|
+
parserError.textContent
|
|
930
|
+
);
|
|
852
931
|
return null;
|
|
853
932
|
}
|
|
854
933
|
const adElement = xmlDoc.querySelector("Ad");
|
|
@@ -864,17 +943,23 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
864
943
|
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
865
944
|
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
866
945
|
const mediaFiles = [];
|
|
867
|
-
console.log(
|
|
946
|
+
console.log(
|
|
947
|
+
`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`
|
|
948
|
+
);
|
|
868
949
|
mediaFileElements.forEach((mf, index) => {
|
|
869
950
|
var _a2;
|
|
870
951
|
const type = mf.getAttribute("type") || "";
|
|
871
952
|
const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
|
|
872
953
|
const width = mf.getAttribute("width") || "";
|
|
873
954
|
const height = mf.getAttribute("height") || "";
|
|
874
|
-
console.log(
|
|
955
|
+
console.log(
|
|
956
|
+
`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`
|
|
957
|
+
);
|
|
875
958
|
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
876
959
|
if (!url) {
|
|
877
|
-
console.warn(
|
|
960
|
+
console.warn(
|
|
961
|
+
`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`
|
|
962
|
+
);
|
|
878
963
|
return;
|
|
879
964
|
}
|
|
880
965
|
const bitrateAttr = mf.getAttribute("bitrate");
|
|
@@ -888,12 +973,16 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
888
973
|
});
|
|
889
974
|
console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
|
|
890
975
|
} else {
|
|
891
|
-
console.log(
|
|
976
|
+
console.log(
|
|
977
|
+
`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`
|
|
978
|
+
);
|
|
892
979
|
}
|
|
893
980
|
});
|
|
894
981
|
if (mediaFiles.length === 0) {
|
|
895
982
|
if (isNoAdAvailable) {
|
|
896
|
-
console.warn(
|
|
983
|
+
console.warn(
|
|
984
|
+
"[HlsAdPlayer] No ads available (VAST response indicates no ads)"
|
|
985
|
+
);
|
|
897
986
|
} else {
|
|
898
987
|
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
899
988
|
}
|
|
@@ -956,6 +1045,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
956
1045
|
video.style.backgroundColor = "#000";
|
|
957
1046
|
video.playsInline = true;
|
|
958
1047
|
video.muted = false;
|
|
1048
|
+
video.volume = 1;
|
|
1049
|
+
console.log(
|
|
1050
|
+
`[HlsAdPlayer] Created ad video element with volume ${video.volume}`
|
|
1051
|
+
);
|
|
959
1052
|
return video;
|
|
960
1053
|
}
|
|
961
1054
|
function setupAdEventListeners() {
|
|
@@ -1015,10 +1108,22 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1015
1108
|
}
|
|
1016
1109
|
});
|
|
1017
1110
|
}
|
|
1111
|
+
function setAdPlayingFlag(isPlaying) {
|
|
1112
|
+
if (isPlaying) {
|
|
1113
|
+
contentVideo.dataset.stormcloudAdPlaying = "true";
|
|
1114
|
+
} else {
|
|
1115
|
+
delete contentVideo.dataset.stormcloudAdPlaying;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1018
1118
|
function handleAdComplete() {
|
|
1019
1119
|
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1020
1120
|
adPlaying = false;
|
|
1121
|
+
setAdPlayingFlag(false);
|
|
1122
|
+
const previousMutedState = contentVideo.muted;
|
|
1021
1123
|
contentVideo.muted = originalMutedState;
|
|
1124
|
+
console.log(
|
|
1125
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1126
|
+
);
|
|
1022
1127
|
if (adContainerEl) {
|
|
1023
1128
|
adContainerEl.style.display = "none";
|
|
1024
1129
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -1036,7 +1141,12 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1036
1141
|
function handleAdError() {
|
|
1037
1142
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
1038
1143
|
adPlaying = false;
|
|
1144
|
+
setAdPlayingFlag(false);
|
|
1145
|
+
const previousMutedState = contentVideo.muted;
|
|
1039
1146
|
contentVideo.muted = originalMutedState;
|
|
1147
|
+
console.log(
|
|
1148
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1149
|
+
);
|
|
1040
1150
|
if (adContainerEl) {
|
|
1041
1151
|
adContainerEl.style.display = "none";
|
|
1042
1152
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -1073,7 +1183,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1073
1183
|
async requestAds(vastTagUrl) {
|
|
1074
1184
|
console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
|
|
1075
1185
|
if (adPlaying) {
|
|
1076
|
-
console.warn(
|
|
1186
|
+
console.warn(
|
|
1187
|
+
"[HlsAdPlayer] Cannot request new ads while an ad is playing"
|
|
1188
|
+
);
|
|
1077
1189
|
return Promise.reject(new Error("Ad already playing"));
|
|
1078
1190
|
}
|
|
1079
1191
|
try {
|
|
@@ -1084,14 +1196,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1084
1196
|
}
|
|
1085
1197
|
const vastXml = await response.text();
|
|
1086
1198
|
console.log("[HlsAdPlayer] VAST XML received");
|
|
1087
|
-
console.log(
|
|
1199
|
+
console.log(
|
|
1200
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1201
|
+
vastXml.substring(0, 2e3)
|
|
1202
|
+
);
|
|
1088
1203
|
const ad = parseVastXml(vastXml);
|
|
1089
1204
|
if (!ad) {
|
|
1090
1205
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1206
|
+
emit("ad_error");
|
|
1091
1207
|
return Promise.resolve();
|
|
1092
1208
|
}
|
|
1093
1209
|
currentAd = ad;
|
|
1094
|
-
console.log(
|
|
1210
|
+
console.log(
|
|
1211
|
+
`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`
|
|
1212
|
+
);
|
|
1095
1213
|
fireTrackingPixels(ad.trackingUrls.impression);
|
|
1096
1214
|
trackingFired.impression = true;
|
|
1097
1215
|
return Promise.resolve();
|
|
@@ -1103,7 +1221,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1103
1221
|
},
|
|
1104
1222
|
async play() {
|
|
1105
1223
|
if (!currentAd) {
|
|
1106
|
-
console.warn(
|
|
1224
|
+
console.warn(
|
|
1225
|
+
"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)"
|
|
1226
|
+
);
|
|
1107
1227
|
return Promise.reject(new Error("No ad loaded"));
|
|
1108
1228
|
}
|
|
1109
1229
|
console.log("[HlsAdPlayer] Starting ad playback");
|
|
@@ -1121,6 +1241,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1121
1241
|
thirdQuartile: false,
|
|
1122
1242
|
complete: false
|
|
1123
1243
|
};
|
|
1244
|
+
const contentVolume = contentVideo.volume;
|
|
1124
1245
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1125
1246
|
contentVideo.pause();
|
|
1126
1247
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
@@ -1129,6 +1250,15 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1129
1250
|
}
|
|
1130
1251
|
contentVideo.muted = true;
|
|
1131
1252
|
adPlaying = true;
|
|
1253
|
+
setAdPlayingFlag(true);
|
|
1254
|
+
if (adVideoElement) {
|
|
1255
|
+
const adVolume = originalMutedState ? 0 : contentVolume;
|
|
1256
|
+
adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
|
|
1257
|
+
adVideoElement.muted = false;
|
|
1258
|
+
console.log(
|
|
1259
|
+
`[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`
|
|
1260
|
+
);
|
|
1261
|
+
}
|
|
1132
1262
|
if (adContainerEl) {
|
|
1133
1263
|
adContainerEl.style.display = "flex";
|
|
1134
1264
|
adContainerEl.style.pointerEvents = "auto";
|
|
@@ -1181,6 +1311,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1181
1311
|
async stop() {
|
|
1182
1312
|
console.log("[HlsAdPlayer] Stopping ad");
|
|
1183
1313
|
adPlaying = false;
|
|
1314
|
+
setAdPlayingFlag(false);
|
|
1184
1315
|
contentVideo.muted = originalMutedState;
|
|
1185
1316
|
if (adContainerEl) {
|
|
1186
1317
|
adContainerEl.style.display = "none";
|
|
@@ -1203,6 +1334,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1203
1334
|
destroy() {
|
|
1204
1335
|
console.log("[HlsAdPlayer] Destroying");
|
|
1205
1336
|
adPlaying = false;
|
|
1337
|
+
setAdPlayingFlag(false);
|
|
1206
1338
|
contentVideo.muted = originalMutedState;
|
|
1207
1339
|
if (adHls) {
|
|
1208
1340
|
adHls.destroy();
|
|
@@ -1244,6 +1376,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1244
1376
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1245
1377
|
},
|
|
1246
1378
|
updateOriginalMutedState(muted) {
|
|
1379
|
+
console.log(
|
|
1380
|
+
`[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
1381
|
+
);
|
|
1247
1382
|
originalMutedState = muted;
|
|
1248
1383
|
},
|
|
1249
1384
|
getOriginalMutedState() {
|
|
@@ -1736,6 +1871,9 @@ var StormcloudVideoPlayer = class {
|
|
|
1736
1871
|
this.isLiveStream = false;
|
|
1737
1872
|
this.nativeHlsMode = false;
|
|
1738
1873
|
this.videoSrcProtection = null;
|
|
1874
|
+
this.bufferedSegmentsCount = 0;
|
|
1875
|
+
this.shouldAutoplayAfterBuffering = false;
|
|
1876
|
+
this.hasInitialBufferCompleted = false;
|
|
1739
1877
|
initializePolyfills();
|
|
1740
1878
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1741
1879
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -1822,14 +1960,22 @@ var StormcloudVideoPlayer = class {
|
|
|
1822
1960
|
liveDurationInfinity: true,
|
|
1823
1961
|
lowLatencyMode: !!this.config.lowLatencyMode,
|
|
1824
1962
|
maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,
|
|
1825
|
-
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
|
|
1963
|
+
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {},
|
|
1964
|
+
maxBufferLength: 30,
|
|
1965
|
+
maxMaxBufferLength: 600,
|
|
1966
|
+
maxBufferSize: 60 * 1e3 * 1e3,
|
|
1967
|
+
maxBufferHole: 0.5,
|
|
1968
|
+
highBufferWatchdogPeriod: 2,
|
|
1969
|
+
nudgeOffset: 0.1,
|
|
1970
|
+
nudgeMaxRetry: 3,
|
|
1971
|
+
startPosition: -1
|
|
1826
1972
|
});
|
|
1827
1973
|
this.hls.on(Hls2.Events.MEDIA_ATTACHED, () => {
|
|
1828
1974
|
var _a2;
|
|
1829
1975
|
(_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
|
|
1830
1976
|
});
|
|
1831
1977
|
this.hls.on(Hls2.Events.MANIFEST_PARSED, async (_, data) => {
|
|
1832
|
-
var _a2, _b2, _c, _d;
|
|
1978
|
+
var _a2, _b2, _c, _d, _e;
|
|
1833
1979
|
this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
|
|
1834
1980
|
(level) => {
|
|
1835
1981
|
var _a3, _b3;
|
|
@@ -1847,9 +1993,51 @@ var StormcloudVideoPlayer = class {
|
|
|
1847
1993
|
this.ima.destroy();
|
|
1848
1994
|
this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
|
|
1849
1995
|
this.ima.initialize();
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1996
|
+
this.bufferedSegmentsCount = 0;
|
|
1997
|
+
this.hasInitialBufferCompleted = false;
|
|
1998
|
+
this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
|
|
1999
|
+
const minSegments = (_d = this.config.minSegmentsBeforePlay) != null ? _d : 2;
|
|
2000
|
+
if (this.config.debugAdTiming) {
|
|
2001
|
+
console.log(
|
|
2002
|
+
"[StormcloudVideoPlayer] Waiting for",
|
|
2003
|
+
minSegments,
|
|
2004
|
+
"segments to buffer before playback"
|
|
2005
|
+
);
|
|
2006
|
+
}
|
|
2007
|
+
if (minSegments === 0 || !this.config.autoplay) {
|
|
2008
|
+
this.hasInitialBufferCompleted = true;
|
|
2009
|
+
if (this.config.autoplay) {
|
|
2010
|
+
await ((_e = this.video.play()) == null ? void 0 : _e.catch(() => {
|
|
2011
|
+
}));
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
});
|
|
2015
|
+
this.hls.on(Hls2.Events.FRAG_BUFFERED, async (_evt, data) => {
|
|
2016
|
+
var _a2, _b2;
|
|
2017
|
+
if (this.hasInitialBufferCompleted) {
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
2020
|
+
this.bufferedSegmentsCount++;
|
|
2021
|
+
const minSegments = (_a2 = this.config.minSegmentsBeforePlay) != null ? _a2 : 2;
|
|
2022
|
+
if (this.config.debugAdTiming) {
|
|
2023
|
+
console.log(
|
|
2024
|
+
`[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`
|
|
2025
|
+
);
|
|
2026
|
+
}
|
|
2027
|
+
if (this.bufferedSegmentsCount >= minSegments) {
|
|
2028
|
+
this.hasInitialBufferCompleted = true;
|
|
2029
|
+
if (this.shouldAutoplayAfterBuffering) {
|
|
2030
|
+
if (this.config.debugAdTiming) {
|
|
2031
|
+
console.log(
|
|
2032
|
+
`[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`
|
|
2033
|
+
);
|
|
2034
|
+
}
|
|
2035
|
+
await ((_b2 = this.video.play()) == null ? void 0 : _b2.catch((err) => {
|
|
2036
|
+
if (this.config.debugAdTiming) {
|
|
2037
|
+
console.warn("[StormcloudVideoPlayer] Autoplay failed:", err);
|
|
2038
|
+
}
|
|
2039
|
+
}));
|
|
2040
|
+
}
|
|
1853
2041
|
}
|
|
1854
2042
|
});
|
|
1855
2043
|
this.hls.on(Hls2.Events.FRAG_PARSING_METADATA, (_evt, data) => {
|
|
@@ -1945,6 +2133,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1945
2133
|
this.video.autoplay = !!this.config.autoplay;
|
|
1946
2134
|
this.video.muted = !!this.config.muted;
|
|
1947
2135
|
this.ima.initialize();
|
|
2136
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
1948
2137
|
this.ima.on("all_ads_completed", () => {
|
|
1949
2138
|
if (this.config.debugAdTiming) {
|
|
1950
2139
|
console.log(
|
|
@@ -2729,7 +2918,23 @@ var StormcloudVideoPlayer = class {
|
|
|
2729
2918
|
}
|
|
2730
2919
|
return;
|
|
2731
2920
|
}
|
|
2732
|
-
|
|
2921
|
+
if (!this.showAds) {
|
|
2922
|
+
if (this.config.debugAdTiming) {
|
|
2923
|
+
console.log(
|
|
2924
|
+
`[StormcloudVideoPlayer] Capturing original state before ad request:`,
|
|
2925
|
+
{
|
|
2926
|
+
videoMuted: this.video.muted,
|
|
2927
|
+
videoVolume: this.video.volume,
|
|
2928
|
+
showAds: this.showAds
|
|
2929
|
+
}
|
|
2930
|
+
);
|
|
2931
|
+
}
|
|
2932
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2933
|
+
} else if (this.config.debugAdTiming) {
|
|
2934
|
+
console.log(
|
|
2935
|
+
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
2936
|
+
);
|
|
2937
|
+
}
|
|
2733
2938
|
this.startAdFailsafeTimer();
|
|
2734
2939
|
try {
|
|
2735
2940
|
await this.ima.requestAds(vastTagUrl);
|
|
@@ -2784,11 +2989,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2784
2989
|
this.showAds = false;
|
|
2785
2990
|
this.currentAdIndex = 0;
|
|
2786
2991
|
this.totalAdsInBreak = 0;
|
|
2992
|
+
const currentMutedState = this.video.muted;
|
|
2787
2993
|
const originalMutedState = this.ima.getOriginalMutedState();
|
|
2788
2994
|
this.video.muted = originalMutedState;
|
|
2789
2995
|
if (this.config.debugAdTiming) {
|
|
2790
2996
|
console.log(
|
|
2791
|
-
`[StormcloudVideoPlayer] Restored mute state
|
|
2997
|
+
`[StormcloudVideoPlayer] Restored mute state: ${currentMutedState} -> ${originalMutedState}`
|
|
2792
2998
|
);
|
|
2793
2999
|
}
|
|
2794
3000
|
if (this.video.paused) {
|
|
@@ -2880,6 +3086,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2880
3086
|
}
|
|
2881
3087
|
} else {
|
|
2882
3088
|
this.video.muted = !this.video.muted;
|
|
3089
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2883
3090
|
if (this.config.debugAdTiming) {
|
|
2884
3091
|
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
2885
3092
|
}
|
|
@@ -2924,11 +3131,47 @@ var StormcloudVideoPlayer = class {
|
|
|
2924
3131
|
}
|
|
2925
3132
|
isMuted() {
|
|
2926
3133
|
if (this.ima.isAdPlaying()) {
|
|
2927
|
-
|
|
2928
|
-
|
|
3134
|
+
if (this.config.debugAdTiming) {
|
|
3135
|
+
console.log(
|
|
3136
|
+
"[StormcloudVideoPlayer] isMuted() override during ad playback -> false"
|
|
3137
|
+
);
|
|
3138
|
+
}
|
|
3139
|
+
return false;
|
|
3140
|
+
}
|
|
3141
|
+
if (this.config.debugAdTiming) {
|
|
3142
|
+
console.log(
|
|
3143
|
+
`[StormcloudVideoPlayer] isMuted() no ad playing: video.muted=${this.video.muted}`
|
|
3144
|
+
);
|
|
2929
3145
|
}
|
|
2930
3146
|
return this.video.muted;
|
|
2931
3147
|
}
|
|
3148
|
+
setMuted(muted) {
|
|
3149
|
+
const adPlaying = this.ima.isAdPlaying();
|
|
3150
|
+
if (adPlaying && muted === this.video.muted) {
|
|
3151
|
+
if (this.config.debugAdTiming) {
|
|
3152
|
+
console.log(
|
|
3153
|
+
"[StormcloudVideoPlayer] setMuted reflective update during ad ignored",
|
|
3154
|
+
{ muted }
|
|
3155
|
+
);
|
|
3156
|
+
}
|
|
3157
|
+
return;
|
|
3158
|
+
}
|
|
3159
|
+
this.video.muted = muted;
|
|
3160
|
+
if (adPlaying) {
|
|
3161
|
+
this.ima.updateOriginalMutedState(muted);
|
|
3162
|
+
this.ima.setAdVolume(muted ? 0 : 1);
|
|
3163
|
+
if (this.config.debugAdTiming) {
|
|
3164
|
+
console.log("[StormcloudVideoPlayer] setMuted applied during ad", {
|
|
3165
|
+
muted
|
|
3166
|
+
});
|
|
3167
|
+
}
|
|
3168
|
+
return;
|
|
3169
|
+
}
|
|
3170
|
+
this.ima.updateOriginalMutedState(muted);
|
|
3171
|
+
if (this.config.debugAdTiming) {
|
|
3172
|
+
console.log("[StormcloudVideoPlayer] setMuted called:", muted);
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
2932
3175
|
isFullscreen() {
|
|
2933
3176
|
return !!document.fullscreenElement;
|
|
2934
3177
|
}
|
|
@@ -3016,10 +3259,12 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
3016
3259
|
vastMode,
|
|
3017
3260
|
vastTagUrl,
|
|
3018
3261
|
adPlayerType,
|
|
3262
|
+
minSegmentsBeforePlay,
|
|
3019
3263
|
...restVideoAttrs
|
|
3020
3264
|
} = props;
|
|
3021
3265
|
const videoRef = useRef(null);
|
|
3022
3266
|
const playerRef = useRef(null);
|
|
3267
|
+
const bufferingTimeoutRef = useRef(null);
|
|
3023
3268
|
const [adStatus, setAdStatus] = React.useState({ showAds: false, currentIndex: 0, totalAds: 0 });
|
|
3024
3269
|
const [shouldShowNativeControls, setShouldShowNativeControls] = React.useState(true);
|
|
3025
3270
|
const [isMuted, setIsMuted] = React.useState(false);
|
|
@@ -3141,6 +3386,9 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
3141
3386
|
return;
|
|
3142
3387
|
}
|
|
3143
3388
|
setShowLicenseWarning(false);
|
|
3389
|
+
if (debugAdTiming) {
|
|
3390
|
+
console.log("[StormcloudUI] Initializing player, isLoading=true");
|
|
3391
|
+
}
|
|
3144
3392
|
if (playerRef.current) {
|
|
3145
3393
|
try {
|
|
3146
3394
|
playerRef.current.destroy();
|
|
@@ -3171,17 +3419,25 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
3171
3419
|
if (vastMode !== void 0) cfg.vastMode = vastMode;
|
|
3172
3420
|
if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
|
|
3173
3421
|
if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;
|
|
3422
|
+
if (minSegmentsBeforePlay !== void 0)
|
|
3423
|
+
cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
|
|
3174
3424
|
const player = new StormcloudVideoPlayer(cfg);
|
|
3175
3425
|
playerRef.current = player;
|
|
3176
3426
|
player.load().then(() => {
|
|
3177
3427
|
const showNative = player.shouldShowNativeControls();
|
|
3178
3428
|
setShouldShowNativeControls(showNative);
|
|
3429
|
+
if (debugAdTiming) {
|
|
3430
|
+
console.log(
|
|
3431
|
+
"[StormcloudUI] Player loaded successfully, waiting for video ready"
|
|
3432
|
+
);
|
|
3433
|
+
}
|
|
3179
3434
|
onReady == null ? void 0 : onReady(player);
|
|
3180
3435
|
}).catch((error) => {
|
|
3181
3436
|
console.error(
|
|
3182
3437
|
"StormcloudVideoPlayer: Failed to load player:",
|
|
3183
3438
|
error
|
|
3184
3439
|
);
|
|
3440
|
+
setIsLoading(false);
|
|
3185
3441
|
onReady == null ? void 0 : onReady(player);
|
|
3186
3442
|
});
|
|
3187
3443
|
return () => {
|
|
@@ -3198,8 +3454,8 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
3198
3454
|
if (autoplay !== void 0 && playerRef.current.videoElement) {
|
|
3199
3455
|
playerRef.current.videoElement.autoplay = autoplay;
|
|
3200
3456
|
}
|
|
3201
|
-
if (muted !== void 0
|
|
3202
|
-
playerRef.current.
|
|
3457
|
+
if (muted !== void 0) {
|
|
3458
|
+
playerRef.current.setMuted(muted);
|
|
3203
3459
|
}
|
|
3204
3460
|
} catch (error) {
|
|
3205
3461
|
console.warn("Failed to update player properties:", error);
|
|
@@ -3280,26 +3536,108 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
3280
3536
|
useEffect(() => {
|
|
3281
3537
|
if (!videoRef.current) return;
|
|
3282
3538
|
const handleLoadedMetadata = () => {
|
|
3539
|
+
var _a;
|
|
3283
3540
|
if (videoRef.current) {
|
|
3284
3541
|
const video2 = videoRef.current;
|
|
3285
3542
|
void video2.offsetHeight;
|
|
3286
3543
|
}
|
|
3544
|
+
if (debugAdTiming) {
|
|
3545
|
+
console.log(
|
|
3546
|
+
"[StormcloudUI] Video event: loadedmetadata, readyState:",
|
|
3547
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState
|
|
3548
|
+
);
|
|
3549
|
+
}
|
|
3550
|
+
};
|
|
3551
|
+
const handleLoadedData = () => {
|
|
3552
|
+
var _a;
|
|
3553
|
+
if (debugAdTiming) {
|
|
3554
|
+
console.log(
|
|
3555
|
+
"[StormcloudUI] Video event: loadeddata, readyState:",
|
|
3556
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState
|
|
3557
|
+
);
|
|
3558
|
+
}
|
|
3287
3559
|
};
|
|
3288
3560
|
const handleLoadStart = () => {
|
|
3289
|
-
|
|
3290
|
-
|
|
3561
|
+
var _a;
|
|
3562
|
+
if (debugAdTiming) {
|
|
3563
|
+
console.log(
|
|
3564
|
+
"[StormcloudUI] Video event: loadstart, readyState:",
|
|
3565
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState
|
|
3566
|
+
);
|
|
3567
|
+
}
|
|
3291
3568
|
};
|
|
3292
3569
|
const handleCanPlay = () => {
|
|
3570
|
+
var _a;
|
|
3571
|
+
setIsLoading(false);
|
|
3572
|
+
if (bufferingTimeoutRef.current) {
|
|
3573
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3574
|
+
bufferingTimeoutRef.current = null;
|
|
3575
|
+
}
|
|
3576
|
+
setIsBuffering(false);
|
|
3577
|
+
if (debugAdTiming) {
|
|
3578
|
+
console.log(
|
|
3579
|
+
"[StormcloudUI] Video event: canplay, readyState:",
|
|
3580
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState,
|
|
3581
|
+
"- clearing loading state, isLoading=false"
|
|
3582
|
+
);
|
|
3583
|
+
}
|
|
3584
|
+
};
|
|
3585
|
+
const handleCanPlayThrough = () => {
|
|
3586
|
+
var _a;
|
|
3293
3587
|
setIsLoading(false);
|
|
3588
|
+
if (bufferingTimeoutRef.current) {
|
|
3589
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3590
|
+
bufferingTimeoutRef.current = null;
|
|
3591
|
+
}
|
|
3294
3592
|
setIsBuffering(false);
|
|
3593
|
+
if (debugAdTiming) {
|
|
3594
|
+
console.log(
|
|
3595
|
+
"[StormcloudUI] Video event: canplaythrough, readyState:",
|
|
3596
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState,
|
|
3597
|
+
"- clearing loading state, isLoading=false"
|
|
3598
|
+
);
|
|
3599
|
+
}
|
|
3295
3600
|
};
|
|
3296
3601
|
const handleWaiting = () => {
|
|
3297
|
-
|
|
3602
|
+
var _a;
|
|
3603
|
+
if (bufferingTimeoutRef.current) {
|
|
3604
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3605
|
+
}
|
|
3606
|
+
bufferingTimeoutRef.current = window.setTimeout(() => {
|
|
3607
|
+
var _a2;
|
|
3608
|
+
setIsBuffering(true);
|
|
3609
|
+
if (debugAdTiming) {
|
|
3610
|
+
console.log(
|
|
3611
|
+
"[StormcloudUI] Video buffering detected (after 300ms delay), readyState:",
|
|
3612
|
+
(_a2 = videoRef.current) == null ? void 0 : _a2.readyState,
|
|
3613
|
+
"- showing spinner, isBuffering=true"
|
|
3614
|
+
);
|
|
3615
|
+
}
|
|
3616
|
+
}, 300);
|
|
3617
|
+
if (debugAdTiming) {
|
|
3618
|
+
console.log(
|
|
3619
|
+
"[StormcloudUI] Video event: waiting, readyState:",
|
|
3620
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState,
|
|
3621
|
+
"- buffering delay started (300ms)"
|
|
3622
|
+
);
|
|
3623
|
+
}
|
|
3298
3624
|
};
|
|
3299
3625
|
const handlePlaying = () => {
|
|
3626
|
+
var _a;
|
|
3300
3627
|
setIsLoading(false);
|
|
3628
|
+
if (bufferingTimeoutRef.current) {
|
|
3629
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3630
|
+
bufferingTimeoutRef.current = null;
|
|
3631
|
+
}
|
|
3301
3632
|
setIsBuffering(false);
|
|
3302
3633
|
setShowCenterPlay(false);
|
|
3634
|
+
if (debugAdTiming) {
|
|
3635
|
+
console.log(
|
|
3636
|
+
"[StormcloudUI] Video event: playing, readyState:",
|
|
3637
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState,
|
|
3638
|
+
"- playback started, isLoading=false, isBuffering=false"
|
|
3639
|
+
);
|
|
3640
|
+
}
|
|
3303
3641
|
};
|
|
3304
3642
|
const handlePause = () => {
|
|
3305
3643
|
if (playerRef.current && !playerRef.current.isShowingAds()) {
|
|
@@ -3314,8 +3652,9 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
3314
3652
|
const video = videoRef.current;
|
|
3315
3653
|
video.addEventListener("loadstart", handleLoadStart);
|
|
3316
3654
|
video.addEventListener("loadedmetadata", handleLoadedMetadata);
|
|
3317
|
-
video.addEventListener("loadeddata",
|
|
3655
|
+
video.addEventListener("loadeddata", handleLoadedData);
|
|
3318
3656
|
video.addEventListener("canplay", handleCanPlay);
|
|
3657
|
+
video.addEventListener("canplaythrough", handleCanPlayThrough);
|
|
3319
3658
|
video.addEventListener("waiting", handleWaiting);
|
|
3320
3659
|
video.addEventListener("playing", handlePlaying);
|
|
3321
3660
|
video.addEventListener("pause", handlePause);
|
|
@@ -3324,16 +3663,21 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
3324
3663
|
setShowCenterPlay(true);
|
|
3325
3664
|
}
|
|
3326
3665
|
return () => {
|
|
3666
|
+
if (bufferingTimeoutRef.current) {
|
|
3667
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3668
|
+
bufferingTimeoutRef.current = null;
|
|
3669
|
+
}
|
|
3327
3670
|
video.removeEventListener("loadstart", handleLoadStart);
|
|
3328
3671
|
video.removeEventListener("loadedmetadata", handleLoadedMetadata);
|
|
3329
|
-
video.removeEventListener("loadeddata",
|
|
3672
|
+
video.removeEventListener("loadeddata", handleLoadedData);
|
|
3330
3673
|
video.removeEventListener("canplay", handleCanPlay);
|
|
3674
|
+
video.removeEventListener("canplaythrough", handleCanPlayThrough);
|
|
3331
3675
|
video.removeEventListener("waiting", handleWaiting);
|
|
3332
3676
|
video.removeEventListener("playing", handlePlaying);
|
|
3333
3677
|
video.removeEventListener("pause", handlePause);
|
|
3334
3678
|
video.removeEventListener("ended", handleEnded);
|
|
3335
3679
|
};
|
|
3336
|
-
}, []);
|
|
3680
|
+
}, [debugAdTiming]);
|
|
3337
3681
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3338
3682
|
/* @__PURE__ */ jsx("style", { children: `
|
|
3339
3683
|
@keyframes spin {
|
|
@@ -3440,35 +3784,18 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
3440
3784
|
}
|
|
3441
3785
|
),
|
|
3442
3786
|
(isLoading || isBuffering) && /* @__PURE__ */ jsx(
|
|
3443
|
-
|
|
3787
|
+
FaSpinner,
|
|
3444
3788
|
{
|
|
3789
|
+
size: 42,
|
|
3790
|
+
color: "white",
|
|
3445
3791
|
style: {
|
|
3446
3792
|
position: "absolute",
|
|
3447
|
-
top: "50%",
|
|
3448
|
-
left: "50%",
|
|
3449
|
-
transform: "translate(-50%, -50%)",
|
|
3793
|
+
top: "calc(50% - 21px)",
|
|
3794
|
+
left: "calc(50% - 21px)",
|
|
3450
3795
|
zIndex: 20,
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(20, 20, 20, 0.6) 100%)",
|
|
3455
|
-
width: "80px",
|
|
3456
|
-
height: "80px",
|
|
3457
|
-
borderRadius: "50%",
|
|
3458
|
-
backdropFilter: "blur(20px)",
|
|
3459
|
-
boxShadow: "0 12px 40px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.1)"
|
|
3460
|
-
},
|
|
3461
|
-
children: /* @__PURE__ */ jsx(
|
|
3462
|
-
FaSpinner,
|
|
3463
|
-
{
|
|
3464
|
-
size: 28,
|
|
3465
|
-
color: "white",
|
|
3466
|
-
style: {
|
|
3467
|
-
animation: "spin 1s linear infinite",
|
|
3468
|
-
filter: "drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))"
|
|
3469
|
-
}
|
|
3470
|
-
}
|
|
3471
|
-
)
|
|
3796
|
+
animation: "spin 1s linear infinite",
|
|
3797
|
+
filter: "drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))"
|
|
3798
|
+
}
|
|
3472
3799
|
}
|
|
3473
3800
|
),
|
|
3474
3801
|
showLicenseWarning && /* @__PURE__ */ jsxs(
|
|
@@ -4581,6 +4908,7 @@ var defaultProps = {
|
|
|
4581
4908
|
showCustomControls: false,
|
|
4582
4909
|
licenseKey: "",
|
|
4583
4910
|
adFailsafeTimeoutMs: 1e4,
|
|
4911
|
+
minSegmentsBeforePlay: 2,
|
|
4584
4912
|
onStart: noop,
|
|
4585
4913
|
onPlay: noop,
|
|
4586
4914
|
onPause: noop,
|
|
@@ -4754,6 +5082,8 @@ var HlsPlayer = class extends Component {
|
|
|
4754
5082
|
config.licenseKey = this.props.licenseKey;
|
|
4755
5083
|
if (this.props.adFailsafeTimeoutMs !== void 0)
|
|
4756
5084
|
config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;
|
|
5085
|
+
if (this.props.minSegmentsBeforePlay !== void 0)
|
|
5086
|
+
config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;
|
|
4757
5087
|
this.player = new StormcloudVideoPlayer(config);
|
|
4758
5088
|
(_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
|
|
4759
5089
|
await this.player.load();
|
|
@@ -5360,6 +5690,7 @@ var SUPPORTED_PROPS = [
|
|
|
5360
5690
|
"showCustomControls",
|
|
5361
5691
|
"licenseKey",
|
|
5362
5692
|
"adFailsafeTimeoutMs",
|
|
5693
|
+
"minSegmentsBeforePlay",
|
|
5363
5694
|
"onReady",
|
|
5364
5695
|
"onStart",
|
|
5365
5696
|
"onPlay",
|