stormcloud-video-player 0.2.24 → 0.2.25
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 +256 -32
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +10 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.js +256 -32
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +256 -32
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +7 -1
- package/lib/players/HlsPlayer.cjs +256 -32
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +256 -32
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +87 -10
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/sdk/ima.cjs +87 -19
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-D1xfSdLP.d.cts → types-9_2sbHCg.d.cts} +4 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +256 -32
- 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-9_2sbHCg.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;
|
|
@@ -203,6 +203,8 @@ function createImaController(video, options) {
|
|
|
203
203
|
let adPlaying = false;
|
|
204
204
|
let originalMutedState = false;
|
|
205
205
|
const listeners = /* @__PURE__ */ new Map();
|
|
206
|
+
const preloadedVast = /* @__PURE__ */ new Map();
|
|
207
|
+
const preloadingVast = /* @__PURE__ */ new Map();
|
|
206
208
|
function setAdPlayingFlag(isPlaying) {
|
|
207
209
|
if (isPlaying) {
|
|
208
210
|
video.dataset.stormcloudAdPlaying = "true";
|
|
@@ -293,7 +295,15 @@ function createImaController(video, options) {
|
|
|
293
295
|
let adsLoadedReject;
|
|
294
296
|
function makeAdsRequest(google, vastTagUrl) {
|
|
295
297
|
const adsRequest = new google.ima.AdsRequest();
|
|
296
|
-
|
|
298
|
+
const preloadedResponse = preloadedVast.get(vastTagUrl);
|
|
299
|
+
if (preloadedResponse) {
|
|
300
|
+
adsRequest.adsResponse = preloadedResponse;
|
|
301
|
+
console.log(
|
|
302
|
+
"[IMA] Using preloaded VAST response for immediate ad request"
|
|
303
|
+
);
|
|
304
|
+
} else {
|
|
305
|
+
adsRequest.adTagUrl = vastTagUrl;
|
|
306
|
+
}
|
|
297
307
|
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
298
308
|
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
299
309
|
adsRequest.linearAdSlotWidth = videoWidth;
|
|
@@ -303,6 +313,36 @@ function createImaController(video, options) {
|
|
|
303
313
|
adsRequest.vastLoadTimeout = 5e3;
|
|
304
314
|
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
305
315
|
adsLoader.requestAds(adsRequest);
|
|
316
|
+
if (preloadedResponse) {
|
|
317
|
+
preloadedVast.delete(vastTagUrl);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
function ensurePlaceholderContainer() {
|
|
321
|
+
var _a;
|
|
322
|
+
if (adContainerEl) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const container = document.createElement("div");
|
|
326
|
+
container.style.position = "absolute";
|
|
327
|
+
container.style.left = "0";
|
|
328
|
+
container.style.top = "0";
|
|
329
|
+
container.style.right = "0";
|
|
330
|
+
container.style.bottom = "0";
|
|
331
|
+
container.style.display = "none";
|
|
332
|
+
container.style.alignItems = "center";
|
|
333
|
+
container.style.justifyContent = "center";
|
|
334
|
+
container.style.pointerEvents = "none";
|
|
335
|
+
container.style.zIndex = "10";
|
|
336
|
+
container.style.backgroundColor = "#000";
|
|
337
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
338
|
+
adContainerEl = container;
|
|
339
|
+
}
|
|
340
|
+
async function fetchVastDocument(vastTagUrl) {
|
|
341
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
342
|
+
if (!response.ok) {
|
|
343
|
+
throw new Error(`Failed to preload VAST: ${response.status}`);
|
|
344
|
+
}
|
|
345
|
+
return response.text();
|
|
306
346
|
}
|
|
307
347
|
function destroyAdsManager() {
|
|
308
348
|
if (adsManager) {
|
|
@@ -318,29 +358,16 @@ function createImaController(video, options) {
|
|
|
318
358
|
return {
|
|
319
359
|
initialize() {
|
|
320
360
|
ensureImaLoaded().then(() => {
|
|
321
|
-
var _a
|
|
361
|
+
var _a;
|
|
322
362
|
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;
|
|
363
|
+
ensurePlaceholderContainer();
|
|
364
|
+
if (!adDisplayContainer && adContainerEl) {
|
|
338
365
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
339
|
-
|
|
366
|
+
adContainerEl,
|
|
340
367
|
video
|
|
341
368
|
);
|
|
342
369
|
try {
|
|
343
|
-
(
|
|
370
|
+
(_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
|
|
344
371
|
} catch {
|
|
345
372
|
}
|
|
346
373
|
}
|
|
@@ -644,6 +671,32 @@ function createImaController(video, options) {
|
|
|
644
671
|
return Promise.reject(error);
|
|
645
672
|
}
|
|
646
673
|
},
|
|
674
|
+
async preloadAds(vastTagUrl) {
|
|
675
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
676
|
+
return Promise.resolve();
|
|
677
|
+
}
|
|
678
|
+
if (preloadedVast.has(vastTagUrl)) {
|
|
679
|
+
return Promise.resolve();
|
|
680
|
+
}
|
|
681
|
+
const inflight = preloadingVast.get(vastTagUrl);
|
|
682
|
+
if (inflight) {
|
|
683
|
+
return inflight;
|
|
684
|
+
}
|
|
685
|
+
const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
|
|
686
|
+
preloadedVast.set(vastTagUrl, xml);
|
|
687
|
+
console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
|
|
688
|
+
}).catch((error) => {
|
|
689
|
+
console.warn("[IMA] Failed to preload VAST response:", error);
|
|
690
|
+
preloadedVast.delete(vastTagUrl);
|
|
691
|
+
}).finally(() => {
|
|
692
|
+
preloadingVast.delete(vastTagUrl);
|
|
693
|
+
});
|
|
694
|
+
preloadingVast.set(vastTagUrl, preloadPromise);
|
|
695
|
+
return preloadPromise;
|
|
696
|
+
},
|
|
697
|
+
hasPreloadedAd(vastTagUrl) {
|
|
698
|
+
return preloadedVast.has(vastTagUrl);
|
|
699
|
+
},
|
|
647
700
|
async play() {
|
|
648
701
|
var _a, _b;
|
|
649
702
|
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
@@ -719,6 +772,8 @@ function createImaController(video, options) {
|
|
|
719
772
|
adContainerEl = void 0;
|
|
720
773
|
adDisplayContainer = void 0;
|
|
721
774
|
adsLoader = void 0;
|
|
775
|
+
preloadedVast.clear();
|
|
776
|
+
preloadingVast.clear();
|
|
722
777
|
},
|
|
723
778
|
isAdPlaying() {
|
|
724
779
|
return adPlaying;
|
|
@@ -774,6 +829,19 @@ function createImaController(video, options) {
|
|
|
774
829
|
}
|
|
775
830
|
}
|
|
776
831
|
return 1;
|
|
832
|
+
},
|
|
833
|
+
showPlaceholder() {
|
|
834
|
+
ensurePlaceholderContainer();
|
|
835
|
+
if (adContainerEl) {
|
|
836
|
+
adContainerEl.style.display = "flex";
|
|
837
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
838
|
+
}
|
|
839
|
+
},
|
|
840
|
+
hidePlaceholder() {
|
|
841
|
+
if (adContainerEl) {
|
|
842
|
+
adContainerEl.style.display = "none";
|
|
843
|
+
adContainerEl.style.pointerEvents = "none";
|
|
844
|
+
}
|
|
777
845
|
}
|
|
778
846
|
};
|
|
779
847
|
}
|
|
@@ -791,6 +859,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
791
859
|
let adContainerEl;
|
|
792
860
|
let currentAd;
|
|
793
861
|
let sessionId;
|
|
862
|
+
const preloadedAds = /* @__PURE__ */ new Map();
|
|
863
|
+
const preloadingAds = /* @__PURE__ */ new Map();
|
|
794
864
|
let trackingFired = {
|
|
795
865
|
impression: false,
|
|
796
866
|
start: false,
|
|
@@ -1020,6 +1090,19 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1020
1090
|
return null;
|
|
1021
1091
|
}
|
|
1022
1092
|
}
|
|
1093
|
+
async function fetchAndParseVastAd(vastTagUrl) {
|
|
1094
|
+
const response = await fetch(vastTagUrl);
|
|
1095
|
+
if (!response.ok) {
|
|
1096
|
+
throw new Error(`Failed to fetch VAST: ${response.statusText}`);
|
|
1097
|
+
}
|
|
1098
|
+
const vastXml = await response.text();
|
|
1099
|
+
console.log("[HlsAdPlayer] VAST XML received");
|
|
1100
|
+
console.log(
|
|
1101
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1102
|
+
vastXml.substring(0, 2e3)
|
|
1103
|
+
);
|
|
1104
|
+
return parseVastXml(vastXml);
|
|
1105
|
+
}
|
|
1023
1106
|
function createAdVideoElement() {
|
|
1024
1107
|
const video = document.createElement("video");
|
|
1025
1108
|
video.style.position = "absolute";
|
|
@@ -1171,17 +1254,17 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1171
1254
|
}
|
|
1172
1255
|
try {
|
|
1173
1256
|
sessionId = generateSessionId();
|
|
1174
|
-
|
|
1175
|
-
if (
|
|
1176
|
-
|
|
1257
|
+
let ad;
|
|
1258
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1259
|
+
ad = preloadedAds.get(vastTagUrl);
|
|
1260
|
+
preloadedAds.delete(vastTagUrl);
|
|
1261
|
+
console.log(
|
|
1262
|
+
"[HlsAdPlayer] Using preloaded VAST response:",
|
|
1263
|
+
vastTagUrl
|
|
1264
|
+
);
|
|
1265
|
+
} else {
|
|
1266
|
+
ad = await fetchAndParseVastAd(vastTagUrl);
|
|
1177
1267
|
}
|
|
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
1268
|
if (!ad) {
|
|
1186
1269
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1187
1270
|
emit("ad_error");
|
|
@@ -1200,6 +1283,37 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1200
1283
|
return Promise.reject(error);
|
|
1201
1284
|
}
|
|
1202
1285
|
},
|
|
1286
|
+
async preloadAds(vastTagUrl) {
|
|
1287
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
1288
|
+
return Promise.resolve();
|
|
1289
|
+
}
|
|
1290
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1291
|
+
return Promise.resolve();
|
|
1292
|
+
}
|
|
1293
|
+
const inflight = preloadingAds.get(vastTagUrl);
|
|
1294
|
+
if (inflight) {
|
|
1295
|
+
return inflight;
|
|
1296
|
+
}
|
|
1297
|
+
const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {
|
|
1298
|
+
if (ad) {
|
|
1299
|
+
preloadedAds.set(vastTagUrl, ad);
|
|
1300
|
+
console.log(
|
|
1301
|
+
"[HlsAdPlayer] Cached VAST response for preloading:",
|
|
1302
|
+
vastTagUrl
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1305
|
+
}).catch((error) => {
|
|
1306
|
+
console.warn("[HlsAdPlayer] Failed to preload VAST response:", error);
|
|
1307
|
+
preloadedAds.delete(vastTagUrl);
|
|
1308
|
+
}).finally(() => {
|
|
1309
|
+
preloadingAds.delete(vastTagUrl);
|
|
1310
|
+
});
|
|
1311
|
+
preloadingAds.set(vastTagUrl, preloadPromise);
|
|
1312
|
+
return preloadPromise;
|
|
1313
|
+
},
|
|
1314
|
+
hasPreloadedAd(vastTagUrl) {
|
|
1315
|
+
return preloadedAds.has(vastTagUrl);
|
|
1316
|
+
},
|
|
1203
1317
|
async play() {
|
|
1204
1318
|
if (!currentAd) {
|
|
1205
1319
|
console.warn(
|
|
@@ -1330,6 +1444,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1330
1444
|
adContainerEl = void 0;
|
|
1331
1445
|
currentAd = void 0;
|
|
1332
1446
|
listeners.clear();
|
|
1447
|
+
preloadedAds.clear();
|
|
1448
|
+
preloadingAds.clear();
|
|
1333
1449
|
},
|
|
1334
1450
|
isAdPlaying() {
|
|
1335
1451
|
return adPlaying;
|
|
@@ -1372,6 +1488,35 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1372
1488
|
return adVideoElement.volume;
|
|
1373
1489
|
}
|
|
1374
1490
|
return 1;
|
|
1491
|
+
},
|
|
1492
|
+
showPlaceholder() {
|
|
1493
|
+
var _a;
|
|
1494
|
+
if (!adContainerEl) {
|
|
1495
|
+
const container = document.createElement("div");
|
|
1496
|
+
container.style.position = "absolute";
|
|
1497
|
+
container.style.left = "0";
|
|
1498
|
+
container.style.top = "0";
|
|
1499
|
+
container.style.right = "0";
|
|
1500
|
+
container.style.bottom = "0";
|
|
1501
|
+
container.style.display = "none";
|
|
1502
|
+
container.style.alignItems = "center";
|
|
1503
|
+
container.style.justifyContent = "center";
|
|
1504
|
+
container.style.pointerEvents = "none";
|
|
1505
|
+
container.style.zIndex = "10";
|
|
1506
|
+
container.style.backgroundColor = "#000";
|
|
1507
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
1508
|
+
adContainerEl = container;
|
|
1509
|
+
}
|
|
1510
|
+
if (adContainerEl) {
|
|
1511
|
+
adContainerEl.style.display = "flex";
|
|
1512
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1513
|
+
}
|
|
1514
|
+
},
|
|
1515
|
+
hidePlaceholder() {
|
|
1516
|
+
if (adContainerEl) {
|
|
1517
|
+
adContainerEl.style.display = "none";
|
|
1518
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1519
|
+
}
|
|
1375
1520
|
}
|
|
1376
1521
|
};
|
|
1377
1522
|
}
|
|
@@ -1852,6 +1997,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1852
1997
|
this.bufferedSegmentsCount = 0;
|
|
1853
1998
|
this.shouldAutoplayAfterBuffering = false;
|
|
1854
1999
|
this.hasInitialBufferCompleted = false;
|
|
2000
|
+
this.adPodAllUrls = [];
|
|
2001
|
+
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
1855
2002
|
initializePolyfills();
|
|
1856
2003
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1857
2004
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2152,6 +2299,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2152
2299
|
console.log("[StormcloudVideoPlayer] IMA content_pause event received");
|
|
2153
2300
|
}
|
|
2154
2301
|
this.clearAdFailsafeTimer();
|
|
2302
|
+
this.enforceAdHoldState();
|
|
2155
2303
|
});
|
|
2156
2304
|
this.ima.on("content_resume", () => {
|
|
2157
2305
|
if (this.config.debugAdTiming) {
|
|
@@ -2176,9 +2324,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2176
2324
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2177
2325
|
const next = this.adPodQueue.shift();
|
|
2178
2326
|
this.currentAdIndex++;
|
|
2179
|
-
this.
|
|
2180
|
-
this.video.muted = true;
|
|
2181
|
-
this.video.volume = 0;
|
|
2327
|
+
this.enforceAdHoldState();
|
|
2182
2328
|
if (this.config.debugAdTiming) {
|
|
2183
2329
|
console.log(
|
|
2184
2330
|
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
@@ -2790,11 +2936,16 @@ var StormcloudVideoPlayer = class {
|
|
|
2790
2936
|
return;
|
|
2791
2937
|
}
|
|
2792
2938
|
if (vastTagUrls.length > 0) {
|
|
2939
|
+
this.adPodAllUrls = [...vastTagUrls];
|
|
2940
|
+
this.preloadingAdUrls.clear();
|
|
2941
|
+
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
2793
2942
|
this.inAdBreak = true;
|
|
2794
2943
|
this.showAds = true;
|
|
2795
2944
|
this.currentAdIndex = 0;
|
|
2796
2945
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
2797
2946
|
this.adPodQueue = [...vastTagUrls];
|
|
2947
|
+
this.enforceAdHoldState();
|
|
2948
|
+
this.preloadUpcomingAds();
|
|
2798
2949
|
if (this.config.debugAdTiming) {
|
|
2799
2950
|
console.log(
|
|
2800
2951
|
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - will play continuously`
|
|
@@ -2865,6 +3016,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2865
3016
|
const first = tags[0];
|
|
2866
3017
|
const rest = tags.slice(1);
|
|
2867
3018
|
this.adPodQueue = rest;
|
|
3019
|
+
this.enforceAdHoldState();
|
|
2868
3020
|
await this.playSingleAd(first);
|
|
2869
3021
|
this.inAdBreak = true;
|
|
2870
3022
|
this.expectedAdBreakDurationMs = remainingMs;
|
|
@@ -2978,6 +3130,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2978
3130
|
}
|
|
2979
3131
|
return;
|
|
2980
3132
|
}
|
|
3133
|
+
const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
|
|
3134
|
+
if (wasPreloaded && this.config.debugAdTiming) {
|
|
3135
|
+
console.log(
|
|
3136
|
+
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3137
|
+
);
|
|
3138
|
+
}
|
|
2981
3139
|
if (!this.showAds) {
|
|
2982
3140
|
if (this.config.debugAdTiming) {
|
|
2983
3141
|
console.log(
|
|
@@ -2998,12 +3156,14 @@ var StormcloudVideoPlayer = class {
|
|
|
2998
3156
|
this.startAdFailsafeTimer();
|
|
2999
3157
|
try {
|
|
3000
3158
|
await this.ima.requestAds(vastTagUrl);
|
|
3159
|
+
this.preloadUpcomingAds();
|
|
3001
3160
|
try {
|
|
3002
3161
|
if (this.config.debugAdTiming) {
|
|
3003
3162
|
console.log(
|
|
3004
3163
|
"[StormcloudVideoPlayer] Ad request completed, attempting playback"
|
|
3005
3164
|
);
|
|
3006
3165
|
}
|
|
3166
|
+
this.enforceAdHoldState();
|
|
3007
3167
|
await this.ima.play();
|
|
3008
3168
|
if (this.config.debugAdTiming) {
|
|
3009
3169
|
console.log(
|
|
@@ -3033,6 +3193,8 @@ var StormcloudVideoPlayer = class {
|
|
|
3033
3193
|
"[StormcloudVideoPlayer] Handling ad pod completion - resuming content and hiding ad layer"
|
|
3034
3194
|
);
|
|
3035
3195
|
}
|
|
3196
|
+
this.releaseAdHoldState();
|
|
3197
|
+
this.preloadingAdUrls.clear();
|
|
3036
3198
|
this.inAdBreak = false;
|
|
3037
3199
|
this.expectedAdBreakDurationMs = void 0;
|
|
3038
3200
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3040,6 +3202,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3040
3202
|
this.clearAdStopTimer();
|
|
3041
3203
|
this.clearAdFailsafeTimer();
|
|
3042
3204
|
this.adPodQueue = [];
|
|
3205
|
+
this.adPodAllUrls = [];
|
|
3043
3206
|
this.showAds = false;
|
|
3044
3207
|
this.currentAdIndex = 0;
|
|
3045
3208
|
this.totalAdsInBreak = 0;
|
|
@@ -3120,6 +3283,64 @@ var StormcloudVideoPlayer = class {
|
|
|
3120
3283
|
}
|
|
3121
3284
|
return [b.vastTagUrl];
|
|
3122
3285
|
}
|
|
3286
|
+
logQueuedAdUrls(urls) {
|
|
3287
|
+
if (!this.config.debugAdTiming) {
|
|
3288
|
+
return;
|
|
3289
|
+
}
|
|
3290
|
+
console.log("[StormcloudVideoPlayer] ALL ad URLs queued:", urls);
|
|
3291
|
+
}
|
|
3292
|
+
enforceAdHoldState() {
|
|
3293
|
+
this.video.dataset.stormcloudAdPlaying = "true";
|
|
3294
|
+
this.video.muted = true;
|
|
3295
|
+
this.video.volume = 0;
|
|
3296
|
+
if (typeof this.ima.showPlaceholder === "function") {
|
|
3297
|
+
this.ima.showPlaceholder();
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
releaseAdHoldState() {
|
|
3301
|
+
delete this.video.dataset.stormcloudAdPlaying;
|
|
3302
|
+
if (typeof this.ima.hidePlaceholder === "function") {
|
|
3303
|
+
this.ima.hidePlaceholder();
|
|
3304
|
+
}
|
|
3305
|
+
}
|
|
3306
|
+
preloadUpcomingAds() {
|
|
3307
|
+
if (!this.ima.preloadAds || this.adPodQueue.length === 0) {
|
|
3308
|
+
return;
|
|
3309
|
+
}
|
|
3310
|
+
const upcoming = this.adPodQueue.slice(0, 2);
|
|
3311
|
+
for (const url of upcoming) {
|
|
3312
|
+
if (!url) continue;
|
|
3313
|
+
if (this.ima.hasPreloadedAd(url)) {
|
|
3314
|
+
this.preloadingAdUrls.delete(url);
|
|
3315
|
+
continue;
|
|
3316
|
+
}
|
|
3317
|
+
if (this.preloadingAdUrls.has(url)) {
|
|
3318
|
+
continue;
|
|
3319
|
+
}
|
|
3320
|
+
if (this.config.debugAdTiming) {
|
|
3321
|
+
console.log(
|
|
3322
|
+
`[StormcloudVideoPlayer] Scheduling IMA preload for upcoming ad: ${url}`
|
|
3323
|
+
);
|
|
3324
|
+
}
|
|
3325
|
+
this.preloadingAdUrls.add(url);
|
|
3326
|
+
this.ima.preloadAds(url).then(() => {
|
|
3327
|
+
if (this.config.debugAdTiming) {
|
|
3328
|
+
console.log(
|
|
3329
|
+
`[StormcloudVideoPlayer] IMA preload complete for ad: ${url}`
|
|
3330
|
+
);
|
|
3331
|
+
}
|
|
3332
|
+
}).catch((error) => {
|
|
3333
|
+
if (this.config.debugAdTiming) {
|
|
3334
|
+
console.warn(
|
|
3335
|
+
`[StormcloudVideoPlayer] IMA preload failed for ad: ${url}`,
|
|
3336
|
+
error
|
|
3337
|
+
);
|
|
3338
|
+
}
|
|
3339
|
+
}).finally(() => {
|
|
3340
|
+
this.preloadingAdUrls.delete(url);
|
|
3341
|
+
});
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3123
3344
|
getRemainingAdMs() {
|
|
3124
3345
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
3125
3346
|
return 0;
|
|
@@ -3271,6 +3492,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3271
3492
|
}
|
|
3272
3493
|
(_a = this.hls) == null ? void 0 : _a.destroy();
|
|
3273
3494
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3495
|
+
this.releaseAdHoldState();
|
|
3496
|
+
this.preloadingAdUrls.clear();
|
|
3497
|
+
this.adPodAllUrls = [];
|
|
3274
3498
|
}
|
|
3275
3499
|
};
|
|
3276
3500
|
|