@nikelroot/video-player 0.2.3 → 0.2.4
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 +1 -1
- package/dist/index.cjs +54 -8
- package/dist/index.js +54 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ export function Example() {
|
|
|
37
37
|
}
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
When `active` is `true`, pressing `F` toggles fullscreen.
|
|
40
|
+
When `active` is `true`, pressing `F` toggles fullscreen. When `active` is `false`, the player releases native media loading so inactive MP4 players do not keep network requests open.
|
|
41
41
|
|
|
42
42
|
For public CDN-hosted videos, prefer non-credentialed requests unless the CDN is explicitly configured for cookies:
|
|
43
43
|
|
package/dist/index.cjs
CHANGED
|
@@ -725,6 +725,7 @@ var LIVE_STALL_WINDOW_MS = 2e4;
|
|
|
725
725
|
var LIVE_STALLS_BEFORE_STABILITY = 3;
|
|
726
726
|
var hlsCtorPromise = null;
|
|
727
727
|
var activeExclusiveVideo = null;
|
|
728
|
+
var exclusiveMediaReleasers = /* @__PURE__ */ new WeakMap();
|
|
728
729
|
var loadHlsCtor = () => {
|
|
729
730
|
if (!hlsCtorPromise) {
|
|
730
731
|
hlsCtorPromise = import("hls.js").then((mod) => mod.default);
|
|
@@ -738,6 +739,9 @@ var isInterruptedPlayRequestError = (error) => {
|
|
|
738
739
|
var canAttemptPlayback = (video) => {
|
|
739
740
|
return !!video && video.readyState >= HTMLMediaElement.HAVE_METADATA;
|
|
740
741
|
};
|
|
742
|
+
var isVideoSourceAttached = (video) => {
|
|
743
|
+
return !!video.currentSrc || !!video.getAttribute("src");
|
|
744
|
+
};
|
|
741
745
|
function hasNativeHlsSupport() {
|
|
742
746
|
if (typeof navigator === "undefined" || typeof document === "undefined") return false;
|
|
743
747
|
const isSafari = /^((?!chrome|android|firefox|opera|edg).)*safari/i.test(navigator.userAgent);
|
|
@@ -854,6 +858,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
854
858
|
const liveStallEvents = (0, import_react3.useRef)([]);
|
|
855
859
|
const controlTime = (0, import_react3.useRef)(null);
|
|
856
860
|
const sourceLoadId = (0, import_react3.useRef)(0);
|
|
861
|
+
const sourceLoadMode = (0, import_react3.useRef)("native");
|
|
857
862
|
const [playingState, setPlayingState] = (0, import_react3.useState)(!!defaultPlaying);
|
|
858
863
|
const [mutedState, setMutedState] = (0, import_react3.useState)(!!defaultMuted);
|
|
859
864
|
const [durationState, setDurationState] = (0, import_react3.useState)(0);
|
|
@@ -909,6 +914,20 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
909
914
|
video.removeAttribute("src");
|
|
910
915
|
video.load();
|
|
911
916
|
}, [clearTimers]);
|
|
917
|
+
const releaseNativeMedia = (0, import_react3.useCallback)(() => {
|
|
918
|
+
const video = videoRef.current;
|
|
919
|
+
if (!video) return;
|
|
920
|
+
video.pause();
|
|
921
|
+
if (sourceLoadMode.current !== "native" || !isVideoSourceAttached(video)) return;
|
|
922
|
+
video.removeAttribute("src");
|
|
923
|
+
video.load();
|
|
924
|
+
}, []);
|
|
925
|
+
const ensureNativeMediaAttached = (0, import_react3.useCallback)(() => {
|
|
926
|
+
const video = videoRef.current;
|
|
927
|
+
if (!video || sourceLoadMode.current !== "native" || isVideoSourceAttached(video)) return;
|
|
928
|
+
video.src = videoSrc;
|
|
929
|
+
if (initialTime > 0) video.currentTime = initialTime;
|
|
930
|
+
}, [initialTime, videoSrc]);
|
|
912
931
|
const setNextPlaying = (0, import_react3.useCallback)(
|
|
913
932
|
(value) => {
|
|
914
933
|
if (playingProp === void 0) setPlayingState(value);
|
|
@@ -974,6 +993,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
974
993
|
if (prev) {
|
|
975
994
|
prev.removeEventListener("timeupdate", onTime);
|
|
976
995
|
prev.removeEventListener("durationchange", onDur);
|
|
996
|
+
exclusiveMediaReleasers.delete(prev);
|
|
977
997
|
}
|
|
978
998
|
videoRef.current = el;
|
|
979
999
|
assignRef(externalVideoRef, el);
|
|
@@ -983,8 +1003,9 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
983
1003
|
el.muted = muted;
|
|
984
1004
|
el.addEventListener("timeupdate", onTime);
|
|
985
1005
|
el.addEventListener("durationchange", onDur);
|
|
1006
|
+
exclusiveMediaReleasers.set(el, releaseNativeMedia);
|
|
986
1007
|
},
|
|
987
|
-
[externalVideoRef, muted, notifyActiveChange, onDur, onTime, onVideoRefChange]
|
|
1008
|
+
[externalVideoRef, muted, notifyActiveChange, onDur, onTime, onVideoRefChange, releaseNativeMedia]
|
|
988
1009
|
);
|
|
989
1010
|
const pauseOtherVideos = (0, import_react3.useCallback)(
|
|
990
1011
|
(el) => {
|
|
@@ -993,8 +1014,10 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
993
1014
|
exclusivePlayback.pauseOthers(el);
|
|
994
1015
|
return;
|
|
995
1016
|
}
|
|
996
|
-
if (activeExclusiveVideo && activeExclusiveVideo !== el
|
|
997
|
-
|
|
1017
|
+
if (activeExclusiveVideo && activeExclusiveVideo !== el) {
|
|
1018
|
+
const releasePrevious = exclusiveMediaReleasers.get(activeExclusiveVideo);
|
|
1019
|
+
if (releasePrevious) releasePrevious();
|
|
1020
|
+
else activeExclusiveVideo.pause();
|
|
998
1021
|
}
|
|
999
1022
|
activeExclusiveVideo = el;
|
|
1000
1023
|
},
|
|
@@ -1004,6 +1027,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1004
1027
|
const el = videoRef.current;
|
|
1005
1028
|
if (!el) return;
|
|
1006
1029
|
pauseOtherVideos(el);
|
|
1030
|
+
ensureNativeMediaAttached();
|
|
1007
1031
|
try {
|
|
1008
1032
|
await el.play();
|
|
1009
1033
|
clearErrorState();
|
|
@@ -1025,7 +1049,16 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1025
1049
|
});
|
|
1026
1050
|
}
|
|
1027
1051
|
}
|
|
1028
|
-
}, [
|
|
1052
|
+
}, [
|
|
1053
|
+
clearErrorState,
|
|
1054
|
+
ensureNativeMediaAttached,
|
|
1055
|
+
messages.playFailed,
|
|
1056
|
+
notifyActiveChange,
|
|
1057
|
+
pauseOtherVideos,
|
|
1058
|
+
reportError,
|
|
1059
|
+
scrollTo,
|
|
1060
|
+
setNextPlaying
|
|
1061
|
+
]);
|
|
1029
1062
|
const pauseAction = (0, import_react3.useCallback)(() => {
|
|
1030
1063
|
const el = videoRef.current;
|
|
1031
1064
|
if (!el) return;
|
|
@@ -1103,6 +1136,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1103
1136
|
async (startAt = initialTime, loadId = sourceLoadId.current) => {
|
|
1104
1137
|
const startVideoRef = videoRef.current;
|
|
1105
1138
|
if (!startVideoRef) return;
|
|
1139
|
+
sourceLoadMode.current = "hls";
|
|
1106
1140
|
let HlsCtor;
|
|
1107
1141
|
try {
|
|
1108
1142
|
HlsCtor = await loadHlsCtor();
|
|
@@ -1245,6 +1279,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1245
1279
|
if (loadId !== sourceLoadId.current) return;
|
|
1246
1280
|
const video = videoRef.current;
|
|
1247
1281
|
if (!video) return;
|
|
1282
|
+
sourceLoadMode.current = "native";
|
|
1248
1283
|
video.src = videoSrc;
|
|
1249
1284
|
video.currentTime = initialTime;
|
|
1250
1285
|
if (autoPlay) void playAction();
|
|
@@ -1252,6 +1287,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1252
1287
|
const loadVideoHls = (0, import_react3.useCallback)(async (loadId = sourceLoadId.current) => {
|
|
1253
1288
|
const video = videoRef.current;
|
|
1254
1289
|
const canNativeHls = !!(video == null ? void 0 : video.canPlayType) && video.canPlayType("application/vnd.apple.mpegurl") !== "";
|
|
1290
|
+
sourceLoadMode.current = "hls";
|
|
1255
1291
|
let HlsCtor;
|
|
1256
1292
|
try {
|
|
1257
1293
|
HlsCtor = await loadHlsCtor();
|
|
@@ -1387,6 +1423,10 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1387
1423
|
if (playingProp) void playAction();
|
|
1388
1424
|
else pauseAction();
|
|
1389
1425
|
}, [pauseAction, playAction, playingProp]);
|
|
1426
|
+
(0, import_react3.useEffect)(() => {
|
|
1427
|
+
if (active !== false) return;
|
|
1428
|
+
releaseNativeMedia();
|
|
1429
|
+
}, [active, releaseNativeMedia]);
|
|
1390
1430
|
(0, import_react3.useEffect)(() => {
|
|
1391
1431
|
if (!videoRef.current) return;
|
|
1392
1432
|
const loadId = sourceLoadId.current + 1;
|
|
@@ -1398,16 +1438,22 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1398
1438
|
liveStabilityMode.current = false;
|
|
1399
1439
|
liveStallEvents.current = [];
|
|
1400
1440
|
resetMediaForSourceChange();
|
|
1401
|
-
if (
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1441
|
+
if (active === false) return;
|
|
1442
|
+
const nextSourceLoadMode = sourceType === "hls" || sourceType !== "native" && type !== "video" && isLikelyHlsSource(videoSrc) ? "hls" : "native";
|
|
1443
|
+
sourceLoadMode.current = nextSourceLoadMode;
|
|
1444
|
+
if (nextSourceLoadMode === "hls") {
|
|
1445
|
+
if (sourceType === "hls") void loadVideo(initialTime, loadId);
|
|
1446
|
+
else void loadVideoHls(loadId);
|
|
1447
|
+
} else {
|
|
1448
|
+
loadVideoNative(loadId);
|
|
1449
|
+
}
|
|
1405
1450
|
return () => {
|
|
1406
1451
|
sourceLoadId.current += 1;
|
|
1407
1452
|
resetMediaForSourceChange();
|
|
1408
1453
|
};
|
|
1409
1454
|
}, [
|
|
1410
1455
|
clearErrorState,
|
|
1456
|
+
active,
|
|
1411
1457
|
loadVideo,
|
|
1412
1458
|
loadVideoHls,
|
|
1413
1459
|
loadVideoNative,
|
package/dist/index.js
CHANGED
|
@@ -696,6 +696,7 @@ var LIVE_STALL_WINDOW_MS = 2e4;
|
|
|
696
696
|
var LIVE_STALLS_BEFORE_STABILITY = 3;
|
|
697
697
|
var hlsCtorPromise = null;
|
|
698
698
|
var activeExclusiveVideo = null;
|
|
699
|
+
var exclusiveMediaReleasers = /* @__PURE__ */ new WeakMap();
|
|
699
700
|
var loadHlsCtor = () => {
|
|
700
701
|
if (!hlsCtorPromise) {
|
|
701
702
|
hlsCtorPromise = import("hls.js").then((mod) => mod.default);
|
|
@@ -709,6 +710,9 @@ var isInterruptedPlayRequestError = (error) => {
|
|
|
709
710
|
var canAttemptPlayback = (video) => {
|
|
710
711
|
return !!video && video.readyState >= HTMLMediaElement.HAVE_METADATA;
|
|
711
712
|
};
|
|
713
|
+
var isVideoSourceAttached = (video) => {
|
|
714
|
+
return !!video.currentSrc || !!video.getAttribute("src");
|
|
715
|
+
};
|
|
712
716
|
function hasNativeHlsSupport() {
|
|
713
717
|
if (typeof navigator === "undefined" || typeof document === "undefined") return false;
|
|
714
718
|
const isSafari = /^((?!chrome|android|firefox|opera|edg).)*safari/i.test(navigator.userAgent);
|
|
@@ -825,6 +829,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
825
829
|
const liveStallEvents = useRef2([]);
|
|
826
830
|
const controlTime = useRef2(null);
|
|
827
831
|
const sourceLoadId = useRef2(0);
|
|
832
|
+
const sourceLoadMode = useRef2("native");
|
|
828
833
|
const [playingState, setPlayingState] = useState(!!defaultPlaying);
|
|
829
834
|
const [mutedState, setMutedState] = useState(!!defaultMuted);
|
|
830
835
|
const [durationState, setDurationState] = useState(0);
|
|
@@ -880,6 +885,20 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
880
885
|
video.removeAttribute("src");
|
|
881
886
|
video.load();
|
|
882
887
|
}, [clearTimers]);
|
|
888
|
+
const releaseNativeMedia = useCallback(() => {
|
|
889
|
+
const video = videoRef.current;
|
|
890
|
+
if (!video) return;
|
|
891
|
+
video.pause();
|
|
892
|
+
if (sourceLoadMode.current !== "native" || !isVideoSourceAttached(video)) return;
|
|
893
|
+
video.removeAttribute("src");
|
|
894
|
+
video.load();
|
|
895
|
+
}, []);
|
|
896
|
+
const ensureNativeMediaAttached = useCallback(() => {
|
|
897
|
+
const video = videoRef.current;
|
|
898
|
+
if (!video || sourceLoadMode.current !== "native" || isVideoSourceAttached(video)) return;
|
|
899
|
+
video.src = videoSrc;
|
|
900
|
+
if (initialTime > 0) video.currentTime = initialTime;
|
|
901
|
+
}, [initialTime, videoSrc]);
|
|
883
902
|
const setNextPlaying = useCallback(
|
|
884
903
|
(value) => {
|
|
885
904
|
if (playingProp === void 0) setPlayingState(value);
|
|
@@ -945,6 +964,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
945
964
|
if (prev) {
|
|
946
965
|
prev.removeEventListener("timeupdate", onTime);
|
|
947
966
|
prev.removeEventListener("durationchange", onDur);
|
|
967
|
+
exclusiveMediaReleasers.delete(prev);
|
|
948
968
|
}
|
|
949
969
|
videoRef.current = el;
|
|
950
970
|
assignRef(externalVideoRef, el);
|
|
@@ -954,8 +974,9 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
954
974
|
el.muted = muted;
|
|
955
975
|
el.addEventListener("timeupdate", onTime);
|
|
956
976
|
el.addEventListener("durationchange", onDur);
|
|
977
|
+
exclusiveMediaReleasers.set(el, releaseNativeMedia);
|
|
957
978
|
},
|
|
958
|
-
[externalVideoRef, muted, notifyActiveChange, onDur, onTime, onVideoRefChange]
|
|
979
|
+
[externalVideoRef, muted, notifyActiveChange, onDur, onTime, onVideoRefChange, releaseNativeMedia]
|
|
959
980
|
);
|
|
960
981
|
const pauseOtherVideos = useCallback(
|
|
961
982
|
(el) => {
|
|
@@ -964,8 +985,10 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
964
985
|
exclusivePlayback.pauseOthers(el);
|
|
965
986
|
return;
|
|
966
987
|
}
|
|
967
|
-
if (activeExclusiveVideo && activeExclusiveVideo !== el
|
|
968
|
-
|
|
988
|
+
if (activeExclusiveVideo && activeExclusiveVideo !== el) {
|
|
989
|
+
const releasePrevious = exclusiveMediaReleasers.get(activeExclusiveVideo);
|
|
990
|
+
if (releasePrevious) releasePrevious();
|
|
991
|
+
else activeExclusiveVideo.pause();
|
|
969
992
|
}
|
|
970
993
|
activeExclusiveVideo = el;
|
|
971
994
|
},
|
|
@@ -975,6 +998,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
975
998
|
const el = videoRef.current;
|
|
976
999
|
if (!el) return;
|
|
977
1000
|
pauseOtherVideos(el);
|
|
1001
|
+
ensureNativeMediaAttached();
|
|
978
1002
|
try {
|
|
979
1003
|
await el.play();
|
|
980
1004
|
clearErrorState();
|
|
@@ -996,7 +1020,16 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
996
1020
|
});
|
|
997
1021
|
}
|
|
998
1022
|
}
|
|
999
|
-
}, [
|
|
1023
|
+
}, [
|
|
1024
|
+
clearErrorState,
|
|
1025
|
+
ensureNativeMediaAttached,
|
|
1026
|
+
messages.playFailed,
|
|
1027
|
+
notifyActiveChange,
|
|
1028
|
+
pauseOtherVideos,
|
|
1029
|
+
reportError,
|
|
1030
|
+
scrollTo,
|
|
1031
|
+
setNextPlaying
|
|
1032
|
+
]);
|
|
1000
1033
|
const pauseAction = useCallback(() => {
|
|
1001
1034
|
const el = videoRef.current;
|
|
1002
1035
|
if (!el) return;
|
|
@@ -1074,6 +1107,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1074
1107
|
async (startAt = initialTime, loadId = sourceLoadId.current) => {
|
|
1075
1108
|
const startVideoRef = videoRef.current;
|
|
1076
1109
|
if (!startVideoRef) return;
|
|
1110
|
+
sourceLoadMode.current = "hls";
|
|
1077
1111
|
let HlsCtor;
|
|
1078
1112
|
try {
|
|
1079
1113
|
HlsCtor = await loadHlsCtor();
|
|
@@ -1216,6 +1250,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1216
1250
|
if (loadId !== sourceLoadId.current) return;
|
|
1217
1251
|
const video = videoRef.current;
|
|
1218
1252
|
if (!video) return;
|
|
1253
|
+
sourceLoadMode.current = "native";
|
|
1219
1254
|
video.src = videoSrc;
|
|
1220
1255
|
video.currentTime = initialTime;
|
|
1221
1256
|
if (autoPlay) void playAction();
|
|
@@ -1223,6 +1258,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1223
1258
|
const loadVideoHls = useCallback(async (loadId = sourceLoadId.current) => {
|
|
1224
1259
|
const video = videoRef.current;
|
|
1225
1260
|
const canNativeHls = !!(video == null ? void 0 : video.canPlayType) && video.canPlayType("application/vnd.apple.mpegurl") !== "";
|
|
1261
|
+
sourceLoadMode.current = "hls";
|
|
1226
1262
|
let HlsCtor;
|
|
1227
1263
|
try {
|
|
1228
1264
|
HlsCtor = await loadHlsCtor();
|
|
@@ -1358,6 +1394,10 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1358
1394
|
if (playingProp) void playAction();
|
|
1359
1395
|
else pauseAction();
|
|
1360
1396
|
}, [pauseAction, playAction, playingProp]);
|
|
1397
|
+
useEffect(() => {
|
|
1398
|
+
if (active !== false) return;
|
|
1399
|
+
releaseNativeMedia();
|
|
1400
|
+
}, [active, releaseNativeMedia]);
|
|
1361
1401
|
useEffect(() => {
|
|
1362
1402
|
if (!videoRef.current) return;
|
|
1363
1403
|
const loadId = sourceLoadId.current + 1;
|
|
@@ -1369,16 +1409,22 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1369
1409
|
liveStabilityMode.current = false;
|
|
1370
1410
|
liveStallEvents.current = [];
|
|
1371
1411
|
resetMediaForSourceChange();
|
|
1372
|
-
if (
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1412
|
+
if (active === false) return;
|
|
1413
|
+
const nextSourceLoadMode = sourceType === "hls" || sourceType !== "native" && type !== "video" && isLikelyHlsSource(videoSrc) ? "hls" : "native";
|
|
1414
|
+
sourceLoadMode.current = nextSourceLoadMode;
|
|
1415
|
+
if (nextSourceLoadMode === "hls") {
|
|
1416
|
+
if (sourceType === "hls") void loadVideo(initialTime, loadId);
|
|
1417
|
+
else void loadVideoHls(loadId);
|
|
1418
|
+
} else {
|
|
1419
|
+
loadVideoNative(loadId);
|
|
1420
|
+
}
|
|
1376
1421
|
return () => {
|
|
1377
1422
|
sourceLoadId.current += 1;
|
|
1378
1423
|
resetMediaForSourceChange();
|
|
1379
1424
|
};
|
|
1380
1425
|
}, [
|
|
1381
1426
|
clearErrorState,
|
|
1427
|
+
active,
|
|
1382
1428
|
loadVideo,
|
|
1383
1429
|
loadVideoHls,
|
|
1384
1430
|
loadVideoNative,
|