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.cjs
CHANGED
|
@@ -121,6 +121,9 @@ function createImaController(video) {
|
|
|
121
121
|
container.style.top = "0";
|
|
122
122
|
container.style.right = "0";
|
|
123
123
|
container.style.bottom = "0";
|
|
124
|
+
container.style.display = "flex";
|
|
125
|
+
container.style.alignItems = "center";
|
|
126
|
+
container.style.justifyContent = "center";
|
|
124
127
|
container.style.pointerEvents = "none";
|
|
125
128
|
container.style.zIndex = "2";
|
|
126
129
|
video.parentElement?.appendChild(container);
|
|
@@ -163,6 +166,9 @@ function createImaController(video) {
|
|
|
163
166
|
container.style.top = "0";
|
|
164
167
|
container.style.right = "0";
|
|
165
168
|
container.style.bottom = "0";
|
|
169
|
+
container.style.display = "flex";
|
|
170
|
+
container.style.alignItems = "center";
|
|
171
|
+
container.style.justifyContent = "center";
|
|
166
172
|
container.style.pointerEvents = "none";
|
|
167
173
|
container.style.zIndex = "2";
|
|
168
174
|
if (!video.parentElement) {
|
|
@@ -369,6 +375,20 @@ function createImaController(video) {
|
|
|
369
375
|
isAdPlaying() {
|
|
370
376
|
return adPlaying;
|
|
371
377
|
},
|
|
378
|
+
resize(width, height) {
|
|
379
|
+
if (!adsManager || !window.google?.ima) {
|
|
380
|
+
console.warn(
|
|
381
|
+
"[IMA] Cannot resize: No ads manager or IMA SDK available"
|
|
382
|
+
);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
try {
|
|
386
|
+
console.log(`[IMA] Resizing ads manager to ${width}x${height}`);
|
|
387
|
+
adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);
|
|
388
|
+
} catch (error) {
|
|
389
|
+
console.warn("[IMA] Error resizing ads manager:", error);
|
|
390
|
+
}
|
|
391
|
+
},
|
|
372
392
|
on(event, listener) {
|
|
373
393
|
if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
|
|
374
394
|
listeners.get(event).add(listener);
|
|
@@ -539,7 +559,9 @@ async function sendInitialTracking(licenseKey) {
|
|
|
539
559
|
browserId,
|
|
540
560
|
...clientInfo
|
|
541
561
|
};
|
|
542
|
-
const headers = {
|
|
562
|
+
const headers = {
|
|
563
|
+
"Content-Type": "application/json"
|
|
564
|
+
};
|
|
543
565
|
if (licenseKey) {
|
|
544
566
|
headers["Authorization"] = `Bearer ${licenseKey}`;
|
|
545
567
|
}
|
|
@@ -554,11 +576,7 @@ async function sendInitialTracking(licenseKey) {
|
|
|
554
576
|
if (!response.ok) {
|
|
555
577
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
556
578
|
}
|
|
557
|
-
|
|
558
|
-
console.log(
|
|
559
|
-
"[StormcloudVideoPlayer] Initial tracking data sent successfully:",
|
|
560
|
-
data
|
|
561
|
-
);
|
|
579
|
+
await response.json();
|
|
562
580
|
} catch (error) {
|
|
563
581
|
console.error(
|
|
564
582
|
"[StormcloudVideoPlayer] Error sending initial tracking data:",
|
|
@@ -574,7 +592,9 @@ async function sendHeartbeat(licenseKey) {
|
|
|
574
592
|
browserId,
|
|
575
593
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
576
594
|
};
|
|
577
|
-
const headers = {
|
|
595
|
+
const headers = {
|
|
596
|
+
"Content-Type": "application/json"
|
|
597
|
+
};
|
|
578
598
|
if (licenseKey) {
|
|
579
599
|
headers["Authorization"] = `Bearer ${licenseKey}`;
|
|
580
600
|
}
|
|
@@ -589,8 +609,7 @@ async function sendHeartbeat(licenseKey) {
|
|
|
589
609
|
if (!response.ok) {
|
|
590
610
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
591
611
|
}
|
|
592
|
-
|
|
593
|
-
console.log("[StormcloudVideoPlayer] Heartbeat sent successfully:", data);
|
|
612
|
+
await response.json();
|
|
594
613
|
} catch (error) {
|
|
595
614
|
console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
|
|
596
615
|
}
|
|
@@ -609,7 +628,6 @@ var StormcloudVideoPlayer = class {
|
|
|
609
628
|
this.showAds = false;
|
|
610
629
|
this.config = config;
|
|
611
630
|
this.video = config.videoElement;
|
|
612
|
-
this.adSchedule = config.adSchedule;
|
|
613
631
|
this.ima = createImaController(this.video);
|
|
614
632
|
}
|
|
615
633
|
async load() {
|
|
@@ -915,70 +933,61 @@ var StormcloudVideoPlayer = class {
|
|
|
915
933
|
const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0;
|
|
916
934
|
this.expectedAdBreakDurationMs = durationMs;
|
|
917
935
|
this.currentAdBreakStartWallClockMs = Date.now();
|
|
918
|
-
const
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
936
|
+
const isManifestMarker = this.isManifestBasedMarker(marker);
|
|
937
|
+
const forceImmediate = this.config.immediateManifestAds ?? true;
|
|
938
|
+
if (this.config.debugAdTiming) {
|
|
939
|
+
console.log("[StormcloudVideoPlayer] Ad start decision:", {
|
|
940
|
+
isManifestMarker,
|
|
941
|
+
forceImmediate,
|
|
942
|
+
hasPts: typeof marker.ptsSeconds === "number"
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
if (isManifestMarker && forceImmediate) {
|
|
922
946
|
if (this.config.debugAdTiming) {
|
|
923
|
-
console.log(
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
947
|
+
console.log(
|
|
948
|
+
"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)"
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
this.clearAdStartTimer();
|
|
952
|
+
this.handleAdStart(marker);
|
|
953
|
+
} else if (typeof marker.ptsSeconds === "number") {
|
|
954
|
+
const tol = this.config.driftToleranceMs ?? 1e3;
|
|
955
|
+
const nowMs = this.video.currentTime * 1e3;
|
|
956
|
+
const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
|
|
957
|
+
const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
|
|
958
|
+
if (this.config.debugAdTiming) {
|
|
959
|
+
console.log("[StormcloudVideoPlayer] PTS-based timing calculation:", {
|
|
960
|
+
nowMs,
|
|
961
|
+
estCurrentPtsMs,
|
|
962
|
+
markerPtsMs: marker.ptsSeconds * 1e3,
|
|
963
|
+
deltaMs,
|
|
964
|
+
tolerance: tol
|
|
928
965
|
});
|
|
929
966
|
}
|
|
930
|
-
if (
|
|
931
|
-
if (this.config.debugAdTiming) {
|
|
932
|
-
console.log(
|
|
933
|
-
"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)"
|
|
934
|
-
);
|
|
935
|
-
}
|
|
936
|
-
this.clearAdStartTimer();
|
|
937
|
-
this.handleAdStart(marker);
|
|
938
|
-
} else if (typeof marker.ptsSeconds === "number") {
|
|
939
|
-
const tol = this.config.driftToleranceMs ?? 1e3;
|
|
940
|
-
const nowMs = this.video.currentTime * 1e3;
|
|
941
|
-
const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
|
|
942
|
-
const deltaMs = Math.floor(
|
|
943
|
-
marker.ptsSeconds * 1e3 - estCurrentPtsMs
|
|
944
|
-
);
|
|
967
|
+
if (deltaMs > tol) {
|
|
945
968
|
if (this.config.debugAdTiming) {
|
|
946
969
|
console.log(
|
|
947
|
-
|
|
948
|
-
{
|
|
949
|
-
nowMs,
|
|
950
|
-
estCurrentPtsMs,
|
|
951
|
-
markerPtsMs: marker.ptsSeconds * 1e3,
|
|
952
|
-
deltaMs,
|
|
953
|
-
tolerance: tol
|
|
954
|
-
}
|
|
970
|
+
`[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`
|
|
955
971
|
);
|
|
956
972
|
}
|
|
957
|
-
|
|
958
|
-
if (this.config.debugAdTiming) {
|
|
959
|
-
console.log(
|
|
960
|
-
`[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`
|
|
961
|
-
);
|
|
962
|
-
}
|
|
963
|
-
this.scheduleAdStartIn(deltaMs);
|
|
964
|
-
} else {
|
|
965
|
-
if (this.config.debugAdTiming) {
|
|
966
|
-
console.log(
|
|
967
|
-
"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)"
|
|
968
|
-
);
|
|
969
|
-
}
|
|
970
|
-
this.clearAdStartTimer();
|
|
971
|
-
this.handleAdStart(marker);
|
|
972
|
-
}
|
|
973
|
+
this.scheduleAdStartIn(deltaMs);
|
|
973
974
|
} else {
|
|
974
975
|
if (this.config.debugAdTiming) {
|
|
975
976
|
console.log(
|
|
976
|
-
"[StormcloudVideoPlayer] Starting ad immediately (
|
|
977
|
+
"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)"
|
|
977
978
|
);
|
|
978
979
|
}
|
|
979
980
|
this.clearAdStartTimer();
|
|
980
981
|
this.handleAdStart(marker);
|
|
981
982
|
}
|
|
983
|
+
} else {
|
|
984
|
+
if (this.config.debugAdTiming) {
|
|
985
|
+
console.log(
|
|
986
|
+
"[StormcloudVideoPlayer] Starting ad immediately (fallback)"
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
this.clearAdStartTimer();
|
|
990
|
+
this.handleAdStart(marker);
|
|
982
991
|
}
|
|
983
992
|
if (this.expectedAdBreakDurationMs != null) {
|
|
984
993
|
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
@@ -998,12 +1007,11 @@ var StormcloudVideoPlayer = class {
|
|
|
998
1007
|
this.scheduleAdStopCountdown(remainingMs);
|
|
999
1008
|
}
|
|
1000
1009
|
if (!this.ima.isAdPlaying()) {
|
|
1001
|
-
const policy = this.adSchedule?.lateJoinPolicy ?? "play_remaining";
|
|
1002
1010
|
const scheduled = this.findCurrentOrNextBreak(
|
|
1003
1011
|
this.video.currentTime * 1e3
|
|
1004
1012
|
);
|
|
1005
1013
|
const tags = this.selectVastTagsForBreak(scheduled) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);
|
|
1006
|
-
if (
|
|
1014
|
+
if (tags && tags.length > 0) {
|
|
1007
1015
|
const first = tags[0];
|
|
1008
1016
|
const rest = tags.slice(1);
|
|
1009
1017
|
this.adPodQueue = rest;
|
|
@@ -1202,11 +1210,11 @@ var StormcloudVideoPlayer = class {
|
|
|
1202
1210
|
});
|
|
1203
1211
|
this.heartbeatInterval = window.setInterval(() => {
|
|
1204
1212
|
this.sendHeartbeatIfNeeded();
|
|
1205
|
-
},
|
|
1213
|
+
}, 5e3);
|
|
1206
1214
|
}
|
|
1207
1215
|
sendHeartbeatIfNeeded() {
|
|
1208
1216
|
const now = Date.now();
|
|
1209
|
-
if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime >
|
|
1217
|
+
if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {
|
|
1210
1218
|
this.lastHeartbeatTime = now;
|
|
1211
1219
|
sendHeartbeat(this.config.licenseKey).catch((error) => {
|
|
1212
1220
|
if (this.config.debugAdTiming) {
|
|
@@ -1253,9 +1261,6 @@ var StormcloudVideoPlayer = class {
|
|
|
1253
1261
|
});
|
|
1254
1262
|
}
|
|
1255
1263
|
}
|
|
1256
|
-
setAdSchedule(schedule) {
|
|
1257
|
-
this.adSchedule = schedule;
|
|
1258
|
-
}
|
|
1259
1264
|
getCurrentAdIndex() {
|
|
1260
1265
|
return this.currentAdIndex;
|
|
1261
1266
|
}
|
|
@@ -1278,17 +1283,11 @@ var StormcloudVideoPlayer = class {
|
|
|
1278
1283
|
shouldShowNativeControls() {
|
|
1279
1284
|
return this.getStreamType() !== "hls";
|
|
1280
1285
|
}
|
|
1281
|
-
async
|
|
1282
|
-
const res = await fetch(url);
|
|
1283
|
-
if (!res.ok) throw new Error(`Failed to fetch ad schedule: ${res.status}`);
|
|
1284
|
-
const data = await res.json();
|
|
1285
|
-
this.adSchedule = data;
|
|
1286
|
-
}
|
|
1287
|
-
async loadDefaultVastFromAiry(airyApiUrl, params) {
|
|
1286
|
+
async loadDefaultVastFromAdstorm(adstormApiUrl, params) {
|
|
1288
1287
|
const usp = new URLSearchParams(params || {});
|
|
1289
|
-
const url = `${
|
|
1288
|
+
const url = `${adstormApiUrl}?${usp.toString()}`;
|
|
1290
1289
|
const res = await fetch(url);
|
|
1291
|
-
if (!res.ok) throw new Error(`Failed to fetch
|
|
1290
|
+
if (!res.ok) throw new Error(`Failed to fetch adstorm ads: ${res.status}`);
|
|
1292
1291
|
const data = await res.json();
|
|
1293
1292
|
const tag = data?.adTagUrl || data?.vastTagUrl || data?.tagUrl;
|
|
1294
1293
|
if (typeof tag === "string" && tag.length > 0) {
|
|
@@ -1351,7 +1350,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1351
1350
|
}
|
|
1352
1351
|
}
|
|
1353
1352
|
findCurrentOrNextBreak(nowMs) {
|
|
1354
|
-
const schedule =
|
|
1353
|
+
const schedule = [];
|
|
1355
1354
|
let candidate;
|
|
1356
1355
|
for (const b of schedule) {
|
|
1357
1356
|
const tol = this.config.driftToleranceMs ?? 1e3;
|
|
@@ -1362,7 +1361,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1362
1361
|
return candidate;
|
|
1363
1362
|
}
|
|
1364
1363
|
onTimeUpdate(currentTimeSec) {
|
|
1365
|
-
if (
|
|
1364
|
+
if (this.ima.isAdPlaying()) return;
|
|
1366
1365
|
const nowMs = currentTimeSec * 1e3;
|
|
1367
1366
|
const breakToPlay = this.findBreakForTime(nowMs);
|
|
1368
1367
|
if (breakToPlay) {
|
|
@@ -1374,10 +1373,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1374
1373
|
const endMs = adBreak.startTimeMs + durationMs;
|
|
1375
1374
|
if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {
|
|
1376
1375
|
const remainingMs = endMs - nowMs;
|
|
1377
|
-
const policy = this.adSchedule?.lateJoinPolicy ?? "play_remaining";
|
|
1378
|
-
if (policy === "skip_to_content") return;
|
|
1379
1376
|
const tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);
|
|
1380
|
-
if (
|
|
1377
|
+
if (tags && tags.length > 0) {
|
|
1381
1378
|
const first = tags[0];
|
|
1382
1379
|
const rest = tags.slice(1);
|
|
1383
1380
|
this.adPodQueue = rest;
|
|
@@ -1525,7 +1522,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1525
1522
|
return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
|
|
1526
1523
|
}
|
|
1527
1524
|
findBreakForTime(nowMs) {
|
|
1528
|
-
const schedule =
|
|
1525
|
+
const schedule = [];
|
|
1529
1526
|
for (const b of schedule) {
|
|
1530
1527
|
const end = (b.startTimeMs || 0) + (b.durationMs || 0);
|
|
1531
1528
|
if (nowMs >= (b.startTimeMs || 0) && (b.durationMs ? nowMs < end : true)) {
|
|
@@ -1534,6 +1531,73 @@ var StormcloudVideoPlayer = class {
|
|
|
1534
1531
|
}
|
|
1535
1532
|
return void 0;
|
|
1536
1533
|
}
|
|
1534
|
+
toggleMute() {
|
|
1535
|
+
this.video.muted = !this.video.muted;
|
|
1536
|
+
if (this.config.debugAdTiming) {
|
|
1537
|
+
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
toggleFullscreen() {
|
|
1541
|
+
return new Promise((resolve, reject) => {
|
|
1542
|
+
if (!document.fullscreenElement) {
|
|
1543
|
+
const container = this.video.parentElement;
|
|
1544
|
+
if (!container) {
|
|
1545
|
+
reject(new Error("No parent container found for fullscreen"));
|
|
1546
|
+
return;
|
|
1547
|
+
}
|
|
1548
|
+
container.requestFullscreen().then(() => {
|
|
1549
|
+
if (this.config.debugAdTiming) {
|
|
1550
|
+
console.log("[StormcloudVideoPlayer] Entered fullscreen");
|
|
1551
|
+
}
|
|
1552
|
+
resolve();
|
|
1553
|
+
}).catch((err) => {
|
|
1554
|
+
if (this.config.debugAdTiming) {
|
|
1555
|
+
console.error("[StormcloudVideoPlayer] Fullscreen error:", err);
|
|
1556
|
+
}
|
|
1557
|
+
reject(err);
|
|
1558
|
+
});
|
|
1559
|
+
} else {
|
|
1560
|
+
document.exitFullscreen().then(() => {
|
|
1561
|
+
if (this.config.debugAdTiming) {
|
|
1562
|
+
console.log("[StormcloudVideoPlayer] Exited fullscreen");
|
|
1563
|
+
}
|
|
1564
|
+
resolve();
|
|
1565
|
+
}).catch((err) => {
|
|
1566
|
+
if (this.config.debugAdTiming) {
|
|
1567
|
+
console.error(
|
|
1568
|
+
"[StormcloudVideoPlayer] Exit fullscreen error:",
|
|
1569
|
+
err
|
|
1570
|
+
);
|
|
1571
|
+
}
|
|
1572
|
+
reject(err);
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
isMuted() {
|
|
1578
|
+
return this.video.muted;
|
|
1579
|
+
}
|
|
1580
|
+
isFullscreen() {
|
|
1581
|
+
return !!document.fullscreenElement;
|
|
1582
|
+
}
|
|
1583
|
+
get videoElement() {
|
|
1584
|
+
return this.video;
|
|
1585
|
+
}
|
|
1586
|
+
resize() {
|
|
1587
|
+
if (this.config.debugAdTiming) {
|
|
1588
|
+
console.log("[StormcloudVideoPlayer] Resizing player");
|
|
1589
|
+
}
|
|
1590
|
+
if (this.ima && this.ima.isAdPlaying()) {
|
|
1591
|
+
const width = this.video.clientWidth || 640;
|
|
1592
|
+
const height = this.video.clientHeight || 360;
|
|
1593
|
+
if (this.config.debugAdTiming) {
|
|
1594
|
+
console.log(
|
|
1595
|
+
`[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
this.ima.resize(width, height);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1537
1601
|
destroy() {
|
|
1538
1602
|
this.clearAdStartTimer();
|
|
1539
1603
|
this.clearAdStopTimer();
|
|
@@ -1550,238 +1614,586 @@ var StormcloudVideoPlayer = class {
|
|
|
1550
1614
|
// src/ui/StormcloudVideoPlayer.tsx
|
|
1551
1615
|
var import_react = __toESM(require("react"), 1);
|
|
1552
1616
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1553
|
-
var
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
debugAdTiming,
|
|
1564
|
-
showCustomControls,
|
|
1565
|
-
onVolumeToggle,
|
|
1566
|
-
onFullscreenToggle,
|
|
1567
|
-
onControlClick,
|
|
1568
|
-
onReady,
|
|
1569
|
-
wrapperClassName,
|
|
1570
|
-
wrapperStyle,
|
|
1571
|
-
className,
|
|
1572
|
-
style,
|
|
1573
|
-
controls,
|
|
1574
|
-
playsInline,
|
|
1575
|
-
preload,
|
|
1576
|
-
poster,
|
|
1577
|
-
children,
|
|
1578
|
-
licenseKey,
|
|
1579
|
-
...restVideoAttrs
|
|
1580
|
-
} = props;
|
|
1581
|
-
const videoRef = (0, import_react.useRef)(null);
|
|
1582
|
-
const playerRef = (0, import_react.useRef)(null);
|
|
1583
|
-
const [adStatus, setAdStatus] = import_react.default.useState({ showAds: false, currentIndex: 0, totalAds: 0 });
|
|
1584
|
-
const [shouldShowNativeControls, setShouldShowNativeControls] = import_react.default.useState(true);
|
|
1585
|
-
(0, import_react.useEffect)(() => {
|
|
1586
|
-
if (typeof window === "undefined") return;
|
|
1587
|
-
const el = videoRef.current;
|
|
1588
|
-
if (!el || !src) return;
|
|
1589
|
-
if (playerRef.current) {
|
|
1590
|
-
try {
|
|
1591
|
-
playerRef.current.destroy();
|
|
1592
|
-
} catch {
|
|
1593
|
-
}
|
|
1594
|
-
playerRef.current = null;
|
|
1595
|
-
}
|
|
1596
|
-
const cfg = {
|
|
1617
|
+
var CRITICAL_PROPS = [
|
|
1618
|
+
"src",
|
|
1619
|
+
"allowNativeHls",
|
|
1620
|
+
"licenseKey",
|
|
1621
|
+
"lowLatencyMode",
|
|
1622
|
+
"driftToleranceMs"
|
|
1623
|
+
];
|
|
1624
|
+
var StormcloudVideoPlayerComponent = import_react.default.memo(
|
|
1625
|
+
(props) => {
|
|
1626
|
+
const {
|
|
1597
1627
|
src,
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
+
autoplay,
|
|
1629
|
+
muted,
|
|
1630
|
+
lowLatencyMode,
|
|
1631
|
+
allowNativeHls,
|
|
1632
|
+
driftToleranceMs,
|
|
1633
|
+
immediateManifestAds,
|
|
1634
|
+
debugAdTiming,
|
|
1635
|
+
showCustomControls,
|
|
1636
|
+
onVolumeToggle,
|
|
1637
|
+
onFullscreenToggle,
|
|
1638
|
+
onControlClick,
|
|
1639
|
+
onReady,
|
|
1640
|
+
wrapperClassName,
|
|
1641
|
+
wrapperStyle,
|
|
1642
|
+
className,
|
|
1643
|
+
style,
|
|
1644
|
+
controls,
|
|
1645
|
+
playsInline,
|
|
1646
|
+
preload,
|
|
1647
|
+
poster,
|
|
1648
|
+
children,
|
|
1649
|
+
licenseKey,
|
|
1650
|
+
...restVideoAttrs
|
|
1651
|
+
} = props;
|
|
1652
|
+
const videoRef = (0, import_react.useRef)(null);
|
|
1653
|
+
const playerRef = (0, import_react.useRef)(null);
|
|
1654
|
+
const [adStatus, setAdStatus] = import_react.default.useState({ showAds: false, currentIndex: 0, totalAds: 0 });
|
|
1655
|
+
const [shouldShowNativeControls, setShouldShowNativeControls] = import_react.default.useState(true);
|
|
1656
|
+
const [isMuted, setIsMuted] = import_react.default.useState(false);
|
|
1657
|
+
const [isFullscreen, setIsFullscreen] = import_react.default.useState(false);
|
|
1658
|
+
const criticalPropsKey = (0, import_react.useMemo)(() => {
|
|
1659
|
+
return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join("|");
|
|
1660
|
+
}, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs]);
|
|
1661
|
+
(0, import_react.useEffect)(() => {
|
|
1662
|
+
if (typeof window === "undefined") return;
|
|
1663
|
+
const el = videoRef.current;
|
|
1664
|
+
if (!el || !src) return;
|
|
1665
|
+
if (playerRef.current) {
|
|
1666
|
+
try {
|
|
1667
|
+
playerRef.current.destroy();
|
|
1668
|
+
} catch {
|
|
1669
|
+
}
|
|
1670
|
+
playerRef.current = null;
|
|
1628
1671
|
}
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1672
|
+
const cfg = {
|
|
1673
|
+
src,
|
|
1674
|
+
videoElement: el
|
|
1675
|
+
};
|
|
1676
|
+
if (autoplay !== void 0) cfg.autoplay = autoplay;
|
|
1677
|
+
if (muted !== void 0) cfg.muted = muted;
|
|
1678
|
+
if (lowLatencyMode !== void 0) cfg.lowLatencyMode = lowLatencyMode;
|
|
1679
|
+
if (allowNativeHls !== void 0) cfg.allowNativeHls = allowNativeHls;
|
|
1680
|
+
if (driftToleranceMs !== void 0)
|
|
1681
|
+
cfg.driftToleranceMs = driftToleranceMs;
|
|
1682
|
+
if (immediateManifestAds !== void 0)
|
|
1683
|
+
cfg.immediateManifestAds = immediateManifestAds;
|
|
1684
|
+
if (debugAdTiming !== void 0) cfg.debugAdTiming = debugAdTiming;
|
|
1685
|
+
if (showCustomControls !== void 0)
|
|
1686
|
+
cfg.showCustomControls = showCustomControls;
|
|
1687
|
+
if (onVolumeToggle !== void 0) cfg.onVolumeToggle = onVolumeToggle;
|
|
1688
|
+
if (onFullscreenToggle !== void 0)
|
|
1689
|
+
cfg.onFullscreenToggle = onFullscreenToggle;
|
|
1690
|
+
if (onControlClick !== void 0) cfg.onControlClick = onControlClick;
|
|
1691
|
+
if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
|
|
1692
|
+
const player = new StormcloudVideoPlayer(cfg);
|
|
1693
|
+
playerRef.current = player;
|
|
1694
|
+
player.load().then(() => {
|
|
1695
|
+
const showNative = player.shouldShowNativeControls();
|
|
1696
|
+
setShouldShowNativeControls(showNative);
|
|
1697
|
+
onReady?.(player);
|
|
1698
|
+
}).catch(() => {
|
|
1699
|
+
});
|
|
1700
|
+
return () => {
|
|
1701
|
+
try {
|
|
1702
|
+
player.destroy();
|
|
1703
|
+
} catch {
|
|
1704
|
+
}
|
|
1705
|
+
playerRef.current = null;
|
|
1706
|
+
};
|
|
1707
|
+
}, [criticalPropsKey]);
|
|
1708
|
+
(0, import_react.useEffect)(() => {
|
|
1709
|
+
if (!playerRef.current) return;
|
|
1650
1710
|
try {
|
|
1651
|
-
playerRef.current.
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
if (playerRef.current) {
|
|
1660
|
-
const showAds = playerRef.current.isShowingAds();
|
|
1661
|
-
const currentIndex = playerRef.current.getCurrentAdIndex();
|
|
1662
|
-
const totalAds = playerRef.current.getTotalAdsInBreak();
|
|
1663
|
-
setAdStatus((prev) => {
|
|
1664
|
-
if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {
|
|
1665
|
-
return { showAds, currentIndex, totalAds };
|
|
1666
|
-
}
|
|
1667
|
-
return prev;
|
|
1668
|
-
});
|
|
1711
|
+
if (autoplay !== void 0 && playerRef.current.videoElement) {
|
|
1712
|
+
playerRef.current.videoElement.autoplay = autoplay;
|
|
1713
|
+
}
|
|
1714
|
+
if (muted !== void 0 && playerRef.current.videoElement) {
|
|
1715
|
+
playerRef.current.videoElement.muted = muted;
|
|
1716
|
+
}
|
|
1717
|
+
} catch (error) {
|
|
1718
|
+
console.warn("Failed to update player properties:", error);
|
|
1669
1719
|
}
|
|
1670
|
-
};
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
"video",
|
|
1682
|
-
{
|
|
1683
|
-
ref: videoRef,
|
|
1684
|
-
className,
|
|
1685
|
-
style: { display: "block", width: "100%", height: "100%", ...style },
|
|
1686
|
-
controls: shouldShowNativeControls && controls,
|
|
1687
|
-
playsInline,
|
|
1688
|
-
preload,
|
|
1689
|
-
poster,
|
|
1690
|
-
...restVideoAttrs,
|
|
1691
|
-
children
|
|
1692
|
-
}
|
|
1693
|
-
),
|
|
1694
|
-
adStatus.showAds && adStatus.totalAds > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1695
|
-
"div",
|
|
1696
|
-
{
|
|
1697
|
-
style: {
|
|
1698
|
-
position: "absolute",
|
|
1699
|
-
top: "10px",
|
|
1700
|
-
right: "10px",
|
|
1701
|
-
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
1702
|
-
color: "white",
|
|
1703
|
-
padding: "4px 8px",
|
|
1704
|
-
borderRadius: "4px",
|
|
1705
|
-
fontSize: "12px",
|
|
1706
|
-
fontFamily: "Arial, sans-serif",
|
|
1707
|
-
zIndex: 10
|
|
1708
|
-
},
|
|
1709
|
-
children: [
|
|
1710
|
-
"Ad ",
|
|
1711
|
-
adStatus.currentIndex,
|
|
1712
|
-
"/",
|
|
1713
|
-
adStatus.totalAds
|
|
1714
|
-
]
|
|
1715
|
-
}
|
|
1716
|
-
),
|
|
1717
|
-
!shouldShowNativeControls && showCustomControls && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1718
|
-
"div",
|
|
1719
|
-
{
|
|
1720
|
-
style: {
|
|
1721
|
-
position: "absolute",
|
|
1722
|
-
bottom: "10px",
|
|
1723
|
-
right: "10px",
|
|
1724
|
-
display: "flex",
|
|
1725
|
-
gap: "8px",
|
|
1726
|
-
zIndex: 10
|
|
1727
|
-
},
|
|
1728
|
-
children: [
|
|
1729
|
-
onVolumeToggle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1730
|
-
"button",
|
|
1731
|
-
{
|
|
1732
|
-
onClick: onVolumeToggle,
|
|
1733
|
-
style: {
|
|
1734
|
-
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
1735
|
-
color: "white",
|
|
1736
|
-
border: "1px solid rgba(255, 255, 255, 0.3)",
|
|
1737
|
-
borderRadius: "4px",
|
|
1738
|
-
padding: "8px",
|
|
1739
|
-
cursor: "pointer",
|
|
1740
|
-
fontSize: "14px"
|
|
1741
|
-
},
|
|
1742
|
-
title: "Toggle Volume",
|
|
1743
|
-
children: "\u{1F50A}"
|
|
1744
|
-
}
|
|
1745
|
-
),
|
|
1746
|
-
onFullscreenToggle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1747
|
-
"button",
|
|
1748
|
-
{
|
|
1749
|
-
onClick: onFullscreenToggle,
|
|
1750
|
-
style: {
|
|
1751
|
-
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
1752
|
-
color: "white",
|
|
1753
|
-
border: "1px solid rgba(255, 255, 255, 0.3)",
|
|
1754
|
-
borderRadius: "4px",
|
|
1755
|
-
padding: "8px",
|
|
1756
|
-
cursor: "pointer",
|
|
1757
|
-
fontSize: "14px"
|
|
1758
|
-
},
|
|
1759
|
-
title: "Toggle Fullscreen",
|
|
1760
|
-
children: "\u2922"
|
|
1761
|
-
}
|
|
1762
|
-
)
|
|
1763
|
-
]
|
|
1764
|
-
}
|
|
1765
|
-
),
|
|
1766
|
-
onControlClick && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1767
|
-
"div",
|
|
1768
|
-
{
|
|
1769
|
-
onClick: onControlClick,
|
|
1770
|
-
style: {
|
|
1771
|
-
position: "absolute",
|
|
1772
|
-
top: 0,
|
|
1773
|
-
left: 0,
|
|
1774
|
-
right: 0,
|
|
1775
|
-
bottom: 0,
|
|
1776
|
-
zIndex: 1,
|
|
1777
|
-
cursor: "pointer"
|
|
1720
|
+
}, [autoplay, muted]);
|
|
1721
|
+
(0, import_react.useEffect)(() => {
|
|
1722
|
+
if (!playerRef.current) return;
|
|
1723
|
+
const checkAdStatus = () => {
|
|
1724
|
+
if (playerRef.current) {
|
|
1725
|
+
const showAds = playerRef.current.isShowingAds();
|
|
1726
|
+
const currentIndex = playerRef.current.getCurrentAdIndex();
|
|
1727
|
+
const totalAds = playerRef.current.getTotalAdsInBreak();
|
|
1728
|
+
setAdStatus((prev) => {
|
|
1729
|
+
if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {
|
|
1730
|
+
return { showAds, currentIndex, totalAds };
|
|
1778
1731
|
}
|
|
1732
|
+
return prev;
|
|
1733
|
+
});
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1736
|
+
const interval = setInterval(checkAdStatus, 500);
|
|
1737
|
+
return () => clearInterval(interval);
|
|
1738
|
+
}, []);
|
|
1739
|
+
(0, import_react.useEffect)(() => {
|
|
1740
|
+
if (typeof window === "undefined" || !playerRef.current) return;
|
|
1741
|
+
const handleResize = () => {
|
|
1742
|
+
if (playerRef.current && videoRef.current) {
|
|
1743
|
+
if (typeof playerRef.current.resize === "function") {
|
|
1744
|
+
playerRef.current.resize();
|
|
1779
1745
|
}
|
|
1780
|
-
|
|
1781
|
-
|
|
1746
|
+
}
|
|
1747
|
+
};
|
|
1748
|
+
window.addEventListener("resize", handleResize);
|
|
1749
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
1750
|
+
}, []);
|
|
1751
|
+
(0, import_react.useEffect)(() => {
|
|
1752
|
+
if (!playerRef.current || !videoRef.current) return;
|
|
1753
|
+
const updateStates = () => {
|
|
1754
|
+
if (videoRef.current) {
|
|
1755
|
+
setIsMuted(videoRef.current.muted);
|
|
1756
|
+
}
|
|
1757
|
+
setIsFullscreen(
|
|
1758
|
+
document.fullscreenElement === videoRef.current?.parentElement
|
|
1759
|
+
);
|
|
1760
|
+
};
|
|
1761
|
+
const interval = setInterval(updateStates, 200);
|
|
1762
|
+
const handleFullscreenChange = () => {
|
|
1763
|
+
setIsFullscreen(
|
|
1764
|
+
document.fullscreenElement === videoRef.current?.parentElement
|
|
1765
|
+
);
|
|
1766
|
+
};
|
|
1767
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
1768
|
+
return () => {
|
|
1769
|
+
clearInterval(interval);
|
|
1770
|
+
document.removeEventListener(
|
|
1771
|
+
"fullscreenchange",
|
|
1772
|
+
handleFullscreenChange
|
|
1773
|
+
);
|
|
1774
|
+
};
|
|
1775
|
+
}, []);
|
|
1776
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1777
|
+
"div",
|
|
1778
|
+
{
|
|
1779
|
+
className: wrapperClassName,
|
|
1780
|
+
style: {
|
|
1781
|
+
display: "flex",
|
|
1782
|
+
alignItems: "center",
|
|
1783
|
+
justifyContent: "center",
|
|
1784
|
+
position: isFullscreen ? "fixed" : "relative",
|
|
1785
|
+
top: isFullscreen ? 0 : void 0,
|
|
1786
|
+
left: isFullscreen ? 0 : void 0,
|
|
1787
|
+
overflow: "hidden",
|
|
1788
|
+
width: isFullscreen ? "100vw" : "100%",
|
|
1789
|
+
height: isFullscreen ? "100vh" : "100%",
|
|
1790
|
+
maxWidth: isFullscreen ? "100vw" : "100%",
|
|
1791
|
+
maxHeight: isFullscreen ? "100vh" : "100%",
|
|
1792
|
+
zIndex: isFullscreen ? 9999 : void 0,
|
|
1793
|
+
backgroundColor: isFullscreen ? "#000" : void 0,
|
|
1794
|
+
...wrapperStyle
|
|
1795
|
+
},
|
|
1796
|
+
children: [
|
|
1797
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1798
|
+
"video",
|
|
1799
|
+
{
|
|
1800
|
+
ref: videoRef,
|
|
1801
|
+
className,
|
|
1802
|
+
style: {
|
|
1803
|
+
display: "block",
|
|
1804
|
+
width: "100%",
|
|
1805
|
+
height: "100%",
|
|
1806
|
+
objectFit: isFullscreen ? "cover" : "contain",
|
|
1807
|
+
backgroundColor: "#000",
|
|
1808
|
+
...style
|
|
1809
|
+
},
|
|
1810
|
+
controls: shouldShowNativeControls && controls && !showCustomControls,
|
|
1811
|
+
playsInline,
|
|
1812
|
+
preload,
|
|
1813
|
+
poster,
|
|
1814
|
+
...restVideoAttrs,
|
|
1815
|
+
children
|
|
1816
|
+
}
|
|
1817
|
+
),
|
|
1818
|
+
adStatus.showAds && adStatus.totalAds > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1819
|
+
"div",
|
|
1820
|
+
{
|
|
1821
|
+
style: {
|
|
1822
|
+
position: "absolute",
|
|
1823
|
+
top: "10px",
|
|
1824
|
+
right: "10px",
|
|
1825
|
+
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
1826
|
+
color: "white",
|
|
1827
|
+
padding: "4px 8px",
|
|
1828
|
+
borderRadius: "4px",
|
|
1829
|
+
fontSize: "12px",
|
|
1830
|
+
fontFamily: "Arial, sans-serif",
|
|
1831
|
+
zIndex: 10
|
|
1832
|
+
},
|
|
1833
|
+
children: [
|
|
1834
|
+
"Ad ",
|
|
1835
|
+
adStatus.currentIndex,
|
|
1836
|
+
"/",
|
|
1837
|
+
adStatus.totalAds
|
|
1838
|
+
]
|
|
1839
|
+
}
|
|
1840
|
+
),
|
|
1841
|
+
showCustomControls && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1842
|
+
"div",
|
|
1843
|
+
{
|
|
1844
|
+
style: {
|
|
1845
|
+
position: "absolute",
|
|
1846
|
+
bottom: "10px",
|
|
1847
|
+
right: "10px",
|
|
1848
|
+
display: "flex",
|
|
1849
|
+
gap: "8px",
|
|
1850
|
+
zIndex: 10
|
|
1851
|
+
},
|
|
1852
|
+
children: [
|
|
1853
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1854
|
+
"button",
|
|
1855
|
+
{
|
|
1856
|
+
onClick: () => {
|
|
1857
|
+
if (onVolumeToggle) {
|
|
1858
|
+
onVolumeToggle();
|
|
1859
|
+
} else if (playerRef.current) {
|
|
1860
|
+
playerRef.current.toggleMute();
|
|
1861
|
+
}
|
|
1862
|
+
},
|
|
1863
|
+
onMouseEnter: (e) => {
|
|
1864
|
+
const target = e.currentTarget;
|
|
1865
|
+
target.style.transform = "translateY(-2px) scale(1.05)";
|
|
1866
|
+
target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
|
|
1867
|
+
target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
|
|
1868
|
+
},
|
|
1869
|
+
onMouseLeave: (e) => {
|
|
1870
|
+
const target = e.currentTarget;
|
|
1871
|
+
target.style.transform = "translateY(0) scale(1)";
|
|
1872
|
+
target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
|
|
1873
|
+
target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
|
|
1874
|
+
},
|
|
1875
|
+
style: {
|
|
1876
|
+
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
|
|
1877
|
+
color: "white",
|
|
1878
|
+
border: "1px solid rgba(255, 255, 255, 0.2)",
|
|
1879
|
+
borderRadius: "8px",
|
|
1880
|
+
padding: "10px",
|
|
1881
|
+
cursor: "pointer",
|
|
1882
|
+
display: "flex",
|
|
1883
|
+
alignItems: "center",
|
|
1884
|
+
justifyContent: "center",
|
|
1885
|
+
backdropFilter: "blur(10px)",
|
|
1886
|
+
boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
|
|
1887
|
+
transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
|
|
1888
|
+
},
|
|
1889
|
+
title: isMuted ? "Unmute" : "Mute",
|
|
1890
|
+
children: isMuted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1891
|
+
"svg",
|
|
1892
|
+
{
|
|
1893
|
+
width: "18",
|
|
1894
|
+
height: "18",
|
|
1895
|
+
viewBox: "0 0 24 24",
|
|
1896
|
+
fill: "none",
|
|
1897
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1898
|
+
children: [
|
|
1899
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1900
|
+
"linearGradient",
|
|
1901
|
+
{
|
|
1902
|
+
id: "volumeGradient",
|
|
1903
|
+
x1: "0%",
|
|
1904
|
+
y1: "0%",
|
|
1905
|
+
x2: "100%",
|
|
1906
|
+
y2: "100%",
|
|
1907
|
+
children: [
|
|
1908
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: "1" }),
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1910
|
+
"stop",
|
|
1911
|
+
{
|
|
1912
|
+
offset: "100%",
|
|
1913
|
+
stopColor: "#e0e0e0",
|
|
1914
|
+
stopOpacity: "0.9"
|
|
1915
|
+
}
|
|
1916
|
+
)
|
|
1917
|
+
]
|
|
1918
|
+
}
|
|
1919
|
+
) }),
|
|
1920
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1921
|
+
"path",
|
|
1922
|
+
{
|
|
1923
|
+
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",
|
|
1924
|
+
fill: "url(#volumeGradient)",
|
|
1925
|
+
stroke: "rgba(255,255,255,0.3)",
|
|
1926
|
+
strokeWidth: "0.5"
|
|
1927
|
+
}
|
|
1928
|
+
),
|
|
1929
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1930
|
+
"path",
|
|
1931
|
+
{
|
|
1932
|
+
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",
|
|
1933
|
+
fill: "#ff4444",
|
|
1934
|
+
stroke: "rgba(255,255,255,0.5)",
|
|
1935
|
+
strokeWidth: "0.5"
|
|
1936
|
+
}
|
|
1937
|
+
)
|
|
1938
|
+
]
|
|
1939
|
+
}
|
|
1940
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1941
|
+
"svg",
|
|
1942
|
+
{
|
|
1943
|
+
width: "18",
|
|
1944
|
+
height: "18",
|
|
1945
|
+
viewBox: "0 0 24 24",
|
|
1946
|
+
fill: "none",
|
|
1947
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1948
|
+
children: [
|
|
1949
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1950
|
+
"linearGradient",
|
|
1951
|
+
{
|
|
1952
|
+
id: "volumeGradient",
|
|
1953
|
+
x1: "0%",
|
|
1954
|
+
y1: "0%",
|
|
1955
|
+
x2: "100%",
|
|
1956
|
+
y2: "100%",
|
|
1957
|
+
children: [
|
|
1958
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: "1" }),
|
|
1959
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1960
|
+
"stop",
|
|
1961
|
+
{
|
|
1962
|
+
offset: "100%",
|
|
1963
|
+
stopColor: "#e0e0e0",
|
|
1964
|
+
stopOpacity: "0.9"
|
|
1965
|
+
}
|
|
1966
|
+
)
|
|
1967
|
+
]
|
|
1968
|
+
}
|
|
1969
|
+
) }),
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1971
|
+
"path",
|
|
1972
|
+
{
|
|
1973
|
+
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",
|
|
1974
|
+
fill: "url(#volumeGradient)",
|
|
1975
|
+
stroke: "rgba(255,255,255,0.3)",
|
|
1976
|
+
strokeWidth: "0.5"
|
|
1977
|
+
}
|
|
1978
|
+
),
|
|
1979
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1980
|
+
"path",
|
|
1981
|
+
{
|
|
1982
|
+
d: "M15.5 12c0-1.33-.58-2.53-1.5-3.35v6.69c.92-.81 1.5-2.01 1.5-3.34z",
|
|
1983
|
+
fill: "url(#volumeGradient)",
|
|
1984
|
+
opacity: "0.8"
|
|
1985
|
+
}
|
|
1986
|
+
),
|
|
1987
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1988
|
+
"path",
|
|
1989
|
+
{
|
|
1990
|
+
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",
|
|
1991
|
+
fill: "url(#volumeGradient)",
|
|
1992
|
+
opacity: "0.6"
|
|
1993
|
+
}
|
|
1994
|
+
)
|
|
1995
|
+
]
|
|
1996
|
+
}
|
|
1997
|
+
)
|
|
1998
|
+
}
|
|
1999
|
+
),
|
|
2000
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2001
|
+
"button",
|
|
2002
|
+
{
|
|
2003
|
+
onClick: () => {
|
|
2004
|
+
if (onFullscreenToggle) {
|
|
2005
|
+
onFullscreenToggle();
|
|
2006
|
+
} else if (playerRef.current) {
|
|
2007
|
+
playerRef.current.toggleFullscreen().catch((err) => {
|
|
2008
|
+
console.error("Fullscreen error:", err);
|
|
2009
|
+
});
|
|
2010
|
+
}
|
|
2011
|
+
},
|
|
2012
|
+
onMouseEnter: (e) => {
|
|
2013
|
+
const target = e.currentTarget;
|
|
2014
|
+
target.style.transform = "translateY(-2px) scale(1.05)";
|
|
2015
|
+
target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
|
|
2016
|
+
target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
|
|
2017
|
+
},
|
|
2018
|
+
onMouseLeave: (e) => {
|
|
2019
|
+
const target = e.currentTarget;
|
|
2020
|
+
target.style.transform = "translateY(0) scale(1)";
|
|
2021
|
+
target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
|
|
2022
|
+
target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
|
|
2023
|
+
},
|
|
2024
|
+
style: {
|
|
2025
|
+
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
|
|
2026
|
+
color: "white",
|
|
2027
|
+
border: "1px solid rgba(255, 255, 255, 0.2)",
|
|
2028
|
+
borderRadius: "8px",
|
|
2029
|
+
padding: "10px",
|
|
2030
|
+
cursor: "pointer",
|
|
2031
|
+
display: "flex",
|
|
2032
|
+
alignItems: "center",
|
|
2033
|
+
justifyContent: "center",
|
|
2034
|
+
backdropFilter: "blur(10px)",
|
|
2035
|
+
boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
|
|
2036
|
+
transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
|
|
2037
|
+
},
|
|
2038
|
+
title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
|
|
2039
|
+
children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2040
|
+
"svg",
|
|
2041
|
+
{
|
|
2042
|
+
width: "20",
|
|
2043
|
+
height: "20",
|
|
2044
|
+
viewBox: "0 0 24 24",
|
|
2045
|
+
fill: "none",
|
|
2046
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2047
|
+
children: [
|
|
2048
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2049
|
+
"path",
|
|
2050
|
+
{
|
|
2051
|
+
d: "M8 8h3v3l-1-1-2 2-1.5-1.5L8.5 8.5 8 8z",
|
|
2052
|
+
fill: "white",
|
|
2053
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2054
|
+
strokeWidth: "0.5"
|
|
2055
|
+
}
|
|
2056
|
+
),
|
|
2057
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2058
|
+
"path",
|
|
2059
|
+
{
|
|
2060
|
+
d: "M16 8h-3v3l1-1 2 2 1.5-1.5L15.5 8.5 16 8z",
|
|
2061
|
+
fill: "white",
|
|
2062
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2063
|
+
strokeWidth: "0.5"
|
|
2064
|
+
}
|
|
2065
|
+
),
|
|
2066
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2067
|
+
"path",
|
|
2068
|
+
{
|
|
2069
|
+
d: "M8 16h3v-3l-1 1-2-2-1.5 1.5L8.5 15.5 8 16z",
|
|
2070
|
+
fill: "white",
|
|
2071
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2072
|
+
strokeWidth: "0.5"
|
|
2073
|
+
}
|
|
2074
|
+
),
|
|
2075
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2076
|
+
"path",
|
|
2077
|
+
{
|
|
2078
|
+
d: "M16 16h-3v-3l1 1 2-2 1.5 1.5L15.5 15.5 16 16z",
|
|
2079
|
+
fill: "white",
|
|
2080
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2081
|
+
strokeWidth: "0.5"
|
|
2082
|
+
}
|
|
2083
|
+
)
|
|
2084
|
+
]
|
|
2085
|
+
}
|
|
2086
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2087
|
+
"svg",
|
|
2088
|
+
{
|
|
2089
|
+
width: "20",
|
|
2090
|
+
height: "20",
|
|
2091
|
+
viewBox: "0 0 24 24",
|
|
2092
|
+
fill: "none",
|
|
2093
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2094
|
+
children: [
|
|
2095
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2096
|
+
"path",
|
|
2097
|
+
{
|
|
2098
|
+
d: "M3 3h6v2H5v4H3V3z",
|
|
2099
|
+
fill: "white",
|
|
2100
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2101
|
+
strokeWidth: "0.5"
|
|
2102
|
+
}
|
|
2103
|
+
),
|
|
2104
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2105
|
+
"path",
|
|
2106
|
+
{
|
|
2107
|
+
d: "M21 3h-6v2h4v4h2V3z",
|
|
2108
|
+
fill: "white",
|
|
2109
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2110
|
+
strokeWidth: "0.5"
|
|
2111
|
+
}
|
|
2112
|
+
),
|
|
2113
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2114
|
+
"path",
|
|
2115
|
+
{
|
|
2116
|
+
d: "M3 21v-6h2v4h4v2H3z",
|
|
2117
|
+
fill: "white",
|
|
2118
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2119
|
+
strokeWidth: "0.5"
|
|
2120
|
+
}
|
|
2121
|
+
),
|
|
2122
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2123
|
+
"path",
|
|
2124
|
+
{
|
|
2125
|
+
d: "M21 21h-6v-2h4v-4h2v6z",
|
|
2126
|
+
fill: "white",
|
|
2127
|
+
stroke: "rgba(255,255,255,0.8)",
|
|
2128
|
+
strokeWidth: "0.5"
|
|
2129
|
+
}
|
|
2130
|
+
)
|
|
2131
|
+
]
|
|
2132
|
+
}
|
|
2133
|
+
)
|
|
2134
|
+
}
|
|
2135
|
+
)
|
|
2136
|
+
]
|
|
2137
|
+
}
|
|
2138
|
+
),
|
|
2139
|
+
onControlClick && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2140
|
+
"div",
|
|
2141
|
+
{
|
|
2142
|
+
onClick: onControlClick,
|
|
2143
|
+
style: {
|
|
2144
|
+
position: "absolute",
|
|
2145
|
+
top: 0,
|
|
2146
|
+
left: 0,
|
|
2147
|
+
right: 0,
|
|
2148
|
+
bottom: 0,
|
|
2149
|
+
zIndex: 1,
|
|
2150
|
+
cursor: "pointer"
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
)
|
|
2154
|
+
]
|
|
2155
|
+
}
|
|
2156
|
+
);
|
|
2157
|
+
},
|
|
2158
|
+
(prevProps, nextProps) => {
|
|
2159
|
+
for (const prop of CRITICAL_PROPS) {
|
|
2160
|
+
if (prevProps[prop] !== nextProps[prop]) {
|
|
2161
|
+
return false;
|
|
2162
|
+
}
|
|
1782
2163
|
}
|
|
1783
|
-
|
|
1784
|
-
|
|
2164
|
+
const uiProps = [
|
|
2165
|
+
"autoplay",
|
|
2166
|
+
"muted",
|
|
2167
|
+
"controls",
|
|
2168
|
+
"showCustomControls",
|
|
2169
|
+
"className",
|
|
2170
|
+
"style",
|
|
2171
|
+
"wrapperClassName",
|
|
2172
|
+
"wrapperStyle",
|
|
2173
|
+
"playsInline",
|
|
2174
|
+
"preload",
|
|
2175
|
+
"poster",
|
|
2176
|
+
"children"
|
|
2177
|
+
];
|
|
2178
|
+
for (const prop of uiProps) {
|
|
2179
|
+
if (prevProps[prop] !== nextProps[prop]) {
|
|
2180
|
+
return false;
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
const callbackProps = [
|
|
2184
|
+
"onReady",
|
|
2185
|
+
"onVolumeToggle",
|
|
2186
|
+
"onFullscreenToggle",
|
|
2187
|
+
"onControlClick"
|
|
2188
|
+
];
|
|
2189
|
+
for (const prop of callbackProps) {
|
|
2190
|
+
if (prevProps[prop] !== nextProps[prop]) {
|
|
2191
|
+
return false;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
return true;
|
|
2195
|
+
}
|
|
2196
|
+
);
|
|
1785
2197
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1786
2198
|
0 && (module.exports = {
|
|
1787
2199
|
StormcloudVideoPlayer,
|