stormcloud-video-player 0.1.7 → 0.1.9
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/README.md +205 -173
- package/dist/stormcloud-vp.min.js +3 -3
- package/lib/index.cjs +718 -306
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +7 -5
- package/lib/index.d.ts +7 -5
- package/lib/index.js +719 -307
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -80,6 +80,9 @@ function createImaController(video) {
|
|
|
80
80
|
container.style.top = "0";
|
|
81
81
|
container.style.right = "0";
|
|
82
82
|
container.style.bottom = "0";
|
|
83
|
+
container.style.display = "flex";
|
|
84
|
+
container.style.alignItems = "center";
|
|
85
|
+
container.style.justifyContent = "center";
|
|
83
86
|
container.style.pointerEvents = "none";
|
|
84
87
|
container.style.zIndex = "2";
|
|
85
88
|
video.parentElement?.appendChild(container);
|
|
@@ -122,6 +125,9 @@ function createImaController(video) {
|
|
|
122
125
|
container.style.top = "0";
|
|
123
126
|
container.style.right = "0";
|
|
124
127
|
container.style.bottom = "0";
|
|
128
|
+
container.style.display = "flex";
|
|
129
|
+
container.style.alignItems = "center";
|
|
130
|
+
container.style.justifyContent = "center";
|
|
125
131
|
container.style.pointerEvents = "none";
|
|
126
132
|
container.style.zIndex = "2";
|
|
127
133
|
if (!video.parentElement) {
|
|
@@ -328,6 +334,20 @@ function createImaController(video) {
|
|
|
328
334
|
isAdPlaying() {
|
|
329
335
|
return adPlaying;
|
|
330
336
|
},
|
|
337
|
+
resize(width, height) {
|
|
338
|
+
if (!adsManager || !window.google?.ima) {
|
|
339
|
+
console.warn(
|
|
340
|
+
"[IMA] Cannot resize: No ads manager or IMA SDK available"
|
|
341
|
+
);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
try {
|
|
345
|
+
console.log(`[IMA] Resizing ads manager to ${width}x${height}`);
|
|
346
|
+
adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);
|
|
347
|
+
} catch (error) {
|
|
348
|
+
console.warn("[IMA] Error resizing ads manager:", error);
|
|
349
|
+
}
|
|
350
|
+
},
|
|
331
351
|
on(event, listener) {
|
|
332
352
|
if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
|
|
333
353
|
listeners.get(event).add(listener);
|
|
@@ -498,7 +518,9 @@ async function sendInitialTracking(licenseKey) {
|
|
|
498
518
|
browserId,
|
|
499
519
|
...clientInfo
|
|
500
520
|
};
|
|
501
|
-
const headers = {
|
|
521
|
+
const headers = {
|
|
522
|
+
"Content-Type": "application/json"
|
|
523
|
+
};
|
|
502
524
|
if (licenseKey) {
|
|
503
525
|
headers["Authorization"] = `Bearer ${licenseKey}`;
|
|
504
526
|
}
|
|
@@ -513,11 +535,7 @@ async function sendInitialTracking(licenseKey) {
|
|
|
513
535
|
if (!response.ok) {
|
|
514
536
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
515
537
|
}
|
|
516
|
-
|
|
517
|
-
console.log(
|
|
518
|
-
"[StormcloudVideoPlayer] Initial tracking data sent successfully:",
|
|
519
|
-
data
|
|
520
|
-
);
|
|
538
|
+
await response.json();
|
|
521
539
|
} catch (error) {
|
|
522
540
|
console.error(
|
|
523
541
|
"[StormcloudVideoPlayer] Error sending initial tracking data:",
|
|
@@ -533,7 +551,9 @@ async function sendHeartbeat(licenseKey) {
|
|
|
533
551
|
browserId,
|
|
534
552
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
535
553
|
};
|
|
536
|
-
const headers = {
|
|
554
|
+
const headers = {
|
|
555
|
+
"Content-Type": "application/json"
|
|
556
|
+
};
|
|
537
557
|
if (licenseKey) {
|
|
538
558
|
headers["Authorization"] = `Bearer ${licenseKey}`;
|
|
539
559
|
}
|
|
@@ -548,8 +568,7 @@ async function sendHeartbeat(licenseKey) {
|
|
|
548
568
|
if (!response.ok) {
|
|
549
569
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
550
570
|
}
|
|
551
|
-
|
|
552
|
-
console.log("[StormcloudVideoPlayer] Heartbeat sent successfully:", data);
|
|
571
|
+
await response.json();
|
|
553
572
|
} catch (error) {
|
|
554
573
|
console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
|
|
555
574
|
}
|
|
@@ -568,7 +587,6 @@ var StormcloudVideoPlayer = class {
|
|
|
568
587
|
this.showAds = false;
|
|
569
588
|
this.config = config;
|
|
570
589
|
this.video = config.videoElement;
|
|
571
|
-
this.adSchedule = config.adSchedule;
|
|
572
590
|
this.ima = createImaController(this.video);
|
|
573
591
|
}
|
|
574
592
|
async load() {
|
|
@@ -874,70 +892,61 @@ var StormcloudVideoPlayer = class {
|
|
|
874
892
|
const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0;
|
|
875
893
|
this.expectedAdBreakDurationMs = durationMs;
|
|
876
894
|
this.currentAdBreakStartWallClockMs = Date.now();
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
895
|
+
const isManifestMarker = this.isManifestBasedMarker(marker);
|
|
896
|
+
const forceImmediate = this.config.immediateManifestAds ?? true;
|
|
897
|
+
if (this.config.debugAdTiming) {
|
|
898
|
+
console.log("[StormcloudVideoPlayer] Ad start decision:", {
|
|
899
|
+
isManifestMarker,
|
|
900
|
+
forceImmediate,
|
|
901
|
+
hasPts: typeof marker.ptsSeconds === "number"
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
if (isManifestMarker && forceImmediate) {
|
|
881
905
|
if (this.config.debugAdTiming) {
|
|
882
|
-
console.log(
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
906
|
+
console.log(
|
|
907
|
+
"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)"
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
this.clearAdStartTimer();
|
|
911
|
+
this.handleAdStart(marker);
|
|
912
|
+
} else if (typeof marker.ptsSeconds === "number") {
|
|
913
|
+
const tol = this.config.driftToleranceMs ?? 1e3;
|
|
914
|
+
const nowMs = this.video.currentTime * 1e3;
|
|
915
|
+
const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
|
|
916
|
+
const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
|
|
917
|
+
if (this.config.debugAdTiming) {
|
|
918
|
+
console.log("[StormcloudVideoPlayer] PTS-based timing calculation:", {
|
|
919
|
+
nowMs,
|
|
920
|
+
estCurrentPtsMs,
|
|
921
|
+
markerPtsMs: marker.ptsSeconds * 1e3,
|
|
922
|
+
deltaMs,
|
|
923
|
+
tolerance: tol
|
|
887
924
|
});
|
|
888
925
|
}
|
|
889
|
-
if (
|
|
890
|
-
if (this.config.debugAdTiming) {
|
|
891
|
-
console.log(
|
|
892
|
-
"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)"
|
|
893
|
-
);
|
|
894
|
-
}
|
|
895
|
-
this.clearAdStartTimer();
|
|
896
|
-
this.handleAdStart(marker);
|
|
897
|
-
} else if (typeof marker.ptsSeconds === "number") {
|
|
898
|
-
const tol = this.config.driftToleranceMs ?? 1e3;
|
|
899
|
-
const nowMs = this.video.currentTime * 1e3;
|
|
900
|
-
const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
|
|
901
|
-
const deltaMs = Math.floor(
|
|
902
|
-
marker.ptsSeconds * 1e3 - estCurrentPtsMs
|
|
903
|
-
);
|
|
926
|
+
if (deltaMs > tol) {
|
|
904
927
|
if (this.config.debugAdTiming) {
|
|
905
928
|
console.log(
|
|
906
|
-
|
|
907
|
-
{
|
|
908
|
-
nowMs,
|
|
909
|
-
estCurrentPtsMs,
|
|
910
|
-
markerPtsMs: marker.ptsSeconds * 1e3,
|
|
911
|
-
deltaMs,
|
|
912
|
-
tolerance: tol
|
|
913
|
-
}
|
|
929
|
+
`[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`
|
|
914
930
|
);
|
|
915
931
|
}
|
|
916
|
-
|
|
917
|
-
if (this.config.debugAdTiming) {
|
|
918
|
-
console.log(
|
|
919
|
-
`[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`
|
|
920
|
-
);
|
|
921
|
-
}
|
|
922
|
-
this.scheduleAdStartIn(deltaMs);
|
|
923
|
-
} else {
|
|
924
|
-
if (this.config.debugAdTiming) {
|
|
925
|
-
console.log(
|
|
926
|
-
"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)"
|
|
927
|
-
);
|
|
928
|
-
}
|
|
929
|
-
this.clearAdStartTimer();
|
|
930
|
-
this.handleAdStart(marker);
|
|
931
|
-
}
|
|
932
|
+
this.scheduleAdStartIn(deltaMs);
|
|
932
933
|
} else {
|
|
933
934
|
if (this.config.debugAdTiming) {
|
|
934
935
|
console.log(
|
|
935
|
-
"[StormcloudVideoPlayer] Starting ad immediately (
|
|
936
|
+
"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)"
|
|
936
937
|
);
|
|
937
938
|
}
|
|
938
939
|
this.clearAdStartTimer();
|
|
939
940
|
this.handleAdStart(marker);
|
|
940
941
|
}
|
|
942
|
+
} else {
|
|
943
|
+
if (this.config.debugAdTiming) {
|
|
944
|
+
console.log(
|
|
945
|
+
"[StormcloudVideoPlayer] Starting ad immediately (fallback)"
|
|
946
|
+
);
|
|
947
|
+
}
|
|
948
|
+
this.clearAdStartTimer();
|
|
949
|
+
this.handleAdStart(marker);
|
|
941
950
|
}
|
|
942
951
|
if (this.expectedAdBreakDurationMs != null) {
|
|
943
952
|
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
@@ -957,12 +966,11 @@ var StormcloudVideoPlayer = class {
|
|
|
957
966
|
this.scheduleAdStopCountdown(remainingMs);
|
|
958
967
|
}
|
|
959
968
|
if (!this.ima.isAdPlaying()) {
|
|
960
|
-
const policy = this.adSchedule?.lateJoinPolicy ?? "play_remaining";
|
|
961
969
|
const scheduled = this.findCurrentOrNextBreak(
|
|
962
970
|
this.video.currentTime * 1e3
|
|
963
971
|
);
|
|
964
972
|
const tags = this.selectVastTagsForBreak(scheduled) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);
|
|
965
|
-
if (
|
|
973
|
+
if (tags && tags.length > 0) {
|
|
966
974
|
const first = tags[0];
|
|
967
975
|
const rest = tags.slice(1);
|
|
968
976
|
this.adPodQueue = rest;
|
|
@@ -1161,11 +1169,11 @@ var StormcloudVideoPlayer = class {
|
|
|
1161
1169
|
});
|
|
1162
1170
|
this.heartbeatInterval = window.setInterval(() => {
|
|
1163
1171
|
this.sendHeartbeatIfNeeded();
|
|
1164
|
-
},
|
|
1172
|
+
}, 5e3);
|
|
1165
1173
|
}
|
|
1166
1174
|
sendHeartbeatIfNeeded() {
|
|
1167
1175
|
const now = Date.now();
|
|
1168
|
-
if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime >
|
|
1176
|
+
if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {
|
|
1169
1177
|
this.lastHeartbeatTime = now;
|
|
1170
1178
|
sendHeartbeat(this.config.licenseKey).catch((error) => {
|
|
1171
1179
|
if (this.config.debugAdTiming) {
|
|
@@ -1212,9 +1220,6 @@ var StormcloudVideoPlayer = class {
|
|
|
1212
1220
|
});
|
|
1213
1221
|
}
|
|
1214
1222
|
}
|
|
1215
|
-
setAdSchedule(schedule) {
|
|
1216
|
-
this.adSchedule = schedule;
|
|
1217
|
-
}
|
|
1218
1223
|
getCurrentAdIndex() {
|
|
1219
1224
|
return this.currentAdIndex;
|
|
1220
1225
|
}
|
|
@@ -1237,17 +1242,11 @@ var StormcloudVideoPlayer = class {
|
|
|
1237
1242
|
shouldShowNativeControls() {
|
|
1238
1243
|
return this.getStreamType() !== "hls";
|
|
1239
1244
|
}
|
|
1240
|
-
async
|
|
1241
|
-
const res = await fetch(url);
|
|
1242
|
-
if (!res.ok) throw new Error(`Failed to fetch ad schedule: ${res.status}`);
|
|
1243
|
-
const data = await res.json();
|
|
1244
|
-
this.adSchedule = data;
|
|
1245
|
-
}
|
|
1246
|
-
async loadDefaultVastFromAiry(airyApiUrl, params) {
|
|
1245
|
+
async loadDefaultVastFromAdstorm(adstormApiUrl, params) {
|
|
1247
1246
|
const usp = new URLSearchParams(params || {});
|
|
1248
|
-
const url = `${
|
|
1247
|
+
const url = `${adstormApiUrl}?${usp.toString()}`;
|
|
1249
1248
|
const res = await fetch(url);
|
|
1250
|
-
if (!res.ok) throw new Error(`Failed to fetch
|
|
1249
|
+
if (!res.ok) throw new Error(`Failed to fetch adstorm ads: ${res.status}`);
|
|
1251
1250
|
const data = await res.json();
|
|
1252
1251
|
const tag = data?.adTagUrl || data?.vastTagUrl || data?.tagUrl;
|
|
1253
1252
|
if (typeof tag === "string" && tag.length > 0) {
|
|
@@ -1310,7 +1309,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1310
1309
|
}
|
|
1311
1310
|
}
|
|
1312
1311
|
findCurrentOrNextBreak(nowMs) {
|
|
1313
|
-
const schedule =
|
|
1312
|
+
const schedule = [];
|
|
1314
1313
|
let candidate;
|
|
1315
1314
|
for (const b of schedule) {
|
|
1316
1315
|
const tol = this.config.driftToleranceMs ?? 1e3;
|
|
@@ -1321,7 +1320,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1321
1320
|
return candidate;
|
|
1322
1321
|
}
|
|
1323
1322
|
onTimeUpdate(currentTimeSec) {
|
|
1324
|
-
if (
|
|
1323
|
+
if (this.ima.isAdPlaying()) return;
|
|
1325
1324
|
const nowMs = currentTimeSec * 1e3;
|
|
1326
1325
|
const breakToPlay = this.findBreakForTime(nowMs);
|
|
1327
1326
|
if (breakToPlay) {
|
|
@@ -1333,10 +1332,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1333
1332
|
const endMs = adBreak.startTimeMs + durationMs;
|
|
1334
1333
|
if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {
|
|
1335
1334
|
const remainingMs = endMs - nowMs;
|
|
1336
|
-
const policy = this.adSchedule?.lateJoinPolicy ?? "play_remaining";
|
|
1337
|
-
if (policy === "skip_to_content") return;
|
|
1338
1335
|
const tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);
|
|
1339
|
-
if (
|
|
1336
|
+
if (tags && tags.length > 0) {
|
|
1340
1337
|
const first = tags[0];
|
|
1341
1338
|
const rest = tags.slice(1);
|
|
1342
1339
|
this.adPodQueue = rest;
|
|
@@ -1484,7 +1481,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1484
1481
|
return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
|
|
1485
1482
|
}
|
|
1486
1483
|
findBreakForTime(nowMs) {
|
|
1487
|
-
const schedule =
|
|
1484
|
+
const schedule = [];
|
|
1488
1485
|
for (const b of schedule) {
|
|
1489
1486
|
const end = (b.startTimeMs || 0) + (b.durationMs || 0);
|
|
1490
1487
|
if (nowMs >= (b.startTimeMs || 0) && (b.durationMs ? nowMs < end : true)) {
|
|
@@ -1493,6 +1490,73 @@ var StormcloudVideoPlayer = class {
|
|
|
1493
1490
|
}
|
|
1494
1491
|
return void 0;
|
|
1495
1492
|
}
|
|
1493
|
+
toggleMute() {
|
|
1494
|
+
this.video.muted = !this.video.muted;
|
|
1495
|
+
if (this.config.debugAdTiming) {
|
|
1496
|
+
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
toggleFullscreen() {
|
|
1500
|
+
return new Promise((resolve, reject) => {
|
|
1501
|
+
if (!document.fullscreenElement) {
|
|
1502
|
+
const container = this.video.parentElement;
|
|
1503
|
+
if (!container) {
|
|
1504
|
+
reject(new Error("No parent container found for fullscreen"));
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
container.requestFullscreen().then(() => {
|
|
1508
|
+
if (this.config.debugAdTiming) {
|
|
1509
|
+
console.log("[StormcloudVideoPlayer] Entered fullscreen");
|
|
1510
|
+
}
|
|
1511
|
+
resolve();
|
|
1512
|
+
}).catch((err) => {
|
|
1513
|
+
if (this.config.debugAdTiming) {
|
|
1514
|
+
console.error("[StormcloudVideoPlayer] Fullscreen error:", err);
|
|
1515
|
+
}
|
|
1516
|
+
reject(err);
|
|
1517
|
+
});
|
|
1518
|
+
} else {
|
|
1519
|
+
document.exitFullscreen().then(() => {
|
|
1520
|
+
if (this.config.debugAdTiming) {
|
|
1521
|
+
console.log("[StormcloudVideoPlayer] Exited fullscreen");
|
|
1522
|
+
}
|
|
1523
|
+
resolve();
|
|
1524
|
+
}).catch((err) => {
|
|
1525
|
+
if (this.config.debugAdTiming) {
|
|
1526
|
+
console.error(
|
|
1527
|
+
"[StormcloudVideoPlayer] Exit fullscreen error:",
|
|
1528
|
+
err
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
reject(err);
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
isMuted() {
|
|
1537
|
+
return this.video.muted;
|
|
1538
|
+
}
|
|
1539
|
+
isFullscreen() {
|
|
1540
|
+
return !!document.fullscreenElement;
|
|
1541
|
+
}
|
|
1542
|
+
get videoElement() {
|
|
1543
|
+
return this.video;
|
|
1544
|
+
}
|
|
1545
|
+
resize() {
|
|
1546
|
+
if (this.config.debugAdTiming) {
|
|
1547
|
+
console.log("[StormcloudVideoPlayer] Resizing player");
|
|
1548
|
+
}
|
|
1549
|
+
if (this.ima && this.ima.isAdPlaying()) {
|
|
1550
|
+
const width = this.video.clientWidth || 640;
|
|
1551
|
+
const height = this.video.clientHeight || 360;
|
|
1552
|
+
if (this.config.debugAdTiming) {
|
|
1553
|
+
console.log(
|
|
1554
|
+
`[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`
|
|
1555
|
+
);
|
|
1556
|
+
}
|
|
1557
|
+
this.ima.resize(width, height);
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1496
1560
|
destroy() {
|
|
1497
1561
|
this.clearAdStartTimer();
|
|
1498
1562
|
this.clearAdStopTimer();
|
|
@@ -1507,240 +1571,588 @@ var StormcloudVideoPlayer = class {
|
|
|
1507
1571
|
};
|
|
1508
1572
|
|
|
1509
1573
|
// src/ui/StormcloudVideoPlayer.tsx
|
|
1510
|
-
import React, { useEffect, useRef } from "react";
|
|
1574
|
+
import React, { useEffect, useRef, useMemo } from "react";
|
|
1511
1575
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1512
|
-
var
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
debugAdTiming,
|
|
1523
|
-
showCustomControls,
|
|
1524
|
-
onVolumeToggle,
|
|
1525
|
-
onFullscreenToggle,
|
|
1526
|
-
onControlClick,
|
|
1527
|
-
onReady,
|
|
1528
|
-
wrapperClassName,
|
|
1529
|
-
wrapperStyle,
|
|
1530
|
-
className,
|
|
1531
|
-
style,
|
|
1532
|
-
controls,
|
|
1533
|
-
playsInline,
|
|
1534
|
-
preload,
|
|
1535
|
-
poster,
|
|
1536
|
-
children,
|
|
1537
|
-
licenseKey,
|
|
1538
|
-
...restVideoAttrs
|
|
1539
|
-
} = props;
|
|
1540
|
-
const videoRef = useRef(null);
|
|
1541
|
-
const playerRef = useRef(null);
|
|
1542
|
-
const [adStatus, setAdStatus] = React.useState({ showAds: false, currentIndex: 0, totalAds: 0 });
|
|
1543
|
-
const [shouldShowNativeControls, setShouldShowNativeControls] = React.useState(true);
|
|
1544
|
-
useEffect(() => {
|
|
1545
|
-
if (typeof window === "undefined") return;
|
|
1546
|
-
const el = videoRef.current;
|
|
1547
|
-
if (!el || !src) return;
|
|
1548
|
-
if (playerRef.current) {
|
|
1549
|
-
try {
|
|
1550
|
-
playerRef.current.destroy();
|
|
1551
|
-
} catch {
|
|
1552
|
-
}
|
|
1553
|
-
playerRef.current = null;
|
|
1554
|
-
}
|
|
1555
|
-
const cfg = {
|
|
1576
|
+
var CRITICAL_PROPS = [
|
|
1577
|
+
"src",
|
|
1578
|
+
"allowNativeHls",
|
|
1579
|
+
"licenseKey",
|
|
1580
|
+
"lowLatencyMode",
|
|
1581
|
+
"driftToleranceMs"
|
|
1582
|
+
];
|
|
1583
|
+
var StormcloudVideoPlayerComponent = React.memo(
|
|
1584
|
+
(props) => {
|
|
1585
|
+
const {
|
|
1556
1586
|
src,
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
+
autoplay,
|
|
1588
|
+
muted,
|
|
1589
|
+
lowLatencyMode,
|
|
1590
|
+
allowNativeHls,
|
|
1591
|
+
driftToleranceMs,
|
|
1592
|
+
immediateManifestAds,
|
|
1593
|
+
debugAdTiming,
|
|
1594
|
+
showCustomControls,
|
|
1595
|
+
onVolumeToggle,
|
|
1596
|
+
onFullscreenToggle,
|
|
1597
|
+
onControlClick,
|
|
1598
|
+
onReady,
|
|
1599
|
+
wrapperClassName,
|
|
1600
|
+
wrapperStyle,
|
|
1601
|
+
className,
|
|
1602
|
+
style,
|
|
1603
|
+
controls,
|
|
1604
|
+
playsInline,
|
|
1605
|
+
preload,
|
|
1606
|
+
poster,
|
|
1607
|
+
children,
|
|
1608
|
+
licenseKey,
|
|
1609
|
+
...restVideoAttrs
|
|
1610
|
+
} = props;
|
|
1611
|
+
const videoRef = useRef(null);
|
|
1612
|
+
const playerRef = useRef(null);
|
|
1613
|
+
const [adStatus, setAdStatus] = React.useState({ showAds: false, currentIndex: 0, totalAds: 0 });
|
|
1614
|
+
const [shouldShowNativeControls, setShouldShowNativeControls] = React.useState(true);
|
|
1615
|
+
const [isMuted, setIsMuted] = React.useState(false);
|
|
1616
|
+
const [isFullscreen, setIsFullscreen] = React.useState(false);
|
|
1617
|
+
const criticalPropsKey = useMemo(() => {
|
|
1618
|
+
return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join("|");
|
|
1619
|
+
}, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs]);
|
|
1620
|
+
useEffect(() => {
|
|
1621
|
+
if (typeof window === "undefined") return;
|
|
1622
|
+
const el = videoRef.current;
|
|
1623
|
+
if (!el || !src) return;
|
|
1624
|
+
if (playerRef.current) {
|
|
1625
|
+
try {
|
|
1626
|
+
playerRef.current.destroy();
|
|
1627
|
+
} catch {
|
|
1628
|
+
}
|
|
1629
|
+
playerRef.current = null;
|
|
1587
1630
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1631
|
+
const cfg = {
|
|
1632
|
+
src,
|
|
1633
|
+
videoElement: el
|
|
1634
|
+
};
|
|
1635
|
+
if (autoplay !== void 0) cfg.autoplay = autoplay;
|
|
1636
|
+
if (muted !== void 0) cfg.muted = muted;
|
|
1637
|
+
if (lowLatencyMode !== void 0) cfg.lowLatencyMode = lowLatencyMode;
|
|
1638
|
+
if (allowNativeHls !== void 0) cfg.allowNativeHls = allowNativeHls;
|
|
1639
|
+
if (driftToleranceMs !== void 0)
|
|
1640
|
+
cfg.driftToleranceMs = driftToleranceMs;
|
|
1641
|
+
if (immediateManifestAds !== void 0)
|
|
1642
|
+
cfg.immediateManifestAds = immediateManifestAds;
|
|
1643
|
+
if (debugAdTiming !== void 0) cfg.debugAdTiming = debugAdTiming;
|
|
1644
|
+
if (showCustomControls !== void 0)
|
|
1645
|
+
cfg.showCustomControls = showCustomControls;
|
|
1646
|
+
if (onVolumeToggle !== void 0) cfg.onVolumeToggle = onVolumeToggle;
|
|
1647
|
+
if (onFullscreenToggle !== void 0)
|
|
1648
|
+
cfg.onFullscreenToggle = onFullscreenToggle;
|
|
1649
|
+
if (onControlClick !== void 0) cfg.onControlClick = onControlClick;
|
|
1650
|
+
if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
|
|
1651
|
+
const player = new StormcloudVideoPlayer(cfg);
|
|
1652
|
+
playerRef.current = player;
|
|
1653
|
+
player.load().then(() => {
|
|
1654
|
+
const showNative = player.shouldShowNativeControls();
|
|
1655
|
+
setShouldShowNativeControls(showNative);
|
|
1656
|
+
onReady?.(player);
|
|
1657
|
+
}).catch(() => {
|
|
1658
|
+
});
|
|
1659
|
+
return () => {
|
|
1660
|
+
try {
|
|
1661
|
+
player.destroy();
|
|
1662
|
+
} catch {
|
|
1663
|
+
}
|
|
1664
|
+
playerRef.current = null;
|
|
1665
|
+
};
|
|
1666
|
+
}, [criticalPropsKey]);
|
|
1667
|
+
useEffect(() => {
|
|
1668
|
+
if (!playerRef.current) return;
|
|
1609
1669
|
try {
|
|
1610
|
-
playerRef.current.
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
if (playerRef.current) {
|
|
1619
|
-
const showAds = playerRef.current.isShowingAds();
|
|
1620
|
-
const currentIndex = playerRef.current.getCurrentAdIndex();
|
|
1621
|
-
const totalAds = playerRef.current.getTotalAdsInBreak();
|
|
1622
|
-
setAdStatus((prev) => {
|
|
1623
|
-
if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {
|
|
1624
|
-
return { showAds, currentIndex, totalAds };
|
|
1625
|
-
}
|
|
1626
|
-
return prev;
|
|
1627
|
-
});
|
|
1670
|
+
if (autoplay !== void 0 && playerRef.current.videoElement) {
|
|
1671
|
+
playerRef.current.videoElement.autoplay = autoplay;
|
|
1672
|
+
}
|
|
1673
|
+
if (muted !== void 0 && playerRef.current.videoElement) {
|
|
1674
|
+
playerRef.current.videoElement.muted = muted;
|
|
1675
|
+
}
|
|
1676
|
+
} catch (error) {
|
|
1677
|
+
console.warn("Failed to update player properties:", error);
|
|
1628
1678
|
}
|
|
1629
|
-
};
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
"video",
|
|
1641
|
-
{
|
|
1642
|
-
ref: videoRef,
|
|
1643
|
-
className,
|
|
1644
|
-
style: { display: "block", width: "100%", height: "100%", ...style },
|
|
1645
|
-
controls: shouldShowNativeControls && controls,
|
|
1646
|
-
playsInline,
|
|
1647
|
-
preload,
|
|
1648
|
-
poster,
|
|
1649
|
-
...restVideoAttrs,
|
|
1650
|
-
children
|
|
1651
|
-
}
|
|
1652
|
-
),
|
|
1653
|
-
adStatus.showAds && adStatus.totalAds > 0 && /* @__PURE__ */ jsxs(
|
|
1654
|
-
"div",
|
|
1655
|
-
{
|
|
1656
|
-
style: {
|
|
1657
|
-
position: "absolute",
|
|
1658
|
-
top: "10px",
|
|
1659
|
-
right: "10px",
|
|
1660
|
-
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
1661
|
-
color: "white",
|
|
1662
|
-
padding: "4px 8px",
|
|
1663
|
-
borderRadius: "4px",
|
|
1664
|
-
fontSize: "12px",
|
|
1665
|
-
fontFamily: "Arial, sans-serif",
|
|
1666
|
-
zIndex: 10
|
|
1667
|
-
},
|
|
1668
|
-
children: [
|
|
1669
|
-
"Ad ",
|
|
1670
|
-
adStatus.currentIndex,
|
|
1671
|
-
"/",
|
|
1672
|
-
adStatus.totalAds
|
|
1673
|
-
]
|
|
1674
|
-
}
|
|
1675
|
-
),
|
|
1676
|
-
!shouldShowNativeControls && showCustomControls && /* @__PURE__ */ jsxs(
|
|
1677
|
-
"div",
|
|
1678
|
-
{
|
|
1679
|
-
style: {
|
|
1680
|
-
position: "absolute",
|
|
1681
|
-
bottom: "10px",
|
|
1682
|
-
right: "10px",
|
|
1683
|
-
display: "flex",
|
|
1684
|
-
gap: "8px",
|
|
1685
|
-
zIndex: 10
|
|
1686
|
-
},
|
|
1687
|
-
children: [
|
|
1688
|
-
onVolumeToggle && /* @__PURE__ */ jsx(
|
|
1689
|
-
"button",
|
|
1690
|
-
{
|
|
1691
|
-
onClick: onVolumeToggle,
|
|
1692
|
-
style: {
|
|
1693
|
-
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
1694
|
-
color: "white",
|
|
1695
|
-
border: "1px solid rgba(255, 255, 255, 0.3)",
|
|
1696
|
-
borderRadius: "4px",
|
|
1697
|
-
padding: "8px",
|
|
1698
|
-
cursor: "pointer",
|
|
1699
|
-
fontSize: "14px"
|
|
1700
|
-
},
|
|
1701
|
-
title: "Toggle Volume",
|
|
1702
|
-
children: "\u{1F50A}"
|
|
1703
|
-
}
|
|
1704
|
-
),
|
|
1705
|
-
onFullscreenToggle && /* @__PURE__ */ jsx(
|
|
1706
|
-
"button",
|
|
1707
|
-
{
|
|
1708
|
-
onClick: onFullscreenToggle,
|
|
1709
|
-
style: {
|
|
1710
|
-
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
1711
|
-
color: "white",
|
|
1712
|
-
border: "1px solid rgba(255, 255, 255, 0.3)",
|
|
1713
|
-
borderRadius: "4px",
|
|
1714
|
-
padding: "8px",
|
|
1715
|
-
cursor: "pointer",
|
|
1716
|
-
fontSize: "14px"
|
|
1717
|
-
},
|
|
1718
|
-
title: "Toggle Fullscreen",
|
|
1719
|
-
children: "\u2922"
|
|
1720
|
-
}
|
|
1721
|
-
)
|
|
1722
|
-
]
|
|
1723
|
-
}
|
|
1724
|
-
),
|
|
1725
|
-
onControlClick && /* @__PURE__ */ jsx(
|
|
1726
|
-
"div",
|
|
1727
|
-
{
|
|
1728
|
-
onClick: onControlClick,
|
|
1729
|
-
style: {
|
|
1730
|
-
position: "absolute",
|
|
1731
|
-
top: 0,
|
|
1732
|
-
left: 0,
|
|
1733
|
-
right: 0,
|
|
1734
|
-
bottom: 0,
|
|
1735
|
-
zIndex: 1,
|
|
1736
|
-
cursor: "pointer"
|
|
1679
|
+
}, [autoplay, muted]);
|
|
1680
|
+
useEffect(() => {
|
|
1681
|
+
if (!playerRef.current) return;
|
|
1682
|
+
const checkAdStatus = () => {
|
|
1683
|
+
if (playerRef.current) {
|
|
1684
|
+
const showAds = playerRef.current.isShowingAds();
|
|
1685
|
+
const currentIndex = playerRef.current.getCurrentAdIndex();
|
|
1686
|
+
const totalAds = playerRef.current.getTotalAdsInBreak();
|
|
1687
|
+
setAdStatus((prev) => {
|
|
1688
|
+
if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {
|
|
1689
|
+
return { showAds, currentIndex, totalAds };
|
|
1737
1690
|
}
|
|
1691
|
+
return prev;
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1694
|
+
};
|
|
1695
|
+
const interval = setInterval(checkAdStatus, 500);
|
|
1696
|
+
return () => clearInterval(interval);
|
|
1697
|
+
}, []);
|
|
1698
|
+
useEffect(() => {
|
|
1699
|
+
if (typeof window === "undefined" || !playerRef.current) return;
|
|
1700
|
+
const handleResize = () => {
|
|
1701
|
+
if (playerRef.current && videoRef.current) {
|
|
1702
|
+
if (typeof playerRef.current.resize === "function") {
|
|
1703
|
+
playerRef.current.resize();
|
|
1738
1704
|
}
|
|
1739
|
-
|
|
1740
|
-
|
|
1705
|
+
}
|
|
1706
|
+
};
|
|
1707
|
+
window.addEventListener("resize", handleResize);
|
|
1708
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
1709
|
+
}, []);
|
|
1710
|
+
useEffect(() => {
|
|
1711
|
+
if (!playerRef.current || !videoRef.current) return;
|
|
1712
|
+
const updateStates = () => {
|
|
1713
|
+
if (videoRef.current) {
|
|
1714
|
+
setIsMuted(videoRef.current.muted);
|
|
1715
|
+
}
|
|
1716
|
+
setIsFullscreen(
|
|
1717
|
+
document.fullscreenElement === videoRef.current?.parentElement
|
|
1718
|
+
);
|
|
1719
|
+
};
|
|
1720
|
+
const interval = setInterval(updateStates, 200);
|
|
1721
|
+
const handleFullscreenChange = () => {
|
|
1722
|
+
setIsFullscreen(
|
|
1723
|
+
document.fullscreenElement === videoRef.current?.parentElement
|
|
1724
|
+
);
|
|
1725
|
+
};
|
|
1726
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
1727
|
+
return () => {
|
|
1728
|
+
clearInterval(interval);
|
|
1729
|
+
document.removeEventListener(
|
|
1730
|
+
"fullscreenchange",
|
|
1731
|
+
handleFullscreenChange
|
|
1732
|
+
);
|
|
1733
|
+
};
|
|
1734
|
+
}, []);
|
|
1735
|
+
return /* @__PURE__ */ jsxs(
|
|
1736
|
+
"div",
|
|
1737
|
+
{
|
|
1738
|
+
className: wrapperClassName,
|
|
1739
|
+
style: {
|
|
1740
|
+
display: "flex",
|
|
1741
|
+
alignItems: "center",
|
|
1742
|
+
justifyContent: "center",
|
|
1743
|
+
position: isFullscreen ? "fixed" : "relative",
|
|
1744
|
+
top: isFullscreen ? 0 : void 0,
|
|
1745
|
+
left: isFullscreen ? 0 : void 0,
|
|
1746
|
+
overflow: "hidden",
|
|
1747
|
+
width: isFullscreen ? "100vw" : "100%",
|
|
1748
|
+
height: isFullscreen ? "100vh" : "100%",
|
|
1749
|
+
maxWidth: isFullscreen ? "100vw" : "100%",
|
|
1750
|
+
maxHeight: isFullscreen ? "100vh" : "100%",
|
|
1751
|
+
zIndex: isFullscreen ? 9999 : void 0,
|
|
1752
|
+
backgroundColor: isFullscreen ? "#000" : void 0,
|
|
1753
|
+
...wrapperStyle
|
|
1754
|
+
},
|
|
1755
|
+
children: [
|
|
1756
|
+
/* @__PURE__ */ jsx(
|
|
1757
|
+
"video",
|
|
1758
|
+
{
|
|
1759
|
+
ref: videoRef,
|
|
1760
|
+
className,
|
|
1761
|
+
style: {
|
|
1762
|
+
display: "block",
|
|
1763
|
+
width: "100%",
|
|
1764
|
+
height: "100%",
|
|
1765
|
+
objectFit: isFullscreen ? "cover" : "contain",
|
|
1766
|
+
backgroundColor: "#000",
|
|
1767
|
+
...style
|
|
1768
|
+
},
|
|
1769
|
+
controls: shouldShowNativeControls && controls && !showCustomControls,
|
|
1770
|
+
playsInline,
|
|
1771
|
+
preload,
|
|
1772
|
+
poster,
|
|
1773
|
+
...restVideoAttrs,
|
|
1774
|
+
children
|
|
1775
|
+
}
|
|
1776
|
+
),
|
|
1777
|
+
adStatus.showAds && adStatus.totalAds > 0 && /* @__PURE__ */ jsxs(
|
|
1778
|
+
"div",
|
|
1779
|
+
{
|
|
1780
|
+
style: {
|
|
1781
|
+
position: "absolute",
|
|
1782
|
+
top: "10px",
|
|
1783
|
+
right: "10px",
|
|
1784
|
+
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
1785
|
+
color: "white",
|
|
1786
|
+
padding: "4px 8px",
|
|
1787
|
+
borderRadius: "4px",
|
|
1788
|
+
fontSize: "12px",
|
|
1789
|
+
fontFamily: "Arial, sans-serif",
|
|
1790
|
+
zIndex: 10
|
|
1791
|
+
},
|
|
1792
|
+
children: [
|
|
1793
|
+
"Ad ",
|
|
1794
|
+
adStatus.currentIndex,
|
|
1795
|
+
"/",
|
|
1796
|
+
adStatus.totalAds
|
|
1797
|
+
]
|
|
1798
|
+
}
|
|
1799
|
+
),
|
|
1800
|
+
showCustomControls && /* @__PURE__ */ jsxs(
|
|
1801
|
+
"div",
|
|
1802
|
+
{
|
|
1803
|
+
style: {
|
|
1804
|
+
position: "absolute",
|
|
1805
|
+
bottom: "10px",
|
|
1806
|
+
right: "10px",
|
|
1807
|
+
display: "flex",
|
|
1808
|
+
gap: "8px",
|
|
1809
|
+
zIndex: 10
|
|
1810
|
+
},
|
|
1811
|
+
children: [
|
|
1812
|
+
/* @__PURE__ */ jsx(
|
|
1813
|
+
"button",
|
|
1814
|
+
{
|
|
1815
|
+
onClick: () => {
|
|
1816
|
+
if (onVolumeToggle) {
|
|
1817
|
+
onVolumeToggle();
|
|
1818
|
+
} else if (playerRef.current) {
|
|
1819
|
+
playerRef.current.toggleMute();
|
|
1820
|
+
}
|
|
1821
|
+
},
|
|
1822
|
+
onMouseEnter: (e) => {
|
|
1823
|
+
const target = e.currentTarget;
|
|
1824
|
+
target.style.transform = "translateY(-2px) scale(1.05)";
|
|
1825
|
+
target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
|
|
1826
|
+
target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
|
|
1827
|
+
},
|
|
1828
|
+
onMouseLeave: (e) => {
|
|
1829
|
+
const target = e.currentTarget;
|
|
1830
|
+
target.style.transform = "translateY(0) scale(1)";
|
|
1831
|
+
target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
|
|
1832
|
+
target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
|
|
1833
|
+
},
|
|
1834
|
+
style: {
|
|
1835
|
+
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
|
|
1836
|
+
color: "white",
|
|
1837
|
+
border: "1px solid rgba(255, 255, 255, 0.2)",
|
|
1838
|
+
borderRadius: "8px",
|
|
1839
|
+
padding: "10px",
|
|
1840
|
+
cursor: "pointer",
|
|
1841
|
+
display: "flex",
|
|
1842
|
+
alignItems: "center",
|
|
1843
|
+
justifyContent: "center",
|
|
1844
|
+
backdropFilter: "blur(10px)",
|
|
1845
|
+
boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
|
|
1846
|
+
transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
|
|
1847
|
+
},
|
|
1848
|
+
title: isMuted ? "Unmute" : "Mute",
|
|
1849
|
+
children: isMuted ? /* @__PURE__ */ jsxs(
|
|
1850
|
+
"svg",
|
|
1851
|
+
{
|
|
1852
|
+
width: "18",
|
|
1853
|
+
height: "18",
|
|
1854
|
+
viewBox: "0 0 24 24",
|
|
1855
|
+
fill: "none",
|
|
1856
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1857
|
+
children: [
|
|
1858
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
|
|
1859
|
+
"linearGradient",
|
|
1860
|
+
{
|
|
1861
|
+
id: "volumeGradient",
|
|
1862
|
+
x1: "0%",
|
|
1863
|
+
y1: "0%",
|
|
1864
|
+
x2: "100%",
|
|
1865
|
+
y2: "100%",
|
|
1866
|
+
children: [
|
|
1867
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: "1" }),
|
|
1868
|
+
/* @__PURE__ */ jsx(
|
|
1869
|
+
"stop",
|
|
1870
|
+
{
|
|
1871
|
+
offset: "100%",
|
|
1872
|
+
stopColor: "#e0e0e0",
|
|
1873
|
+
stopOpacity: "0.9"
|
|
1874
|
+
}
|
|
1875
|
+
)
|
|
1876
|
+
]
|
|
1877
|
+
}
|
|
1878
|
+
) }),
|
|
1879
|
+
/* @__PURE__ */ jsx(
|
|
1880
|
+
"path",
|
|
1881
|
+
{
|
|
1882
|
+
d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z",
|
|
1883
|
+
fill: "url(#volumeGradient)",
|
|
1884
|
+
stroke: "rgba(255,255,255,0.3)",
|
|
1885
|
+
strokeWidth: "0.5"
|
|
1886
|
+
}
|
|
1887
|
+
),
|
|
1888
|
+
/* @__PURE__ */ jsx(
|
|
1889
|
+
"path",
|
|
1890
|
+
{
|
|
1891
|
+
d: "M16.5 8.5l-1.41-1.41L12 10.18 8.91 7.09 7.5 8.5l3.09 3.09L7.5 14.68l1.41 1.41L12 13l3.09 3.09 1.41-1.41L13.41 12l3.09-3.5z",
|
|
1892
|
+
fill: "#ff4444",
|
|
1893
|
+
stroke: "rgba(255,255,255,0.5)",
|
|
1894
|
+
strokeWidth: "0.5"
|
|
1895
|
+
}
|
|
1896
|
+
)
|
|
1897
|
+
]
|
|
1898
|
+
}
|
|
1899
|
+
) : /* @__PURE__ */ jsxs(
|
|
1900
|
+
"svg",
|
|
1901
|
+
{
|
|
1902
|
+
width: "18",
|
|
1903
|
+
height: "18",
|
|
1904
|
+
viewBox: "0 0 24 24",
|
|
1905
|
+
fill: "none",
|
|
1906
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1907
|
+
children: [
|
|
1908
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
|
|
1909
|
+
"linearGradient",
|
|
1910
|
+
{
|
|
1911
|
+
id: "volumeGradient",
|
|
1912
|
+
x1: "0%",
|
|
1913
|
+
y1: "0%",
|
|
1914
|
+
x2: "100%",
|
|
1915
|
+
y2: "100%",
|
|
1916
|
+
children: [
|
|
1917
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: "1" }),
|
|
1918
|
+
/* @__PURE__ */ jsx(
|
|
1919
|
+
"stop",
|
|
1920
|
+
{
|
|
1921
|
+
offset: "100%",
|
|
1922
|
+
stopColor: "#e0e0e0",
|
|
1923
|
+
stopOpacity: "0.9"
|
|
1924
|
+
}
|
|
1925
|
+
)
|
|
1926
|
+
]
|
|
1927
|
+
}
|
|
1928
|
+
) }),
|
|
1929
|
+
/* @__PURE__ */ jsx(
|
|
1930
|
+
"path",
|
|
1931
|
+
{
|
|
1932
|
+
d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z",
|
|
1933
|
+
fill: "url(#volumeGradient)",
|
|
1934
|
+
stroke: "rgba(255,255,255,0.3)",
|
|
1935
|
+
strokeWidth: "0.5"
|
|
1936
|
+
}
|
|
1937
|
+
),
|
|
1938
|
+
/* @__PURE__ */ jsx(
|
|
1939
|
+
"path",
|
|
1940
|
+
{
|
|
1941
|
+
d: "M15.5 12c0-1.33-.58-2.53-1.5-3.35v6.69c.92-.81 1.5-2.01 1.5-3.34z",
|
|
1942
|
+
fill: "url(#volumeGradient)",
|
|
1943
|
+
opacity: "0.8"
|
|
1944
|
+
}
|
|
1945
|
+
),
|
|
1946
|
+
/* @__PURE__ */ jsx(
|
|
1947
|
+
"path",
|
|
1948
|
+
{
|
|
1949
|
+
d: "M14 4.45v1.75c2.01.91 3.5 3.02 3.5 5.3 0 2.28-1.49 4.39-3.5 5.3v1.75c2.89-.86 5-3.54 5-7.05s-2.11-6.19-5-7.05z",
|
|
1950
|
+
fill: "url(#volumeGradient)",
|
|
1951
|
+
opacity: "0.6"
|
|
1952
|
+
}
|
|
1953
|
+
)
|
|
1954
|
+
]
|
|
1955
|
+
}
|
|
1956
|
+
)
|
|
1957
|
+
}
|
|
1958
|
+
),
|
|
1959
|
+
/* @__PURE__ */ jsx(
|
|
1960
|
+
"button",
|
|
1961
|
+
{
|
|
1962
|
+
onClick: () => {
|
|
1963
|
+
if (onFullscreenToggle) {
|
|
1964
|
+
onFullscreenToggle();
|
|
1965
|
+
} else if (playerRef.current) {
|
|
1966
|
+
playerRef.current.toggleFullscreen().catch((err) => {
|
|
1967
|
+
console.error("Fullscreen error:", err);
|
|
1968
|
+
});
|
|
1969
|
+
}
|
|
1970
|
+
},
|
|
1971
|
+
onMouseEnter: (e) => {
|
|
1972
|
+
const target = e.currentTarget;
|
|
1973
|
+
target.style.transform = "translateY(-2px) scale(1.05)";
|
|
1974
|
+
target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
|
|
1975
|
+
target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
|
|
1976
|
+
},
|
|
1977
|
+
onMouseLeave: (e) => {
|
|
1978
|
+
const target = e.currentTarget;
|
|
1979
|
+
target.style.transform = "translateY(0) scale(1)";
|
|
1980
|
+
target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
|
|
1981
|
+
target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
|
|
1982
|
+
},
|
|
1983
|
+
style: {
|
|
1984
|
+
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
|
|
1985
|
+
color: "white",
|
|
1986
|
+
border: "1px solid rgba(255, 255, 255, 0.2)",
|
|
1987
|
+
borderRadius: "8px",
|
|
1988
|
+
padding: "10px",
|
|
1989
|
+
cursor: "pointer",
|
|
1990
|
+
display: "flex",
|
|
1991
|
+
alignItems: "center",
|
|
1992
|
+
justifyContent: "center",
|
|
1993
|
+
backdropFilter: "blur(10px)",
|
|
1994
|
+
boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
|
|
1995
|
+
transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
|
|
1996
|
+
},
|
|
1997
|
+
title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
|
|
1998
|
+
children: isFullscreen ? /* @__PURE__ */ jsxs(
|
|
1999
|
+
"svg",
|
|
2000
|
+
{
|
|
2001
|
+
width: "20",
|
|
2002
|
+
height: "20",
|
|
2003
|
+
viewBox: "0 0 24 24",
|
|
2004
|
+
fill: "none",
|
|
2005
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2006
|
+
children: [
|
|
2007
|
+
/* @__PURE__ */ jsx(
|
|
2008
|
+
"path",
|
|
2009
|
+
{
|
|
2010
|
+
d: "M8 8h3v3l-1-1-2 2-1.5-1.5L8.5 8.5 8 8z",
|
|
2011
|
+
fill: "white",
|
|
2012
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2013
|
+
strokeWidth: "0.5"
|
|
2014
|
+
}
|
|
2015
|
+
),
|
|
2016
|
+
/* @__PURE__ */ jsx(
|
|
2017
|
+
"path",
|
|
2018
|
+
{
|
|
2019
|
+
d: "M16 8h-3v3l1-1 2 2 1.5-1.5L15.5 8.5 16 8z",
|
|
2020
|
+
fill: "white",
|
|
2021
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2022
|
+
strokeWidth: "0.5"
|
|
2023
|
+
}
|
|
2024
|
+
),
|
|
2025
|
+
/* @__PURE__ */ jsx(
|
|
2026
|
+
"path",
|
|
2027
|
+
{
|
|
2028
|
+
d: "M8 16h3v-3l-1 1-2-2-1.5 1.5L8.5 15.5 8 16z",
|
|
2029
|
+
fill: "white",
|
|
2030
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2031
|
+
strokeWidth: "0.5"
|
|
2032
|
+
}
|
|
2033
|
+
),
|
|
2034
|
+
/* @__PURE__ */ jsx(
|
|
2035
|
+
"path",
|
|
2036
|
+
{
|
|
2037
|
+
d: "M16 16h-3v-3l1 1 2-2 1.5 1.5L15.5 15.5 16 16z",
|
|
2038
|
+
fill: "white",
|
|
2039
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2040
|
+
strokeWidth: "0.5"
|
|
2041
|
+
}
|
|
2042
|
+
)
|
|
2043
|
+
]
|
|
2044
|
+
}
|
|
2045
|
+
) : /* @__PURE__ */ jsxs(
|
|
2046
|
+
"svg",
|
|
2047
|
+
{
|
|
2048
|
+
width: "20",
|
|
2049
|
+
height: "20",
|
|
2050
|
+
viewBox: "0 0 24 24",
|
|
2051
|
+
fill: "none",
|
|
2052
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2053
|
+
children: [
|
|
2054
|
+
/* @__PURE__ */ jsx(
|
|
2055
|
+
"path",
|
|
2056
|
+
{
|
|
2057
|
+
d: "M3 3h6v2H5v4H3V3z",
|
|
2058
|
+
fill: "white",
|
|
2059
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2060
|
+
strokeWidth: "0.5"
|
|
2061
|
+
}
|
|
2062
|
+
),
|
|
2063
|
+
/* @__PURE__ */ jsx(
|
|
2064
|
+
"path",
|
|
2065
|
+
{
|
|
2066
|
+
d: "M21 3h-6v2h4v4h2V3z",
|
|
2067
|
+
fill: "white",
|
|
2068
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2069
|
+
strokeWidth: "0.5"
|
|
2070
|
+
}
|
|
2071
|
+
),
|
|
2072
|
+
/* @__PURE__ */ jsx(
|
|
2073
|
+
"path",
|
|
2074
|
+
{
|
|
2075
|
+
d: "M3 21v-6h2v4h4v2H3z",
|
|
2076
|
+
fill: "white",
|
|
2077
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2078
|
+
strokeWidth: "0.5"
|
|
2079
|
+
}
|
|
2080
|
+
),
|
|
2081
|
+
/* @__PURE__ */ jsx(
|
|
2082
|
+
"path",
|
|
2083
|
+
{
|
|
2084
|
+
d: "M21 21h-6v-2h4v-4h2v6z",
|
|
2085
|
+
fill: "white",
|
|
2086
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2087
|
+
strokeWidth: "0.5"
|
|
2088
|
+
}
|
|
2089
|
+
)
|
|
2090
|
+
]
|
|
2091
|
+
}
|
|
2092
|
+
)
|
|
2093
|
+
}
|
|
2094
|
+
)
|
|
2095
|
+
]
|
|
2096
|
+
}
|
|
2097
|
+
),
|
|
2098
|
+
onControlClick && /* @__PURE__ */ jsx(
|
|
2099
|
+
"div",
|
|
2100
|
+
{
|
|
2101
|
+
onClick: onControlClick,
|
|
2102
|
+
style: {
|
|
2103
|
+
position: "absolute",
|
|
2104
|
+
top: 0,
|
|
2105
|
+
left: 0,
|
|
2106
|
+
right: 0,
|
|
2107
|
+
bottom: 0,
|
|
2108
|
+
zIndex: 1,
|
|
2109
|
+
cursor: "pointer"
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
)
|
|
2113
|
+
]
|
|
2114
|
+
}
|
|
2115
|
+
);
|
|
2116
|
+
},
|
|
2117
|
+
(prevProps, nextProps) => {
|
|
2118
|
+
for (const prop of CRITICAL_PROPS) {
|
|
2119
|
+
if (prevProps[prop] !== nextProps[prop]) {
|
|
2120
|
+
return false;
|
|
2121
|
+
}
|
|
1741
2122
|
}
|
|
1742
|
-
|
|
1743
|
-
|
|
2123
|
+
const uiProps = [
|
|
2124
|
+
"autoplay",
|
|
2125
|
+
"muted",
|
|
2126
|
+
"controls",
|
|
2127
|
+
"showCustomControls",
|
|
2128
|
+
"className",
|
|
2129
|
+
"style",
|
|
2130
|
+
"wrapperClassName",
|
|
2131
|
+
"wrapperStyle",
|
|
2132
|
+
"playsInline",
|
|
2133
|
+
"preload",
|
|
2134
|
+
"poster",
|
|
2135
|
+
"children"
|
|
2136
|
+
];
|
|
2137
|
+
for (const prop of uiProps) {
|
|
2138
|
+
if (prevProps[prop] !== nextProps[prop]) {
|
|
2139
|
+
return false;
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
const callbackProps = [
|
|
2143
|
+
"onReady",
|
|
2144
|
+
"onVolumeToggle",
|
|
2145
|
+
"onFullscreenToggle",
|
|
2146
|
+
"onControlClick"
|
|
2147
|
+
];
|
|
2148
|
+
for (const prop of callbackProps) {
|
|
2149
|
+
if (prevProps[prop] !== nextProps[prop]) {
|
|
2150
|
+
return false;
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
return true;
|
|
2154
|
+
}
|
|
2155
|
+
);
|
|
1744
2156
|
export {
|
|
1745
2157
|
StormcloudVideoPlayer,
|
|
1746
2158
|
StormcloudVideoPlayerComponent,
|