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.d.cts
CHANGED
|
@@ -148,6 +148,8 @@ declare class StormcloudVideoPlayer {
|
|
|
148
148
|
private maxPlaceholderDurationMs;
|
|
149
149
|
private placeholderStartTimeMs;
|
|
150
150
|
private isShowingPlaceholder;
|
|
151
|
+
private timeUpdateHandler?;
|
|
152
|
+
private emptiedHandler?;
|
|
151
153
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
152
154
|
private createAdPlayer;
|
|
153
155
|
load(): Promise<void>;
|
package/lib/index.d.ts
CHANGED
|
@@ -148,6 +148,8 @@ declare class StormcloudVideoPlayer {
|
|
|
148
148
|
private maxPlaceholderDurationMs;
|
|
149
149
|
private placeholderStartTimeMs;
|
|
150
150
|
private isShowingPlaceholder;
|
|
151
|
+
private timeUpdateHandler?;
|
|
152
|
+
private emptiedHandler?;
|
|
151
153
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
152
154
|
private createAdPlayer;
|
|
153
155
|
load(): Promise<void>;
|
package/lib/index.js
CHANGED
|
@@ -920,6 +920,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
920
920
|
let sessionId;
|
|
921
921
|
const preloadedAds = /* @__PURE__ */ new Map();
|
|
922
922
|
const preloadingAds = /* @__PURE__ */ new Map();
|
|
923
|
+
let destroyed = false;
|
|
924
|
+
let pendingTimeouts = [];
|
|
923
925
|
let trackingFired = {
|
|
924
926
|
impression: false,
|
|
925
927
|
start: false,
|
|
@@ -1248,13 +1250,27 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1248
1250
|
adPlaying = false;
|
|
1249
1251
|
setAdPlayingFlag(false);
|
|
1250
1252
|
emit("content_resume");
|
|
1251
|
-
setTimeout(() => {
|
|
1252
|
-
if (
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1253
|
+
const timeoutId = window.setTimeout(() => {
|
|
1254
|
+
if (destroyed) {
|
|
1255
|
+
console.log("[HlsAdPlayer] Player destroyed, skipping post-completion check");
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1258
|
+
const stillInPod = contentVideo.dataset.stormcloudAdPlaying === "true";
|
|
1259
|
+
if (stillInPod) {
|
|
1260
|
+
console.log(
|
|
1261
|
+
"[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)"
|
|
1262
|
+
);
|
|
1263
|
+
if (adContainerEl) {
|
|
1264
|
+
adContainerEl.style.display = "flex";
|
|
1265
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
const idx = pendingTimeouts.indexOf(timeoutId);
|
|
1269
|
+
if (idx !== -1) {
|
|
1270
|
+
pendingTimeouts.splice(idx, 1);
|
|
1256
1271
|
}
|
|
1257
1272
|
}, 50);
|
|
1273
|
+
pendingTimeouts.push(timeoutId);
|
|
1258
1274
|
}
|
|
1259
1275
|
function handleAdError() {
|
|
1260
1276
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
@@ -1484,6 +1500,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1484
1500
|
},
|
|
1485
1501
|
destroy() {
|
|
1486
1502
|
console.log("[HlsAdPlayer] Destroying");
|
|
1503
|
+
destroyed = true;
|
|
1504
|
+
for (const timeoutId of pendingTimeouts) {
|
|
1505
|
+
clearTimeout(timeoutId);
|
|
1506
|
+
}
|
|
1507
|
+
pendingTimeouts = [];
|
|
1487
1508
|
adPlaying = false;
|
|
1488
1509
|
setAdPlayingFlag(false);
|
|
1489
1510
|
contentVideo.muted = originalMutedState;
|
|
@@ -2396,10 +2417,11 @@ var StormcloudVideoPlayer = class {
|
|
|
2396
2417
|
this.handleAdPodComplete();
|
|
2397
2418
|
}
|
|
2398
2419
|
});
|
|
2399
|
-
this.
|
|
2420
|
+
this.timeUpdateHandler = () => {
|
|
2400
2421
|
this.onTimeUpdate(this.video.currentTime);
|
|
2401
|
-
}
|
|
2402
|
-
this.video.addEventListener("
|
|
2422
|
+
};
|
|
2423
|
+
this.video.addEventListener("timeupdate", this.timeUpdateHandler);
|
|
2424
|
+
this.emptiedHandler = () => {
|
|
2403
2425
|
if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {
|
|
2404
2426
|
if (this.config.debugAdTiming) {
|
|
2405
2427
|
console.log(
|
|
@@ -2416,7 +2438,8 @@ var StormcloudVideoPlayer = class {
|
|
|
2416
2438
|
});
|
|
2417
2439
|
}
|
|
2418
2440
|
}
|
|
2419
|
-
}
|
|
2441
|
+
};
|
|
2442
|
+
this.video.addEventListener("emptied", this.emptiedHandler);
|
|
2420
2443
|
}
|
|
2421
2444
|
shouldUseNativeHls() {
|
|
2422
2445
|
const streamType = this.getStreamType();
|
|
@@ -3108,7 +3131,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3108
3131
|
continue;
|
|
3109
3132
|
}
|
|
3110
3133
|
if (this.config.debugAdTiming) {
|
|
3111
|
-
console.log(`[CONTINUOUS-FETCH] \u{1F4E1} Attempting to fetch ad
|
|
3134
|
+
console.log(`[CONTINUOUS-FETCH] \u{1F4E1} Attempting to fetch ad (${this.successfulAdRequests.length + this.adRequestQueue.length + 1} total)...`);
|
|
3112
3135
|
}
|
|
3113
3136
|
try {
|
|
3114
3137
|
const response = await fetch(newAdUrl, { mode: "cors" });
|
|
@@ -3124,8 +3147,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3124
3147
|
console.log("[CONTINUOUS-FETCH] \u26A0\uFE0F VAST response has no media files, skipping");
|
|
3125
3148
|
}
|
|
3126
3149
|
this.failedVastUrls.add(newAdUrl);
|
|
3127
|
-
|
|
3128
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
3150
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3129
3151
|
continue;
|
|
3130
3152
|
}
|
|
3131
3153
|
if (this.config.debugAdTiming) {
|
|
@@ -3133,19 +3155,17 @@ var StormcloudVideoPlayer = class {
|
|
|
3133
3155
|
}
|
|
3134
3156
|
this.adRequestQueue.push(newAdUrl);
|
|
3135
3157
|
this.totalAdsInBreak++;
|
|
3136
|
-
|
|
3137
|
-
await new Promise((resolve) => setTimeout(resolve, successDelay));
|
|
3158
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3138
3159
|
} catch (error) {
|
|
3139
3160
|
if (this.config.debugAdTiming) {
|
|
3140
3161
|
console.log("[CONTINUOUS-FETCH] \u274C Ad fetch failed:", error.message);
|
|
3141
3162
|
}
|
|
3142
3163
|
this.failedVastUrls.add(newAdUrl);
|
|
3143
|
-
|
|
3144
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
3164
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
3145
3165
|
}
|
|
3146
3166
|
}
|
|
3147
3167
|
if (this.config.debugAdTiming) {
|
|
3148
|
-
console.log(
|
|
3168
|
+
console.log("[CONTINUOUS-FETCH] \u{1F6D1} Continuous fetch loop ended");
|
|
3149
3169
|
}
|
|
3150
3170
|
}
|
|
3151
3171
|
stopContinuousFetching() {
|
|
@@ -3183,27 +3203,20 @@ var StormcloudVideoPlayer = class {
|
|
|
3183
3203
|
return;
|
|
3184
3204
|
}
|
|
3185
3205
|
}
|
|
3186
|
-
const
|
|
3187
|
-
|
|
3188
|
-
const retryDelayMs = hasPlayedAtLeastOneAd ? 500 : 1e3;
|
|
3189
|
-
const minRemainingForRetry = 1e3;
|
|
3190
|
-
if (this.continuousFetchingActive && retryCount < maxRetries && remaining > minRemainingForRetry) {
|
|
3206
|
+
const maxRetries = 5;
|
|
3207
|
+
if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2e3) {
|
|
3191
3208
|
if (this.config.debugAdTiming) {
|
|
3192
|
-
console.log(`[CONTINUOUS-FETCH] \u23F3 Queue empty but fetching active, waiting
|
|
3209
|
+
console.log(`[CONTINUOUS-FETCH] \u23F3 Queue empty but fetching active, waiting... (retry ${retryCount + 1}/${maxRetries})`);
|
|
3193
3210
|
}
|
|
3194
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3211
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3195
3212
|
await this.tryNextAvailableAd(retryCount + 1);
|
|
3196
3213
|
return;
|
|
3197
3214
|
}
|
|
3198
|
-
|
|
3199
|
-
if (!this.isShowingPlaceholder && remaining >= minTimeForPlaceholder && this.continuousFetchingActive) {
|
|
3200
|
-
if (this.config.debugAdTiming) {
|
|
3201
|
-
console.log(`[CONTINUOUS-FETCH] \u2B1B Last resort: showing placeholder (${remaining}ms remaining)`);
|
|
3202
|
-
}
|
|
3215
|
+
if (!this.isShowingPlaceholder && remaining > 1e3) {
|
|
3203
3216
|
this.showPlaceholderAndWaitForAds();
|
|
3204
3217
|
} else {
|
|
3205
3218
|
if (this.config.debugAdTiming) {
|
|
3206
|
-
console.log(
|
|
3219
|
+
console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No more ads available, ending ad break");
|
|
3207
3220
|
}
|
|
3208
3221
|
this.handleAdPodComplete();
|
|
3209
3222
|
}
|
|
@@ -3211,36 +3224,26 @@ var StormcloudVideoPlayer = class {
|
|
|
3211
3224
|
async showPlaceholderAndWaitForAds() {
|
|
3212
3225
|
const remaining = this.getRemainingAdMs();
|
|
3213
3226
|
const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);
|
|
3214
|
-
if (waitTime <
|
|
3215
|
-
if (this.config.debugAdTiming) {
|
|
3216
|
-
console.log(`[CONTINUOUS-FETCH] \u23F9\uFE0F Insufficient time for placeholder (${waitTime}ms), ending ad break`);
|
|
3217
|
-
}
|
|
3227
|
+
if (waitTime < 1e3) {
|
|
3218
3228
|
this.handleAdPodComplete();
|
|
3219
3229
|
return;
|
|
3220
3230
|
}
|
|
3221
3231
|
if (this.config.debugAdTiming) {
|
|
3222
|
-
console.log(`[CONTINUOUS-FETCH] \u2B1B Showing black placeholder for
|
|
3232
|
+
console.log(`[CONTINUOUS-FETCH] \u2B1B Showing black placeholder for ${waitTime}ms while waiting for ads`);
|
|
3223
3233
|
}
|
|
3224
3234
|
this.isShowingPlaceholder = true;
|
|
3225
3235
|
this.placeholderStartTimeMs = Date.now();
|
|
3226
3236
|
this.ima.showPlaceholder();
|
|
3227
|
-
const checkInterval =
|
|
3237
|
+
const checkInterval = 500;
|
|
3228
3238
|
const maxChecks = Math.floor(waitTime / checkInterval);
|
|
3229
3239
|
for (let i = 0; i < maxChecks; i++) {
|
|
3230
3240
|
await new Promise((resolve) => setTimeout(resolve, checkInterval));
|
|
3231
3241
|
if (!this.inAdBreak) {
|
|
3232
|
-
if (this.config.debugAdTiming) {
|
|
3233
|
-
console.log("[CONTINUOUS-FETCH] \u2139\uFE0F Ad break ended during placeholder wait");
|
|
3234
|
-
}
|
|
3235
|
-
this.isShowingPlaceholder = false;
|
|
3236
|
-
this.placeholderStartTimeMs = null;
|
|
3237
|
-
this.ima.hidePlaceholder();
|
|
3238
3242
|
return;
|
|
3239
3243
|
}
|
|
3240
3244
|
if (this.adRequestQueue.length > 0) {
|
|
3241
|
-
const elapsedInPlaceholder = Date.now() - (this.placeholderStartTimeMs || Date.now());
|
|
3242
3245
|
if (this.config.debugAdTiming) {
|
|
3243
|
-
console.log(
|
|
3246
|
+
console.log("[CONTINUOUS-FETCH] \u2705 New ad became available during placeholder");
|
|
3244
3247
|
}
|
|
3245
3248
|
this.isShowingPlaceholder = false;
|
|
3246
3249
|
this.placeholderStartTimeMs = null;
|
|
@@ -3259,9 +3262,8 @@ var StormcloudVideoPlayer = class {
|
|
|
3259
3262
|
return;
|
|
3260
3263
|
}
|
|
3261
3264
|
}
|
|
3262
|
-
const totalPlaceholderTime = Date.now() - (this.placeholderStartTimeMs || Date.now());
|
|
3263
3265
|
if (this.config.debugAdTiming) {
|
|
3264
|
-
console.log(
|
|
3266
|
+
console.log("[CONTINUOUS-FETCH] \u23F0 Placeholder timeout reached, no ads fetched");
|
|
3265
3267
|
}
|
|
3266
3268
|
this.isShowingPlaceholder = false;
|
|
3267
3269
|
this.placeholderStartTimeMs = null;
|
|
@@ -4073,6 +4075,15 @@ var StormcloudVideoPlayer = class {
|
|
|
4073
4075
|
this.clearAdStartTimer();
|
|
4074
4076
|
this.clearAdStopTimer();
|
|
4075
4077
|
this.clearAdFailsafeTimer();
|
|
4078
|
+
this.clearAdRequestWatchdog();
|
|
4079
|
+
if (this.timeUpdateHandler) {
|
|
4080
|
+
this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
|
|
4081
|
+
delete this.timeUpdateHandler;
|
|
4082
|
+
}
|
|
4083
|
+
if (this.emptiedHandler) {
|
|
4084
|
+
this.video.removeEventListener("emptied", this.emptiedHandler);
|
|
4085
|
+
delete this.emptiedHandler;
|
|
4086
|
+
}
|
|
4076
4087
|
if (this.heartbeatInterval) {
|
|
4077
4088
|
clearInterval(this.heartbeatInterval);
|
|
4078
4089
|
this.heartbeatInterval = void 0;
|