stormcloud-video-player 0.3.9 → 0.3.10
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 +233 -183
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +11 -2
- package/lib/index.d.ts +11 -2
- package/lib/index.js +233 -183
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +233 -183
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +11 -2
- package/lib/players/HlsPlayer.cjs +233 -183
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +233 -183
- package/lib/players/index.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +233 -183
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
package/lib/players/index.cjs
CHANGED
|
@@ -2124,6 +2124,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2124
2124
|
this.targetAdBreakDurationMs = null;
|
|
2125
2125
|
this.isAdaptiveMode = false;
|
|
2126
2126
|
this.failedVastUrls = /* @__PURE__ */ new Set();
|
|
2127
|
+
this.continuousFetchingActive = false;
|
|
2128
|
+
this.adRequestQueue = [];
|
|
2129
|
+
this.successfulAdRequests = [];
|
|
2130
|
+
this.maxPlaceholderDurationMs = 5e3;
|
|
2131
|
+
this.placeholderStartTimeMs = null;
|
|
2132
|
+
this.isShowingPlaceholder = false;
|
|
2127
2133
|
initializePolyfills();
|
|
2128
2134
|
const browserOverrides = getBrowserConfigOverrides();
|
|
2129
2135
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2430,16 +2436,11 @@ var StormcloudVideoPlayer = class {
|
|
|
2430
2436
|
return;
|
|
2431
2437
|
}
|
|
2432
2438
|
const remaining = this.getRemainingAdMs();
|
|
2433
|
-
if (
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
this.handleAdPodComplete();
|
|
2439
|
-
});
|
|
2440
|
-
} else {
|
|
2441
|
-
this.handleAdPodComplete();
|
|
2442
|
-
}
|
|
2439
|
+
if (this.config.debugAdTiming) {
|
|
2440
|
+
console.log(`[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);
|
|
2441
|
+
}
|
|
2442
|
+
if (remaining > 500) {
|
|
2443
|
+
this.tryNextAvailableAd();
|
|
2443
2444
|
} else {
|
|
2444
2445
|
this.handleAdPodComplete();
|
|
2445
2446
|
}
|
|
@@ -3039,155 +3040,240 @@ var StormcloudVideoPlayer = class {
|
|
|
3039
3040
|
return true;
|
|
3040
3041
|
}
|
|
3041
3042
|
async handleAdStart(_marker) {
|
|
3042
|
-
var _a;
|
|
3043
3043
|
const scheduled = this.findCurrentOrNextBreak(
|
|
3044
3044
|
this.video.currentTime * 1e3
|
|
3045
3045
|
);
|
|
3046
3046
|
const tags = this.selectVastTagsForBreak(scheduled);
|
|
3047
|
-
let
|
|
3047
|
+
let baseVastUrl;
|
|
3048
3048
|
if (this.apiVastTagUrl) {
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3049
|
+
baseVastUrl = this.apiVastTagUrl;
|
|
3050
|
+
} else if (tags && tags.length > 0 && tags[0]) {
|
|
3051
|
+
baseVastUrl = tags[0];
|
|
3052
|
+
} else {
|
|
3053
|
+
return;
|
|
3054
|
+
}
|
|
3055
|
+
const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled == null ? void 0 : scheduled.durationMs;
|
|
3056
|
+
if (this.isLiveStream && adBreakDurationMs != null && adBreakDurationMs > 0) {
|
|
3057
|
+
this.isAdaptiveMode = true;
|
|
3058
|
+
this.targetAdBreakDurationMs = adBreakDurationMs;
|
|
3059
|
+
this.fetchedAdDurations.clear();
|
|
3060
|
+
if (this.config.debugAdTiming) {
|
|
3061
|
+
console.log(
|
|
3062
|
+
`[CONTINUOUS-FETCH] \u{1F4FA} LIVE MODE: Target duration=${adBreakDurationMs}ms | Will continuously fetch ads during break`
|
|
3063
|
+
);
|
|
3064
|
+
}
|
|
3065
|
+
} else {
|
|
3066
|
+
this.isAdaptiveMode = false;
|
|
3067
|
+
this.targetAdBreakDurationMs = null;
|
|
3068
|
+
this.fetchedAdDurations.clear();
|
|
3069
|
+
if (this.config.debugAdTiming) {
|
|
3070
|
+
console.log(
|
|
3071
|
+
`[CONTINUOUS-FETCH] \u{1F3AC} VOD MODE: Using fixed ad strategy`
|
|
3072
|
+
);
|
|
3073
|
+
}
|
|
3074
|
+
}
|
|
3075
|
+
this.adPodAllUrls = [];
|
|
3076
|
+
this.preloadingAdUrls.clear();
|
|
3077
|
+
this.vastToMediaUrlMap.clear();
|
|
3078
|
+
this.preloadedMediaUrls.clear();
|
|
3079
|
+
this.preloadingMediaUrls.clear();
|
|
3080
|
+
this.failedVastUrls.clear();
|
|
3081
|
+
this.adRequestQueue = [];
|
|
3082
|
+
this.successfulAdRequests = [];
|
|
3083
|
+
this.continuousFetchingActive = true;
|
|
3084
|
+
this.isShowingPlaceholder = false;
|
|
3085
|
+
this.placeholderStartTimeMs = null;
|
|
3086
|
+
const currentMuted = this.video.muted;
|
|
3087
|
+
const currentVolume = this.video.volume;
|
|
3088
|
+
this.ima.updateOriginalMutedState(currentMuted, currentVolume);
|
|
3089
|
+
this.inAdBreak = true;
|
|
3090
|
+
this.currentAdIndex = 0;
|
|
3091
|
+
this.totalAdsInBreak = 1;
|
|
3092
|
+
this.adPodQueue = [];
|
|
3093
|
+
if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
|
|
3094
|
+
this.expectedAdBreakDurationMs = adBreakDurationMs;
|
|
3095
|
+
this.currentAdBreakStartWallClockMs = Date.now();
|
|
3096
|
+
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
3097
|
+
}
|
|
3098
|
+
if (this.config.debugAdTiming) {
|
|
3099
|
+
console.log("[CONTINUOUS-FETCH] \u{1F680} Immediately requesting first ad...");
|
|
3100
|
+
}
|
|
3101
|
+
const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);
|
|
3102
|
+
const firstAdUrl = firstAdUrlArray[0];
|
|
3103
|
+
if (!firstAdUrl) {
|
|
3104
|
+
if (this.config.debugAdTiming) {
|
|
3105
|
+
console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F Failed to generate first ad URL");
|
|
3106
|
+
}
|
|
3107
|
+
this.handleAdPodComplete();
|
|
3108
|
+
return;
|
|
3109
|
+
}
|
|
3110
|
+
try {
|
|
3111
|
+
await this.ima.requestAds(firstAdUrl);
|
|
3112
|
+
if (this.config.debugAdTiming) {
|
|
3113
|
+
console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
|
|
3114
|
+
}
|
|
3115
|
+
this.successfulAdRequests.push(firstAdUrl);
|
|
3116
|
+
this.currentAdIndex++;
|
|
3117
|
+
this.startContinuousFetching(baseVastUrl);
|
|
3118
|
+
await this.ima.play();
|
|
3119
|
+
} catch (error) {
|
|
3120
|
+
if (this.config.debugAdTiming) {
|
|
3121
|
+
console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F First ad request failed:", error);
|
|
3122
|
+
}
|
|
3123
|
+
this.failedVastUrls.add(firstAdUrl);
|
|
3124
|
+
this.startContinuousFetching(baseVastUrl);
|
|
3125
|
+
this.tryNextAvailableAd();
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
startContinuousFetching(baseVastUrl) {
|
|
3129
|
+
if (!this.continuousFetchingActive) {
|
|
3130
|
+
return;
|
|
3131
|
+
}
|
|
3132
|
+
if (this.config.debugAdTiming) {
|
|
3133
|
+
console.log("[CONTINUOUS-FETCH] \u{1F504} Starting continuous ad fetching loop");
|
|
3134
|
+
}
|
|
3135
|
+
this.continuousFetchLoop(baseVastUrl);
|
|
3136
|
+
}
|
|
3137
|
+
async continuousFetchLoop(baseVastUrl) {
|
|
3138
|
+
while (this.continuousFetchingActive && this.inAdBreak) {
|
|
3139
|
+
const remaining = this.getRemainingAdMs();
|
|
3140
|
+
if (remaining <= 0) {
|
|
3141
|
+
if (this.config.debugAdTiming) {
|
|
3142
|
+
console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F Ad break time expired, stopping fetch loop");
|
|
3068
3143
|
}
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
this.
|
|
3073
|
-
|
|
3074
|
-
|
|
3144
|
+
break;
|
|
3145
|
+
}
|
|
3146
|
+
if (this.adRequestQueue.length > 0) {
|
|
3147
|
+
if (this.config.debugAdTiming) {
|
|
3148
|
+
console.log(`[CONTINUOUS-FETCH] \u23F3 Already have ${this.adRequestQueue.length} ads queued, waiting...`);
|
|
3149
|
+
}
|
|
3150
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
3151
|
+
continue;
|
|
3152
|
+
}
|
|
3153
|
+
const newAdUrl = this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
|
|
3154
|
+
if (!newAdUrl || this.failedVastUrls.has(newAdUrl)) {
|
|
3155
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3156
|
+
continue;
|
|
3157
|
+
}
|
|
3158
|
+
if (this.config.debugAdTiming) {
|
|
3159
|
+
console.log("[CONTINUOUS-FETCH] \u{1F4E1} Attempting to fetch additional ad...");
|
|
3160
|
+
}
|
|
3161
|
+
try {
|
|
3162
|
+
const response = await fetch(newAdUrl, { mode: "cors" });
|
|
3163
|
+
if (!response.ok) {
|
|
3164
|
+
throw new Error(`Failed to fetch VAST: ${response.status}`);
|
|
3165
|
+
}
|
|
3166
|
+
const xmlText = await response.text();
|
|
3167
|
+
const parser = new DOMParser();
|
|
3168
|
+
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
|
|
3169
|
+
const mediaFiles = xmlDoc.querySelectorAll("MediaFile");
|
|
3170
|
+
if (mediaFiles.length === 0) {
|
|
3075
3171
|
if (this.config.debugAdTiming) {
|
|
3076
|
-
console.log(
|
|
3077
|
-
`[DEBUG-POD] \u{1F3AC} VOD MODE (FIXED): Using number_ads=${numberOfAds} from API`
|
|
3078
|
-
);
|
|
3172
|
+
console.log("[CONTINUOUS-FETCH] \u26A0\uFE0F VAST response has no media files, skipping");
|
|
3079
3173
|
}
|
|
3174
|
+
this.failedVastUrls.add(newAdUrl);
|
|
3175
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3176
|
+
continue;
|
|
3080
3177
|
}
|
|
3081
|
-
}
|
|
3082
|
-
if (numberOfAds > 1) {
|
|
3083
|
-
vastTagUrls = this.generateVastUrlsWithCorrelators(
|
|
3084
|
-
this.apiVastTagUrl,
|
|
3085
|
-
numberOfAds
|
|
3086
|
-
);
|
|
3087
3178
|
if (this.config.debugAdTiming) {
|
|
3088
|
-
console.log(
|
|
3089
|
-
`[DEBUG-POD] \u{1F504} Generated ${vastTagUrls.length} initial VAST URLs with unique correlators`
|
|
3090
|
-
);
|
|
3179
|
+
console.log("[CONTINUOUS-FETCH] \u2705 Successfully fetched new ad, adding to queue");
|
|
3091
3180
|
}
|
|
3092
|
-
|
|
3093
|
-
|
|
3181
|
+
this.adRequestQueue.push(newAdUrl);
|
|
3182
|
+
this.totalAdsInBreak++;
|
|
3183
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
3184
|
+
} catch (error) {
|
|
3185
|
+
if (this.config.debugAdTiming) {
|
|
3186
|
+
console.log("[CONTINUOUS-FETCH] \u274C Ad fetch failed:", error.message);
|
|
3187
|
+
}
|
|
3188
|
+
this.failedVastUrls.add(newAdUrl);
|
|
3189
|
+
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
3094
3190
|
}
|
|
3095
|
-
}
|
|
3096
|
-
|
|
3097
|
-
|
|
3191
|
+
}
|
|
3192
|
+
if (this.config.debugAdTiming) {
|
|
3193
|
+
console.log("[CONTINUOUS-FETCH] \u{1F6D1} Continuous fetch loop ended");
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
stopContinuousFetching() {
|
|
3197
|
+
this.continuousFetchingActive = false;
|
|
3198
|
+
if (this.config.debugAdTiming) {
|
|
3199
|
+
console.log("[CONTINUOUS-FETCH] \u{1F6D1} Stopping continuous ad fetching");
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
async tryNextAvailableAd() {
|
|
3203
|
+
const remaining = this.getRemainingAdMs();
|
|
3204
|
+
if (remaining <= 500) {
|
|
3205
|
+
if (this.config.debugAdTiming) {
|
|
3206
|
+
console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No time remaining, ending ad break");
|
|
3207
|
+
}
|
|
3208
|
+
this.handleAdPodComplete();
|
|
3098
3209
|
return;
|
|
3099
3210
|
}
|
|
3100
|
-
if (
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
this.vastToMediaUrlMap.clear();
|
|
3104
|
-
this.preloadedMediaUrls.clear();
|
|
3105
|
-
this.preloadingMediaUrls.clear();
|
|
3106
|
-
this.failedVastUrls.clear();
|
|
3107
|
-
const currentMuted = this.video.muted;
|
|
3108
|
-
const currentVolume = this.video.volume;
|
|
3109
|
-
this.ima.updateOriginalMutedState(currentMuted, currentVolume);
|
|
3110
|
-
this.inAdBreak = true;
|
|
3111
|
-
this.currentAdIndex = 0;
|
|
3112
|
-
this.totalAdsInBreak = vastTagUrls.length;
|
|
3113
|
-
this.adPodQueue = [...vastTagUrls];
|
|
3114
|
-
if (this.isAdaptiveMode) {
|
|
3211
|
+
if (this.adRequestQueue.length > 0) {
|
|
3212
|
+
const nextAdUrl = this.adRequestQueue.shift();
|
|
3213
|
+
if (nextAdUrl) {
|
|
3115
3214
|
if (this.config.debugAdTiming) {
|
|
3116
|
-
console.log("[
|
|
3117
|
-
}
|
|
3118
|
-
try {
|
|
3119
|
-
const adsToPreloadBeforeStart = Math.min(2, this.adPodAllUrls.length);
|
|
3120
|
-
for (let i = 0; i < adsToPreloadBeforeStart; i++) {
|
|
3121
|
-
const url = this.adPodAllUrls[i];
|
|
3122
|
-
if (url) {
|
|
3123
|
-
await this.preloadSingleAd(url);
|
|
3124
|
-
if (this.config.debugAdTiming) {
|
|
3125
|
-
console.log(`[ADAPTIVE-POD] \u2705 Preloaded ad ${i + 1}/${adsToPreloadBeforeStart}`);
|
|
3126
|
-
}
|
|
3127
|
-
}
|
|
3128
|
-
}
|
|
3129
|
-
if (this.config.debugAdTiming) {
|
|
3130
|
-
console.log("[ADAPTIVE-POD] \u{1F3AC} First ads preloaded, starting playback immediately");
|
|
3131
|
-
}
|
|
3132
|
-
} catch (error) {
|
|
3133
|
-
if (this.config.debugAdTiming) {
|
|
3134
|
-
console.warn(
|
|
3135
|
-
"[ADAPTIVE-POD] \u26A0\uFE0F Error preloading initial ads:",
|
|
3136
|
-
error
|
|
3137
|
-
);
|
|
3138
|
-
}
|
|
3215
|
+
console.log("[CONTINUOUS-FETCH] \u{1F3AC} Playing next queued ad");
|
|
3139
3216
|
}
|
|
3140
|
-
this.
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
"[ADAPTIVE-POD] Error in background preloading:",
|
|
3144
|
-
error
|
|
3145
|
-
);
|
|
3146
|
-
}
|
|
3147
|
-
});
|
|
3148
|
-
await this.playAdPod();
|
|
3149
|
-
} else {
|
|
3150
|
-
this.preloadAllAdsInBackground().catch((error) => {
|
|
3151
|
-
if (this.config.debugAdTiming) {
|
|
3152
|
-
console.warn(
|
|
3153
|
-
"[StormcloudVideoPlayer] Error in background preloading:",
|
|
3154
|
-
error
|
|
3155
|
-
);
|
|
3156
|
-
}
|
|
3217
|
+
this.currentAdIndex++;
|
|
3218
|
+
await this.playSingleAd(nextAdUrl).catch(() => {
|
|
3219
|
+
this.tryNextAvailableAd();
|
|
3157
3220
|
});
|
|
3158
|
-
|
|
3221
|
+
return;
|
|
3159
3222
|
}
|
|
3160
3223
|
}
|
|
3161
|
-
if (this.
|
|
3162
|
-
this.
|
|
3163
|
-
|
|
3164
|
-
|
|
3224
|
+
if (!this.isShowingPlaceholder && remaining > 1e3) {
|
|
3225
|
+
this.showPlaceholderAndWaitForAds();
|
|
3226
|
+
} else {
|
|
3227
|
+
if (this.config.debugAdTiming) {
|
|
3228
|
+
console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No more ads available, ending ad break");
|
|
3229
|
+
}
|
|
3230
|
+
this.handleAdPodComplete();
|
|
3165
3231
|
}
|
|
3166
3232
|
}
|
|
3167
|
-
async
|
|
3168
|
-
|
|
3233
|
+
async showPlaceholderAndWaitForAds() {
|
|
3234
|
+
const remaining = this.getRemainingAdMs();
|
|
3235
|
+
const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);
|
|
3236
|
+
if (waitTime < 1e3) {
|
|
3237
|
+
this.handleAdPodComplete();
|
|
3169
3238
|
return;
|
|
3170
3239
|
}
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3240
|
+
if (this.config.debugAdTiming) {
|
|
3241
|
+
console.log(`[CONTINUOUS-FETCH] \u2B1B Showing black placeholder for ${waitTime}ms while waiting for ads`);
|
|
3242
|
+
}
|
|
3243
|
+
this.isShowingPlaceholder = true;
|
|
3244
|
+
this.placeholderStartTimeMs = Date.now();
|
|
3245
|
+
this.ima.showPlaceholder();
|
|
3246
|
+
const checkInterval = 500;
|
|
3247
|
+
const maxChecks = Math.floor(waitTime / checkInterval);
|
|
3248
|
+
for (let i = 0; i < maxChecks; i++) {
|
|
3249
|
+
await new Promise((resolve) => setTimeout(resolve, checkInterval));
|
|
3250
|
+
if (!this.inAdBreak) {
|
|
3251
|
+
return;
|
|
3252
|
+
}
|
|
3253
|
+
if (this.adRequestQueue.length > 0) {
|
|
3254
|
+
if (this.config.debugAdTiming) {
|
|
3255
|
+
console.log("[CONTINUOUS-FETCH] \u2705 New ad became available during placeholder");
|
|
3256
|
+
}
|
|
3257
|
+
this.isShowingPlaceholder = false;
|
|
3258
|
+
this.placeholderStartTimeMs = null;
|
|
3259
|
+
this.ima.hidePlaceholder();
|
|
3260
|
+
const nextAdUrl = this.adRequestQueue.shift();
|
|
3261
|
+
if (nextAdUrl) {
|
|
3262
|
+
this.currentAdIndex++;
|
|
3263
|
+
await this.playSingleAd(nextAdUrl).catch(() => {
|
|
3264
|
+
this.tryNextAvailableAd();
|
|
3265
|
+
});
|
|
3182
3266
|
}
|
|
3267
|
+
return;
|
|
3183
3268
|
}
|
|
3184
|
-
return;
|
|
3185
3269
|
}
|
|
3186
|
-
this.
|
|
3187
|
-
|
|
3188
|
-
await this.playSingleAd(firstPreloaded);
|
|
3189
|
-
} catch (error) {
|
|
3270
|
+
if (this.config.debugAdTiming) {
|
|
3271
|
+
console.log("[CONTINUOUS-FETCH] \u23F0 Placeholder timeout reached, no ads fetched");
|
|
3190
3272
|
}
|
|
3273
|
+
this.isShowingPlaceholder = false;
|
|
3274
|
+
this.placeholderStartTimeMs = null;
|
|
3275
|
+
this.ima.hidePlaceholder();
|
|
3276
|
+
this.handleAdPodComplete();
|
|
3191
3277
|
}
|
|
3192
3278
|
findCurrentOrNextBreak(nowMs) {
|
|
3193
3279
|
var _a;
|
|
@@ -3347,10 +3433,18 @@ var StormcloudVideoPlayer = class {
|
|
|
3347
3433
|
this.clearAdRequestWatchdog();
|
|
3348
3434
|
this.clearAdFailsafeTimer();
|
|
3349
3435
|
this.activeAdRequestToken = null;
|
|
3436
|
+
this.stopContinuousFetching();
|
|
3437
|
+
if (this.isShowingPlaceholder) {
|
|
3438
|
+
this.ima.hidePlaceholder();
|
|
3439
|
+
this.isShowingPlaceholder = false;
|
|
3440
|
+
this.placeholderStartTimeMs = null;
|
|
3441
|
+
}
|
|
3350
3442
|
this.preloadingAdUrls.clear();
|
|
3351
3443
|
this.vastToMediaUrlMap.clear();
|
|
3352
3444
|
this.preloadedMediaUrls.clear();
|
|
3353
3445
|
this.preloadingMediaUrls.clear();
|
|
3446
|
+
this.adRequestQueue = [];
|
|
3447
|
+
this.successfulAdRequests = [];
|
|
3354
3448
|
this.inAdBreak = false;
|
|
3355
3449
|
this.expectedAdBreakDurationMs = void 0;
|
|
3356
3450
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3377,61 +3471,14 @@ var StormcloudVideoPlayer = class {
|
|
|
3377
3471
|
}
|
|
3378
3472
|
}
|
|
3379
3473
|
handleAdFailure() {
|
|
3380
|
-
const remaining = this.getRemainingAdMs();
|
|
3381
|
-
const availableAds = this.adPodQueue.filter((url) => !this.failedVastUrls.has(url)).length;
|
|
3382
|
-
if (remaining > 500 && availableAds > 0) {
|
|
3383
|
-
if (this.isAdaptiveMode && this.currentAdIndex <= 1) {
|
|
3384
|
-
console.log("[ADAPTIVE-POD] \u23F3 First ad failed, waiting for sequential preload to catch up...");
|
|
3385
|
-
setTimeout(() => {
|
|
3386
|
-
this.tryNextAdWithRetry(0);
|
|
3387
|
-
}, 1500);
|
|
3388
|
-
return;
|
|
3389
|
-
}
|
|
3390
|
-
const nextPreloaded = this.findNextPreloadedAd();
|
|
3391
|
-
if (nextPreloaded) {
|
|
3392
|
-
this.currentAdIndex++;
|
|
3393
|
-
this.playSingleAd(nextPreloaded).catch(() => {
|
|
3394
|
-
this.handleAdPodComplete();
|
|
3395
|
-
});
|
|
3396
|
-
return;
|
|
3397
|
-
}
|
|
3398
|
-
}
|
|
3399
|
-
console.error("[AD-ERROR] All ads failed or time expired. Failed URLs:", this.failedVastUrls.size);
|
|
3400
|
-
this.handleAdPodComplete();
|
|
3401
|
-
}
|
|
3402
|
-
tryNextAdWithRetry(retryCount) {
|
|
3403
|
-
const maxRetries = 3;
|
|
3404
3474
|
const remaining = this.getRemainingAdMs();
|
|
3405
3475
|
if (this.config.debugAdTiming) {
|
|
3406
|
-
console.log(
|
|
3407
|
-
`[ADAPTIVE-POD] \u{1F50D} Retry attempt ${retryCount}: remaining=${remaining}ms, queue=${this.adPodQueue.length}, totalAds=${this.totalAdsInBreak}`
|
|
3408
|
-
);
|
|
3409
|
-
}
|
|
3410
|
-
if (remaining <= 500 || this.adPodQueue.length === 0) {
|
|
3411
|
-
console.log("[ADAPTIVE-POD] \u23F9\uFE0F No more time or ads available");
|
|
3412
|
-
this.handleAdPodComplete();
|
|
3413
|
-
return;
|
|
3476
|
+
console.log(`[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);
|
|
3414
3477
|
}
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
this.currentAdIndex++;
|
|
3418
|
-
console.log(
|
|
3419
|
-
`[ADAPTIVE-POD] \u2705 Found preloaded ad after retry ${retryCount}, playing (${this.currentAdIndex}/${this.totalAdsInBreak})`
|
|
3420
|
-
);
|
|
3421
|
-
this.playSingleAd(nextPreloaded).catch(() => {
|
|
3422
|
-
this.handleAdPodComplete();
|
|
3423
|
-
});
|
|
3424
|
-
} else if (retryCount < maxRetries) {
|
|
3425
|
-
console.log(
|
|
3426
|
-
`[ADAPTIVE-POD] \u23F3 No preloaded ads yet (queue has ${this.adPodQueue.length} URLs), retry ${retryCount + 1}/${maxRetries} in 1s...`
|
|
3427
|
-
);
|
|
3428
|
-
setTimeout(() => {
|
|
3429
|
-
this.tryNextAdWithRetry(retryCount + 1);
|
|
3430
|
-
}, 1e3);
|
|
3478
|
+
if (remaining > 500) {
|
|
3479
|
+
this.tryNextAvailableAd();
|
|
3431
3480
|
} else {
|
|
3432
|
-
console.
|
|
3433
|
-
`[ADAPTIVE-POD] \u274C Max retries reached, no preloaded ads available (queue=${this.adPodQueue.length} URLs)`
|
|
3434
|
-
);
|
|
3481
|
+
console.error("[AD-ERROR] Ad failed and no time remaining. Failed URLs:", this.failedVastUrls.size);
|
|
3435
3482
|
this.handleAdPodComplete();
|
|
3436
3483
|
}
|
|
3437
3484
|
}
|
|
@@ -4029,6 +4076,7 @@ var StormcloudVideoPlayer = class {
|
|
|
4029
4076
|
}
|
|
4030
4077
|
destroy() {
|
|
4031
4078
|
var _a, _b;
|
|
4079
|
+
this.stopContinuousFetching();
|
|
4032
4080
|
this.clearAdStartTimer();
|
|
4033
4081
|
this.clearAdStopTimer();
|
|
4034
4082
|
this.clearAdFailsafeTimer();
|
|
@@ -4043,6 +4091,8 @@ var StormcloudVideoPlayer = class {
|
|
|
4043
4091
|
this.preloadedMediaUrls.clear();
|
|
4044
4092
|
this.preloadingMediaUrls.clear();
|
|
4045
4093
|
this.adPodAllUrls = [];
|
|
4094
|
+
this.adRequestQueue = [];
|
|
4095
|
+
this.successfulAdRequests = [];
|
|
4046
4096
|
}
|
|
4047
4097
|
};
|
|
4048
4098
|
|