@nikelroot/video-player 0.2.10 → 0.3.0
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 +22 -0
- package/dist/index.cjs +291 -125
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +288 -122
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -37,10 +37,98 @@ __export(index_exports, {
|
|
|
37
37
|
module.exports = __toCommonJS(index_exports);
|
|
38
38
|
|
|
39
39
|
// src/VideoPlayer.tsx
|
|
40
|
-
var
|
|
40
|
+
var import_react4 = require("react");
|
|
41
|
+
|
|
42
|
+
// src/useAudioFallback.ts
|
|
43
|
+
var import_react = require("react");
|
|
44
|
+
function useAudioFallback(options) {
|
|
45
|
+
const latest = (0, import_react.useRef)(options);
|
|
46
|
+
latest.current = options;
|
|
47
|
+
const [videoOnly, setVideoOnly] = (0, import_react.useState)(false);
|
|
48
|
+
const mode = (0, import_react.useRef)(false);
|
|
49
|
+
const cooldown = (0, import_react.useRef)(0);
|
|
50
|
+
const audioErrors = (0, import_react.useRef)(0);
|
|
51
|
+
const audioErrorTimer = (0, import_react.useRef)(null);
|
|
52
|
+
const snapshot = (0, import_react.useRef)(null);
|
|
53
|
+
const switchSource = (0, import_react.useCallback)((next, failure = false) => {
|
|
54
|
+
const { video, fallback, onChange } = latest.current;
|
|
55
|
+
const element = video.current;
|
|
56
|
+
if (!fallback || !element || mode.current === next) return false;
|
|
57
|
+
snapshot.current = {
|
|
58
|
+
time: Number.isFinite(element.currentTime) ? element.currentTime : 0,
|
|
59
|
+
playing: latest.current.playingIntent.current,
|
|
60
|
+
rate: element.playbackRate,
|
|
61
|
+
volume: element.volume,
|
|
62
|
+
muted: element.muted
|
|
63
|
+
};
|
|
64
|
+
mode.current = next;
|
|
65
|
+
audioErrors.current = 0;
|
|
66
|
+
if (audioErrorTimer.current) clearTimeout(audioErrorTimer.current);
|
|
67
|
+
audioErrorTimer.current = null;
|
|
68
|
+
if (failure) cooldown.current = Date.now() + 15e3;
|
|
69
|
+
setVideoOnly(next);
|
|
70
|
+
onChange == null ? void 0 : onChange(next);
|
|
71
|
+
return true;
|
|
72
|
+
}, []);
|
|
73
|
+
const onAudioError = (0, import_react.useCallback)((data) => {
|
|
74
|
+
var _a, _b, _c;
|
|
75
|
+
if (!latest.current.fallback || mode.current) return false;
|
|
76
|
+
const isAudio = ((_a = data == null ? void 0 : data.frag) == null ? void 0 : _a.type) === "audio" || (data == null ? void 0 : data.parent) === "audio" || ((_b = data == null ? void 0 : data.context) == null ? void 0 : _b.type) === "audioTrack" || /^audioTrack/.test((data == null ? void 0 : data.details) || "");
|
|
77
|
+
if (!isAudio) return false;
|
|
78
|
+
if ((data == null ? void 0 : data.details) === "fragGap" && ((_c = latest.current.ranges) == null ? void 0 : _c.some((range) => {
|
|
79
|
+
var _a2, _b2;
|
|
80
|
+
const time = (_b2 = (_a2 = latest.current.video.current) == null ? void 0 : _a2.currentTime) != null ? _b2 : 0;
|
|
81
|
+
return time >= range.start - 0.05 && time < range.end - 0.05;
|
|
82
|
+
}))) return true;
|
|
83
|
+
audioErrors.current++;
|
|
84
|
+
if ((data == null ? void 0 : data.fatal) || audioErrors.current >= 2) return switchSource(true, true);
|
|
85
|
+
if (!audioErrorTimer.current) {
|
|
86
|
+
audioErrorTimer.current = setTimeout(() => {
|
|
87
|
+
audioErrorTimer.current = null;
|
|
88
|
+
switchSource(true, true);
|
|
89
|
+
}, 8e3);
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
}, [switchSource]);
|
|
93
|
+
const onAudioProgress = (0, import_react.useCallback)(() => {
|
|
94
|
+
audioErrors.current = 0;
|
|
95
|
+
if (audioErrorTimer.current) clearTimeout(audioErrorTimer.current);
|
|
96
|
+
audioErrorTimer.current = null;
|
|
97
|
+
}, []);
|
|
98
|
+
(0, import_react.useEffect)(() => {
|
|
99
|
+
mode.current = false;
|
|
100
|
+
setVideoOnly(false);
|
|
101
|
+
snapshot.current = null;
|
|
102
|
+
cooldown.current = 0;
|
|
103
|
+
onAudioProgress();
|
|
104
|
+
return onAudioProgress;
|
|
105
|
+
}, [options.primary, options.fallback, onAudioProgress]);
|
|
106
|
+
(0, import_react.useEffect)(() => {
|
|
107
|
+
const check = () => {
|
|
108
|
+
const { ranges, video, fallback } = latest.current;
|
|
109
|
+
if (!fallback || !ranges || snapshot.current) return;
|
|
110
|
+
const element = video.current;
|
|
111
|
+
if (!element) return;
|
|
112
|
+
const time = element.currentTime;
|
|
113
|
+
const available = ranges.some((range) => time >= range.start - 0.05 && time < range.end - 0.05);
|
|
114
|
+
if (!mode.current && !available) switchSource(true);
|
|
115
|
+
else if (mode.current && available && Date.now() >= cooldown.current && ranges.some((range) => time >= range.start - 0.05 && time + 4 <= range.end)) switchSource(false);
|
|
116
|
+
};
|
|
117
|
+
const timer = setInterval(check, 500);
|
|
118
|
+
return () => clearInterval(timer);
|
|
119
|
+
}, [switchSource]);
|
|
120
|
+
return {
|
|
121
|
+
videoOnly,
|
|
122
|
+
source: videoOnly && options.fallback ? options.fallback : options.primary,
|
|
123
|
+
snapshot,
|
|
124
|
+
switchSource,
|
|
125
|
+
onAudioError,
|
|
126
|
+
onAudioProgress
|
|
127
|
+
};
|
|
128
|
+
}
|
|
41
129
|
|
|
42
130
|
// src/controls.tsx
|
|
43
|
-
var
|
|
131
|
+
var import_react3 = require("react");
|
|
44
132
|
|
|
45
133
|
// src/styles.ts
|
|
46
134
|
var import_styled_components = require("styled-components");
|
|
@@ -180,6 +268,18 @@ var VideoPlayerStyles = import_styled_components.styled.div`
|
|
|
180
268
|
align-items: center;
|
|
181
269
|
}
|
|
182
270
|
|
|
271
|
+
.video-audio-status {
|
|
272
|
+
position: absolute;
|
|
273
|
+
top: 0.75rem;
|
|
274
|
+
left: 0.75rem;
|
|
275
|
+
padding: 0.35rem 0.6rem;
|
|
276
|
+
color: inherit;
|
|
277
|
+
background: rgb(24 27 31 / 85%);
|
|
278
|
+
border-radius: 0.25rem;
|
|
279
|
+
font-size: 0.75rem;
|
|
280
|
+
pointer-events: none;
|
|
281
|
+
}
|
|
282
|
+
|
|
183
283
|
.video-error-overlay {
|
|
184
284
|
position: absolute;
|
|
185
285
|
inset: 0;
|
|
@@ -326,7 +426,7 @@ var SeekSliderStyled = import_styled_components.styled.div`
|
|
|
326
426
|
`;
|
|
327
427
|
|
|
328
428
|
// src/utils.ts
|
|
329
|
-
var
|
|
429
|
+
var import_react2 = require("react");
|
|
330
430
|
var formatTime = (seconds) => {
|
|
331
431
|
const totalSeconds = Number.parseInt(String(seconds), 10);
|
|
332
432
|
const safeSeconds = Number.isFinite(totalSeconds) ? totalSeconds : 0;
|
|
@@ -387,9 +487,9 @@ var getSnapshot = () => {
|
|
|
387
487
|
};
|
|
388
488
|
var getServerSnapshot = () => 0;
|
|
389
489
|
function useWindowWidth(mobileLimit = 768) {
|
|
390
|
-
const width = (0,
|
|
490
|
+
const width = (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getServerSnapshot);
|
|
391
491
|
const isMobile = width <= mobileLimit;
|
|
392
|
-
const mobileType = (0,
|
|
492
|
+
const mobileType = (0, import_react2.useMemo)(() => {
|
|
393
493
|
if (width <= mobileLimit) return "mobile";
|
|
394
494
|
if (width <= 1024) return "laptop";
|
|
395
495
|
return "default";
|
|
@@ -430,7 +530,7 @@ var createThrottledNumberFn = (fn, waitMs) => {
|
|
|
430
530
|
// src/controls.tsx
|
|
431
531
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
432
532
|
var SeekSlider = ({ playAction, duration, currentTime, seekSetTime }) => {
|
|
433
|
-
const ref = (0,
|
|
533
|
+
const ref = (0, import_react3.useRef)(null);
|
|
434
534
|
const clickHandler = (e) => {
|
|
435
535
|
e.preventDefault();
|
|
436
536
|
e.stopPropagation();
|
|
@@ -844,56 +944,67 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
844
944
|
messages: messagesProp,
|
|
845
945
|
accentColor,
|
|
846
946
|
videoSrc: rawVideoSrc = "",
|
|
947
|
+
videoOnlySrc,
|
|
948
|
+
audioRanges,
|
|
949
|
+
onAudioFallbackChange,
|
|
847
950
|
...videoProps
|
|
848
951
|
} = props;
|
|
849
|
-
const
|
|
850
|
-
const
|
|
952
|
+
const primarySrc = rawVideoSrc.replaceAll(" ", "%20").replaceAll("#", "%23");
|
|
953
|
+
const propsRef = (0, import_react4.useRef)(props);
|
|
954
|
+
propsRef.current = props;
|
|
955
|
+
const messages = (0, import_react4.useMemo)(() => ({ ...defaultMessages, ...messagesProp }), [messagesProp]);
|
|
851
956
|
const [, isMobile, mobileType] = useWindowWidth();
|
|
852
|
-
const videoRef = (0,
|
|
853
|
-
const
|
|
854
|
-
const
|
|
855
|
-
const
|
|
856
|
-
const
|
|
857
|
-
const
|
|
858
|
-
const
|
|
859
|
-
const
|
|
860
|
-
const
|
|
861
|
-
const
|
|
862
|
-
const
|
|
863
|
-
const
|
|
864
|
-
const
|
|
865
|
-
const
|
|
866
|
-
const
|
|
867
|
-
const
|
|
868
|
-
const
|
|
869
|
-
const
|
|
870
|
-
const
|
|
871
|
-
const
|
|
872
|
-
const
|
|
873
|
-
const [
|
|
874
|
-
const [
|
|
875
|
-
const
|
|
957
|
+
const videoRef = (0, import_react4.useRef)(null);
|
|
958
|
+
const playbackIntent = (0, import_react4.useRef)(autoPlay || defaultPlaying || Boolean(playingProp));
|
|
959
|
+
const audioFallback = useAudioFallback({ primary: primarySrc, fallback: videoOnlySrc, ranges: audioRanges, video: videoRef, playingIntent: playbackIntent, onChange: onAudioFallbackChange });
|
|
960
|
+
const videoSrc = audioFallback.source;
|
|
961
|
+
const { snapshot: resumeSnapshot, onAudioError, onAudioProgress, switchSource } = audioFallback;
|
|
962
|
+
const hlsRef = (0, import_react4.useRef)(null);
|
|
963
|
+
const containerRef = (0, import_react4.useRef)(null);
|
|
964
|
+
const lastProgressTime = (0, import_react4.useRef)(0);
|
|
965
|
+
const netRetryCount = (0, import_react4.useRef)(0);
|
|
966
|
+
const mediaRecoverCount = (0, import_react4.useRef)(0);
|
|
967
|
+
const fatalReloadCount = (0, import_react4.useRef)(0);
|
|
968
|
+
const reloadTimer = (0, import_react4.useRef)(null);
|
|
969
|
+
const stalledNudgeTimer = (0, import_react4.useRef)(null);
|
|
970
|
+
const liveStabilityMode = (0, import_react4.useRef)(false);
|
|
971
|
+
const liveStallEvents = (0, import_react4.useRef)([]);
|
|
972
|
+
const controlTime = (0, import_react4.useRef)(null);
|
|
973
|
+
const sourceLoadId = (0, import_react4.useRef)(0);
|
|
974
|
+
const sourceLoadMode = (0, import_react4.useRef)("native");
|
|
975
|
+
const pendingPlay = (0, import_react4.useRef)(false);
|
|
976
|
+
const playRequestInFlight = (0, import_react4.useRef)(false);
|
|
977
|
+
const playRequestId = (0, import_react4.useRef)(0);
|
|
978
|
+
const [playingState, setPlayingState] = (0, import_react4.useState)(!!defaultPlaying);
|
|
979
|
+
const [mutedState, setMutedState] = (0, import_react4.useState)(!!defaultMuted);
|
|
980
|
+
const [durationState, setDurationState] = (0, import_react4.useState)(0);
|
|
981
|
+
const [currentTimeState, setCurrentTimeState] = (0, import_react4.useState)(0);
|
|
982
|
+
const [isFullscreen, setIsFullscreen] = (0, import_react4.useState)(false);
|
|
983
|
+
const [showControl, setControlVisible] = (0, import_react4.useState)(true);
|
|
984
|
+
const [errorState, setErrorState] = (0, import_react4.useState)(null);
|
|
985
|
+
const [reloadToken, setReloadToken] = (0, import_react4.useState)(0);
|
|
986
|
+
const showControlRef = (0, import_react4.useRef)(showControl);
|
|
876
987
|
const playing = playingProp != null ? playingProp : playingState;
|
|
877
988
|
const muted = mutedProp != null ? mutedProp : mutedState;
|
|
878
989
|
const isDurationControlled = durationProp !== void 0;
|
|
879
990
|
const duration = durationProp != null ? durationProp : durationState;
|
|
880
991
|
const currentTime = currentTimeState;
|
|
881
992
|
const fullscreenAllowed = active != null ? active : true;
|
|
882
|
-
const onTimeChangeRef = (0,
|
|
883
|
-
const onDurationChangeRef = (0,
|
|
993
|
+
const onTimeChangeRef = (0, import_react4.useRef)(onTimeChange);
|
|
994
|
+
const onDurationChangeRef = (0, import_react4.useRef)(onDurationChange);
|
|
884
995
|
onTimeChangeRef.current = onTimeChange;
|
|
885
996
|
onDurationChangeRef.current = onDurationChange;
|
|
886
997
|
showControlRef.current = showControl;
|
|
887
998
|
const { currentTime: _ignoredCurrentTime, ...domVideoProps } = videoProps;
|
|
888
|
-
const setTimeD = (0,
|
|
999
|
+
const setTimeD = (0, import_react4.useRef)(
|
|
889
1000
|
createThrottledNumberFn((value) => {
|
|
890
1001
|
const v = videoRef.current;
|
|
891
1002
|
if (!v) return;
|
|
892
1003
|
v.currentTime = value;
|
|
893
1004
|
}, 30)
|
|
894
1005
|
);
|
|
895
|
-
const setCurrentTimeUi = (0,
|
|
896
|
-
const clearTimers = (0,
|
|
1006
|
+
const setCurrentTimeUi = (0, import_react4.useRef)(createThrottledNumberFn((value) => setCurrentTimeState(value), 250));
|
|
1007
|
+
const clearTimers = (0, import_react4.useCallback)(() => {
|
|
897
1008
|
if (reloadTimer.current) {
|
|
898
1009
|
clearTimeout(reloadTimer.current);
|
|
899
1010
|
reloadTimer.current = null;
|
|
@@ -907,9 +1018,11 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
907
1018
|
controlTime.current = null;
|
|
908
1019
|
}
|
|
909
1020
|
}, []);
|
|
910
|
-
const resetMediaForSourceChange = (0,
|
|
1021
|
+
const resetMediaForSourceChange = (0, import_react4.useCallback)(() => {
|
|
911
1022
|
clearTimers();
|
|
912
1023
|
pendingPlay.current = false;
|
|
1024
|
+
playRequestId.current++;
|
|
1025
|
+
playRequestInFlight.current = false;
|
|
913
1026
|
if (hlsRef.current) {
|
|
914
1027
|
hlsRef.current.destroy();
|
|
915
1028
|
hlsRef.current = null;
|
|
@@ -920,7 +1033,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
920
1033
|
video.removeAttribute("src");
|
|
921
1034
|
video.load();
|
|
922
1035
|
}, [clearTimers]);
|
|
923
|
-
const releaseNativeMedia = (0,
|
|
1036
|
+
const releaseNativeMedia = (0, import_react4.useCallback)(() => {
|
|
924
1037
|
const video = videoRef.current;
|
|
925
1038
|
if (!video) return;
|
|
926
1039
|
pendingPlay.current = false;
|
|
@@ -929,7 +1042,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
929
1042
|
video.removeAttribute("src");
|
|
930
1043
|
video.load();
|
|
931
1044
|
}, []);
|
|
932
|
-
const ensureNativeMediaAttached = (0,
|
|
1045
|
+
const ensureNativeMediaAttached = (0, import_react4.useCallback)(() => {
|
|
933
1046
|
const video = videoRef.current;
|
|
934
1047
|
if (!video || sourceLoadMode.current !== "native" || isVideoSourceAttached(video)) return false;
|
|
935
1048
|
video.src = videoSrc;
|
|
@@ -937,27 +1050,30 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
937
1050
|
video.load();
|
|
938
1051
|
return true;
|
|
939
1052
|
}, [initialTime, videoSrc]);
|
|
940
|
-
const setNextPlaying = (0,
|
|
1053
|
+
const setNextPlaying = (0, import_react4.useCallback)(
|
|
941
1054
|
(value) => {
|
|
942
|
-
|
|
943
|
-
|
|
1055
|
+
var _a, _b;
|
|
1056
|
+
if (propsRef.current.playing === void 0) setPlayingState(value);
|
|
1057
|
+
(_b = (_a = propsRef.current).onPlayingChange) == null ? void 0 : _b.call(_a, value);
|
|
944
1058
|
},
|
|
945
|
-
[
|
|
1059
|
+
[]
|
|
946
1060
|
);
|
|
947
|
-
const setNextMuted = (0,
|
|
1061
|
+
const setNextMuted = (0, import_react4.useCallback)(
|
|
948
1062
|
(value) => {
|
|
949
|
-
|
|
1063
|
+
var _a, _b;
|
|
1064
|
+
if (propsRef.current.muted === void 0) setMutedState(value);
|
|
950
1065
|
const el = videoRef.current;
|
|
951
1066
|
if (el) el.muted = value;
|
|
952
|
-
onMutedChange == null ? void 0 :
|
|
1067
|
+
(_b = (_a = propsRef.current).onMutedChange) == null ? void 0 : _b.call(_a, value);
|
|
953
1068
|
},
|
|
954
|
-
[
|
|
1069
|
+
[]
|
|
955
1070
|
);
|
|
956
|
-
const clearErrorState = (0,
|
|
1071
|
+
const clearErrorState = (0, import_react4.useCallback)(() => {
|
|
957
1072
|
setErrorState((prev) => prev ? null : prev);
|
|
958
1073
|
}, []);
|
|
959
|
-
const reportError = (0,
|
|
1074
|
+
const reportError = (0, import_react4.useCallback)(
|
|
960
1075
|
(error, data, message = messages.defaultError) => {
|
|
1076
|
+
var _a, _b;
|
|
961
1077
|
const details = formatPlaybackErrorDetails(error, data);
|
|
962
1078
|
const code = getPlaybackErrorCodeText(error);
|
|
963
1079
|
setNextPlaying(false);
|
|
@@ -969,25 +1085,32 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
969
1085
|
error,
|
|
970
1086
|
data
|
|
971
1087
|
});
|
|
972
|
-
onPlaybackError == null ? void 0 :
|
|
1088
|
+
(_b = (_a = propsRef.current).onPlaybackError) == null ? void 0 : _b.call(_a, { error, data, message, details });
|
|
973
1089
|
},
|
|
974
|
-
[messages.defaultError,
|
|
1090
|
+
[messages.defaultError, setNextPlaying]
|
|
975
1091
|
);
|
|
976
|
-
const notifyActiveChange = (0,
|
|
1092
|
+
const notifyActiveChange = (0, import_react4.useCallback)(
|
|
977
1093
|
(video, reason) => {
|
|
978
|
-
|
|
1094
|
+
var _a, _b;
|
|
1095
|
+
(_b = (_a = propsRef.current).onActiveChange) == null ? void 0 : _b.call(_a, { video, reason });
|
|
979
1096
|
},
|
|
980
|
-
[
|
|
1097
|
+
[]
|
|
981
1098
|
);
|
|
982
|
-
const onTime = (0,
|
|
1099
|
+
const onTime = (0, import_react4.useCallback)(() => {
|
|
983
1100
|
var _a;
|
|
984
1101
|
const el = videoRef.current;
|
|
985
1102
|
if (!el) return;
|
|
986
1103
|
const nextTime = Number.isFinite(el.currentTime) ? el.currentTime : 0;
|
|
1104
|
+
if (!el.paused && !el.seeking && nextTime > lastProgressTime.current + 0.5) {
|
|
1105
|
+
netRetryCount.current = 0;
|
|
1106
|
+
fatalReloadCount.current = 0;
|
|
1107
|
+
mediaRecoverCount.current = 0;
|
|
1108
|
+
lastProgressTime.current = nextTime;
|
|
1109
|
+
}
|
|
987
1110
|
setCurrentTimeUi.current(nextTime);
|
|
988
1111
|
(_a = onTimeChangeRef.current) == null ? void 0 : _a.call(onTimeChangeRef, nextTime, el);
|
|
989
1112
|
}, []);
|
|
990
|
-
const onDur = (0,
|
|
1113
|
+
const onDur = (0, import_react4.useCallback)(() => {
|
|
991
1114
|
var _a;
|
|
992
1115
|
const el = videoRef.current;
|
|
993
1116
|
if (!el) return;
|
|
@@ -995,8 +1118,9 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
995
1118
|
if (!isDurationControlled) setDurationState(nextDuration);
|
|
996
1119
|
(_a = onDurationChangeRef.current) == null ? void 0 : _a.call(onDurationChangeRef, nextDuration, el);
|
|
997
1120
|
}, [isDurationControlled]);
|
|
998
|
-
const setVideoEl = (0,
|
|
1121
|
+
const setVideoEl = (0, import_react4.useCallback)(
|
|
999
1122
|
(el) => {
|
|
1123
|
+
var _a, _b, _c;
|
|
1000
1124
|
const prev = videoRef.current;
|
|
1001
1125
|
if (prev === el) return;
|
|
1002
1126
|
if (prev) {
|
|
@@ -1005,18 +1129,18 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1005
1129
|
exclusiveMediaReleasers.delete(prev);
|
|
1006
1130
|
}
|
|
1007
1131
|
videoRef.current = el;
|
|
1008
|
-
assignRef(
|
|
1009
|
-
onVideoRefChange == null ? void 0 :
|
|
1132
|
+
assignRef(propsRef.current.videoRef, el);
|
|
1133
|
+
(_b = (_a = propsRef.current).onVideoRefChange) == null ? void 0 : _b.call(_a, el);
|
|
1010
1134
|
notifyActiveChange(el, "ref");
|
|
1011
1135
|
if (!el) return;
|
|
1012
|
-
el.muted = muted;
|
|
1136
|
+
el.muted = (_c = propsRef.current.muted) != null ? _c : mutedState;
|
|
1013
1137
|
el.addEventListener("timeupdate", onTime);
|
|
1014
1138
|
el.addEventListener("durationchange", onDur);
|
|
1015
1139
|
exclusiveMediaReleasers.set(el, releaseNativeMedia);
|
|
1016
1140
|
},
|
|
1017
|
-
[
|
|
1141
|
+
[notifyActiveChange, onDur, onTime, releaseNativeMedia]
|
|
1018
1142
|
);
|
|
1019
|
-
const pauseOtherVideos = (0,
|
|
1143
|
+
const pauseOtherVideos = (0, import_react4.useCallback)(
|
|
1020
1144
|
(el) => {
|
|
1021
1145
|
if (!exclusivePlayback) return;
|
|
1022
1146
|
if (typeof exclusivePlayback === "object") {
|
|
@@ -1032,20 +1156,25 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1032
1156
|
},
|
|
1033
1157
|
[exclusivePlayback]
|
|
1034
1158
|
);
|
|
1035
|
-
const playAction = (0,
|
|
1159
|
+
const playAction = (0, import_react4.useCallback)(async () => {
|
|
1036
1160
|
const el = videoRef.current;
|
|
1037
1161
|
if (!el) return;
|
|
1162
|
+
const requestId = ++playRequestId.current;
|
|
1038
1163
|
pendingPlay.current = true;
|
|
1164
|
+
playbackIntent.current = true;
|
|
1165
|
+
if (resumeSnapshot.current) resumeSnapshot.current.playing = true;
|
|
1039
1166
|
pauseOtherVideos(el);
|
|
1040
1167
|
ensureNativeMediaAttached();
|
|
1041
1168
|
try {
|
|
1042
1169
|
playRequestInFlight.current = true;
|
|
1043
1170
|
await el.play();
|
|
1171
|
+
if (requestId !== playRequestId.current || videoRef.current !== el) return;
|
|
1044
1172
|
pendingPlay.current = false;
|
|
1045
1173
|
clearErrorState();
|
|
1046
1174
|
setNextPlaying(true);
|
|
1047
1175
|
notifyActiveChange(el, "play");
|
|
1048
1176
|
} catch (e) {
|
|
1177
|
+
if (requestId !== playRequestId.current || videoRef.current !== el) return;
|
|
1049
1178
|
if (isInterruptedPlayRequestError(e)) {
|
|
1050
1179
|
pendingPlay.current = true;
|
|
1051
1180
|
return;
|
|
@@ -1054,7 +1183,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1054
1183
|
console.debug(e);
|
|
1055
1184
|
reportError(e, { type: "play" }, messages.playFailed);
|
|
1056
1185
|
} finally {
|
|
1057
|
-
playRequestInFlight.current = false;
|
|
1186
|
+
if (requestId === playRequestId.current) playRequestInFlight.current = false;
|
|
1058
1187
|
}
|
|
1059
1188
|
if (scrollTo === true) {
|
|
1060
1189
|
const rect = el.getBoundingClientRect();
|
|
@@ -1077,15 +1206,17 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1077
1206
|
scrollTo,
|
|
1078
1207
|
setNextPlaying
|
|
1079
1208
|
]);
|
|
1080
|
-
const pauseAction = (0,
|
|
1209
|
+
const pauseAction = (0, import_react4.useCallback)(() => {
|
|
1081
1210
|
const el = videoRef.current;
|
|
1082
1211
|
if (!el) return;
|
|
1083
1212
|
pendingPlay.current = false;
|
|
1213
|
+
if (resumeSnapshot.current) resumeSnapshot.current.playing = false;
|
|
1214
|
+
playbackIntent.current = false;
|
|
1084
1215
|
el.pause();
|
|
1085
1216
|
setNextPlaying(false);
|
|
1086
1217
|
notifyActiveChange(el, "pause");
|
|
1087
1218
|
}, [notifyActiveChange, setNextPlaying]);
|
|
1088
|
-
const seekSetTime = (0,
|
|
1219
|
+
const seekSetTime = (0, import_react4.useCallback)(
|
|
1089
1220
|
(value) => {
|
|
1090
1221
|
const el = videoRef.current;
|
|
1091
1222
|
if (!el) return;
|
|
@@ -1097,7 +1228,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1097
1228
|
},
|
|
1098
1229
|
[duration, notifyActiveChange]
|
|
1099
1230
|
);
|
|
1100
|
-
const seekPrevAction = (0,
|
|
1231
|
+
const seekPrevAction = (0, import_react4.useCallback)(
|
|
1101
1232
|
(sec = 15) => {
|
|
1102
1233
|
const el = videoRef.current;
|
|
1103
1234
|
if (!el) return;
|
|
@@ -1105,7 +1236,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1105
1236
|
},
|
|
1106
1237
|
[seekSetTime]
|
|
1107
1238
|
);
|
|
1108
|
-
const seekNextAction = (0,
|
|
1239
|
+
const seekNextAction = (0, import_react4.useCallback)(
|
|
1109
1240
|
(sec = 15) => {
|
|
1110
1241
|
const el = videoRef.current;
|
|
1111
1242
|
if (!el) return;
|
|
@@ -1113,7 +1244,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1113
1244
|
},
|
|
1114
1245
|
[seekSetTime]
|
|
1115
1246
|
);
|
|
1116
|
-
const toggleAction = (0,
|
|
1247
|
+
const toggleAction = (0, import_react4.useCallback)(
|
|
1117
1248
|
(force) => {
|
|
1118
1249
|
const el = videoRef.current;
|
|
1119
1250
|
if (!el) return;
|
|
@@ -1125,12 +1256,12 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1125
1256
|
},
|
|
1126
1257
|
[pauseAction, playAction]
|
|
1127
1258
|
);
|
|
1128
|
-
const nudgeOnStall = (0,
|
|
1259
|
+
const nudgeOnStall = (0, import_react4.useCallback)(() => {
|
|
1129
1260
|
const v = videoRef.current;
|
|
1130
1261
|
if (!v) return;
|
|
1131
1262
|
v.currentTime = Math.max(0, v.currentTime + 0.05);
|
|
1132
1263
|
}, []);
|
|
1133
|
-
const shouldSwitchLiveToStability = (0,
|
|
1264
|
+
const shouldSwitchLiveToStability = (0, import_react4.useCallback)(() => {
|
|
1134
1265
|
if (!live || liveStabilityMode.current) return false;
|
|
1135
1266
|
const now = Date.now();
|
|
1136
1267
|
liveStallEvents.current = [...liveStallEvents.current.filter((ts) => now - ts <= LIVE_STALL_WINDOW_MS), now];
|
|
@@ -1139,7 +1270,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1139
1270
|
liveStallEvents.current = [];
|
|
1140
1271
|
return true;
|
|
1141
1272
|
}, [live]);
|
|
1142
|
-
const resolvedHlsConfig = (0,
|
|
1273
|
+
const resolvedHlsConfig = (0, import_react4.useCallback)(() => {
|
|
1143
1274
|
const modeConfig = live ? liveHlsConfig : vodHlsConfig;
|
|
1144
1275
|
const base = live ? confLiveStability : confVod;
|
|
1145
1276
|
return withCredentialsConfig(
|
|
@@ -1151,8 +1282,8 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1151
1282
|
hlsCredentials
|
|
1152
1283
|
);
|
|
1153
1284
|
}, [hlsConfig, hlsCredentials, live, liveHlsConfig, vodHlsConfig]);
|
|
1154
|
-
const loadVideo = (0,
|
|
1155
|
-
async (startAt = initialTime, loadId = sourceLoadId.current) => {
|
|
1285
|
+
const loadVideo = (0, import_react4.useCallback)(
|
|
1286
|
+
async (startAt = ((_b) => (_b = ((_a) => (_a = resumeSnapshot.current) == null ? void 0 : _a.time)()) != null ? _b : initialTime)(), loadId = sourceLoadId.current) => {
|
|
1156
1287
|
const startVideoRef = videoRef.current;
|
|
1157
1288
|
if (!startVideoRef) return;
|
|
1158
1289
|
sourceLoadMode.current = "hls";
|
|
@@ -1160,6 +1291,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1160
1291
|
try {
|
|
1161
1292
|
HlsCtor = await loadHlsCtor();
|
|
1162
1293
|
} catch (error) {
|
|
1294
|
+
if (loadId !== sourceLoadId.current || videoRef.current !== startVideoRef) return;
|
|
1163
1295
|
reportError(error, { type: "hls-loader", src: videoSrc }, messages.streamLoadFailed);
|
|
1164
1296
|
return;
|
|
1165
1297
|
}
|
|
@@ -1171,10 +1303,11 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1171
1303
|
hlsRef.current = h;
|
|
1172
1304
|
const isStaleLoad = () => loadId !== sourceLoadId.current || hlsRef.current !== h || videoRef.current !== video;
|
|
1173
1305
|
h.on(HlsCtor.Events.ERROR, (_evt, data) => {
|
|
1174
|
-
var
|
|
1306
|
+
var _a2, _b2;
|
|
1175
1307
|
if (isStaleLoad()) return;
|
|
1176
1308
|
const { type: errorType, details, fatal } = data;
|
|
1177
|
-
if (
|
|
1309
|
+
if (onAudioError(data)) return;
|
|
1310
|
+
if (!fatal && (details === HlsCtor.ErrorDetails.BUFFER_APPEND_ERROR || details === "bufferAppendingError")) return;
|
|
1178
1311
|
if (!fatal) {
|
|
1179
1312
|
switch (details) {
|
|
1180
1313
|
case HlsCtor.ErrorDetails.BUFFER_STALLED_ERROR:
|
|
@@ -1186,7 +1319,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1186
1319
|
}, 200);
|
|
1187
1320
|
}
|
|
1188
1321
|
if (shouldSwitchLiveToStability()) {
|
|
1189
|
-
const resumeTime2 = ((
|
|
1322
|
+
const resumeTime2 = ((_a2 = videoRef.current) == null ? void 0 : _a2.currentTime) || 0;
|
|
1190
1323
|
clearTimers();
|
|
1191
1324
|
reloadTimer.current = setTimeout(() => {
|
|
1192
1325
|
if (hlsRef.current) {
|
|
@@ -1201,7 +1334,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1201
1334
|
return;
|
|
1202
1335
|
}
|
|
1203
1336
|
}
|
|
1204
|
-
const resumeTime = ((
|
|
1337
|
+
const resumeTime = ((_b2 = videoRef.current) == null ? void 0 : _b2.currentTime) || 0;
|
|
1205
1338
|
if (errorType === HlsCtor.ErrorTypes.NETWORK_ERROR) {
|
|
1206
1339
|
if (netRetryCount.current < MAX_NET_RETRIES) {
|
|
1207
1340
|
netRetryCount.current += 1;
|
|
@@ -1265,21 +1398,25 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1265
1398
|
});
|
|
1266
1399
|
h.on(HlsCtor.Events.MANIFEST_PARSED, () => {
|
|
1267
1400
|
if (isStaleLoad()) return;
|
|
1268
|
-
|
|
1269
|
-
netRetryCount.current = 0;
|
|
1270
|
-
mediaRecoverCount.current = 0;
|
|
1271
|
-
if (!live && startAt > 0) {
|
|
1401
|
+
if (startAt > 0) {
|
|
1272
1402
|
h.startLoad(startAt);
|
|
1273
1403
|
video.currentTime = startAt;
|
|
1274
1404
|
} else {
|
|
1275
1405
|
h.startLoad();
|
|
1276
1406
|
}
|
|
1277
|
-
if (autoPlay) void playAction();
|
|
1407
|
+
if (resumeSnapshot.current ? resumeSnapshot.current.playing : autoPlay) void playAction();
|
|
1408
|
+
});
|
|
1409
|
+
h.on(HlsCtor.Events.FRAG_BUFFERED, (_evt, data) => {
|
|
1410
|
+
if (isStaleLoad()) return;
|
|
1411
|
+
if (data.frag.type === "audio") onAudioProgress();
|
|
1278
1412
|
});
|
|
1279
1413
|
h.attachMedia(video);
|
|
1280
1414
|
},
|
|
1281
1415
|
[
|
|
1282
1416
|
autoPlay,
|
|
1417
|
+
onAudioError,
|
|
1418
|
+
onAudioProgress,
|
|
1419
|
+
resumeSnapshot,
|
|
1283
1420
|
clearErrorState,
|
|
1284
1421
|
clearTimers,
|
|
1285
1422
|
initialTime,
|
|
@@ -1294,21 +1431,23 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1294
1431
|
videoSrc
|
|
1295
1432
|
]
|
|
1296
1433
|
);
|
|
1297
|
-
const loadVideoNative = (0,
|
|
1434
|
+
const loadVideoNative = (0, import_react4.useCallback)(
|
|
1298
1435
|
(loadId = sourceLoadId.current, options) => {
|
|
1436
|
+
var _a, _b;
|
|
1299
1437
|
if (loadId !== sourceLoadId.current) return;
|
|
1300
1438
|
const video = videoRef.current;
|
|
1301
1439
|
if (!video) return;
|
|
1302
1440
|
sourceLoadMode.current = "native";
|
|
1303
1441
|
video.src = videoSrc;
|
|
1304
1442
|
if (!(options == null ? void 0 : options.metadataOnly)) {
|
|
1305
|
-
video.currentTime = initialTime;
|
|
1306
|
-
if (autoPlay) void playAction();
|
|
1443
|
+
video.currentTime = (_b = (_a = resumeSnapshot.current) == null ? void 0 : _a.time) != null ? _b : initialTime;
|
|
1444
|
+
if (resumeSnapshot.current ? resumeSnapshot.current.playing : autoPlay) void playAction();
|
|
1307
1445
|
}
|
|
1308
1446
|
},
|
|
1309
1447
|
[autoPlay, initialTime, playAction, videoSrc]
|
|
1310
1448
|
);
|
|
1311
|
-
const loadVideoHls = (0,
|
|
1449
|
+
const loadVideoHls = (0, import_react4.useCallback)(async (loadId = sourceLoadId.current) => {
|
|
1450
|
+
var _a, _b;
|
|
1312
1451
|
const video = videoRef.current;
|
|
1313
1452
|
const canNativeHls = !!(video == null ? void 0 : video.canPlayType) && video.canPlayType("application/vnd.apple.mpegurl") !== "";
|
|
1314
1453
|
sourceLoadMode.current = "hls";
|
|
@@ -1316,13 +1455,14 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1316
1455
|
try {
|
|
1317
1456
|
HlsCtor = await loadHlsCtor();
|
|
1318
1457
|
} catch (error) {
|
|
1458
|
+
if (loadId !== sourceLoadId.current || videoRef.current !== video) return;
|
|
1319
1459
|
reportError(error, { type: "hls-loader", src: videoSrc }, messages.streamLoadFailed);
|
|
1320
1460
|
return;
|
|
1321
1461
|
}
|
|
1322
1462
|
if (loadId !== sourceLoadId.current) return;
|
|
1323
1463
|
if (!videoRef.current || videoRef.current !== video) return;
|
|
1324
1464
|
if (HlsCtor.isSupported()) {
|
|
1325
|
-
void loadVideo(initialTime, loadId);
|
|
1465
|
+
void loadVideo((_b = (_a = resumeSnapshot.current) == null ? void 0 : _a.time) != null ? _b : initialTime, loadId);
|
|
1326
1466
|
return;
|
|
1327
1467
|
}
|
|
1328
1468
|
if (canNativeHls) {
|
|
@@ -1331,7 +1471,8 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1331
1471
|
}
|
|
1332
1472
|
reportError(null, { type: "hls", src: videoSrc, reason: "HLS is not supported in this browser" }, messages.unsupported);
|
|
1333
1473
|
}, [initialTime, loadVideo, loadVideoNative, messages.streamLoadFailed, messages.unsupported, reportError, videoSrc]);
|
|
1334
|
-
const destroy = (0,
|
|
1474
|
+
const destroy = (0, import_react4.useCallback)(() => {
|
|
1475
|
+
var _a, _b;
|
|
1335
1476
|
clearTimers();
|
|
1336
1477
|
if (hlsRef.current) {
|
|
1337
1478
|
hlsRef.current.destroy();
|
|
@@ -1347,27 +1488,25 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1347
1488
|
if (activeExclusiveVideo === v) activeExclusiveVideo = null;
|
|
1348
1489
|
}
|
|
1349
1490
|
videoRef.current = null;
|
|
1350
|
-
onVideoRefChange == null ? void 0 :
|
|
1491
|
+
(_b = (_a = propsRef.current).onVideoRefChange) == null ? void 0 : _b.call(_a, null);
|
|
1351
1492
|
notifyActiveChange(null, "destroy");
|
|
1352
1493
|
setNextPlaying(false);
|
|
1353
|
-
if (
|
|
1494
|
+
if (propsRef.current.duration === void 0) setDurationState(0);
|
|
1354
1495
|
setCurrentTimeUi.current.cancel();
|
|
1355
1496
|
setCurrentTimeState(0);
|
|
1356
1497
|
}, [
|
|
1357
1498
|
clearTimers,
|
|
1358
|
-
durationProp,
|
|
1359
1499
|
notifyActiveChange,
|
|
1360
1500
|
onDur,
|
|
1361
1501
|
onTime,
|
|
1362
|
-
onVideoRefChange,
|
|
1363
1502
|
setNextPlaying
|
|
1364
1503
|
]);
|
|
1365
|
-
const videoClickHandler = (0,
|
|
1504
|
+
const videoClickHandler = (0, import_react4.useCallback)(() => {
|
|
1366
1505
|
if (!handleClick) return;
|
|
1367
1506
|
if (playOnClick) toggleAction();
|
|
1368
1507
|
onVideoClick == null ? void 0 : onVideoClick();
|
|
1369
1508
|
}, [handleClick, onVideoClick, playOnClick, toggleAction]);
|
|
1370
|
-
const fullScreenAction = (0,
|
|
1509
|
+
const fullScreenAction = (0, import_react4.useCallback)(() => {
|
|
1371
1510
|
if (typeof document === "undefined") return;
|
|
1372
1511
|
const doc = document;
|
|
1373
1512
|
const videoEl = videoRef.current;
|
|
@@ -1392,33 +1531,51 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1392
1531
|
else if (videoEl.webkitEnterFullscreen) void videoEl.webkitEnterFullscreen();
|
|
1393
1532
|
}
|
|
1394
1533
|
}, [fullscreenAllowed]);
|
|
1395
|
-
const videoDbClickHandler = (0,
|
|
1534
|
+
const videoDbClickHandler = (0, import_react4.useCallback)(() => {
|
|
1396
1535
|
if (!handleClick) return;
|
|
1397
1536
|
fullScreenAction();
|
|
1398
1537
|
onVideoDoubleClick == null ? void 0 : onVideoDoubleClick();
|
|
1399
1538
|
}, [fullScreenAction, handleClick, onVideoDoubleClick]);
|
|
1400
|
-
const showClickHandler = (0,
|
|
1539
|
+
const showClickHandler = (0, import_react4.useCallback)(() => {
|
|
1401
1540
|
setControlVisible((st) => !st);
|
|
1402
1541
|
}, []);
|
|
1403
|
-
const retryLoadHandler = (0,
|
|
1542
|
+
const retryLoadHandler = (0, import_react4.useCallback)(() => {
|
|
1404
1543
|
clearErrorState();
|
|
1405
1544
|
setReloadToken((value) => value + 1);
|
|
1406
1545
|
}, [clearErrorState]);
|
|
1407
|
-
const videoErrorHandler = (0,
|
|
1546
|
+
const videoErrorHandler = (0, import_react4.useCallback)(() => {
|
|
1408
1547
|
const video = videoRef.current;
|
|
1409
1548
|
const error = video == null ? void 0 : video.error;
|
|
1410
1549
|
const src = (video == null ? void 0 : video.currentSrc) || videoSrc;
|
|
1411
1550
|
if (hlsRef.current && src.startsWith("blob:")) return;
|
|
1551
|
+
if (switchSource(true, true)) return;
|
|
1412
1552
|
pendingPlay.current = false;
|
|
1413
1553
|
reportError(error, { type: "native", src }, getNativeVideoErrorMessage(error, messages));
|
|
1414
|
-
}, [messages, reportError, videoSrc]);
|
|
1415
|
-
const videoLoadedHandler = (0,
|
|
1554
|
+
}, [messages, reportError, switchSource, videoSrc]);
|
|
1555
|
+
const videoLoadedHandler = (0, import_react4.useCallback)(() => {
|
|
1416
1556
|
clearErrorState();
|
|
1557
|
+
const saved = resumeSnapshot.current;
|
|
1558
|
+
const element = videoRef.current;
|
|
1559
|
+
if (saved && element && element.readyState >= HTMLMediaElement.HAVE_METADATA) {
|
|
1560
|
+
let time = saved.time;
|
|
1561
|
+
if (element.seekable.length) {
|
|
1562
|
+
const start = element.seekable.start(0);
|
|
1563
|
+
const end = element.seekable.end(element.seekable.length - 1);
|
|
1564
|
+
time = Math.max(start, Math.min(time, Math.max(start, end - 0.05)));
|
|
1565
|
+
}
|
|
1566
|
+
element.currentTime = time;
|
|
1567
|
+
element.playbackRate = saved.rate;
|
|
1568
|
+
element.volume = saved.volume;
|
|
1569
|
+
element.muted = saved.muted;
|
|
1570
|
+
resumeSnapshot.current = null;
|
|
1571
|
+
if (saved.playing) void playAction();
|
|
1572
|
+
else pauseAction();
|
|
1573
|
+
}
|
|
1417
1574
|
if (playRequestInFlight.current) return;
|
|
1418
1575
|
if (!pendingPlay.current || active === false || !canAttemptPlayback(videoRef.current)) return;
|
|
1419
1576
|
void playAction();
|
|
1420
|
-
}, [active, clearErrorState, playAction]);
|
|
1421
|
-
const mouseMoveHandler = (0,
|
|
1577
|
+
}, [active, clearErrorState, playAction, pauseAction, resumeSnapshot]);
|
|
1578
|
+
const mouseMoveHandler = (0, import_react4.useCallback)(() => {
|
|
1422
1579
|
if (controlTime.current) clearTimeout(controlTime.current);
|
|
1423
1580
|
if (!showControlRef.current) {
|
|
1424
1581
|
showControlRef.current = true;
|
|
@@ -1429,7 +1586,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1429
1586
|
setControlVisible(false);
|
|
1430
1587
|
}, 1e3 * 10);
|
|
1431
1588
|
}, []);
|
|
1432
|
-
(0,
|
|
1589
|
+
(0, import_react4.useImperativeHandle)(
|
|
1433
1590
|
ref,
|
|
1434
1591
|
() => ({
|
|
1435
1592
|
play: playAction,
|
|
@@ -1440,22 +1597,26 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1440
1597
|
}),
|
|
1441
1598
|
[fullScreenAction, pauseAction, playAction, seekSetTime]
|
|
1442
1599
|
);
|
|
1443
|
-
(0,
|
|
1600
|
+
(0, import_react4.useEffect)(() => {
|
|
1444
1601
|
const el = videoRef.current;
|
|
1445
1602
|
if (!el) return;
|
|
1446
1603
|
el.muted = muted;
|
|
1447
1604
|
}, [muted]);
|
|
1448
|
-
(0,
|
|
1605
|
+
(0, import_react4.useEffect)(() => {
|
|
1449
1606
|
if (playingProp === void 0) return;
|
|
1450
1607
|
if (playingProp) void playAction();
|
|
1451
1608
|
else pauseAction();
|
|
1452
1609
|
}, [pauseAction, playAction, playingProp]);
|
|
1453
|
-
(0,
|
|
1610
|
+
(0, import_react4.useEffect)(() => {
|
|
1454
1611
|
if (active !== false) return;
|
|
1455
1612
|
releaseNativeMedia();
|
|
1456
1613
|
}, [active, releaseNativeMedia]);
|
|
1457
|
-
(0,
|
|
1614
|
+
const sourceLoaders = (0, import_react4.useRef)({ loadVideo, loadVideoHls, loadVideoNative });
|
|
1615
|
+
sourceLoaders.current = { loadVideo, loadVideoHls, loadVideoNative };
|
|
1616
|
+
(0, import_react4.useEffect)(() => {
|
|
1617
|
+
var _a, _b, _c, _d;
|
|
1458
1618
|
if (!videoRef.current) return;
|
|
1619
|
+
const { loadVideo: loadVideo2, loadVideoHls: loadVideoHls2, loadVideoNative: loadVideoNative2 } = sourceLoaders.current;
|
|
1459
1620
|
const loadId = sourceLoadId.current + 1;
|
|
1460
1621
|
sourceLoadId.current = loadId;
|
|
1461
1622
|
clearErrorState();
|
|
@@ -1464,20 +1625,21 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1464
1625
|
mediaRecoverCount.current = 0;
|
|
1465
1626
|
liveStabilityMode.current = false;
|
|
1466
1627
|
liveStallEvents.current = [];
|
|
1628
|
+
lastProgressTime.current = (_b = (_a = resumeSnapshot.current) == null ? void 0 : _a.time) != null ? _b : initialTime;
|
|
1467
1629
|
resetMediaForSourceChange();
|
|
1468
1630
|
const nextSourceLoadMode = getSourceLoadMode(sourceType, type, videoSrc);
|
|
1469
1631
|
sourceLoadMode.current = nextSourceLoadMode;
|
|
1470
1632
|
if (active === false) {
|
|
1471
1633
|
if (nextSourceLoadMode === "native" && preload === "metadata") {
|
|
1472
|
-
|
|
1634
|
+
loadVideoNative2(loadId, { metadataOnly: true });
|
|
1473
1635
|
}
|
|
1474
1636
|
return;
|
|
1475
1637
|
}
|
|
1476
1638
|
if (nextSourceLoadMode === "hls") {
|
|
1477
|
-
if (sourceType === "hls") void
|
|
1478
|
-
else void
|
|
1639
|
+
if (sourceType === "hls") void loadVideo2((_d = (_c = resumeSnapshot.current) == null ? void 0 : _c.time) != null ? _d : initialTime, loadId);
|
|
1640
|
+
else void loadVideoHls2(loadId);
|
|
1479
1641
|
} else {
|
|
1480
|
-
|
|
1642
|
+
loadVideoNative2(loadId);
|
|
1481
1643
|
}
|
|
1482
1644
|
return () => {
|
|
1483
1645
|
sourceLoadId.current += 1;
|
|
@@ -1486,9 +1648,6 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1486
1648
|
}, [
|
|
1487
1649
|
clearErrorState,
|
|
1488
1650
|
active,
|
|
1489
|
-
loadVideo,
|
|
1490
|
-
loadVideoHls,
|
|
1491
|
-
loadVideoNative,
|
|
1492
1651
|
initialTime,
|
|
1493
1652
|
resetMediaForSourceChange,
|
|
1494
1653
|
reloadKey,
|
|
@@ -1497,12 +1656,13 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1497
1656
|
type,
|
|
1498
1657
|
videoSrc
|
|
1499
1658
|
]);
|
|
1500
|
-
(0,
|
|
1659
|
+
(0, import_react4.useEffect)(() => {
|
|
1501
1660
|
if (!autoPlay) return;
|
|
1661
|
+
if (resumeSnapshot.current) return;
|
|
1502
1662
|
if (!canAttemptPlayback(videoRef.current)) return;
|
|
1503
1663
|
void playAction();
|
|
1504
1664
|
}, [autoPlay, playAction]);
|
|
1505
|
-
(0,
|
|
1665
|
+
(0, import_react4.useEffect)(() => {
|
|
1506
1666
|
if (typeof document === "undefined") return;
|
|
1507
1667
|
const handleKeyDown = (event) => {
|
|
1508
1668
|
if (event.code !== "KeyF") return;
|
|
@@ -1517,7 +1677,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1517
1677
|
document.removeEventListener("keydown", handleKeyDown);
|
|
1518
1678
|
};
|
|
1519
1679
|
}, [active, fullScreenAction]);
|
|
1520
|
-
(0,
|
|
1680
|
+
(0, import_react4.useEffect)(() => {
|
|
1521
1681
|
if (typeof document === "undefined") return;
|
|
1522
1682
|
const doc = document;
|
|
1523
1683
|
const handleFsChange = () => {
|
|
@@ -1535,15 +1695,15 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1535
1695
|
document.removeEventListener("MSFullscreenChange", handleFsChange);
|
|
1536
1696
|
};
|
|
1537
1697
|
}, []);
|
|
1538
|
-
(0,
|
|
1698
|
+
(0, import_react4.useEffect)(() => {
|
|
1539
1699
|
return () => {
|
|
1540
1700
|
setTimeD.current.cancel();
|
|
1541
1701
|
setCurrentTimeUi.current.cancel();
|
|
1542
1702
|
destroy();
|
|
1543
1703
|
};
|
|
1544
1704
|
}, [destroy]);
|
|
1545
|
-
const lastActiveState = (0,
|
|
1546
|
-
(0,
|
|
1705
|
+
const lastActiveState = (0, import_react4.useRef)(active);
|
|
1706
|
+
(0, import_react4.useEffect)(() => {
|
|
1547
1707
|
const prevActive = lastActiveState.current;
|
|
1548
1708
|
lastActiveState.current = active;
|
|
1549
1709
|
if (active === true && prevActive !== true) {
|
|
@@ -1588,8 +1748,13 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1588
1748
|
muted,
|
|
1589
1749
|
preload,
|
|
1590
1750
|
loop,
|
|
1591
|
-
onPlay: () =>
|
|
1592
|
-
|
|
1751
|
+
onPlay: () => {
|
|
1752
|
+
playbackIntent.current = true;
|
|
1753
|
+
setNextPlaying(true);
|
|
1754
|
+
},
|
|
1755
|
+
onPause: () => {
|
|
1756
|
+
if (!resumeSnapshot.current) setNextPlaying(false);
|
|
1757
|
+
},
|
|
1593
1758
|
onEnded: () => setNextPlaying(false),
|
|
1594
1759
|
onLoadedMetadata: videoLoadedHandler,
|
|
1595
1760
|
onLoadedData: videoLoadedHandler,
|
|
@@ -1600,6 +1765,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1600
1765
|
poster
|
|
1601
1766
|
}
|
|
1602
1767
|
),
|
|
1768
|
+
audioFallback.videoOnly && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { role: "status", className: "video-audio-status", children: "\u0417\u0432\u0443\u043A \u0432\u0440\u0435\u043C\u0435\u043D\u043D\u043E \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D" }),
|
|
1603
1769
|
errorState && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "video-error-overlay", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "video-error-content", children: [
|
|
1604
1770
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "video-error-title", children: errorState.message }),
|
|
1605
1771
|
errorState.details.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "video-error-details", children: errorState.details.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "video-error-detail", children: detail }, detail)) }),
|
|
@@ -1630,7 +1796,7 @@ var VideoPlayerBase = (props, ref) => {
|
|
|
1630
1796
|
}
|
|
1631
1797
|
);
|
|
1632
1798
|
};
|
|
1633
|
-
var VideoPlayer = (0,
|
|
1799
|
+
var VideoPlayer = (0, import_react4.memo)((0, import_react4.forwardRef)(VideoPlayerBase));
|
|
1634
1800
|
var VideoPlayer_default = VideoPlayer;
|
|
1635
1801
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1636
1802
|
0 && (module.exports = {
|