stormcloud-video-player 0.3.13 → 0.3.14
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 +57 -46
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +2 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +57 -46
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +57 -46
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +2 -0
- package/lib/players/HlsPlayer.cjs +57 -46
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +57 -46
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +26 -5
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +57 -46
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
package/lib/index.cjs
CHANGED
|
@@ -989,6 +989,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
989
989
|
let sessionId;
|
|
990
990
|
const preloadedAds = /* @__PURE__ */ new Map();
|
|
991
991
|
const preloadingAds = /* @__PURE__ */ new Map();
|
|
992
|
+
let destroyed = false;
|
|
993
|
+
let pendingTimeouts = [];
|
|
992
994
|
let trackingFired = {
|
|
993
995
|
impression: false,
|
|
994
996
|
start: false,
|
|
@@ -1317,13 +1319,27 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1317
1319
|
adPlaying = false;
|
|
1318
1320
|
setAdPlayingFlag(false);
|
|
1319
1321
|
emit("content_resume");
|
|
1320
|
-
setTimeout(() => {
|
|
1321
|
-
if (
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1322
|
+
const timeoutId = window.setTimeout(() => {
|
|
1323
|
+
if (destroyed) {
|
|
1324
|
+
console.log("[HlsAdPlayer] Player destroyed, skipping post-completion check");
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
const stillInPod = contentVideo.dataset.stormcloudAdPlaying === "true";
|
|
1328
|
+
if (stillInPod) {
|
|
1329
|
+
console.log(
|
|
1330
|
+
"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)"
|
|
1331
|
+
);
|
|
1332
|
+
if (adContainerEl) {
|
|
1333
|
+
adContainerEl.style.display = "flex";
|
|
1334
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
const idx = pendingTimeouts.indexOf(timeoutId);
|
|
1338
|
+
if (idx !== -1) {
|
|
1339
|
+
pendingTimeouts.splice(idx, 1);
|
|
1325
1340
|
}
|
|
1326
1341
|
}, 50);
|
|
1342
|
+
pendingTimeouts.push(timeoutId);
|
|
1327
1343
|
}
|
|
1328
1344
|
function handleAdError() {
|
|
1329
1345
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
@@ -1553,6 +1569,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1553
1569
|
},
|
|
1554
1570
|
destroy() {
|
|
1555
1571
|
console.log("[HlsAdPlayer] Destroying");
|
|
1572
|
+
destroyed = true;
|
|
1573
|
+
for (const timeoutId of pendingTimeouts) {
|
|
1574
|
+
clearTimeout(timeoutId);
|
|
1575
|
+
}
|
|
1576
|
+
pendingTimeouts = [];
|
|
1556
1577
|
adPlaying = false;
|
|
1557
1578
|
setAdPlayingFlag(false);
|
|
1558
1579
|
contentVideo.muted = originalMutedState;
|
|
@@ -2465,10 +2486,11 @@ var StormcloudVideoPlayer = class {
|
|
|
2465
2486
|
this.handleAdPodComplete();
|
|
2466
2487
|
}
|
|
2467
2488
|
});
|
|
2468
|
-
this.
|
|
2489
|
+
this.timeUpdateHandler = () => {
|
|
2469
2490
|
this.onTimeUpdate(this.video.currentTime);
|
|
2470
|
-
}
|
|
2471
|
-
this.video.addEventListener("
|
|
2491
|
+
};
|
|
2492
|
+
this.video.addEventListener("timeupdate", this.timeUpdateHandler);
|
|
2493
|
+
this.emptiedHandler = () => {
|
|
2472
2494
|
if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {
|
|
2473
2495
|
if (this.config.debugAdTiming) {
|
|
2474
2496
|
console.log(
|
|
@@ -2485,7 +2507,8 @@ var StormcloudVideoPlayer = class {
|
|
|
2485
2507
|
});
|
|
2486
2508
|
}
|
|
2487
2509
|
}
|
|
2488
|
-
}
|
|
2510
|
+
};
|
|
2511
|
+
this.video.addEventListener("emptied", this.emptiedHandler);
|
|
2489
2512
|
}
|
|
2490
2513
|
shouldUseNativeHls() {
|
|
2491
2514
|
const streamType = this.getStreamType();
|
|
@@ -3177,7 +3200,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3177
3200
|
continue;
|
|
3178
3201
|
}
|
|
3179
3202
|
if (this.config.debugAdTiming) {
|
|
3180
|
-
console.log(`[CONTINUOUS-FETCH] \u{1F4E1} Attempting to fetch ad
|
|
3203
|
+
console.log(`[CONTINUOUS-FETCH] \u{1F4E1} Attempting to fetch ad (${this.successfulAdRequests.length + this.adRequestQueue.length + 1} total)...`);
|
|
3181
3204
|
}
|
|
3182
3205
|
try {
|
|
3183
3206
|
const response = await fetch(newAdUrl, { mode: "cors" });
|
|
@@ -3193,8 +3216,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3193
3216
|
console.log("[CONTINUOUS-FETCH] \u26A0\uFE0F VAST response has no media files, skipping");
|
|
3194
3217
|
}
|
|
3195
3218
|
this.failedVastUrls.add(newAdUrl);
|
|
3196
|
-
|
|
3197
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
3219
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3198
3220
|
continue;
|
|
3199
3221
|
}
|
|
3200
3222
|
if (this.config.debugAdTiming) {
|
|
@@ -3202,19 +3224,17 @@ var StormcloudVideoPlayer = class {
|
|
|
3202
3224
|
}
|
|
3203
3225
|
this.adRequestQueue.push(newAdUrl);
|
|
3204
3226
|
this.totalAdsInBreak++;
|
|
3205
|
-
|
|
3206
|
-
await new Promise((resolve) => setTimeout(resolve, successDelay));
|
|
3227
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3207
3228
|
} catch (error) {
|
|
3208
3229
|
if (this.config.debugAdTiming) {
|
|
3209
3230
|
console.log("[CONTINUOUS-FETCH] \u274C Ad fetch failed:", error.message);
|
|
3210
3231
|
}
|
|
3211
3232
|
this.failedVastUrls.add(newAdUrl);
|
|
3212
|
-
|
|
3213
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
3233
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
3214
3234
|
}
|
|
3215
3235
|
}
|
|
3216
3236
|
if (this.config.debugAdTiming) {
|
|
3217
|
-
console.log(
|
|
3237
|
+
console.log("[CONTINUOUS-FETCH] \u{1F6D1} Continuous fetch loop ended");
|
|
3218
3238
|
}
|
|
3219
3239
|
}
|
|
3220
3240
|
stopContinuousFetching() {
|
|
@@ -3252,27 +3272,20 @@ var StormcloudVideoPlayer = class {
|
|
|
3252
3272
|
return;
|
|
3253
3273
|
}
|
|
3254
3274
|
}
|
|
3255
|
-
const
|
|
3256
|
-
|
|
3257
|
-
const retryDelayMs = hasPlayedAtLeastOneAd ? 500 : 1e3;
|
|
3258
|
-
const minRemainingForRetry = 1e3;
|
|
3259
|
-
if (this.continuousFetchingActive && retryCount < maxRetries && remaining > minRemainingForRetry) {
|
|
3275
|
+
const maxRetries = 5;
|
|
3276
|
+
if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2e3) {
|
|
3260
3277
|
if (this.config.debugAdTiming) {
|
|
3261
|
-
console.log(`[CONTINUOUS-FETCH] \u23F3 Queue empty but fetching active, waiting
|
|
3278
|
+
console.log(`[CONTINUOUS-FETCH] \u23F3 Queue empty but fetching active, waiting... (retry ${retryCount + 1}/${maxRetries})`);
|
|
3262
3279
|
}
|
|
3263
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3280
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3264
3281
|
await this.tryNextAvailableAd(retryCount + 1);
|
|
3265
3282
|
return;
|
|
3266
3283
|
}
|
|
3267
|
-
|
|
3268
|
-
if (!this.isShowingPlaceholder && remaining >= minTimeForPlaceholder && this.continuousFetchingActive) {
|
|
3269
|
-
if (this.config.debugAdTiming) {
|
|
3270
|
-
console.log(`[CONTINUOUS-FETCH] \u2B1B Last resort: showing placeholder (${remaining}ms remaining)`);
|
|
3271
|
-
}
|
|
3284
|
+
if (!this.isShowingPlaceholder && remaining > 1e3) {
|
|
3272
3285
|
this.showPlaceholderAndWaitForAds();
|
|
3273
3286
|
} else {
|
|
3274
3287
|
if (this.config.debugAdTiming) {
|
|
3275
|
-
console.log(
|
|
3288
|
+
console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No more ads available, ending ad break");
|
|
3276
3289
|
}
|
|
3277
3290
|
this.handleAdPodComplete();
|
|
3278
3291
|
}
|
|
@@ -3280,36 +3293,26 @@ var StormcloudVideoPlayer = class {
|
|
|
3280
3293
|
async showPlaceholderAndWaitForAds() {
|
|
3281
3294
|
const remaining = this.getRemainingAdMs();
|
|
3282
3295
|
const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);
|
|
3283
|
-
if (waitTime <
|
|
3284
|
-
if (this.config.debugAdTiming) {
|
|
3285
|
-
console.log(`[CONTINUOUS-FETCH] \u23F9\uFE0F Insufficient time for placeholder (${waitTime}ms), ending ad break`);
|
|
3286
|
-
}
|
|
3296
|
+
if (waitTime < 1e3) {
|
|
3287
3297
|
this.handleAdPodComplete();
|
|
3288
3298
|
return;
|
|
3289
3299
|
}
|
|
3290
3300
|
if (this.config.debugAdTiming) {
|
|
3291
|
-
console.log(`[CONTINUOUS-FETCH] \u2B1B Showing black placeholder for
|
|
3301
|
+
console.log(`[CONTINUOUS-FETCH] \u2B1B Showing black placeholder for ${waitTime}ms while waiting for ads`);
|
|
3292
3302
|
}
|
|
3293
3303
|
this.isShowingPlaceholder = true;
|
|
3294
3304
|
this.placeholderStartTimeMs = Date.now();
|
|
3295
3305
|
this.ima.showPlaceholder();
|
|
3296
|
-
const checkInterval =
|
|
3306
|
+
const checkInterval = 500;
|
|
3297
3307
|
const maxChecks = Math.floor(waitTime / checkInterval);
|
|
3298
3308
|
for (let i = 0; i < maxChecks; i++) {
|
|
3299
3309
|
await new Promise((resolve) => setTimeout(resolve, checkInterval));
|
|
3300
3310
|
if (!this.inAdBreak) {
|
|
3301
|
-
if (this.config.debugAdTiming) {
|
|
3302
|
-
console.log("[CONTINUOUS-FETCH] \u2139\uFE0F Ad break ended during placeholder wait");
|
|
3303
|
-
}
|
|
3304
|
-
this.isShowingPlaceholder = false;
|
|
3305
|
-
this.placeholderStartTimeMs = null;
|
|
3306
|
-
this.ima.hidePlaceholder();
|
|
3307
3311
|
return;
|
|
3308
3312
|
}
|
|
3309
3313
|
if (this.adRequestQueue.length > 0) {
|
|
3310
|
-
const elapsedInPlaceholder = Date.now() - (this.placeholderStartTimeMs || Date.now());
|
|
3311
3314
|
if (this.config.debugAdTiming) {
|
|
3312
|
-
console.log(
|
|
3315
|
+
console.log("[CONTINUOUS-FETCH] \u2705 New ad became available during placeholder");
|
|
3313
3316
|
}
|
|
3314
3317
|
this.isShowingPlaceholder = false;
|
|
3315
3318
|
this.placeholderStartTimeMs = null;
|
|
@@ -3328,9 +3331,8 @@ var StormcloudVideoPlayer = class {
|
|
|
3328
3331
|
return;
|
|
3329
3332
|
}
|
|
3330
3333
|
}
|
|
3331
|
-
const totalPlaceholderTime = Date.now() - (this.placeholderStartTimeMs || Date.now());
|
|
3332
3334
|
if (this.config.debugAdTiming) {
|
|
3333
|
-
console.log(
|
|
3335
|
+
console.log("[CONTINUOUS-FETCH] \u23F0 Placeholder timeout reached, no ads fetched");
|
|
3334
3336
|
}
|
|
3335
3337
|
this.isShowingPlaceholder = false;
|
|
3336
3338
|
this.placeholderStartTimeMs = null;
|
|
@@ -4142,6 +4144,15 @@ var StormcloudVideoPlayer = class {
|
|
|
4142
4144
|
this.clearAdStartTimer();
|
|
4143
4145
|
this.clearAdStopTimer();
|
|
4144
4146
|
this.clearAdFailsafeTimer();
|
|
4147
|
+
this.clearAdRequestWatchdog();
|
|
4148
|
+
if (this.timeUpdateHandler) {
|
|
4149
|
+
this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
|
|
4150
|
+
delete this.timeUpdateHandler;
|
|
4151
|
+
}
|
|
4152
|
+
if (this.emptiedHandler) {
|
|
4153
|
+
this.video.removeEventListener("emptied", this.emptiedHandler);
|
|
4154
|
+
delete this.emptiedHandler;
|
|
4155
|
+
}
|
|
4145
4156
|
if (this.heartbeatInterval) {
|
|
4146
4157
|
clearInterval(this.heartbeatInterval);
|
|
4147
4158
|
this.heartbeatInterval = void 0;
|