stormcloud-video-player 0.2.18 → 0.2.20
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 +151 -39
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +3 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +151 -39
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +151 -39
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +2 -1
- package/lib/players/HlsPlayer.cjs +151 -39
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +151 -39
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +30 -16
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/sdk/ima.cjs +32 -18
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-J6-Dpcvw.d.cts → types-D1xfSdLP.d.cts} +2 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +151 -39
- 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
package/lib/index.d.cts
CHANGED
|
@@ -24,6 +24,8 @@ interface StormcloudVideoPlayerConfig {
|
|
|
24
24
|
immediateManifestAds?: boolean;
|
|
25
25
|
debugAdTiming?: boolean;
|
|
26
26
|
adFailsafeTimeoutMs?: number;
|
|
27
|
+
adBreakCheckIntervalMs?: number;
|
|
28
|
+
maxAdBreakExtensionMs?: number;
|
|
27
29
|
showCustomControls?: boolean;
|
|
28
30
|
onVolumeToggle?: () => void;
|
|
29
31
|
onFullscreenToggle?: () => void;
|
|
@@ -120,6 +122,7 @@ declare class StormcloudVideoPlayer {
|
|
|
120
122
|
private bufferedSegmentsCount;
|
|
121
123
|
private shouldAutoplayAfterBuffering;
|
|
122
124
|
private hasInitialBufferCompleted;
|
|
125
|
+
private isTransitioningBetweenAds;
|
|
123
126
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
124
127
|
private createAdPlayer;
|
|
125
128
|
load(): Promise<void>;
|
package/lib/index.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ interface StormcloudVideoPlayerConfig {
|
|
|
24
24
|
immediateManifestAds?: boolean;
|
|
25
25
|
debugAdTiming?: boolean;
|
|
26
26
|
adFailsafeTimeoutMs?: number;
|
|
27
|
+
adBreakCheckIntervalMs?: number;
|
|
28
|
+
maxAdBreakExtensionMs?: number;
|
|
27
29
|
showCustomControls?: boolean;
|
|
28
30
|
onVolumeToggle?: () => void;
|
|
29
31
|
onFullscreenToggle?: () => void;
|
|
@@ -120,6 +122,7 @@ declare class StormcloudVideoPlayer {
|
|
|
120
122
|
private bufferedSegmentsCount;
|
|
121
123
|
private shouldAutoplayAfterBuffering;
|
|
122
124
|
private hasInitialBufferCompleted;
|
|
125
|
+
private isTransitioningBetweenAds;
|
|
123
126
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
124
127
|
private createAdPlayer;
|
|
125
128
|
load(): Promise<void>;
|
package/lib/index.js
CHANGED
|
@@ -523,28 +523,42 @@ function createImaController(video, options) {
|
|
|
523
523
|
adsManager.addEventListener(
|
|
524
524
|
AdEvent.CONTENT_RESUME_REQUESTED,
|
|
525
525
|
() => {
|
|
526
|
-
var _a;
|
|
527
526
|
console.log("[IMA] Content resume requested");
|
|
528
527
|
adPlaying = false;
|
|
529
|
-
video.muted = originalMutedState;
|
|
530
528
|
setAdPlayingFlag(false);
|
|
531
|
-
if (adContainerEl) {
|
|
532
|
-
adContainerEl.style.pointerEvents = "none";
|
|
533
|
-
adContainerEl.style.display = "none";
|
|
534
|
-
console.log(
|
|
535
|
-
"[IMA] Ad container hidden - pointer events disabled"
|
|
536
|
-
);
|
|
537
|
-
}
|
|
538
|
-
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
539
|
-
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
540
|
-
});
|
|
541
|
-
console.log("[IMA] Video resumed (VOD mode)");
|
|
542
|
-
} else {
|
|
543
|
-
console.log(
|
|
544
|
-
"[IMA] Video unmuted (Live mode - was never paused)"
|
|
545
|
-
);
|
|
546
|
-
}
|
|
547
529
|
emit("content_resume");
|
|
530
|
+
setTimeout(() => {
|
|
531
|
+
var _a;
|
|
532
|
+
const stillInAdPod = video.dataset.stormcloudAdPlaying === "true";
|
|
533
|
+
if (stillInAdPod) {
|
|
534
|
+
console.log(
|
|
535
|
+
"[IMA] Next ad started - keeping content muted/paused and ad container visible"
|
|
536
|
+
);
|
|
537
|
+
if (adContainerEl) {
|
|
538
|
+
adContainerEl.style.display = "flex";
|
|
539
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
540
|
+
}
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
console.log("[IMA] No next ad - resuming content");
|
|
544
|
+
video.muted = originalMutedState;
|
|
545
|
+
if (adContainerEl) {
|
|
546
|
+
adContainerEl.style.pointerEvents = "none";
|
|
547
|
+
adContainerEl.style.display = "none";
|
|
548
|
+
console.log(
|
|
549
|
+
"[IMA] Ad container hidden - pointer events disabled"
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
553
|
+
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
554
|
+
});
|
|
555
|
+
console.log("[IMA] Video resumed (VOD mode)");
|
|
556
|
+
} else {
|
|
557
|
+
console.log(
|
|
558
|
+
"[IMA] Video unmuted (Live mode - was never paused)"
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
}, 100);
|
|
548
562
|
}
|
|
549
563
|
);
|
|
550
564
|
adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {
|
|
@@ -1119,24 +1133,38 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1119
1133
|
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1120
1134
|
adPlaying = false;
|
|
1121
1135
|
setAdPlayingFlag(false);
|
|
1122
|
-
const previousMutedState = contentVideo.muted;
|
|
1123
|
-
contentVideo.muted = originalMutedState;
|
|
1124
|
-
console.log(
|
|
1125
|
-
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1126
|
-
);
|
|
1127
|
-
if (adContainerEl) {
|
|
1128
|
-
adContainerEl.style.display = "none";
|
|
1129
|
-
adContainerEl.style.pointerEvents = "none";
|
|
1130
|
-
}
|
|
1131
|
-
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1132
|
-
contentVideo.play().catch(() => {
|
|
1133
|
-
});
|
|
1134
|
-
console.log("[HlsAdPlayer] Content resumed (VOD mode)");
|
|
1135
|
-
} else {
|
|
1136
|
-
console.log("[HlsAdPlayer] Content unmuted (Live mode)");
|
|
1137
|
-
}
|
|
1138
1136
|
emit("content_resume");
|
|
1139
1137
|
emit("all_ads_completed");
|
|
1138
|
+
setTimeout(() => {
|
|
1139
|
+
const stillInAdPod = contentVideo.dataset.stormcloudAdPlaying === "true";
|
|
1140
|
+
if (stillInAdPod) {
|
|
1141
|
+
console.log(
|
|
1142
|
+
"[HlsAdPlayer] Next ad started - keeping content muted/paused and ad container visible"
|
|
1143
|
+
);
|
|
1144
|
+
if (adContainerEl) {
|
|
1145
|
+
adContainerEl.style.display = "flex";
|
|
1146
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1147
|
+
}
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
console.log("[HlsAdPlayer] No next ad - resuming content");
|
|
1151
|
+
const previousMutedState = contentVideo.muted;
|
|
1152
|
+
contentVideo.muted = originalMutedState;
|
|
1153
|
+
console.log(
|
|
1154
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1155
|
+
);
|
|
1156
|
+
if (adContainerEl) {
|
|
1157
|
+
adContainerEl.style.display = "none";
|
|
1158
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1159
|
+
}
|
|
1160
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1161
|
+
contentVideo.play().catch(() => {
|
|
1162
|
+
});
|
|
1163
|
+
console.log("[HlsAdPlayer] Content resumed (VOD mode)");
|
|
1164
|
+
} else {
|
|
1165
|
+
console.log("[HlsAdPlayer] Content unmuted (Live mode)");
|
|
1166
|
+
}
|
|
1167
|
+
}, 100);
|
|
1140
1168
|
}
|
|
1141
1169
|
function handleAdError() {
|
|
1142
1170
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
@@ -1874,6 +1902,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1874
1902
|
this.bufferedSegmentsCount = 0;
|
|
1875
1903
|
this.shouldAutoplayAfterBuffering = false;
|
|
1876
1904
|
this.hasInitialBufferCompleted = false;
|
|
1905
|
+
this.isTransitioningBetweenAds = false;
|
|
1877
1906
|
initializePolyfills();
|
|
1878
1907
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1879
1908
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2175,29 +2204,60 @@ var StormcloudVideoPlayer = class {
|
|
|
2175
2204
|
this.ima.on("content_resume", () => {
|
|
2176
2205
|
if (this.config.debugAdTiming) {
|
|
2177
2206
|
console.log(
|
|
2178
|
-
"[StormcloudVideoPlayer] IMA content_resume event received"
|
|
2207
|
+
"[StormcloudVideoPlayer] IMA content_resume event received",
|
|
2208
|
+
{
|
|
2209
|
+
inAdBreak: this.inAdBreak,
|
|
2210
|
+
isTransitioningBetweenAds: this.isTransitioningBetweenAds,
|
|
2211
|
+
pendingAds: this.adPodQueue.length
|
|
2212
|
+
}
|
|
2179
2213
|
);
|
|
2180
2214
|
}
|
|
2181
2215
|
this.clearAdFailsafeTimer();
|
|
2182
|
-
if (
|
|
2216
|
+
if (this.isTransitioningBetweenAds) {
|
|
2217
|
+
if (this.config.debugAdTiming) {
|
|
2218
|
+
console.log(
|
|
2219
|
+
"[StormcloudVideoPlayer] Transitioning between ads - keeping content muted/paused"
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
2222
|
+
return;
|
|
2223
|
+
}
|
|
2224
|
+
if (!this.inAdBreak) {
|
|
2225
|
+
if (this.config.debugAdTiming) {
|
|
2226
|
+
console.log(
|
|
2227
|
+
"[StormcloudVideoPlayer] Not in ad break, allowing normal content resume"
|
|
2228
|
+
);
|
|
2229
|
+
}
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
2183
2232
|
const remaining = this.getRemainingAdMs();
|
|
2184
2233
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2234
|
+
this.isTransitioningBetweenAds = true;
|
|
2235
|
+
this.video.muted = true;
|
|
2236
|
+
if (!this.shouldContinueLiveStreamDuringAds()) {
|
|
2237
|
+
this.video.pause();
|
|
2238
|
+
}
|
|
2185
2239
|
const next = this.adPodQueue.shift();
|
|
2186
2240
|
this.currentAdIndex++;
|
|
2187
2241
|
if (this.config.debugAdTiming) {
|
|
2188
2242
|
console.log(
|
|
2189
|
-
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak})`
|
|
2243
|
+
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - keeping content muted/paused`
|
|
2190
2244
|
);
|
|
2191
2245
|
}
|
|
2192
2246
|
this.playSingleAd(next).catch(() => {
|
|
2247
|
+
}).finally(() => {
|
|
2248
|
+
this.isTransitioningBetweenAds = false;
|
|
2193
2249
|
});
|
|
2194
2250
|
} else {
|
|
2195
2251
|
if (this.config.debugAdTiming) {
|
|
2196
2252
|
console.log("[StormcloudVideoPlayer] Ad pod completed");
|
|
2197
2253
|
}
|
|
2254
|
+
this.inAdBreak = false;
|
|
2255
|
+
this.expectedAdBreakDurationMs = void 0;
|
|
2256
|
+
this.currentAdBreakStartWallClockMs = void 0;
|
|
2198
2257
|
this.currentAdIndex = 0;
|
|
2199
2258
|
this.totalAdsInBreak = 0;
|
|
2200
2259
|
this.showAds = false;
|
|
2260
|
+
this.clearAdStopTimer();
|
|
2201
2261
|
}
|
|
2202
2262
|
});
|
|
2203
2263
|
this.video.addEventListener("timeupdate", () => {
|
|
@@ -2871,14 +2931,66 @@ var StormcloudVideoPlayer = class {
|
|
|
2871
2931
|
}
|
|
2872
2932
|
}
|
|
2873
2933
|
ensureAdStoppedByTimer() {
|
|
2934
|
+
var _a, _b;
|
|
2874
2935
|
if (!this.inAdBreak) return;
|
|
2936
|
+
this.adStopTimerId = void 0;
|
|
2937
|
+
const adPlaying = this.ima.isAdPlaying();
|
|
2938
|
+
const pendingAds = this.adPodQueue.length > 0;
|
|
2939
|
+
const checkIntervalMs = Math.max(
|
|
2940
|
+
250,
|
|
2941
|
+
Math.floor((_a = this.config.adBreakCheckIntervalMs) != null ? _a : 1e3)
|
|
2942
|
+
);
|
|
2943
|
+
const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;
|
|
2944
|
+
const maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;
|
|
2945
|
+
let elapsedSinceStartMs = 0;
|
|
2946
|
+
if (this.currentAdBreakStartWallClockMs != null) {
|
|
2947
|
+
elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;
|
|
2948
|
+
}
|
|
2949
|
+
const expectedDurationMs = (_b = this.expectedAdBreakDurationMs) != null ? _b : 0;
|
|
2950
|
+
const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
|
|
2951
|
+
const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
|
|
2952
|
+
if (shouldExtendAdBreak) {
|
|
2953
|
+
if (this.config.debugAdTiming) {
|
|
2954
|
+
console.log(
|
|
2955
|
+
"[StormcloudVideoPlayer] Extending ad break beyond scheduled duration",
|
|
2956
|
+
{
|
|
2957
|
+
adPlaying,
|
|
2958
|
+
pendingAds,
|
|
2959
|
+
showAds: this.showAds,
|
|
2960
|
+
overrunMs,
|
|
2961
|
+
checkIntervalMs,
|
|
2962
|
+
maxExtensionMs
|
|
2963
|
+
}
|
|
2964
|
+
);
|
|
2965
|
+
}
|
|
2966
|
+
this.scheduleAdStopCountdown(checkIntervalMs);
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
if (this.config.debugAdTiming) {
|
|
2970
|
+
console.log("[StormcloudVideoPlayer] Ending ad break via timer", {
|
|
2971
|
+
adPlaying,
|
|
2972
|
+
pendingAds,
|
|
2973
|
+
showAds: this.showAds,
|
|
2974
|
+
overrunMs,
|
|
2975
|
+
maxExtensionMs
|
|
2976
|
+
});
|
|
2977
|
+
}
|
|
2875
2978
|
this.inAdBreak = false;
|
|
2876
2979
|
this.expectedAdBreakDurationMs = void 0;
|
|
2877
2980
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
2878
|
-
this.
|
|
2879
|
-
|
|
2981
|
+
this.showAds = false;
|
|
2982
|
+
this.adPodQueue = [];
|
|
2983
|
+
this.currentAdIndex = 0;
|
|
2984
|
+
this.totalAdsInBreak = 0;
|
|
2985
|
+
this.clearAdFailsafeTimer();
|
|
2986
|
+
if (adPlaying) {
|
|
2880
2987
|
this.ima.stop().catch(() => {
|
|
2881
2988
|
});
|
|
2989
|
+
return;
|
|
2990
|
+
}
|
|
2991
|
+
const originalMutedState = this.ima.getOriginalMutedState();
|
|
2992
|
+
if (this.video.muted !== originalMutedState) {
|
|
2993
|
+
this.video.muted = originalMutedState;
|
|
2882
2994
|
}
|
|
2883
2995
|
}
|
|
2884
2996
|
scheduleAdStartIn(delayMs) {
|