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
package/lib/index.js
CHANGED
|
@@ -197,7 +197,10 @@ function supportsFeature(feature) {
|
|
|
197
197
|
function createImaController(video, options) {
|
|
198
198
|
let adPlaying = false;
|
|
199
199
|
let originalMutedState = false;
|
|
200
|
+
let originalVolume = typeof video.volume === "number" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;
|
|
200
201
|
const listeners = /* @__PURE__ */ new Map();
|
|
202
|
+
const preloadedVast = /* @__PURE__ */ new Map();
|
|
203
|
+
const preloadingVast = /* @__PURE__ */ new Map();
|
|
201
204
|
function setAdPlayingFlag(isPlaying) {
|
|
202
205
|
if (isPlaying) {
|
|
203
206
|
video.dataset.stormcloudAdPlaying = "true";
|
|
@@ -288,16 +291,70 @@ function createImaController(video, options) {
|
|
|
288
291
|
let adsLoadedReject;
|
|
289
292
|
function makeAdsRequest(google, vastTagUrl) {
|
|
290
293
|
const adsRequest = new google.ima.AdsRequest();
|
|
291
|
-
|
|
294
|
+
const preloadedResponse = preloadedVast.get(vastTagUrl);
|
|
295
|
+
if (preloadedResponse) {
|
|
296
|
+
adsRequest.adsResponse = preloadedResponse;
|
|
297
|
+
console.log(
|
|
298
|
+
"[IMA] Using preloaded VAST response for immediate ad request"
|
|
299
|
+
);
|
|
300
|
+
} else {
|
|
301
|
+
adsRequest.adTagUrl = vastTagUrl;
|
|
302
|
+
}
|
|
292
303
|
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
293
304
|
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
294
305
|
adsRequest.linearAdSlotWidth = videoWidth;
|
|
295
306
|
adsRequest.linearAdSlotHeight = videoHeight;
|
|
296
307
|
adsRequest.nonLinearAdSlotWidth = videoWidth;
|
|
297
308
|
adsRequest.nonLinearAdSlotHeight = videoHeight;
|
|
309
|
+
if (typeof adsRequest.setAdWillAutoPlay === "function") {
|
|
310
|
+
try {
|
|
311
|
+
const willAutoPlay = !video.paused || video.autoplay;
|
|
312
|
+
adsRequest.setAdWillAutoPlay(willAutoPlay);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.warn("[IMA] Failed to call setAdWillAutoPlay:", error);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (typeof adsRequest.setAdWillPlayMuted === "function") {
|
|
318
|
+
try {
|
|
319
|
+
const willPlayMuted = video.muted || video.volume === 0;
|
|
320
|
+
adsRequest.setAdWillPlayMuted(willPlayMuted);
|
|
321
|
+
} catch (error) {
|
|
322
|
+
console.warn("[IMA] Failed to call setAdWillPlayMuted:", error);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
298
325
|
adsRequest.vastLoadTimeout = 5e3;
|
|
299
326
|
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
300
327
|
adsLoader.requestAds(adsRequest);
|
|
328
|
+
if (preloadedResponse) {
|
|
329
|
+
preloadedVast.delete(vastTagUrl);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function ensurePlaceholderContainer() {
|
|
333
|
+
var _a;
|
|
334
|
+
if (adContainerEl) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
const container = document.createElement("div");
|
|
338
|
+
container.style.position = "absolute";
|
|
339
|
+
container.style.left = "0";
|
|
340
|
+
container.style.top = "0";
|
|
341
|
+
container.style.right = "0";
|
|
342
|
+
container.style.bottom = "0";
|
|
343
|
+
container.style.display = "none";
|
|
344
|
+
container.style.alignItems = "center";
|
|
345
|
+
container.style.justifyContent = "center";
|
|
346
|
+
container.style.pointerEvents = "none";
|
|
347
|
+
container.style.zIndex = "10";
|
|
348
|
+
container.style.backgroundColor = "#000";
|
|
349
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
350
|
+
adContainerEl = container;
|
|
351
|
+
}
|
|
352
|
+
async function fetchVastDocument(vastTagUrl) {
|
|
353
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
354
|
+
if (!response.ok) {
|
|
355
|
+
throw new Error(`Failed to preload VAST: ${response.status}`);
|
|
356
|
+
}
|
|
357
|
+
return response.text();
|
|
301
358
|
}
|
|
302
359
|
function destroyAdsManager() {
|
|
303
360
|
if (adsManager) {
|
|
@@ -313,29 +370,16 @@ function createImaController(video, options) {
|
|
|
313
370
|
return {
|
|
314
371
|
initialize() {
|
|
315
372
|
ensureImaLoaded().then(() => {
|
|
316
|
-
var _a
|
|
373
|
+
var _a;
|
|
317
374
|
const google = window.google;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
container.style.position = "absolute";
|
|
321
|
-
container.style.left = "0";
|
|
322
|
-
container.style.top = "0";
|
|
323
|
-
container.style.right = "0";
|
|
324
|
-
container.style.bottom = "0";
|
|
325
|
-
container.style.display = "none";
|
|
326
|
-
container.style.alignItems = "center";
|
|
327
|
-
container.style.justifyContent = "center";
|
|
328
|
-
container.style.pointerEvents = "none";
|
|
329
|
-
container.style.zIndex = "10";
|
|
330
|
-
container.style.backgroundColor = "#000";
|
|
331
|
-
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
332
|
-
adContainerEl = container;
|
|
375
|
+
ensurePlaceholderContainer();
|
|
376
|
+
if (!adDisplayContainer && adContainerEl) {
|
|
333
377
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
334
|
-
|
|
378
|
+
adContainerEl,
|
|
335
379
|
video
|
|
336
380
|
);
|
|
337
381
|
try {
|
|
338
|
-
(
|
|
382
|
+
(_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
|
|
339
383
|
} catch {
|
|
340
384
|
}
|
|
341
385
|
}
|
|
@@ -639,6 +683,32 @@ function createImaController(video, options) {
|
|
|
639
683
|
return Promise.reject(error);
|
|
640
684
|
}
|
|
641
685
|
},
|
|
686
|
+
async preloadAds(vastTagUrl) {
|
|
687
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
688
|
+
return Promise.resolve();
|
|
689
|
+
}
|
|
690
|
+
if (preloadedVast.has(vastTagUrl)) {
|
|
691
|
+
return Promise.resolve();
|
|
692
|
+
}
|
|
693
|
+
const inflight = preloadingVast.get(vastTagUrl);
|
|
694
|
+
if (inflight) {
|
|
695
|
+
return inflight;
|
|
696
|
+
}
|
|
697
|
+
const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
|
|
698
|
+
preloadedVast.set(vastTagUrl, xml);
|
|
699
|
+
console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
|
|
700
|
+
}).catch((error) => {
|
|
701
|
+
console.warn("[IMA] Failed to preload VAST response:", error);
|
|
702
|
+
preloadedVast.delete(vastTagUrl);
|
|
703
|
+
}).finally(() => {
|
|
704
|
+
preloadingVast.delete(vastTagUrl);
|
|
705
|
+
});
|
|
706
|
+
preloadingVast.set(vastTagUrl, preloadPromise);
|
|
707
|
+
return preloadPromise;
|
|
708
|
+
},
|
|
709
|
+
hasPreloadedAd(vastTagUrl) {
|
|
710
|
+
return preloadedVast.has(vastTagUrl);
|
|
711
|
+
},
|
|
642
712
|
async play() {
|
|
643
713
|
var _a, _b;
|
|
644
714
|
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
@@ -657,7 +727,7 @@ function createImaController(video, options) {
|
|
|
657
727
|
console.log(`[IMA] Initializing ads manager (${width}x${height})`);
|
|
658
728
|
adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
|
|
659
729
|
adPlaying = true;
|
|
660
|
-
const adVolume = originalMutedState ? 0 :
|
|
730
|
+
const adVolume = originalMutedState ? 0 : originalVolume;
|
|
661
731
|
try {
|
|
662
732
|
adsManager.setVolume(adVolume);
|
|
663
733
|
console.log(`[IMA] Set ad volume to ${adVolume}`);
|
|
@@ -699,6 +769,7 @@ function createImaController(video, options) {
|
|
|
699
769
|
destroyAdsManager();
|
|
700
770
|
adPlaying = false;
|
|
701
771
|
video.muted = originalMutedState;
|
|
772
|
+
video.volume = originalVolume;
|
|
702
773
|
setAdPlayingFlag(false);
|
|
703
774
|
if (adContainerEl) {
|
|
704
775
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -714,6 +785,8 @@ function createImaController(video, options) {
|
|
|
714
785
|
adContainerEl = void 0;
|
|
715
786
|
adDisplayContainer = void 0;
|
|
716
787
|
adsLoader = void 0;
|
|
788
|
+
preloadedVast.clear();
|
|
789
|
+
preloadingVast.clear();
|
|
717
790
|
},
|
|
718
791
|
isAdPlaying() {
|
|
719
792
|
return adPlaying;
|
|
@@ -741,15 +814,20 @@ function createImaController(video, options) {
|
|
|
741
814
|
var _a;
|
|
742
815
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
743
816
|
},
|
|
744
|
-
updateOriginalMutedState(muted) {
|
|
817
|
+
updateOriginalMutedState(muted, volume) {
|
|
818
|
+
const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
|
|
745
819
|
console.log(
|
|
746
|
-
`[IMA] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
820
|
+
`[IMA] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
|
|
747
821
|
);
|
|
748
822
|
originalMutedState = muted;
|
|
823
|
+
originalVolume = nextVolume;
|
|
749
824
|
},
|
|
750
825
|
getOriginalMutedState() {
|
|
751
826
|
return originalMutedState;
|
|
752
827
|
},
|
|
828
|
+
getOriginalVolume() {
|
|
829
|
+
return originalVolume;
|
|
830
|
+
},
|
|
753
831
|
setAdVolume(volume) {
|
|
754
832
|
if (adsManager && adPlaying) {
|
|
755
833
|
try {
|
|
@@ -769,6 +847,19 @@ function createImaController(video, options) {
|
|
|
769
847
|
}
|
|
770
848
|
}
|
|
771
849
|
return 1;
|
|
850
|
+
},
|
|
851
|
+
showPlaceholder() {
|
|
852
|
+
ensurePlaceholderContainer();
|
|
853
|
+
if (adContainerEl) {
|
|
854
|
+
adContainerEl.style.display = "flex";
|
|
855
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
856
|
+
}
|
|
857
|
+
},
|
|
858
|
+
hidePlaceholder() {
|
|
859
|
+
if (adContainerEl) {
|
|
860
|
+
adContainerEl.style.display = "none";
|
|
861
|
+
adContainerEl.style.pointerEvents = "none";
|
|
862
|
+
}
|
|
772
863
|
}
|
|
773
864
|
};
|
|
774
865
|
}
|
|
@@ -778,6 +869,7 @@ import Hls from "hls.js";
|
|
|
778
869
|
function createHlsAdPlayer(contentVideo, options) {
|
|
779
870
|
let adPlaying = false;
|
|
780
871
|
let originalMutedState = false;
|
|
872
|
+
let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
|
|
781
873
|
const listeners = /* @__PURE__ */ new Map();
|
|
782
874
|
const licenseKey = options == null ? void 0 : options.licenseKey;
|
|
783
875
|
const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
|
|
@@ -786,6 +878,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
786
878
|
let adContainerEl;
|
|
787
879
|
let currentAd;
|
|
788
880
|
let sessionId;
|
|
881
|
+
const preloadedAds = /* @__PURE__ */ new Map();
|
|
882
|
+
const preloadingAds = /* @__PURE__ */ new Map();
|
|
789
883
|
let trackingFired = {
|
|
790
884
|
impression: false,
|
|
791
885
|
start: false,
|
|
@@ -1015,6 +1109,19 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1015
1109
|
return null;
|
|
1016
1110
|
}
|
|
1017
1111
|
}
|
|
1112
|
+
async function fetchAndParseVastAd(vastTagUrl) {
|
|
1113
|
+
const response = await fetch(vastTagUrl);
|
|
1114
|
+
if (!response.ok) {
|
|
1115
|
+
throw new Error(`Failed to fetch VAST: ${response.statusText}`);
|
|
1116
|
+
}
|
|
1117
|
+
const vastXml = await response.text();
|
|
1118
|
+
console.log("[HlsAdPlayer] VAST XML received");
|
|
1119
|
+
console.log(
|
|
1120
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1121
|
+
vastXml.substring(0, 2e3)
|
|
1122
|
+
);
|
|
1123
|
+
return parseVastXml(vastXml);
|
|
1124
|
+
}
|
|
1018
1125
|
function createAdVideoElement() {
|
|
1019
1126
|
const video = document.createElement("video");
|
|
1020
1127
|
video.style.position = "absolute";
|
|
@@ -1120,6 +1227,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1120
1227
|
setAdPlayingFlag(false);
|
|
1121
1228
|
const previousMutedState = contentVideo.muted;
|
|
1122
1229
|
contentVideo.muted = originalMutedState;
|
|
1230
|
+
contentVideo.volume = originalMutedState ? 0 : originalVolume;
|
|
1123
1231
|
console.log(
|
|
1124
1232
|
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1125
1233
|
);
|
|
@@ -1166,17 +1274,17 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1166
1274
|
}
|
|
1167
1275
|
try {
|
|
1168
1276
|
sessionId = generateSessionId();
|
|
1169
|
-
|
|
1170
|
-
if (
|
|
1171
|
-
|
|
1277
|
+
let ad;
|
|
1278
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1279
|
+
ad = preloadedAds.get(vastTagUrl);
|
|
1280
|
+
preloadedAds.delete(vastTagUrl);
|
|
1281
|
+
console.log(
|
|
1282
|
+
"[HlsAdPlayer] Using preloaded VAST response:",
|
|
1283
|
+
vastTagUrl
|
|
1284
|
+
);
|
|
1285
|
+
} else {
|
|
1286
|
+
ad = await fetchAndParseVastAd(vastTagUrl);
|
|
1172
1287
|
}
|
|
1173
|
-
const vastXml = await response.text();
|
|
1174
|
-
console.log("[HlsAdPlayer] VAST XML received");
|
|
1175
|
-
console.log(
|
|
1176
|
-
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1177
|
-
vastXml.substring(0, 2e3)
|
|
1178
|
-
);
|
|
1179
|
-
const ad = parseVastXml(vastXml);
|
|
1180
1288
|
if (!ad) {
|
|
1181
1289
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1182
1290
|
emit("ad_error");
|
|
@@ -1195,6 +1303,37 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1195
1303
|
return Promise.reject(error);
|
|
1196
1304
|
}
|
|
1197
1305
|
},
|
|
1306
|
+
async preloadAds(vastTagUrl) {
|
|
1307
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
1308
|
+
return Promise.resolve();
|
|
1309
|
+
}
|
|
1310
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1311
|
+
return Promise.resolve();
|
|
1312
|
+
}
|
|
1313
|
+
const inflight = preloadingAds.get(vastTagUrl);
|
|
1314
|
+
if (inflight) {
|
|
1315
|
+
return inflight;
|
|
1316
|
+
}
|
|
1317
|
+
const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {
|
|
1318
|
+
if (ad) {
|
|
1319
|
+
preloadedAds.set(vastTagUrl, ad);
|
|
1320
|
+
console.log(
|
|
1321
|
+
"[HlsAdPlayer] Cached VAST response for preloading:",
|
|
1322
|
+
vastTagUrl
|
|
1323
|
+
);
|
|
1324
|
+
}
|
|
1325
|
+
}).catch((error) => {
|
|
1326
|
+
console.warn("[HlsAdPlayer] Failed to preload VAST response:", error);
|
|
1327
|
+
preloadedAds.delete(vastTagUrl);
|
|
1328
|
+
}).finally(() => {
|
|
1329
|
+
preloadingAds.delete(vastTagUrl);
|
|
1330
|
+
});
|
|
1331
|
+
preloadingAds.set(vastTagUrl, preloadPromise);
|
|
1332
|
+
return preloadPromise;
|
|
1333
|
+
},
|
|
1334
|
+
hasPreloadedAd(vastTagUrl) {
|
|
1335
|
+
return preloadedAds.has(vastTagUrl);
|
|
1336
|
+
},
|
|
1198
1337
|
async play() {
|
|
1199
1338
|
if (!currentAd) {
|
|
1200
1339
|
console.warn(
|
|
@@ -1218,6 +1357,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1218
1357
|
complete: false
|
|
1219
1358
|
};
|
|
1220
1359
|
const contentVolume = contentVideo.volume;
|
|
1360
|
+
originalVolume = Math.max(
|
|
1361
|
+
0,
|
|
1362
|
+
Math.min(1, contentVolume || originalVolume)
|
|
1363
|
+
);
|
|
1221
1364
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1222
1365
|
contentVideo.pause();
|
|
1223
1366
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
@@ -1230,7 +1373,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1230
1373
|
adPlaying = true;
|
|
1231
1374
|
setAdPlayingFlag(true);
|
|
1232
1375
|
if (adVideoElement) {
|
|
1233
|
-
const adVolume = originalMutedState ? 0 :
|
|
1376
|
+
const adVolume = originalMutedState ? 0 : originalVolume;
|
|
1234
1377
|
adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
|
|
1235
1378
|
adVideoElement.muted = false;
|
|
1236
1379
|
console.log(
|
|
@@ -1309,6 +1452,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1309
1452
|
adPlaying = false;
|
|
1310
1453
|
setAdPlayingFlag(false);
|
|
1311
1454
|
contentVideo.muted = originalMutedState;
|
|
1455
|
+
contentVideo.volume = originalMutedState ? 0 : originalVolume;
|
|
1312
1456
|
if (adHls) {
|
|
1313
1457
|
adHls.destroy();
|
|
1314
1458
|
adHls = void 0;
|
|
@@ -1325,6 +1469,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1325
1469
|
adContainerEl = void 0;
|
|
1326
1470
|
currentAd = void 0;
|
|
1327
1471
|
listeners.clear();
|
|
1472
|
+
preloadedAds.clear();
|
|
1473
|
+
preloadingAds.clear();
|
|
1328
1474
|
},
|
|
1329
1475
|
isAdPlaying() {
|
|
1330
1476
|
return adPlaying;
|
|
@@ -1348,15 +1494,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1348
1494
|
var _a;
|
|
1349
1495
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1350
1496
|
},
|
|
1351
|
-
updateOriginalMutedState(muted) {
|
|
1497
|
+
updateOriginalMutedState(muted, volume) {
|
|
1498
|
+
const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
|
|
1352
1499
|
console.log(
|
|
1353
|
-
`[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
1500
|
+
`[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
|
|
1354
1501
|
);
|
|
1355
1502
|
originalMutedState = muted;
|
|
1503
|
+
originalVolume = nextVolume;
|
|
1356
1504
|
},
|
|
1357
1505
|
getOriginalMutedState() {
|
|
1358
1506
|
return originalMutedState;
|
|
1359
1507
|
},
|
|
1508
|
+
getOriginalVolume() {
|
|
1509
|
+
return originalVolume;
|
|
1510
|
+
},
|
|
1360
1511
|
setAdVolume(volume) {
|
|
1361
1512
|
if (adVideoElement && adPlaying) {
|
|
1362
1513
|
adVideoElement.volume = Math.max(0, Math.min(1, volume));
|
|
@@ -1367,6 +1518,35 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1367
1518
|
return adVideoElement.volume;
|
|
1368
1519
|
}
|
|
1369
1520
|
return 1;
|
|
1521
|
+
},
|
|
1522
|
+
showPlaceholder() {
|
|
1523
|
+
var _a;
|
|
1524
|
+
if (!adContainerEl) {
|
|
1525
|
+
const container = document.createElement("div");
|
|
1526
|
+
container.style.position = "absolute";
|
|
1527
|
+
container.style.left = "0";
|
|
1528
|
+
container.style.top = "0";
|
|
1529
|
+
container.style.right = "0";
|
|
1530
|
+
container.style.bottom = "0";
|
|
1531
|
+
container.style.display = "none";
|
|
1532
|
+
container.style.alignItems = "center";
|
|
1533
|
+
container.style.justifyContent = "center";
|
|
1534
|
+
container.style.pointerEvents = "none";
|
|
1535
|
+
container.style.zIndex = "10";
|
|
1536
|
+
container.style.backgroundColor = "#000";
|
|
1537
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
1538
|
+
adContainerEl = container;
|
|
1539
|
+
}
|
|
1540
|
+
if (adContainerEl) {
|
|
1541
|
+
adContainerEl.style.display = "flex";
|
|
1542
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1543
|
+
}
|
|
1544
|
+
},
|
|
1545
|
+
hidePlaceholder() {
|
|
1546
|
+
if (adContainerEl) {
|
|
1547
|
+
adContainerEl.style.display = "none";
|
|
1548
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1549
|
+
}
|
|
1370
1550
|
}
|
|
1371
1551
|
};
|
|
1372
1552
|
}
|
|
@@ -1847,6 +2027,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1847
2027
|
this.bufferedSegmentsCount = 0;
|
|
1848
2028
|
this.shouldAutoplayAfterBuffering = false;
|
|
1849
2029
|
this.hasInitialBufferCompleted = false;
|
|
2030
|
+
this.adPodAllUrls = [];
|
|
2031
|
+
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
1850
2032
|
initializePolyfills();
|
|
1851
2033
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1852
2034
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2106,7 +2288,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2106
2288
|
this.video.autoplay = !!this.config.autoplay;
|
|
2107
2289
|
this.video.muted = !!this.config.muted;
|
|
2108
2290
|
this.ima.initialize();
|
|
2109
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2291
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2110
2292
|
this.ima.on("all_ads_completed", () => {
|
|
2111
2293
|
if (this.config.debugAdTiming) {
|
|
2112
2294
|
console.log(
|
|
@@ -2147,6 +2329,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2147
2329
|
console.log("[StormcloudVideoPlayer] IMA content_pause event received");
|
|
2148
2330
|
}
|
|
2149
2331
|
this.clearAdFailsafeTimer();
|
|
2332
|
+
this.enforceAdHoldState();
|
|
2150
2333
|
});
|
|
2151
2334
|
this.ima.on("content_resume", () => {
|
|
2152
2335
|
if (this.config.debugAdTiming) {
|
|
@@ -2171,9 +2354,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2171
2354
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2172
2355
|
const next = this.adPodQueue.shift();
|
|
2173
2356
|
this.currentAdIndex++;
|
|
2174
|
-
this.
|
|
2175
|
-
this.video.muted = true;
|
|
2176
|
-
this.video.volume = 0;
|
|
2357
|
+
this.enforceAdHoldState();
|
|
2177
2358
|
if (this.config.debugAdTiming) {
|
|
2178
2359
|
console.log(
|
|
2179
2360
|
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
@@ -2785,11 +2966,16 @@ var StormcloudVideoPlayer = class {
|
|
|
2785
2966
|
return;
|
|
2786
2967
|
}
|
|
2787
2968
|
if (vastTagUrls.length > 0) {
|
|
2969
|
+
this.adPodAllUrls = [...vastTagUrls];
|
|
2970
|
+
this.preloadingAdUrls.clear();
|
|
2971
|
+
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
2788
2972
|
this.inAdBreak = true;
|
|
2789
2973
|
this.showAds = true;
|
|
2790
2974
|
this.currentAdIndex = 0;
|
|
2791
2975
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
2792
2976
|
this.adPodQueue = [...vastTagUrls];
|
|
2977
|
+
this.enforceAdHoldState();
|
|
2978
|
+
this.preloadUpcomingAds();
|
|
2793
2979
|
if (this.config.debugAdTiming) {
|
|
2794
2980
|
console.log(
|
|
2795
2981
|
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - will play continuously`
|
|
@@ -2860,6 +3046,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2860
3046
|
const first = tags[0];
|
|
2861
3047
|
const rest = tags.slice(1);
|
|
2862
3048
|
this.adPodQueue = rest;
|
|
3049
|
+
this.enforceAdHoldState();
|
|
2863
3050
|
await this.playSingleAd(first);
|
|
2864
3051
|
this.inAdBreak = true;
|
|
2865
3052
|
this.expectedAdBreakDurationMs = remainingMs;
|
|
@@ -2973,6 +3160,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2973
3160
|
}
|
|
2974
3161
|
return;
|
|
2975
3162
|
}
|
|
3163
|
+
const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
|
|
3164
|
+
if (wasPreloaded && this.config.debugAdTiming) {
|
|
3165
|
+
console.log(
|
|
3166
|
+
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3167
|
+
);
|
|
3168
|
+
}
|
|
2976
3169
|
if (!this.showAds) {
|
|
2977
3170
|
if (this.config.debugAdTiming) {
|
|
2978
3171
|
console.log(
|
|
@@ -2984,7 +3177,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2984
3177
|
}
|
|
2985
3178
|
);
|
|
2986
3179
|
}
|
|
2987
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3180
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2988
3181
|
} else if (this.config.debugAdTiming) {
|
|
2989
3182
|
console.log(
|
|
2990
3183
|
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
@@ -2993,12 +3186,14 @@ var StormcloudVideoPlayer = class {
|
|
|
2993
3186
|
this.startAdFailsafeTimer();
|
|
2994
3187
|
try {
|
|
2995
3188
|
await this.ima.requestAds(vastTagUrl);
|
|
3189
|
+
this.preloadUpcomingAds();
|
|
2996
3190
|
try {
|
|
2997
3191
|
if (this.config.debugAdTiming) {
|
|
2998
3192
|
console.log(
|
|
2999
3193
|
"[StormcloudVideoPlayer] Ad request completed, attempting playback"
|
|
3000
3194
|
);
|
|
3001
3195
|
}
|
|
3196
|
+
this.enforceAdHoldState();
|
|
3002
3197
|
await this.ima.play();
|
|
3003
3198
|
if (this.config.debugAdTiming) {
|
|
3004
3199
|
console.log(
|
|
@@ -3028,6 +3223,8 @@ var StormcloudVideoPlayer = class {
|
|
|
3028
3223
|
"[StormcloudVideoPlayer] Handling ad pod completion - resuming content and hiding ad layer"
|
|
3029
3224
|
);
|
|
3030
3225
|
}
|
|
3226
|
+
this.releaseAdHoldState();
|
|
3227
|
+
this.preloadingAdUrls.clear();
|
|
3031
3228
|
this.inAdBreak = false;
|
|
3032
3229
|
this.expectedAdBreakDurationMs = void 0;
|
|
3033
3230
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3035,14 +3232,16 @@ var StormcloudVideoPlayer = class {
|
|
|
3035
3232
|
this.clearAdStopTimer();
|
|
3036
3233
|
this.clearAdFailsafeTimer();
|
|
3037
3234
|
this.adPodQueue = [];
|
|
3235
|
+
this.adPodAllUrls = [];
|
|
3038
3236
|
this.showAds = false;
|
|
3039
3237
|
this.currentAdIndex = 0;
|
|
3040
3238
|
this.totalAdsInBreak = 0;
|
|
3041
3239
|
this.ima.stop().catch(() => {
|
|
3042
3240
|
});
|
|
3043
3241
|
const originalMutedState = this.ima.getOriginalMutedState();
|
|
3242
|
+
const originalVolume = typeof this.ima.getOriginalVolume === "function" ? this.ima.getOriginalVolume() : this.video.volume;
|
|
3044
3243
|
this.video.muted = originalMutedState;
|
|
3045
|
-
this.video.volume =
|
|
3244
|
+
this.video.volume = originalVolume;
|
|
3046
3245
|
if (this.config.debugAdTiming) {
|
|
3047
3246
|
console.log(
|
|
3048
3247
|
`[StormcloudVideoPlayer] Restored main video - muted: ${originalMutedState}, volume: ${this.video.volume}`
|
|
@@ -3115,6 +3314,64 @@ var StormcloudVideoPlayer = class {
|
|
|
3115
3314
|
}
|
|
3116
3315
|
return [b.vastTagUrl];
|
|
3117
3316
|
}
|
|
3317
|
+
logQueuedAdUrls(urls) {
|
|
3318
|
+
if (!this.config.debugAdTiming) {
|
|
3319
|
+
return;
|
|
3320
|
+
}
|
|
3321
|
+
console.log("[StormcloudVideoPlayer] ALL ad URLs queued:", urls);
|
|
3322
|
+
}
|
|
3323
|
+
enforceAdHoldState() {
|
|
3324
|
+
this.video.dataset.stormcloudAdPlaying = "true";
|
|
3325
|
+
this.video.muted = true;
|
|
3326
|
+
this.video.volume = 0;
|
|
3327
|
+
if (typeof this.ima.showPlaceholder === "function") {
|
|
3328
|
+
this.ima.showPlaceholder();
|
|
3329
|
+
}
|
|
3330
|
+
}
|
|
3331
|
+
releaseAdHoldState() {
|
|
3332
|
+
delete this.video.dataset.stormcloudAdPlaying;
|
|
3333
|
+
if (typeof this.ima.hidePlaceholder === "function") {
|
|
3334
|
+
this.ima.hidePlaceholder();
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
preloadUpcomingAds() {
|
|
3338
|
+
if (!this.ima.preloadAds || this.adPodQueue.length === 0) {
|
|
3339
|
+
return;
|
|
3340
|
+
}
|
|
3341
|
+
const upcoming = this.adPodQueue.slice(0, 2);
|
|
3342
|
+
for (const url of upcoming) {
|
|
3343
|
+
if (!url) continue;
|
|
3344
|
+
if (this.ima.hasPreloadedAd(url)) {
|
|
3345
|
+
this.preloadingAdUrls.delete(url);
|
|
3346
|
+
continue;
|
|
3347
|
+
}
|
|
3348
|
+
if (this.preloadingAdUrls.has(url)) {
|
|
3349
|
+
continue;
|
|
3350
|
+
}
|
|
3351
|
+
if (this.config.debugAdTiming) {
|
|
3352
|
+
console.log(
|
|
3353
|
+
`[StormcloudVideoPlayer] Scheduling IMA preload for upcoming ad: ${url}`
|
|
3354
|
+
);
|
|
3355
|
+
}
|
|
3356
|
+
this.preloadingAdUrls.add(url);
|
|
3357
|
+
this.ima.preloadAds(url).then(() => {
|
|
3358
|
+
if (this.config.debugAdTiming) {
|
|
3359
|
+
console.log(
|
|
3360
|
+
`[StormcloudVideoPlayer] IMA preload complete for ad: ${url}`
|
|
3361
|
+
);
|
|
3362
|
+
}
|
|
3363
|
+
}).catch((error) => {
|
|
3364
|
+
if (this.config.debugAdTiming) {
|
|
3365
|
+
console.warn(
|
|
3366
|
+
`[StormcloudVideoPlayer] IMA preload failed for ad: ${url}`,
|
|
3367
|
+
error
|
|
3368
|
+
);
|
|
3369
|
+
}
|
|
3370
|
+
}).finally(() => {
|
|
3371
|
+
this.preloadingAdUrls.delete(url);
|
|
3372
|
+
});
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3118
3375
|
getRemainingAdMs() {
|
|
3119
3376
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
3120
3377
|
return 0;
|
|
@@ -3135,7 +3392,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3135
3392
|
if (this.ima.isAdPlaying()) {
|
|
3136
3393
|
const currentPerceptualState = this.isMuted();
|
|
3137
3394
|
const newMutedState = !currentPerceptualState;
|
|
3138
|
-
this.ima.updateOriginalMutedState(newMutedState);
|
|
3395
|
+
this.ima.updateOriginalMutedState(newMutedState, this.video.volume);
|
|
3139
3396
|
this.ima.setAdVolume(newMutedState ? 0 : 1);
|
|
3140
3397
|
if (this.config.debugAdTiming) {
|
|
3141
3398
|
console.log(
|
|
@@ -3145,7 +3402,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3145
3402
|
}
|
|
3146
3403
|
} else {
|
|
3147
3404
|
this.video.muted = !this.video.muted;
|
|
3148
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3405
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3149
3406
|
if (this.config.debugAdTiming) {
|
|
3150
3407
|
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
3151
3408
|
}
|
|
@@ -3217,7 +3474,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3217
3474
|
}
|
|
3218
3475
|
this.video.muted = muted;
|
|
3219
3476
|
if (adPlaying) {
|
|
3220
|
-
this.ima.updateOriginalMutedState(muted);
|
|
3477
|
+
this.ima.updateOriginalMutedState(muted, this.video.volume);
|
|
3221
3478
|
this.ima.setAdVolume(muted ? 0 : 1);
|
|
3222
3479
|
if (this.config.debugAdTiming) {
|
|
3223
3480
|
console.log("[StormcloudVideoPlayer] setMuted applied during ad", {
|
|
@@ -3226,7 +3483,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3226
3483
|
}
|
|
3227
3484
|
return;
|
|
3228
3485
|
}
|
|
3229
|
-
this.ima.updateOriginalMutedState(muted);
|
|
3486
|
+
this.ima.updateOriginalMutedState(muted, this.video.volume);
|
|
3230
3487
|
if (this.config.debugAdTiming) {
|
|
3231
3488
|
console.log("[StormcloudVideoPlayer] setMuted called:", muted);
|
|
3232
3489
|
}
|
|
@@ -3266,6 +3523,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3266
3523
|
}
|
|
3267
3524
|
(_a = this.hls) == null ? void 0 : _a.destroy();
|
|
3268
3525
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3526
|
+
this.releaseAdHoldState();
|
|
3527
|
+
this.preloadingAdUrls.clear();
|
|
3528
|
+
this.adPodAllUrls = [];
|
|
3269
3529
|
}
|
|
3270
3530
|
};
|
|
3271
3531
|
|