stormcloud-video-player 0.2.24 → 0.2.26
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 +305 -45
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +12 -1
- package/lib/index.d.ts +12 -1
- package/lib/index.js +305 -45
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +305 -45
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +7 -1
- package/lib/players/HlsPlayer.cjs +305 -45
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +305 -45
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +102 -13
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/sdk/ima.cjs +113 -22
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-D1xfSdLP.d.cts → types-t9jEJXZy.d.cts} +6 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +305 -45
- 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,4 +1,4 @@
|
|
|
1
|
-
import { S as StormcloudVideoPlayerConfig } from '../types-
|
|
1
|
+
import { S as StormcloudVideoPlayerConfig } from '../types-t9jEJXZy.cjs';
|
|
2
2
|
|
|
3
3
|
declare class StormcloudVideoPlayer {
|
|
4
4
|
private readonly video;
|
|
@@ -26,6 +26,8 @@ declare class StormcloudVideoPlayer {
|
|
|
26
26
|
private bufferedSegmentsCount;
|
|
27
27
|
private shouldAutoplayAfterBuffering;
|
|
28
28
|
private hasInitialBufferCompleted;
|
|
29
|
+
private adPodAllUrls;
|
|
30
|
+
private preloadingAdUrls;
|
|
29
31
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
30
32
|
private createAdPlayer;
|
|
31
33
|
load(): Promise<void>;
|
|
@@ -68,6 +70,10 @@ declare class StormcloudVideoPlayer {
|
|
|
68
70
|
private startAdFailsafeTimer;
|
|
69
71
|
private clearAdFailsafeTimer;
|
|
70
72
|
private selectVastTagsForBreak;
|
|
73
|
+
private logQueuedAdUrls;
|
|
74
|
+
private enforceAdHoldState;
|
|
75
|
+
private releaseAdHoldState;
|
|
76
|
+
private preloadUpcomingAds;
|
|
71
77
|
private getRemainingAdMs;
|
|
72
78
|
private findBreakForTime;
|
|
73
79
|
toggleMute(): void;
|
|
@@ -202,7 +202,10 @@ function getBrowserConfigOverrides() {
|
|
|
202
202
|
function createImaController(video, options) {
|
|
203
203
|
let adPlaying = false;
|
|
204
204
|
let originalMutedState = false;
|
|
205
|
+
let originalVolume = typeof video.volume === "number" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;
|
|
205
206
|
const listeners = /* @__PURE__ */ new Map();
|
|
207
|
+
const preloadedVast = /* @__PURE__ */ new Map();
|
|
208
|
+
const preloadingVast = /* @__PURE__ */ new Map();
|
|
206
209
|
function setAdPlayingFlag(isPlaying) {
|
|
207
210
|
if (isPlaying) {
|
|
208
211
|
video.dataset.stormcloudAdPlaying = "true";
|
|
@@ -293,16 +296,70 @@ function createImaController(video, options) {
|
|
|
293
296
|
let adsLoadedReject;
|
|
294
297
|
function makeAdsRequest(google, vastTagUrl) {
|
|
295
298
|
const adsRequest = new google.ima.AdsRequest();
|
|
296
|
-
|
|
299
|
+
const preloadedResponse = preloadedVast.get(vastTagUrl);
|
|
300
|
+
if (preloadedResponse) {
|
|
301
|
+
adsRequest.adsResponse = preloadedResponse;
|
|
302
|
+
console.log(
|
|
303
|
+
"[IMA] Using preloaded VAST response for immediate ad request"
|
|
304
|
+
);
|
|
305
|
+
} else {
|
|
306
|
+
adsRequest.adTagUrl = vastTagUrl;
|
|
307
|
+
}
|
|
297
308
|
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
298
309
|
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
299
310
|
adsRequest.linearAdSlotWidth = videoWidth;
|
|
300
311
|
adsRequest.linearAdSlotHeight = videoHeight;
|
|
301
312
|
adsRequest.nonLinearAdSlotWidth = videoWidth;
|
|
302
313
|
adsRequest.nonLinearAdSlotHeight = videoHeight;
|
|
314
|
+
if (typeof adsRequest.setAdWillAutoPlay === "function") {
|
|
315
|
+
try {
|
|
316
|
+
const willAutoPlay = !video.paused || video.autoplay;
|
|
317
|
+
adsRequest.setAdWillAutoPlay(willAutoPlay);
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.warn("[IMA] Failed to call setAdWillAutoPlay:", error);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (typeof adsRequest.setAdWillPlayMuted === "function") {
|
|
323
|
+
try {
|
|
324
|
+
const willPlayMuted = video.muted || video.volume === 0;
|
|
325
|
+
adsRequest.setAdWillPlayMuted(willPlayMuted);
|
|
326
|
+
} catch (error) {
|
|
327
|
+
console.warn("[IMA] Failed to call setAdWillPlayMuted:", error);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
303
330
|
adsRequest.vastLoadTimeout = 5e3;
|
|
304
331
|
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
305
332
|
adsLoader.requestAds(adsRequest);
|
|
333
|
+
if (preloadedResponse) {
|
|
334
|
+
preloadedVast.delete(vastTagUrl);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function ensurePlaceholderContainer() {
|
|
338
|
+
var _a;
|
|
339
|
+
if (adContainerEl) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const container = document.createElement("div");
|
|
343
|
+
container.style.position = "absolute";
|
|
344
|
+
container.style.left = "0";
|
|
345
|
+
container.style.top = "0";
|
|
346
|
+
container.style.right = "0";
|
|
347
|
+
container.style.bottom = "0";
|
|
348
|
+
container.style.display = "none";
|
|
349
|
+
container.style.alignItems = "center";
|
|
350
|
+
container.style.justifyContent = "center";
|
|
351
|
+
container.style.pointerEvents = "none";
|
|
352
|
+
container.style.zIndex = "10";
|
|
353
|
+
container.style.backgroundColor = "#000";
|
|
354
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
355
|
+
adContainerEl = container;
|
|
356
|
+
}
|
|
357
|
+
async function fetchVastDocument(vastTagUrl) {
|
|
358
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
359
|
+
if (!response.ok) {
|
|
360
|
+
throw new Error(`Failed to preload VAST: ${response.status}`);
|
|
361
|
+
}
|
|
362
|
+
return response.text();
|
|
306
363
|
}
|
|
307
364
|
function destroyAdsManager() {
|
|
308
365
|
if (adsManager) {
|
|
@@ -318,29 +375,16 @@ function createImaController(video, options) {
|
|
|
318
375
|
return {
|
|
319
376
|
initialize() {
|
|
320
377
|
ensureImaLoaded().then(() => {
|
|
321
|
-
var _a
|
|
378
|
+
var _a;
|
|
322
379
|
const google = window.google;
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
container.style.position = "absolute";
|
|
326
|
-
container.style.left = "0";
|
|
327
|
-
container.style.top = "0";
|
|
328
|
-
container.style.right = "0";
|
|
329
|
-
container.style.bottom = "0";
|
|
330
|
-
container.style.display = "none";
|
|
331
|
-
container.style.alignItems = "center";
|
|
332
|
-
container.style.justifyContent = "center";
|
|
333
|
-
container.style.pointerEvents = "none";
|
|
334
|
-
container.style.zIndex = "10";
|
|
335
|
-
container.style.backgroundColor = "#000";
|
|
336
|
-
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
337
|
-
adContainerEl = container;
|
|
380
|
+
ensurePlaceholderContainer();
|
|
381
|
+
if (!adDisplayContainer && adContainerEl) {
|
|
338
382
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
339
|
-
|
|
383
|
+
adContainerEl,
|
|
340
384
|
video
|
|
341
385
|
);
|
|
342
386
|
try {
|
|
343
|
-
(
|
|
387
|
+
(_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
|
|
344
388
|
} catch {
|
|
345
389
|
}
|
|
346
390
|
}
|
|
@@ -644,6 +688,32 @@ function createImaController(video, options) {
|
|
|
644
688
|
return Promise.reject(error);
|
|
645
689
|
}
|
|
646
690
|
},
|
|
691
|
+
async preloadAds(vastTagUrl) {
|
|
692
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
693
|
+
return Promise.resolve();
|
|
694
|
+
}
|
|
695
|
+
if (preloadedVast.has(vastTagUrl)) {
|
|
696
|
+
return Promise.resolve();
|
|
697
|
+
}
|
|
698
|
+
const inflight = preloadingVast.get(vastTagUrl);
|
|
699
|
+
if (inflight) {
|
|
700
|
+
return inflight;
|
|
701
|
+
}
|
|
702
|
+
const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
|
|
703
|
+
preloadedVast.set(vastTagUrl, xml);
|
|
704
|
+
console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
|
|
705
|
+
}).catch((error) => {
|
|
706
|
+
console.warn("[IMA] Failed to preload VAST response:", error);
|
|
707
|
+
preloadedVast.delete(vastTagUrl);
|
|
708
|
+
}).finally(() => {
|
|
709
|
+
preloadingVast.delete(vastTagUrl);
|
|
710
|
+
});
|
|
711
|
+
preloadingVast.set(vastTagUrl, preloadPromise);
|
|
712
|
+
return preloadPromise;
|
|
713
|
+
},
|
|
714
|
+
hasPreloadedAd(vastTagUrl) {
|
|
715
|
+
return preloadedVast.has(vastTagUrl);
|
|
716
|
+
},
|
|
647
717
|
async play() {
|
|
648
718
|
var _a, _b;
|
|
649
719
|
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
@@ -662,7 +732,7 @@ function createImaController(video, options) {
|
|
|
662
732
|
console.log(`[IMA] Initializing ads manager (${width}x${height})`);
|
|
663
733
|
adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
|
|
664
734
|
adPlaying = true;
|
|
665
|
-
const adVolume = originalMutedState ? 0 :
|
|
735
|
+
const adVolume = originalMutedState ? 0 : originalVolume;
|
|
666
736
|
try {
|
|
667
737
|
adsManager.setVolume(adVolume);
|
|
668
738
|
console.log(`[IMA] Set ad volume to ${adVolume}`);
|
|
@@ -704,6 +774,7 @@ function createImaController(video, options) {
|
|
|
704
774
|
destroyAdsManager();
|
|
705
775
|
adPlaying = false;
|
|
706
776
|
video.muted = originalMutedState;
|
|
777
|
+
video.volume = originalVolume;
|
|
707
778
|
setAdPlayingFlag(false);
|
|
708
779
|
if (adContainerEl) {
|
|
709
780
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -719,6 +790,8 @@ function createImaController(video, options) {
|
|
|
719
790
|
adContainerEl = void 0;
|
|
720
791
|
adDisplayContainer = void 0;
|
|
721
792
|
adsLoader = void 0;
|
|
793
|
+
preloadedVast.clear();
|
|
794
|
+
preloadingVast.clear();
|
|
722
795
|
},
|
|
723
796
|
isAdPlaying() {
|
|
724
797
|
return adPlaying;
|
|
@@ -746,15 +819,20 @@ function createImaController(video, options) {
|
|
|
746
819
|
var _a;
|
|
747
820
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
748
821
|
},
|
|
749
|
-
updateOriginalMutedState(muted) {
|
|
822
|
+
updateOriginalMutedState(muted, volume) {
|
|
823
|
+
const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
|
|
750
824
|
console.log(
|
|
751
|
-
`[IMA] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
825
|
+
`[IMA] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
|
|
752
826
|
);
|
|
753
827
|
originalMutedState = muted;
|
|
828
|
+
originalVolume = nextVolume;
|
|
754
829
|
},
|
|
755
830
|
getOriginalMutedState() {
|
|
756
831
|
return originalMutedState;
|
|
757
832
|
},
|
|
833
|
+
getOriginalVolume() {
|
|
834
|
+
return originalVolume;
|
|
835
|
+
},
|
|
758
836
|
setAdVolume(volume) {
|
|
759
837
|
if (adsManager && adPlaying) {
|
|
760
838
|
try {
|
|
@@ -774,6 +852,19 @@ function createImaController(video, options) {
|
|
|
774
852
|
}
|
|
775
853
|
}
|
|
776
854
|
return 1;
|
|
855
|
+
},
|
|
856
|
+
showPlaceholder() {
|
|
857
|
+
ensurePlaceholderContainer();
|
|
858
|
+
if (adContainerEl) {
|
|
859
|
+
adContainerEl.style.display = "flex";
|
|
860
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
861
|
+
}
|
|
862
|
+
},
|
|
863
|
+
hidePlaceholder() {
|
|
864
|
+
if (adContainerEl) {
|
|
865
|
+
adContainerEl.style.display = "none";
|
|
866
|
+
adContainerEl.style.pointerEvents = "none";
|
|
867
|
+
}
|
|
777
868
|
}
|
|
778
869
|
};
|
|
779
870
|
}
|
|
@@ -783,6 +874,7 @@ var import_hls = __toESM(require("hls.js"), 1);
|
|
|
783
874
|
function createHlsAdPlayer(contentVideo, options) {
|
|
784
875
|
let adPlaying = false;
|
|
785
876
|
let originalMutedState = false;
|
|
877
|
+
let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
|
|
786
878
|
const listeners = /* @__PURE__ */ new Map();
|
|
787
879
|
const licenseKey = options == null ? void 0 : options.licenseKey;
|
|
788
880
|
const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
|
|
@@ -791,6 +883,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
791
883
|
let adContainerEl;
|
|
792
884
|
let currentAd;
|
|
793
885
|
let sessionId;
|
|
886
|
+
const preloadedAds = /* @__PURE__ */ new Map();
|
|
887
|
+
const preloadingAds = /* @__PURE__ */ new Map();
|
|
794
888
|
let trackingFired = {
|
|
795
889
|
impression: false,
|
|
796
890
|
start: false,
|
|
@@ -1020,6 +1114,19 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1020
1114
|
return null;
|
|
1021
1115
|
}
|
|
1022
1116
|
}
|
|
1117
|
+
async function fetchAndParseVastAd(vastTagUrl) {
|
|
1118
|
+
const response = await fetch(vastTagUrl);
|
|
1119
|
+
if (!response.ok) {
|
|
1120
|
+
throw new Error(`Failed to fetch VAST: ${response.statusText}`);
|
|
1121
|
+
}
|
|
1122
|
+
const vastXml = await response.text();
|
|
1123
|
+
console.log("[HlsAdPlayer] VAST XML received");
|
|
1124
|
+
console.log(
|
|
1125
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1126
|
+
vastXml.substring(0, 2e3)
|
|
1127
|
+
);
|
|
1128
|
+
return parseVastXml(vastXml);
|
|
1129
|
+
}
|
|
1023
1130
|
function createAdVideoElement() {
|
|
1024
1131
|
const video = document.createElement("video");
|
|
1025
1132
|
video.style.position = "absolute";
|
|
@@ -1125,6 +1232,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1125
1232
|
setAdPlayingFlag(false);
|
|
1126
1233
|
const previousMutedState = contentVideo.muted;
|
|
1127
1234
|
contentVideo.muted = originalMutedState;
|
|
1235
|
+
contentVideo.volume = originalMutedState ? 0 : originalVolume;
|
|
1128
1236
|
console.log(
|
|
1129
1237
|
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1130
1238
|
);
|
|
@@ -1171,17 +1279,17 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1171
1279
|
}
|
|
1172
1280
|
try {
|
|
1173
1281
|
sessionId = generateSessionId();
|
|
1174
|
-
|
|
1175
|
-
if (
|
|
1176
|
-
|
|
1282
|
+
let ad;
|
|
1283
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1284
|
+
ad = preloadedAds.get(vastTagUrl);
|
|
1285
|
+
preloadedAds.delete(vastTagUrl);
|
|
1286
|
+
console.log(
|
|
1287
|
+
"[HlsAdPlayer] Using preloaded VAST response:",
|
|
1288
|
+
vastTagUrl
|
|
1289
|
+
);
|
|
1290
|
+
} else {
|
|
1291
|
+
ad = await fetchAndParseVastAd(vastTagUrl);
|
|
1177
1292
|
}
|
|
1178
|
-
const vastXml = await response.text();
|
|
1179
|
-
console.log("[HlsAdPlayer] VAST XML received");
|
|
1180
|
-
console.log(
|
|
1181
|
-
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1182
|
-
vastXml.substring(0, 2e3)
|
|
1183
|
-
);
|
|
1184
|
-
const ad = parseVastXml(vastXml);
|
|
1185
1293
|
if (!ad) {
|
|
1186
1294
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1187
1295
|
emit("ad_error");
|
|
@@ -1200,6 +1308,37 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1200
1308
|
return Promise.reject(error);
|
|
1201
1309
|
}
|
|
1202
1310
|
},
|
|
1311
|
+
async preloadAds(vastTagUrl) {
|
|
1312
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
1313
|
+
return Promise.resolve();
|
|
1314
|
+
}
|
|
1315
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1316
|
+
return Promise.resolve();
|
|
1317
|
+
}
|
|
1318
|
+
const inflight = preloadingAds.get(vastTagUrl);
|
|
1319
|
+
if (inflight) {
|
|
1320
|
+
return inflight;
|
|
1321
|
+
}
|
|
1322
|
+
const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {
|
|
1323
|
+
if (ad) {
|
|
1324
|
+
preloadedAds.set(vastTagUrl, ad);
|
|
1325
|
+
console.log(
|
|
1326
|
+
"[HlsAdPlayer] Cached VAST response for preloading:",
|
|
1327
|
+
vastTagUrl
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
}).catch((error) => {
|
|
1331
|
+
console.warn("[HlsAdPlayer] Failed to preload VAST response:", error);
|
|
1332
|
+
preloadedAds.delete(vastTagUrl);
|
|
1333
|
+
}).finally(() => {
|
|
1334
|
+
preloadingAds.delete(vastTagUrl);
|
|
1335
|
+
});
|
|
1336
|
+
preloadingAds.set(vastTagUrl, preloadPromise);
|
|
1337
|
+
return preloadPromise;
|
|
1338
|
+
},
|
|
1339
|
+
hasPreloadedAd(vastTagUrl) {
|
|
1340
|
+
return preloadedAds.has(vastTagUrl);
|
|
1341
|
+
},
|
|
1203
1342
|
async play() {
|
|
1204
1343
|
if (!currentAd) {
|
|
1205
1344
|
console.warn(
|
|
@@ -1223,6 +1362,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1223
1362
|
complete: false
|
|
1224
1363
|
};
|
|
1225
1364
|
const contentVolume = contentVideo.volume;
|
|
1365
|
+
originalVolume = Math.max(
|
|
1366
|
+
0,
|
|
1367
|
+
Math.min(1, contentVolume || originalVolume)
|
|
1368
|
+
);
|
|
1226
1369
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1227
1370
|
contentVideo.pause();
|
|
1228
1371
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
@@ -1235,7 +1378,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1235
1378
|
adPlaying = true;
|
|
1236
1379
|
setAdPlayingFlag(true);
|
|
1237
1380
|
if (adVideoElement) {
|
|
1238
|
-
const adVolume = originalMutedState ? 0 :
|
|
1381
|
+
const adVolume = originalMutedState ? 0 : originalVolume;
|
|
1239
1382
|
adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
|
|
1240
1383
|
adVideoElement.muted = false;
|
|
1241
1384
|
console.log(
|
|
@@ -1314,6 +1457,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1314
1457
|
adPlaying = false;
|
|
1315
1458
|
setAdPlayingFlag(false);
|
|
1316
1459
|
contentVideo.muted = originalMutedState;
|
|
1460
|
+
contentVideo.volume = originalMutedState ? 0 : originalVolume;
|
|
1317
1461
|
if (adHls) {
|
|
1318
1462
|
adHls.destroy();
|
|
1319
1463
|
adHls = void 0;
|
|
@@ -1330,6 +1474,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1330
1474
|
adContainerEl = void 0;
|
|
1331
1475
|
currentAd = void 0;
|
|
1332
1476
|
listeners.clear();
|
|
1477
|
+
preloadedAds.clear();
|
|
1478
|
+
preloadingAds.clear();
|
|
1333
1479
|
},
|
|
1334
1480
|
isAdPlaying() {
|
|
1335
1481
|
return adPlaying;
|
|
@@ -1353,15 +1499,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1353
1499
|
var _a;
|
|
1354
1500
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1355
1501
|
},
|
|
1356
|
-
updateOriginalMutedState(muted) {
|
|
1502
|
+
updateOriginalMutedState(muted, volume) {
|
|
1503
|
+
const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
|
|
1357
1504
|
console.log(
|
|
1358
|
-
`[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
1505
|
+
`[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
|
|
1359
1506
|
);
|
|
1360
1507
|
originalMutedState = muted;
|
|
1508
|
+
originalVolume = nextVolume;
|
|
1361
1509
|
},
|
|
1362
1510
|
getOriginalMutedState() {
|
|
1363
1511
|
return originalMutedState;
|
|
1364
1512
|
},
|
|
1513
|
+
getOriginalVolume() {
|
|
1514
|
+
return originalVolume;
|
|
1515
|
+
},
|
|
1365
1516
|
setAdVolume(volume) {
|
|
1366
1517
|
if (adVideoElement && adPlaying) {
|
|
1367
1518
|
adVideoElement.volume = Math.max(0, Math.min(1, volume));
|
|
@@ -1372,6 +1523,35 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1372
1523
|
return adVideoElement.volume;
|
|
1373
1524
|
}
|
|
1374
1525
|
return 1;
|
|
1526
|
+
},
|
|
1527
|
+
showPlaceholder() {
|
|
1528
|
+
var _a;
|
|
1529
|
+
if (!adContainerEl) {
|
|
1530
|
+
const container = document.createElement("div");
|
|
1531
|
+
container.style.position = "absolute";
|
|
1532
|
+
container.style.left = "0";
|
|
1533
|
+
container.style.top = "0";
|
|
1534
|
+
container.style.right = "0";
|
|
1535
|
+
container.style.bottom = "0";
|
|
1536
|
+
container.style.display = "none";
|
|
1537
|
+
container.style.alignItems = "center";
|
|
1538
|
+
container.style.justifyContent = "center";
|
|
1539
|
+
container.style.pointerEvents = "none";
|
|
1540
|
+
container.style.zIndex = "10";
|
|
1541
|
+
container.style.backgroundColor = "#000";
|
|
1542
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
1543
|
+
adContainerEl = container;
|
|
1544
|
+
}
|
|
1545
|
+
if (adContainerEl) {
|
|
1546
|
+
adContainerEl.style.display = "flex";
|
|
1547
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1548
|
+
}
|
|
1549
|
+
},
|
|
1550
|
+
hidePlaceholder() {
|
|
1551
|
+
if (adContainerEl) {
|
|
1552
|
+
adContainerEl.style.display = "none";
|
|
1553
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1554
|
+
}
|
|
1375
1555
|
}
|
|
1376
1556
|
};
|
|
1377
1557
|
}
|
|
@@ -1852,6 +2032,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1852
2032
|
this.bufferedSegmentsCount = 0;
|
|
1853
2033
|
this.shouldAutoplayAfterBuffering = false;
|
|
1854
2034
|
this.hasInitialBufferCompleted = false;
|
|
2035
|
+
this.adPodAllUrls = [];
|
|
2036
|
+
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
1855
2037
|
initializePolyfills();
|
|
1856
2038
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1857
2039
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2111,7 +2293,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2111
2293
|
this.video.autoplay = !!this.config.autoplay;
|
|
2112
2294
|
this.video.muted = !!this.config.muted;
|
|
2113
2295
|
this.ima.initialize();
|
|
2114
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2296
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2115
2297
|
this.ima.on("all_ads_completed", () => {
|
|
2116
2298
|
if (this.config.debugAdTiming) {
|
|
2117
2299
|
console.log(
|
|
@@ -2152,6 +2334,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2152
2334
|
console.log("[StormcloudVideoPlayer] IMA content_pause event received");
|
|
2153
2335
|
}
|
|
2154
2336
|
this.clearAdFailsafeTimer();
|
|
2337
|
+
this.enforceAdHoldState();
|
|
2155
2338
|
});
|
|
2156
2339
|
this.ima.on("content_resume", () => {
|
|
2157
2340
|
if (this.config.debugAdTiming) {
|
|
@@ -2176,9 +2359,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2176
2359
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2177
2360
|
const next = this.adPodQueue.shift();
|
|
2178
2361
|
this.currentAdIndex++;
|
|
2179
|
-
this.
|
|
2180
|
-
this.video.muted = true;
|
|
2181
|
-
this.video.volume = 0;
|
|
2362
|
+
this.enforceAdHoldState();
|
|
2182
2363
|
if (this.config.debugAdTiming) {
|
|
2183
2364
|
console.log(
|
|
2184
2365
|
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
@@ -2790,11 +2971,16 @@ var StormcloudVideoPlayer = class {
|
|
|
2790
2971
|
return;
|
|
2791
2972
|
}
|
|
2792
2973
|
if (vastTagUrls.length > 0) {
|
|
2974
|
+
this.adPodAllUrls = [...vastTagUrls];
|
|
2975
|
+
this.preloadingAdUrls.clear();
|
|
2976
|
+
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
2793
2977
|
this.inAdBreak = true;
|
|
2794
2978
|
this.showAds = true;
|
|
2795
2979
|
this.currentAdIndex = 0;
|
|
2796
2980
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
2797
2981
|
this.adPodQueue = [...vastTagUrls];
|
|
2982
|
+
this.enforceAdHoldState();
|
|
2983
|
+
this.preloadUpcomingAds();
|
|
2798
2984
|
if (this.config.debugAdTiming) {
|
|
2799
2985
|
console.log(
|
|
2800
2986
|
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - will play continuously`
|
|
@@ -2865,6 +3051,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2865
3051
|
const first = tags[0];
|
|
2866
3052
|
const rest = tags.slice(1);
|
|
2867
3053
|
this.adPodQueue = rest;
|
|
3054
|
+
this.enforceAdHoldState();
|
|
2868
3055
|
await this.playSingleAd(first);
|
|
2869
3056
|
this.inAdBreak = true;
|
|
2870
3057
|
this.expectedAdBreakDurationMs = remainingMs;
|
|
@@ -2978,6 +3165,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2978
3165
|
}
|
|
2979
3166
|
return;
|
|
2980
3167
|
}
|
|
3168
|
+
const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
|
|
3169
|
+
if (wasPreloaded && this.config.debugAdTiming) {
|
|
3170
|
+
console.log(
|
|
3171
|
+
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3172
|
+
);
|
|
3173
|
+
}
|
|
2981
3174
|
if (!this.showAds) {
|
|
2982
3175
|
if (this.config.debugAdTiming) {
|
|
2983
3176
|
console.log(
|
|
@@ -2989,7 +3182,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2989
3182
|
}
|
|
2990
3183
|
);
|
|
2991
3184
|
}
|
|
2992
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3185
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2993
3186
|
} else if (this.config.debugAdTiming) {
|
|
2994
3187
|
console.log(
|
|
2995
3188
|
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
@@ -2998,12 +3191,14 @@ var StormcloudVideoPlayer = class {
|
|
|
2998
3191
|
this.startAdFailsafeTimer();
|
|
2999
3192
|
try {
|
|
3000
3193
|
await this.ima.requestAds(vastTagUrl);
|
|
3194
|
+
this.preloadUpcomingAds();
|
|
3001
3195
|
try {
|
|
3002
3196
|
if (this.config.debugAdTiming) {
|
|
3003
3197
|
console.log(
|
|
3004
3198
|
"[StormcloudVideoPlayer] Ad request completed, attempting playback"
|
|
3005
3199
|
);
|
|
3006
3200
|
}
|
|
3201
|
+
this.enforceAdHoldState();
|
|
3007
3202
|
await this.ima.play();
|
|
3008
3203
|
if (this.config.debugAdTiming) {
|
|
3009
3204
|
console.log(
|
|
@@ -3033,6 +3228,8 @@ var StormcloudVideoPlayer = class {
|
|
|
3033
3228
|
"[StormcloudVideoPlayer] Handling ad pod completion - resuming content and hiding ad layer"
|
|
3034
3229
|
);
|
|
3035
3230
|
}
|
|
3231
|
+
this.releaseAdHoldState();
|
|
3232
|
+
this.preloadingAdUrls.clear();
|
|
3036
3233
|
this.inAdBreak = false;
|
|
3037
3234
|
this.expectedAdBreakDurationMs = void 0;
|
|
3038
3235
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3040,14 +3237,16 @@ var StormcloudVideoPlayer = class {
|
|
|
3040
3237
|
this.clearAdStopTimer();
|
|
3041
3238
|
this.clearAdFailsafeTimer();
|
|
3042
3239
|
this.adPodQueue = [];
|
|
3240
|
+
this.adPodAllUrls = [];
|
|
3043
3241
|
this.showAds = false;
|
|
3044
3242
|
this.currentAdIndex = 0;
|
|
3045
3243
|
this.totalAdsInBreak = 0;
|
|
3046
3244
|
this.ima.stop().catch(() => {
|
|
3047
3245
|
});
|
|
3048
3246
|
const originalMutedState = this.ima.getOriginalMutedState();
|
|
3247
|
+
const originalVolume = typeof this.ima.getOriginalVolume === "function" ? this.ima.getOriginalVolume() : this.video.volume;
|
|
3049
3248
|
this.video.muted = originalMutedState;
|
|
3050
|
-
this.video.volume =
|
|
3249
|
+
this.video.volume = originalVolume;
|
|
3051
3250
|
if (this.config.debugAdTiming) {
|
|
3052
3251
|
console.log(
|
|
3053
3252
|
`[StormcloudVideoPlayer] Restored main video - muted: ${originalMutedState}, volume: ${this.video.volume}`
|
|
@@ -3120,6 +3319,64 @@ var StormcloudVideoPlayer = class {
|
|
|
3120
3319
|
}
|
|
3121
3320
|
return [b.vastTagUrl];
|
|
3122
3321
|
}
|
|
3322
|
+
logQueuedAdUrls(urls) {
|
|
3323
|
+
if (!this.config.debugAdTiming) {
|
|
3324
|
+
return;
|
|
3325
|
+
}
|
|
3326
|
+
console.log("[StormcloudVideoPlayer] ALL ad URLs queued:", urls);
|
|
3327
|
+
}
|
|
3328
|
+
enforceAdHoldState() {
|
|
3329
|
+
this.video.dataset.stormcloudAdPlaying = "true";
|
|
3330
|
+
this.video.muted = true;
|
|
3331
|
+
this.video.volume = 0;
|
|
3332
|
+
if (typeof this.ima.showPlaceholder === "function") {
|
|
3333
|
+
this.ima.showPlaceholder();
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
releaseAdHoldState() {
|
|
3337
|
+
delete this.video.dataset.stormcloudAdPlaying;
|
|
3338
|
+
if (typeof this.ima.hidePlaceholder === "function") {
|
|
3339
|
+
this.ima.hidePlaceholder();
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
preloadUpcomingAds() {
|
|
3343
|
+
if (!this.ima.preloadAds || this.adPodQueue.length === 0) {
|
|
3344
|
+
return;
|
|
3345
|
+
}
|
|
3346
|
+
const upcoming = this.adPodQueue.slice(0, 2);
|
|
3347
|
+
for (const url of upcoming) {
|
|
3348
|
+
if (!url) continue;
|
|
3349
|
+
if (this.ima.hasPreloadedAd(url)) {
|
|
3350
|
+
this.preloadingAdUrls.delete(url);
|
|
3351
|
+
continue;
|
|
3352
|
+
}
|
|
3353
|
+
if (this.preloadingAdUrls.has(url)) {
|
|
3354
|
+
continue;
|
|
3355
|
+
}
|
|
3356
|
+
if (this.config.debugAdTiming) {
|
|
3357
|
+
console.log(
|
|
3358
|
+
`[StormcloudVideoPlayer] Scheduling IMA preload for upcoming ad: ${url}`
|
|
3359
|
+
);
|
|
3360
|
+
}
|
|
3361
|
+
this.preloadingAdUrls.add(url);
|
|
3362
|
+
this.ima.preloadAds(url).then(() => {
|
|
3363
|
+
if (this.config.debugAdTiming) {
|
|
3364
|
+
console.log(
|
|
3365
|
+
`[StormcloudVideoPlayer] IMA preload complete for ad: ${url}`
|
|
3366
|
+
);
|
|
3367
|
+
}
|
|
3368
|
+
}).catch((error) => {
|
|
3369
|
+
if (this.config.debugAdTiming) {
|
|
3370
|
+
console.warn(
|
|
3371
|
+
`[StormcloudVideoPlayer] IMA preload failed for ad: ${url}`,
|
|
3372
|
+
error
|
|
3373
|
+
);
|
|
3374
|
+
}
|
|
3375
|
+
}).finally(() => {
|
|
3376
|
+
this.preloadingAdUrls.delete(url);
|
|
3377
|
+
});
|
|
3378
|
+
}
|
|
3379
|
+
}
|
|
3123
3380
|
getRemainingAdMs() {
|
|
3124
3381
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
3125
3382
|
return 0;
|
|
@@ -3140,7 +3397,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3140
3397
|
if (this.ima.isAdPlaying()) {
|
|
3141
3398
|
const currentPerceptualState = this.isMuted();
|
|
3142
3399
|
const newMutedState = !currentPerceptualState;
|
|
3143
|
-
this.ima.updateOriginalMutedState(newMutedState);
|
|
3400
|
+
this.ima.updateOriginalMutedState(newMutedState, this.video.volume);
|
|
3144
3401
|
this.ima.setAdVolume(newMutedState ? 0 : 1);
|
|
3145
3402
|
if (this.config.debugAdTiming) {
|
|
3146
3403
|
console.log(
|
|
@@ -3150,7 +3407,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3150
3407
|
}
|
|
3151
3408
|
} else {
|
|
3152
3409
|
this.video.muted = !this.video.muted;
|
|
3153
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3410
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3154
3411
|
if (this.config.debugAdTiming) {
|
|
3155
3412
|
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
3156
3413
|
}
|
|
@@ -3222,7 +3479,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3222
3479
|
}
|
|
3223
3480
|
this.video.muted = muted;
|
|
3224
3481
|
if (adPlaying) {
|
|
3225
|
-
this.ima.updateOriginalMutedState(muted);
|
|
3482
|
+
this.ima.updateOriginalMutedState(muted, this.video.volume);
|
|
3226
3483
|
this.ima.setAdVolume(muted ? 0 : 1);
|
|
3227
3484
|
if (this.config.debugAdTiming) {
|
|
3228
3485
|
console.log("[StormcloudVideoPlayer] setMuted applied during ad", {
|
|
@@ -3231,7 +3488,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3231
3488
|
}
|
|
3232
3489
|
return;
|
|
3233
3490
|
}
|
|
3234
|
-
this.ima.updateOriginalMutedState(muted);
|
|
3491
|
+
this.ima.updateOriginalMutedState(muted, this.video.volume);
|
|
3235
3492
|
if (this.config.debugAdTiming) {
|
|
3236
3493
|
console.log("[StormcloudVideoPlayer] setMuted called:", muted);
|
|
3237
3494
|
}
|
|
@@ -3271,6 +3528,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3271
3528
|
}
|
|
3272
3529
|
(_a = this.hls) == null ? void 0 : _a.destroy();
|
|
3273
3530
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3531
|
+
this.releaseAdHoldState();
|
|
3532
|
+
this.preloadingAdUrls.clear();
|
|
3533
|
+
this.adPodAllUrls = [];
|
|
3274
3534
|
}
|
|
3275
3535
|
};
|
|
3276
3536
|
|