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
|
@@ -47,6 +47,8 @@ declare class StormcloudVideoPlayer {
|
|
|
47
47
|
private maxPlaceholderDurationMs;
|
|
48
48
|
private placeholderStartTimeMs;
|
|
49
49
|
private isShowingPlaceholder;
|
|
50
|
+
private timeUpdateHandler?;
|
|
51
|
+
private emptiedHandler?;
|
|
50
52
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
51
53
|
private createAdPlayer;
|
|
52
54
|
load(): Promise<void>;
|
|
@@ -925,6 +925,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
925
925
|
let sessionId;
|
|
926
926
|
const preloadedAds = /* @__PURE__ */ new Map();
|
|
927
927
|
const preloadingAds = /* @__PURE__ */ new Map();
|
|
928
|
+
let destroyed = false;
|
|
929
|
+
let pendingTimeouts = [];
|
|
928
930
|
let trackingFired = {
|
|
929
931
|
impression: false,
|
|
930
932
|
start: false,
|
|
@@ -1253,13 +1255,27 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1253
1255
|
adPlaying = false;
|
|
1254
1256
|
setAdPlayingFlag(false);
|
|
1255
1257
|
emit("content_resume");
|
|
1256
|
-
setTimeout(() => {
|
|
1257
|
-
if (
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1258
|
+
const timeoutId = window.setTimeout(() => {
|
|
1259
|
+
if (destroyed) {
|
|
1260
|
+
console.log("[HlsAdPlayer] Player destroyed, skipping post-completion check");
|
|
1261
|
+
return;
|
|
1262
|
+
}
|
|
1263
|
+
const stillInPod = contentVideo.dataset.stormcloudAdPlaying === "true";
|
|
1264
|
+
if (stillInPod) {
|
|
1265
|
+
console.log(
|
|
1266
|
+
"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)"
|
|
1267
|
+
);
|
|
1268
|
+
if (adContainerEl) {
|
|
1269
|
+
adContainerEl.style.display = "flex";
|
|
1270
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
const idx = pendingTimeouts.indexOf(timeoutId);
|
|
1274
|
+
if (idx !== -1) {
|
|
1275
|
+
pendingTimeouts.splice(idx, 1);
|
|
1261
1276
|
}
|
|
1262
1277
|
}, 50);
|
|
1278
|
+
pendingTimeouts.push(timeoutId);
|
|
1263
1279
|
}
|
|
1264
1280
|
function handleAdError() {
|
|
1265
1281
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
@@ -1489,6 +1505,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1489
1505
|
},
|
|
1490
1506
|
destroy() {
|
|
1491
1507
|
console.log("[HlsAdPlayer] Destroying");
|
|
1508
|
+
destroyed = true;
|
|
1509
|
+
for (const timeoutId of pendingTimeouts) {
|
|
1510
|
+
clearTimeout(timeoutId);
|
|
1511
|
+
}
|
|
1512
|
+
pendingTimeouts = [];
|
|
1492
1513
|
adPlaying = false;
|
|
1493
1514
|
setAdPlayingFlag(false);
|
|
1494
1515
|
contentVideo.muted = originalMutedState;
|
|
@@ -2401,10 +2422,11 @@ var StormcloudVideoPlayer = class {
|
|
|
2401
2422
|
this.handleAdPodComplete();
|
|
2402
2423
|
}
|
|
2403
2424
|
});
|
|
2404
|
-
this.
|
|
2425
|
+
this.timeUpdateHandler = () => {
|
|
2405
2426
|
this.onTimeUpdate(this.video.currentTime);
|
|
2406
|
-
}
|
|
2407
|
-
this.video.addEventListener("
|
|
2427
|
+
};
|
|
2428
|
+
this.video.addEventListener("timeupdate", this.timeUpdateHandler);
|
|
2429
|
+
this.emptiedHandler = () => {
|
|
2408
2430
|
if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {
|
|
2409
2431
|
if (this.config.debugAdTiming) {
|
|
2410
2432
|
console.log(
|
|
@@ -2421,7 +2443,8 @@ var StormcloudVideoPlayer = class {
|
|
|
2421
2443
|
});
|
|
2422
2444
|
}
|
|
2423
2445
|
}
|
|
2424
|
-
}
|
|
2446
|
+
};
|
|
2447
|
+
this.video.addEventListener("emptied", this.emptiedHandler);
|
|
2425
2448
|
}
|
|
2426
2449
|
shouldUseNativeHls() {
|
|
2427
2450
|
const streamType = this.getStreamType();
|
|
@@ -3113,7 +3136,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3113
3136
|
continue;
|
|
3114
3137
|
}
|
|
3115
3138
|
if (this.config.debugAdTiming) {
|
|
3116
|
-
console.log(`[CONTINUOUS-FETCH] \u{1F4E1} Attempting to fetch ad
|
|
3139
|
+
console.log(`[CONTINUOUS-FETCH] \u{1F4E1} Attempting to fetch ad (${this.successfulAdRequests.length + this.adRequestQueue.length + 1} total)...`);
|
|
3117
3140
|
}
|
|
3118
3141
|
try {
|
|
3119
3142
|
const response = await fetch(newAdUrl, { mode: "cors" });
|
|
@@ -3129,8 +3152,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3129
3152
|
console.log("[CONTINUOUS-FETCH] \u26A0\uFE0F VAST response has no media files, skipping");
|
|
3130
3153
|
}
|
|
3131
3154
|
this.failedVastUrls.add(newAdUrl);
|
|
3132
|
-
|
|
3133
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
3155
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3134
3156
|
continue;
|
|
3135
3157
|
}
|
|
3136
3158
|
if (this.config.debugAdTiming) {
|
|
@@ -3138,19 +3160,17 @@ var StormcloudVideoPlayer = class {
|
|
|
3138
3160
|
}
|
|
3139
3161
|
this.adRequestQueue.push(newAdUrl);
|
|
3140
3162
|
this.totalAdsInBreak++;
|
|
3141
|
-
|
|
3142
|
-
await new Promise((resolve) => setTimeout(resolve, successDelay));
|
|
3163
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3143
3164
|
} catch (error) {
|
|
3144
3165
|
if (this.config.debugAdTiming) {
|
|
3145
3166
|
console.log("[CONTINUOUS-FETCH] \u274C Ad fetch failed:", error.message);
|
|
3146
3167
|
}
|
|
3147
3168
|
this.failedVastUrls.add(newAdUrl);
|
|
3148
|
-
|
|
3149
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
3169
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
3150
3170
|
}
|
|
3151
3171
|
}
|
|
3152
3172
|
if (this.config.debugAdTiming) {
|
|
3153
|
-
console.log(
|
|
3173
|
+
console.log("[CONTINUOUS-FETCH] \u{1F6D1} Continuous fetch loop ended");
|
|
3154
3174
|
}
|
|
3155
3175
|
}
|
|
3156
3176
|
stopContinuousFetching() {
|
|
@@ -3188,27 +3208,20 @@ var StormcloudVideoPlayer = class {
|
|
|
3188
3208
|
return;
|
|
3189
3209
|
}
|
|
3190
3210
|
}
|
|
3191
|
-
const
|
|
3192
|
-
|
|
3193
|
-
const retryDelayMs = hasPlayedAtLeastOneAd ? 500 : 1e3;
|
|
3194
|
-
const minRemainingForRetry = 1e3;
|
|
3195
|
-
if (this.continuousFetchingActive && retryCount < maxRetries && remaining > minRemainingForRetry) {
|
|
3211
|
+
const maxRetries = 5;
|
|
3212
|
+
if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2e3) {
|
|
3196
3213
|
if (this.config.debugAdTiming) {
|
|
3197
|
-
console.log(`[CONTINUOUS-FETCH] \u23F3 Queue empty but fetching active, waiting
|
|
3214
|
+
console.log(`[CONTINUOUS-FETCH] \u23F3 Queue empty but fetching active, waiting... (retry ${retryCount + 1}/${maxRetries})`);
|
|
3198
3215
|
}
|
|
3199
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3216
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3200
3217
|
await this.tryNextAvailableAd(retryCount + 1);
|
|
3201
3218
|
return;
|
|
3202
3219
|
}
|
|
3203
|
-
|
|
3204
|
-
if (!this.isShowingPlaceholder && remaining >= minTimeForPlaceholder && this.continuousFetchingActive) {
|
|
3205
|
-
if (this.config.debugAdTiming) {
|
|
3206
|
-
console.log(`[CONTINUOUS-FETCH] \u2B1B Last resort: showing placeholder (${remaining}ms remaining)`);
|
|
3207
|
-
}
|
|
3220
|
+
if (!this.isShowingPlaceholder && remaining > 1e3) {
|
|
3208
3221
|
this.showPlaceholderAndWaitForAds();
|
|
3209
3222
|
} else {
|
|
3210
3223
|
if (this.config.debugAdTiming) {
|
|
3211
|
-
console.log(
|
|
3224
|
+
console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No more ads available, ending ad break");
|
|
3212
3225
|
}
|
|
3213
3226
|
this.handleAdPodComplete();
|
|
3214
3227
|
}
|
|
@@ -3216,36 +3229,26 @@ var StormcloudVideoPlayer = class {
|
|
|
3216
3229
|
async showPlaceholderAndWaitForAds() {
|
|
3217
3230
|
const remaining = this.getRemainingAdMs();
|
|
3218
3231
|
const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);
|
|
3219
|
-
if (waitTime <
|
|
3220
|
-
if (this.config.debugAdTiming) {
|
|
3221
|
-
console.log(`[CONTINUOUS-FETCH] \u23F9\uFE0F Insufficient time for placeholder (${waitTime}ms), ending ad break`);
|
|
3222
|
-
}
|
|
3232
|
+
if (waitTime < 1e3) {
|
|
3223
3233
|
this.handleAdPodComplete();
|
|
3224
3234
|
return;
|
|
3225
3235
|
}
|
|
3226
3236
|
if (this.config.debugAdTiming) {
|
|
3227
|
-
console.log(`[CONTINUOUS-FETCH] \u2B1B Showing black placeholder for
|
|
3237
|
+
console.log(`[CONTINUOUS-FETCH] \u2B1B Showing black placeholder for ${waitTime}ms while waiting for ads`);
|
|
3228
3238
|
}
|
|
3229
3239
|
this.isShowingPlaceholder = true;
|
|
3230
3240
|
this.placeholderStartTimeMs = Date.now();
|
|
3231
3241
|
this.ima.showPlaceholder();
|
|
3232
|
-
const checkInterval =
|
|
3242
|
+
const checkInterval = 500;
|
|
3233
3243
|
const maxChecks = Math.floor(waitTime / checkInterval);
|
|
3234
3244
|
for (let i = 0; i < maxChecks; i++) {
|
|
3235
3245
|
await new Promise((resolve) => setTimeout(resolve, checkInterval));
|
|
3236
3246
|
if (!this.inAdBreak) {
|
|
3237
|
-
if (this.config.debugAdTiming) {
|
|
3238
|
-
console.log("[CONTINUOUS-FETCH] \u2139\uFE0F Ad break ended during placeholder wait");
|
|
3239
|
-
}
|
|
3240
|
-
this.isShowingPlaceholder = false;
|
|
3241
|
-
this.placeholderStartTimeMs = null;
|
|
3242
|
-
this.ima.hidePlaceholder();
|
|
3243
3247
|
return;
|
|
3244
3248
|
}
|
|
3245
3249
|
if (this.adRequestQueue.length > 0) {
|
|
3246
|
-
const elapsedInPlaceholder = Date.now() - (this.placeholderStartTimeMs || Date.now());
|
|
3247
3250
|
if (this.config.debugAdTiming) {
|
|
3248
|
-
console.log(
|
|
3251
|
+
console.log("[CONTINUOUS-FETCH] \u2705 New ad became available during placeholder");
|
|
3249
3252
|
}
|
|
3250
3253
|
this.isShowingPlaceholder = false;
|
|
3251
3254
|
this.placeholderStartTimeMs = null;
|
|
@@ -3264,9 +3267,8 @@ var StormcloudVideoPlayer = class {
|
|
|
3264
3267
|
return;
|
|
3265
3268
|
}
|
|
3266
3269
|
}
|
|
3267
|
-
const totalPlaceholderTime = Date.now() - (this.placeholderStartTimeMs || Date.now());
|
|
3268
3270
|
if (this.config.debugAdTiming) {
|
|
3269
|
-
console.log(
|
|
3271
|
+
console.log("[CONTINUOUS-FETCH] \u23F0 Placeholder timeout reached, no ads fetched");
|
|
3270
3272
|
}
|
|
3271
3273
|
this.isShowingPlaceholder = false;
|
|
3272
3274
|
this.placeholderStartTimeMs = null;
|
|
@@ -4078,6 +4080,15 @@ var StormcloudVideoPlayer = class {
|
|
|
4078
4080
|
this.clearAdStartTimer();
|
|
4079
4081
|
this.clearAdStopTimer();
|
|
4080
4082
|
this.clearAdFailsafeTimer();
|
|
4083
|
+
this.clearAdRequestWatchdog();
|
|
4084
|
+
if (this.timeUpdateHandler) {
|
|
4085
|
+
this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
|
|
4086
|
+
delete this.timeUpdateHandler;
|
|
4087
|
+
}
|
|
4088
|
+
if (this.emptiedHandler) {
|
|
4089
|
+
this.video.removeEventListener("emptied", this.emptiedHandler);
|
|
4090
|
+
delete this.emptiedHandler;
|
|
4091
|
+
}
|
|
4081
4092
|
if (this.heartbeatInterval) {
|
|
4082
4093
|
clearInterval(this.heartbeatInterval);
|
|
4083
4094
|
this.heartbeatInterval = void 0;
|