stormcloud-video-player 0.2.9 → 0.2.11
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 +469 -118
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +469 -118
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +206 -66
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +206 -66
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +206 -66
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/ima.cjs +116 -31
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +469 -118
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -42,9 +42,22 @@ function createImaController(video, options) {
|
|
|
42
42
|
'script[data-ima="true"]'
|
|
43
43
|
);
|
|
44
44
|
if (existing) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
if (window.google?.ima) {
|
|
46
|
+
return Promise.resolve();
|
|
47
|
+
}
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const timeout = setTimeout(() => {
|
|
50
|
+
reject(new Error("IMA SDK load timeout"));
|
|
51
|
+
}, 1e4);
|
|
52
|
+
existing.addEventListener("load", () => {
|
|
53
|
+
clearTimeout(timeout);
|
|
54
|
+
resolve();
|
|
55
|
+
});
|
|
56
|
+
existing.addEventListener("error", () => {
|
|
57
|
+
clearTimeout(timeout);
|
|
58
|
+
reject(new Error("IMA SDK load failed"));
|
|
59
|
+
});
|
|
60
|
+
});
|
|
48
61
|
}
|
|
49
62
|
return new Promise((resolve, reject) => {
|
|
50
63
|
const script = document.createElement("script");
|
|
@@ -73,6 +86,17 @@ function createImaController(video, options) {
|
|
|
73
86
|
adsRequest.adTagUrl = vastTagUrl;
|
|
74
87
|
adsLoader.requestAds(adsRequest);
|
|
75
88
|
}
|
|
89
|
+
function destroyAdsManager() {
|
|
90
|
+
if (adsManager) {
|
|
91
|
+
try {
|
|
92
|
+
console.log("[IMA] Destroying existing ads manager");
|
|
93
|
+
adsManager.destroy();
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.warn("[IMA] Error destroying ads manager:", error);
|
|
96
|
+
}
|
|
97
|
+
adsManager = void 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
76
100
|
return {
|
|
77
101
|
initialize() {
|
|
78
102
|
ensureImaLoaded().then(() => {
|
|
@@ -105,9 +129,22 @@ function createImaController(video, options) {
|
|
|
105
129
|
},
|
|
106
130
|
async requestAds(vastTagUrl) {
|
|
107
131
|
console.log("[IMA] Requesting ads:", vastTagUrl);
|
|
132
|
+
if (adPlaying) {
|
|
133
|
+
console.warn(
|
|
134
|
+
"[IMA] Cannot request new ads while an ad is playing. Call stop() first."
|
|
135
|
+
);
|
|
136
|
+
return Promise.reject(
|
|
137
|
+
new Error("Ad already playing - cannot request new ads")
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
destroyAdsManager();
|
|
141
|
+
adsLoadedReject = void 0;
|
|
142
|
+
adsLoadedResolve = void 0;
|
|
143
|
+
let currentReject;
|
|
108
144
|
adsLoadedPromise = new Promise((resolve, reject) => {
|
|
109
145
|
adsLoadedResolve = resolve;
|
|
110
146
|
adsLoadedReject = reject;
|
|
147
|
+
currentReject = reject;
|
|
111
148
|
setTimeout(() => {
|
|
112
149
|
if (adsLoadedReject) {
|
|
113
150
|
adsLoadedReject(new Error("Ad request timeout"));
|
|
@@ -129,7 +166,7 @@ function createImaController(video, options) {
|
|
|
129
166
|
container.style.top = "0";
|
|
130
167
|
container.style.right = "0";
|
|
131
168
|
container.style.bottom = "0";
|
|
132
|
-
container.style.display = "
|
|
169
|
+
container.style.display = "none";
|
|
133
170
|
container.style.alignItems = "center";
|
|
134
171
|
container.style.justifyContent = "center";
|
|
135
172
|
container.style.pointerEvents = "none";
|
|
@@ -169,14 +206,14 @@ function createImaController(video, options) {
|
|
|
169
206
|
AdErrorEvent.AD_ERROR,
|
|
170
207
|
(errorEvent) => {
|
|
171
208
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
172
|
-
|
|
173
|
-
adsManager?.destroy?.();
|
|
174
|
-
} catch {
|
|
175
|
-
}
|
|
209
|
+
destroyAdsManager();
|
|
176
210
|
adPlaying = false;
|
|
177
211
|
video.muted = originalMutedState;
|
|
178
|
-
if (adContainerEl)
|
|
212
|
+
if (adContainerEl) {
|
|
179
213
|
adContainerEl.style.pointerEvents = "none";
|
|
214
|
+
adContainerEl.style.display = "none";
|
|
215
|
+
console.log("[IMA] Ad container hidden after error");
|
|
216
|
+
}
|
|
180
217
|
if (adsLoadedReject) {
|
|
181
218
|
adsLoadedReject(new Error("Ad playback error"));
|
|
182
219
|
adsLoadedReject = void 0;
|
|
@@ -199,8 +236,11 @@ function createImaController(video, options) {
|
|
|
199
236
|
);
|
|
200
237
|
emit("ad_error");
|
|
201
238
|
if (!options?.continueLiveStreamDuringAds) {
|
|
202
|
-
video.
|
|
203
|
-
|
|
239
|
+
if (video.paused) {
|
|
240
|
+
console.log("[IMA] Resuming paused video after ad error");
|
|
241
|
+
video.play()?.catch(() => {
|
|
242
|
+
});
|
|
243
|
+
}
|
|
204
244
|
}
|
|
205
245
|
}
|
|
206
246
|
}
|
|
@@ -209,10 +249,6 @@ function createImaController(video, options) {
|
|
|
209
249
|
AdEvent.CONTENT_PAUSE_REQUESTED,
|
|
210
250
|
() => {
|
|
211
251
|
console.log("[IMA] Content pause requested");
|
|
212
|
-
if (!adPlaying) {
|
|
213
|
-
originalMutedState = video.muted;
|
|
214
|
-
}
|
|
215
|
-
video.muted = true;
|
|
216
252
|
if (!options?.continueLiveStreamDuringAds) {
|
|
217
253
|
video.pause();
|
|
218
254
|
console.log("[IMA] Video paused (VOD mode)");
|
|
@@ -221,20 +257,34 @@ function createImaController(video, options) {
|
|
|
221
257
|
"[IMA] Video continues playing but muted (Live mode)"
|
|
222
258
|
);
|
|
223
259
|
}
|
|
260
|
+
video.muted = true;
|
|
224
261
|
adPlaying = true;
|
|
225
|
-
if (adContainerEl)
|
|
226
|
-
adContainerEl.style.pointerEvents = "auto";
|
|
227
262
|
emit("content_pause");
|
|
228
263
|
}
|
|
229
264
|
);
|
|
265
|
+
adsManager.addEventListener(AdEvent.STARTED, () => {
|
|
266
|
+
console.log("[IMA] Ad started playing");
|
|
267
|
+
if (adContainerEl) {
|
|
268
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
269
|
+
adContainerEl.style.display = "flex";
|
|
270
|
+
console.log(
|
|
271
|
+
"[IMA] Ad container visibility set to flex with pointer events enabled"
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
230
275
|
adsManager.addEventListener(
|
|
231
276
|
AdEvent.CONTENT_RESUME_REQUESTED,
|
|
232
277
|
() => {
|
|
233
278
|
console.log("[IMA] Content resume requested");
|
|
234
279
|
adPlaying = false;
|
|
235
280
|
video.muted = originalMutedState;
|
|
236
|
-
if (adContainerEl)
|
|
281
|
+
if (adContainerEl) {
|
|
237
282
|
adContainerEl.style.pointerEvents = "none";
|
|
283
|
+
adContainerEl.style.display = "none";
|
|
284
|
+
console.log(
|
|
285
|
+
"[IMA] Ad container hidden - pointer events disabled"
|
|
286
|
+
);
|
|
287
|
+
}
|
|
238
288
|
if (!options?.continueLiveStreamDuringAds) {
|
|
239
289
|
video.play()?.catch(() => {
|
|
240
290
|
});
|
|
@@ -251,7 +301,13 @@ function createImaController(video, options) {
|
|
|
251
301
|
console.log("[IMA] All ads completed");
|
|
252
302
|
adPlaying = false;
|
|
253
303
|
video.muted = originalMutedState;
|
|
254
|
-
if (adContainerEl)
|
|
304
|
+
if (adContainerEl) {
|
|
305
|
+
adContainerEl.style.pointerEvents = "none";
|
|
306
|
+
adContainerEl.style.display = "none";
|
|
307
|
+
console.log(
|
|
308
|
+
"[IMA] Ad container hidden after all ads completed"
|
|
309
|
+
);
|
|
310
|
+
}
|
|
255
311
|
if (!options?.continueLiveStreamDuringAds) {
|
|
256
312
|
video.play().catch(() => {
|
|
257
313
|
});
|
|
@@ -275,10 +331,17 @@ function createImaController(video, options) {
|
|
|
275
331
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
276
332
|
adPlaying = false;
|
|
277
333
|
video.muted = originalMutedState;
|
|
278
|
-
if (adContainerEl)
|
|
334
|
+
if (adContainerEl) {
|
|
335
|
+
adContainerEl.style.pointerEvents = "none";
|
|
336
|
+
adContainerEl.style.display = "none";
|
|
337
|
+
console.log("[IMA] Ad container hidden after setup error");
|
|
338
|
+
}
|
|
279
339
|
if (!options?.continueLiveStreamDuringAds) {
|
|
280
|
-
video.
|
|
281
|
-
|
|
340
|
+
if (video.paused) {
|
|
341
|
+
console.log("[IMA] Resuming paused video after setup error");
|
|
342
|
+
video.play().catch(() => {
|
|
343
|
+
});
|
|
344
|
+
}
|
|
282
345
|
}
|
|
283
346
|
if (adsLoadedReject) {
|
|
284
347
|
adsLoadedReject(new Error("Failed to setup ads manager"));
|
|
@@ -294,6 +357,20 @@ function createImaController(video, options) {
|
|
|
294
357
|
google.ima.AdErrorEvent.Type.AD_ERROR,
|
|
295
358
|
(adErrorEvent) => {
|
|
296
359
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
360
|
+
adPlaying = false;
|
|
361
|
+
video.muted = originalMutedState;
|
|
362
|
+
if (adContainerEl) {
|
|
363
|
+
adContainerEl.style.pointerEvents = "none";
|
|
364
|
+
adContainerEl.style.display = "none";
|
|
365
|
+
console.log("[IMA] Ad container hidden after loader error");
|
|
366
|
+
}
|
|
367
|
+
if (!options?.continueLiveStreamDuringAds) {
|
|
368
|
+
if (video.paused) {
|
|
369
|
+
console.log("[IMA] Resuming paused video after loader error");
|
|
370
|
+
video.play().catch(() => {
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
297
374
|
if (adsLoadedReject) {
|
|
298
375
|
adsLoadedReject(new Error("Ads loader error"));
|
|
299
376
|
adsLoadedReject = void 0;
|
|
@@ -309,11 +386,9 @@ function createImaController(video, options) {
|
|
|
309
386
|
return adsLoadedPromise;
|
|
310
387
|
} catch (error) {
|
|
311
388
|
console.error("[IMA] Failed to request ads:", error);
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
adsLoadedResolve = void 0;
|
|
316
|
-
}
|
|
389
|
+
currentReject?.(error);
|
|
390
|
+
adsLoadedReject = void 0;
|
|
391
|
+
adsLoadedResolve = void 0;
|
|
317
392
|
return Promise.reject(error);
|
|
318
393
|
}
|
|
319
394
|
},
|
|
@@ -350,10 +425,16 @@ function createImaController(video, options) {
|
|
|
350
425
|
async stop() {
|
|
351
426
|
adPlaying = false;
|
|
352
427
|
video.muted = originalMutedState;
|
|
428
|
+
if (adContainerEl) {
|
|
429
|
+
adContainerEl.style.pointerEvents = "none";
|
|
430
|
+
adContainerEl.style.display = "none";
|
|
431
|
+
console.log("[IMA] Ad container hidden after stop");
|
|
432
|
+
}
|
|
353
433
|
try {
|
|
354
434
|
adsManager?.stop?.();
|
|
355
435
|
} catch {
|
|
356
436
|
}
|
|
437
|
+
destroyAdsManager();
|
|
357
438
|
if (!options?.continueLiveStreamDuringAds) {
|
|
358
439
|
video.play().catch(() => {
|
|
359
440
|
});
|
|
@@ -363,12 +444,13 @@ function createImaController(video, options) {
|
|
|
363
444
|
}
|
|
364
445
|
},
|
|
365
446
|
destroy() {
|
|
366
|
-
|
|
367
|
-
adsManager?.destroy?.();
|
|
368
|
-
} catch {
|
|
369
|
-
}
|
|
447
|
+
destroyAdsManager();
|
|
370
448
|
adPlaying = false;
|
|
371
449
|
video.muted = originalMutedState;
|
|
450
|
+
if (adContainerEl) {
|
|
451
|
+
adContainerEl.style.pointerEvents = "none";
|
|
452
|
+
adContainerEl.style.display = "none";
|
|
453
|
+
}
|
|
372
454
|
try {
|
|
373
455
|
adsLoader?.destroy?.();
|
|
374
456
|
} catch {
|
|
@@ -376,6 +458,9 @@ function createImaController(video, options) {
|
|
|
376
458
|
if (adContainerEl?.parentElement) {
|
|
377
459
|
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
378
460
|
}
|
|
461
|
+
adContainerEl = void 0;
|
|
462
|
+
adDisplayContainer = void 0;
|
|
463
|
+
adsLoader = void 0;
|
|
379
464
|
},
|
|
380
465
|
isAdPlaying() {
|
|
381
466
|
return adPlaying;
|
|
@@ -853,32 +938,33 @@ var StormcloudVideoPlayer = class {
|
|
|
853
938
|
this.video.muted = !!this.config.muted;
|
|
854
939
|
this.ima.initialize();
|
|
855
940
|
this.ima.on("all_ads_completed", () => {
|
|
856
|
-
if (
|
|
857
|
-
|
|
858
|
-
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
859
|
-
const next = this.adPodQueue.shift();
|
|
860
|
-
this.currentAdIndex++;
|
|
861
|
-
this.playSingleAd(next).catch(() => {
|
|
862
|
-
});
|
|
863
|
-
} else {
|
|
864
|
-
this.currentAdIndex = 0;
|
|
865
|
-
this.totalAdsInBreak = 0;
|
|
866
|
-
this.showAds = false;
|
|
941
|
+
if (this.config.debugAdTiming) {
|
|
942
|
+
console.log("[StormcloudVideoPlayer] IMA all_ads_completed event received");
|
|
867
943
|
}
|
|
868
944
|
});
|
|
869
945
|
this.ima.on("ad_error", () => {
|
|
870
946
|
if (this.config.debugAdTiming) {
|
|
871
947
|
console.log("[StormcloudVideoPlayer] IMA ad_error event received");
|
|
872
948
|
}
|
|
873
|
-
if (
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
949
|
+
if (this.showAds) {
|
|
950
|
+
if (this.inAdBreak) {
|
|
951
|
+
const remaining = this.getRemainingAdMs();
|
|
952
|
+
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
953
|
+
const next = this.adPodQueue.shift();
|
|
954
|
+
this.currentAdIndex++;
|
|
955
|
+
this.playSingleAd(next).catch(() => {
|
|
956
|
+
});
|
|
957
|
+
} else {
|
|
958
|
+
this.handleAdFailure();
|
|
959
|
+
}
|
|
960
|
+
} else {
|
|
961
|
+
if (this.config.debugAdTiming) {
|
|
962
|
+
console.log(
|
|
963
|
+
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
this.handleAdFailure();
|
|
967
|
+
}
|
|
882
968
|
}
|
|
883
969
|
});
|
|
884
970
|
this.ima.on("content_pause", () => {
|
|
@@ -894,6 +980,26 @@ var StormcloudVideoPlayer = class {
|
|
|
894
980
|
);
|
|
895
981
|
}
|
|
896
982
|
this.clearAdFailsafeTimer();
|
|
983
|
+
if (!this.inAdBreak) return;
|
|
984
|
+
const remaining = this.getRemainingAdMs();
|
|
985
|
+
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
986
|
+
const next = this.adPodQueue.shift();
|
|
987
|
+
this.currentAdIndex++;
|
|
988
|
+
if (this.config.debugAdTiming) {
|
|
989
|
+
console.log(
|
|
990
|
+
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak})`
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
this.playSingleAd(next).catch(() => {
|
|
994
|
+
});
|
|
995
|
+
} else {
|
|
996
|
+
if (this.config.debugAdTiming) {
|
|
997
|
+
console.log("[StormcloudVideoPlayer] Ad pod completed");
|
|
998
|
+
}
|
|
999
|
+
this.currentAdIndex = 0;
|
|
1000
|
+
this.totalAdsInBreak = 0;
|
|
1001
|
+
this.showAds = false;
|
|
1002
|
+
}
|
|
897
1003
|
});
|
|
898
1004
|
this.video.addEventListener("timeupdate", () => {
|
|
899
1005
|
this.onTimeUpdate(this.video.currentTime);
|
|
@@ -1439,9 +1545,20 @@ var StormcloudVideoPlayer = class {
|
|
|
1439
1545
|
return;
|
|
1440
1546
|
}
|
|
1441
1547
|
if (vastTagUrl) {
|
|
1548
|
+
this.inAdBreak = true;
|
|
1442
1549
|
this.showAds = true;
|
|
1443
1550
|
this.currentAdIndex++;
|
|
1444
|
-
|
|
1551
|
+
try {
|
|
1552
|
+
await this.playSingleAd(vastTagUrl);
|
|
1553
|
+
} catch (error) {
|
|
1554
|
+
if (this.config.debugAdTiming) {
|
|
1555
|
+
console.error(
|
|
1556
|
+
"[StormcloudVideoPlayer] Ad playback failed in handleAdStart:",
|
|
1557
|
+
error
|
|
1558
|
+
);
|
|
1559
|
+
}
|
|
1560
|
+
this.handleAdFailure();
|
|
1561
|
+
}
|
|
1445
1562
|
}
|
|
1446
1563
|
if (this.expectedAdBreakDurationMs == null && scheduled?.durationMs != null) {
|
|
1447
1564
|
this.expectedAdBreakDurationMs = scheduled.durationMs;
|
|
@@ -1543,21 +1660,21 @@ var StormcloudVideoPlayer = class {
|
|
|
1543
1660
|
if (this.config.debugAdTiming) {
|
|
1544
1661
|
console.log("[StormcloudVideoPlayer] Attempting to play ad:", vastTagUrl);
|
|
1545
1662
|
}
|
|
1546
|
-
this.ima.
|
|
1547
|
-
if (!this.shouldContinueLiveStreamDuringAds()) {
|
|
1548
|
-
if (this.config.debugAdTiming) {
|
|
1549
|
-
console.log("[StormcloudVideoPlayer] Pausing video immediately for ad (VOD mode)");
|
|
1550
|
-
}
|
|
1551
|
-
this.video.pause();
|
|
1552
|
-
} else {
|
|
1663
|
+
if (this.ima.isAdPlaying()) {
|
|
1553
1664
|
if (this.config.debugAdTiming) {
|
|
1554
|
-
console.
|
|
1665
|
+
console.warn(
|
|
1666
|
+
"[StormcloudVideoPlayer] Ad already playing - skipping new ad request"
|
|
1667
|
+
);
|
|
1555
1668
|
}
|
|
1556
|
-
|
|
1669
|
+
return;
|
|
1557
1670
|
}
|
|
1671
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
1558
1672
|
this.startAdFailsafeTimer();
|
|
1559
1673
|
try {
|
|
1560
1674
|
await this.ima.requestAds(vastTagUrl);
|
|
1675
|
+
if (this.config.debugAdTiming) {
|
|
1676
|
+
console.log("[StormcloudVideoPlayer] Ad request successful, starting playback");
|
|
1677
|
+
}
|
|
1561
1678
|
await this.ima.play();
|
|
1562
1679
|
if (this.config.debugAdTiming) {
|
|
1563
1680
|
console.log("[StormcloudVideoPlayer] Ad playback started successfully");
|
|
@@ -1572,7 +1689,13 @@ var StormcloudVideoPlayer = class {
|
|
|
1572
1689
|
handleAdFailure() {
|
|
1573
1690
|
if (this.config.debugAdTiming) {
|
|
1574
1691
|
console.log(
|
|
1575
|
-
"[StormcloudVideoPlayer] Handling ad failure - resuming content"
|
|
1692
|
+
"[StormcloudVideoPlayer] Handling ad failure - resuming content",
|
|
1693
|
+
{
|
|
1694
|
+
inAdBreak: this.inAdBreak,
|
|
1695
|
+
showAds: this.showAds,
|
|
1696
|
+
videoPaused: this.video.paused,
|
|
1697
|
+
adPlaying: this.ima.isAdPlaying()
|
|
1698
|
+
}
|
|
1576
1699
|
);
|
|
1577
1700
|
}
|
|
1578
1701
|
this.inAdBreak = false;
|
|
@@ -1585,14 +1708,29 @@ var StormcloudVideoPlayer = class {
|
|
|
1585
1708
|
this.showAds = false;
|
|
1586
1709
|
this.currentAdIndex = 0;
|
|
1587
1710
|
this.totalAdsInBreak = 0;
|
|
1711
|
+
const originalMutedState = this.ima.getOriginalMutedState();
|
|
1712
|
+
this.video.muted = originalMutedState;
|
|
1713
|
+
if (this.config.debugAdTiming) {
|
|
1714
|
+
console.log(
|
|
1715
|
+
`[StormcloudVideoPlayer] Restored mute state to: ${originalMutedState}`
|
|
1716
|
+
);
|
|
1717
|
+
}
|
|
1588
1718
|
if (this.video.paused) {
|
|
1589
|
-
this.
|
|
1719
|
+
if (this.config.debugAdTiming) {
|
|
1720
|
+
console.log("[StormcloudVideoPlayer] Resuming paused video");
|
|
1721
|
+
}
|
|
1722
|
+
this.video.play()?.catch((error) => {
|
|
1590
1723
|
if (this.config.debugAdTiming) {
|
|
1591
1724
|
console.error(
|
|
1592
|
-
"[StormcloudVideoPlayer] Failed to resume video after ad failure"
|
|
1725
|
+
"[StormcloudVideoPlayer] Failed to resume video after ad failure:",
|
|
1726
|
+
error
|
|
1593
1727
|
);
|
|
1594
1728
|
}
|
|
1595
1729
|
});
|
|
1730
|
+
} else {
|
|
1731
|
+
if (this.config.debugAdTiming) {
|
|
1732
|
+
console.log("[StormcloudVideoPlayer] Video is already playing, no resume needed");
|
|
1733
|
+
}
|
|
1596
1734
|
}
|
|
1597
1735
|
}
|
|
1598
1736
|
startAdFailsafeTimer() {
|
|
@@ -1604,10 +1742,12 @@ var StormcloudVideoPlayer = class {
|
|
|
1604
1742
|
);
|
|
1605
1743
|
}
|
|
1606
1744
|
this.adFailsafeTimerId = window.setTimeout(() => {
|
|
1607
|
-
|
|
1745
|
+
const shouldTrigger = this.video.paused || this.showAds && !this.ima.isAdPlaying();
|
|
1746
|
+
if (shouldTrigger) {
|
|
1608
1747
|
if (this.config.debugAdTiming) {
|
|
1609
1748
|
console.warn(
|
|
1610
|
-
"[StormcloudVideoPlayer] Failsafe timer triggered - forcing video resume"
|
|
1749
|
+
"[StormcloudVideoPlayer] Failsafe timer triggered - forcing video resume",
|
|
1750
|
+
{ paused: this.video.paused, showAds: this.showAds, adPlaying: this.ima.isAdPlaying() }
|
|
1611
1751
|
);
|
|
1612
1752
|
}
|
|
1613
1753
|
this.handleAdFailure();
|
|
@@ -2537,39 +2677,144 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
2537
2677
|
left: "50%",
|
|
2538
2678
|
transform: "translateX(-50%)",
|
|
2539
2679
|
marginBottom: "4px",
|
|
2540
|
-
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.
|
|
2680
|
+
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)",
|
|
2541
2681
|
backdropFilter: "blur(15px)",
|
|
2542
|
-
padding: "
|
|
2543
|
-
borderRadius: "
|
|
2544
|
-
border: "1px solid rgba(255, 255, 255, 0.
|
|
2682
|
+
padding: "10px 14px",
|
|
2683
|
+
borderRadius: "14px",
|
|
2684
|
+
border: "1px solid rgba(255, 255, 255, 0.15)",
|
|
2545
2685
|
display: "flex",
|
|
2546
2686
|
flexDirection: "column",
|
|
2547
2687
|
alignItems: "center",
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2688
|
+
justifyContent: "center",
|
|
2689
|
+
height: "128px",
|
|
2690
|
+
boxShadow: "0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)",
|
|
2691
|
+
zIndex: 10,
|
|
2692
|
+
transition: "transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out"
|
|
2551
2693
|
},
|
|
2552
|
-
onMouseEnter: () =>
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
"
|
|
2694
|
+
onMouseEnter: (e) => {
|
|
2695
|
+
setShowVolumeSlider(true);
|
|
2696
|
+
e.currentTarget.style.transform = "translateX(-50%) translateY(-2px) scale(1.02)";
|
|
2697
|
+
e.currentTarget.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)";
|
|
2698
|
+
e.currentTarget.style.borderColor = "rgba(59, 130, 246, 0.4)";
|
|
2699
|
+
},
|
|
2700
|
+
onMouseLeave: (e) => {
|
|
2701
|
+
setShowVolumeSlider(false);
|
|
2702
|
+
e.currentTarget.style.transform = "translateX(-50%)";
|
|
2703
|
+
e.currentTarget.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)";
|
|
2704
|
+
e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.15)";
|
|
2705
|
+
},
|
|
2706
|
+
children: /* @__PURE__ */ jsxs(
|
|
2707
|
+
"div",
|
|
2556
2708
|
{
|
|
2557
|
-
type: "range",
|
|
2558
|
-
min: "0",
|
|
2559
|
-
max: "1",
|
|
2560
|
-
step: "0.01",
|
|
2561
|
-
value: isMuted ? 0 : volume,
|
|
2562
|
-
onChange: (e) => handleVolumeChange(parseFloat(e.target.value)),
|
|
2563
2709
|
style: {
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
}
|
|
2710
|
+
position: "relative",
|
|
2711
|
+
width: "8px",
|
|
2712
|
+
height: "104px",
|
|
2713
|
+
cursor: "pointer",
|
|
2714
|
+
transition: "transform 0.2s ease-in-out"
|
|
2715
|
+
},
|
|
2716
|
+
onMouseEnter: (e) => {
|
|
2717
|
+
e.currentTarget.style.transform = "scaleX(1.2)";
|
|
2718
|
+
},
|
|
2719
|
+
onMouseLeave: (e) => {
|
|
2720
|
+
e.currentTarget.style.transform = "scaleX(1)";
|
|
2721
|
+
},
|
|
2722
|
+
onMouseDown: (e) => {
|
|
2723
|
+
e.preventDefault();
|
|
2724
|
+
const sliderElement = e.currentTarget;
|
|
2725
|
+
const handleMouseMove = (moveEvent) => {
|
|
2726
|
+
if (!sliderElement) return;
|
|
2727
|
+
const rect2 = sliderElement.getBoundingClientRect();
|
|
2728
|
+
const y2 = moveEvent.clientY - rect2.top;
|
|
2729
|
+
const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));
|
|
2730
|
+
handleVolumeChange(percentage2);
|
|
2731
|
+
};
|
|
2732
|
+
const handleMouseUp = () => {
|
|
2733
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
2734
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
2735
|
+
};
|
|
2736
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
2737
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
2738
|
+
const rect = sliderElement.getBoundingClientRect();
|
|
2739
|
+
const y = e.clientY - rect.top;
|
|
2740
|
+
const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
|
|
2741
|
+
handleVolumeChange(percentage);
|
|
2742
|
+
},
|
|
2743
|
+
onClick: (e) => {
|
|
2744
|
+
e.stopPropagation();
|
|
2745
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
2746
|
+
const y = e.clientY - rect.top;
|
|
2747
|
+
const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
|
|
2748
|
+
handleVolumeChange(percentage);
|
|
2749
|
+
},
|
|
2750
|
+
children: [
|
|
2751
|
+
/* @__PURE__ */ jsx(
|
|
2752
|
+
"div",
|
|
2753
|
+
{
|
|
2754
|
+
style: {
|
|
2755
|
+
position: "absolute",
|
|
2756
|
+
bottom: "0",
|
|
2757
|
+
left: "0",
|
|
2758
|
+
width: "100%",
|
|
2759
|
+
height: "100%",
|
|
2760
|
+
background: "linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)",
|
|
2761
|
+
borderRadius: "4px",
|
|
2762
|
+
boxShadow: "inset 0 1px 3px rgba(0, 0, 0, 0.2)"
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
),
|
|
2766
|
+
/* @__PURE__ */ jsx(
|
|
2767
|
+
"div",
|
|
2768
|
+
{
|
|
2769
|
+
style: {
|
|
2770
|
+
position: "absolute",
|
|
2771
|
+
bottom: "0",
|
|
2772
|
+
left: "0",
|
|
2773
|
+
width: "100%",
|
|
2774
|
+
height: `${(isMuted ? 0 : volume) * 100}%`,
|
|
2775
|
+
background: "linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)",
|
|
2776
|
+
borderRadius: "4px",
|
|
2777
|
+
transition: "height 0.15s ease-out, box-shadow 0.2s ease-in-out",
|
|
2778
|
+
boxShadow: "0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)"
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
),
|
|
2782
|
+
/* @__PURE__ */ jsx(
|
|
2783
|
+
"div",
|
|
2784
|
+
{
|
|
2785
|
+
style: {
|
|
2786
|
+
position: "absolute",
|
|
2787
|
+
bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 7px)`,
|
|
2788
|
+
left: "50%",
|
|
2789
|
+
transform: "translateX(-50%)",
|
|
2790
|
+
width: "14px",
|
|
2791
|
+
height: "14px",
|
|
2792
|
+
background: "linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)",
|
|
2793
|
+
borderRadius: "50%",
|
|
2794
|
+
boxShadow: "0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)",
|
|
2795
|
+
transition: "bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out",
|
|
2796
|
+
cursor: "grab"
|
|
2797
|
+
},
|
|
2798
|
+
onMouseEnter: (e) => {
|
|
2799
|
+
e.currentTarget.style.transform = "translateX(-50%) scale(1.3)";
|
|
2800
|
+
e.currentTarget.style.boxShadow = "0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)";
|
|
2801
|
+
e.currentTarget.style.cursor = "grab";
|
|
2802
|
+
},
|
|
2803
|
+
onMouseLeave: (e) => {
|
|
2804
|
+
e.currentTarget.style.transform = "translateX(-50%) scale(1)";
|
|
2805
|
+
e.currentTarget.style.boxShadow = "0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)";
|
|
2806
|
+
},
|
|
2807
|
+
onMouseDown: (e) => {
|
|
2808
|
+
e.currentTarget.style.transform = "translateX(-50%) scale(1.4)";
|
|
2809
|
+
e.currentTarget.style.cursor = "grabbing";
|
|
2810
|
+
},
|
|
2811
|
+
onMouseUp: (e) => {
|
|
2812
|
+
e.currentTarget.style.transform = "translateX(-50%) scale(1.3)";
|
|
2813
|
+
e.currentTarget.style.cursor = "grab";
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
)
|
|
2817
|
+
]
|
|
2573
2818
|
}
|
|
2574
2819
|
)
|
|
2575
2820
|
}
|
|
@@ -2886,40 +3131,146 @@ var StormcloudVideoPlayerComponent = React.memo(
|
|
|
2886
3131
|
left: "50%",
|
|
2887
3132
|
transform: "translateX(-50%)",
|
|
2888
3133
|
marginBottom: "4px",
|
|
2889
|
-
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.
|
|
3134
|
+
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)",
|
|
2890
3135
|
backdropFilter: "blur(20px)",
|
|
2891
|
-
padding: "
|
|
2892
|
-
borderRadius: "
|
|
2893
|
-
border: "2px solid rgba(255, 255, 255, 0.
|
|
3136
|
+
padding: "10px 14px",
|
|
3137
|
+
borderRadius: "14px",
|
|
3138
|
+
border: "2px solid rgba(255, 255, 255, 0.7)",
|
|
2894
3139
|
display: "flex",
|
|
2895
3140
|
flexDirection: "column",
|
|
2896
3141
|
alignItems: "center",
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
3142
|
+
justifyContent: "center",
|
|
3143
|
+
height: "128px",
|
|
3144
|
+
boxShadow: "0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)",
|
|
3145
|
+
zIndex: 10,
|
|
3146
|
+
transition: "transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out"
|
|
2900
3147
|
},
|
|
2901
|
-
onMouseEnter: () =>
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
"
|
|
3148
|
+
onMouseEnter: (e) => {
|
|
3149
|
+
setShowVolumeSlider(true);
|
|
3150
|
+
e.currentTarget.style.transform = "translateX(-50%) translateY(-2px) scale(1.02)";
|
|
3151
|
+
e.currentTarget.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)";
|
|
3152
|
+
e.currentTarget.style.borderColor = "rgba(96, 165, 250, 0.8)";
|
|
3153
|
+
},
|
|
3154
|
+
onMouseLeave: (e) => {
|
|
3155
|
+
setShowVolumeSlider(false);
|
|
3156
|
+
e.currentTarget.style.transform = "translateX(-50%)";
|
|
3157
|
+
e.currentTarget.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)";
|
|
3158
|
+
e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.7)";
|
|
3159
|
+
},
|
|
3160
|
+
children: /* @__PURE__ */ jsxs(
|
|
3161
|
+
"div",
|
|
2905
3162
|
{
|
|
2906
|
-
type: "range",
|
|
2907
|
-
min: "0",
|
|
2908
|
-
max: "1",
|
|
2909
|
-
step: "0.01",
|
|
2910
|
-
value: isMuted ? 0 : volume,
|
|
2911
|
-
onChange: (e) => handleVolumeChange(parseFloat(e.target.value)),
|
|
2912
3163
|
style: {
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
height: "90px",
|
|
2917
|
-
background: "linear-gradient(180deg, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0.4) 100%)",
|
|
2918
|
-
borderRadius: "3px",
|
|
2919
|
-
outline: "none",
|
|
3164
|
+
position: "relative",
|
|
3165
|
+
width: "8px",
|
|
3166
|
+
height: "104px",
|
|
2920
3167
|
cursor: "pointer",
|
|
2921
|
-
|
|
2922
|
-
}
|
|
3168
|
+
transition: "transform 0.2s ease-in-out"
|
|
3169
|
+
},
|
|
3170
|
+
onMouseEnter: (e) => {
|
|
3171
|
+
e.currentTarget.style.transform = "scaleX(1.2)";
|
|
3172
|
+
},
|
|
3173
|
+
onMouseLeave: (e) => {
|
|
3174
|
+
e.currentTarget.style.transform = "scaleX(1)";
|
|
3175
|
+
},
|
|
3176
|
+
onMouseDown: (e) => {
|
|
3177
|
+
e.preventDefault();
|
|
3178
|
+
const sliderElement = e.currentTarget;
|
|
3179
|
+
const handleMouseMove = (moveEvent) => {
|
|
3180
|
+
if (!sliderElement) return;
|
|
3181
|
+
const rect2 = sliderElement.getBoundingClientRect();
|
|
3182
|
+
const y2 = moveEvent.clientY - rect2.top;
|
|
3183
|
+
const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));
|
|
3184
|
+
handleVolumeChange(percentage2);
|
|
3185
|
+
};
|
|
3186
|
+
const handleMouseUp = () => {
|
|
3187
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
3188
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
3189
|
+
};
|
|
3190
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
3191
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
3192
|
+
const rect = sliderElement.getBoundingClientRect();
|
|
3193
|
+
const y = e.clientY - rect.top;
|
|
3194
|
+
const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
|
|
3195
|
+
handleVolumeChange(percentage);
|
|
3196
|
+
},
|
|
3197
|
+
onClick: (e) => {
|
|
3198
|
+
e.stopPropagation();
|
|
3199
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
3200
|
+
const y = e.clientY - rect.top;
|
|
3201
|
+
const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
|
|
3202
|
+
handleVolumeChange(percentage);
|
|
3203
|
+
},
|
|
3204
|
+
children: [
|
|
3205
|
+
/* @__PURE__ */ jsx(
|
|
3206
|
+
"div",
|
|
3207
|
+
{
|
|
3208
|
+
style: {
|
|
3209
|
+
position: "absolute",
|
|
3210
|
+
bottom: "0",
|
|
3211
|
+
left: "0",
|
|
3212
|
+
width: "100%",
|
|
3213
|
+
height: "100%",
|
|
3214
|
+
background: "linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)",
|
|
3215
|
+
borderRadius: "4px",
|
|
3216
|
+
border: "1px solid rgba(255, 255, 255, 0.4)",
|
|
3217
|
+
boxShadow: "inset 0 1px 3px rgba(0, 0, 0, 0.3)"
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
),
|
|
3221
|
+
/* @__PURE__ */ jsx(
|
|
3222
|
+
"div",
|
|
3223
|
+
{
|
|
3224
|
+
style: {
|
|
3225
|
+
position: "absolute",
|
|
3226
|
+
bottom: "0",
|
|
3227
|
+
left: "0",
|
|
3228
|
+
width: "100%",
|
|
3229
|
+
height: `${(isMuted ? 0 : volume) * 100}%`,
|
|
3230
|
+
background: "linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)",
|
|
3231
|
+
borderRadius: "4px",
|
|
3232
|
+
transition: "height 0.15s ease-out, box-shadow 0.2s ease-in-out",
|
|
3233
|
+
boxShadow: "0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)"
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
),
|
|
3237
|
+
/* @__PURE__ */ jsx(
|
|
3238
|
+
"div",
|
|
3239
|
+
{
|
|
3240
|
+
style: {
|
|
3241
|
+
position: "absolute",
|
|
3242
|
+
bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 8px)`,
|
|
3243
|
+
left: "50%",
|
|
3244
|
+
transform: "translateX(-50%)",
|
|
3245
|
+
width: "16px",
|
|
3246
|
+
height: "16px",
|
|
3247
|
+
background: "linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)",
|
|
3248
|
+
borderRadius: "50%",
|
|
3249
|
+
border: "2px solid rgba(96, 165, 250, 0.9)",
|
|
3250
|
+
boxShadow: "0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)",
|
|
3251
|
+
transition: "bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out",
|
|
3252
|
+
cursor: "grab"
|
|
3253
|
+
},
|
|
3254
|
+
onMouseEnter: (e) => {
|
|
3255
|
+
e.currentTarget.style.transform = "translateX(-50%) scale(1.35)";
|
|
3256
|
+
e.currentTarget.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)";
|
|
3257
|
+
e.currentTarget.style.cursor = "grab";
|
|
3258
|
+
},
|
|
3259
|
+
onMouseLeave: (e) => {
|
|
3260
|
+
e.currentTarget.style.transform = "translateX(-50%) scale(1)";
|
|
3261
|
+
e.currentTarget.style.boxShadow = "0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)";
|
|
3262
|
+
},
|
|
3263
|
+
onMouseDown: (e) => {
|
|
3264
|
+
e.currentTarget.style.transform = "translateX(-50%) scale(1.45)";
|
|
3265
|
+
e.currentTarget.style.cursor = "grabbing";
|
|
3266
|
+
},
|
|
3267
|
+
onMouseUp: (e) => {
|
|
3268
|
+
e.currentTarget.style.transform = "translateX(-50%) scale(1.35)";
|
|
3269
|
+
e.currentTarget.style.cursor = "grab";
|
|
3270
|
+
}
|
|
3271
|
+
}
|
|
3272
|
+
)
|
|
3273
|
+
]
|
|
2923
3274
|
}
|
|
2924
3275
|
)
|
|
2925
3276
|
}
|