vjs: Fix 'Video-setting persistence broken'
## Issue 5513: Video-setting persistence broken ## Notes - Per videojs recommendation, the setting-restoration should be done after the video has been loaded, so the action was moved to `loadedmetadata`. This fixed the volume slider problem, and should have fixed the playbackRate too. - For playbackRate, there is another special case where it gets reset to 1 (refer to comments in code).
This commit is contained in:
parent
09c1cfeb8f
commit
83912627de
2 changed files with 32 additions and 4 deletions
|
@ -31,6 +31,7 @@ export type Player = {
|
||||||
loadingSpinner: any,
|
loadingSpinner: any,
|
||||||
getChild: (string) => any,
|
getChild: (string) => any,
|
||||||
playbackRate: (?number) => number,
|
playbackRate: (?number) => number,
|
||||||
|
readyState: () => number,
|
||||||
userActive: (?boolean) => boolean,
|
userActive: (?boolean) => boolean,
|
||||||
overlay: (any) => void,
|
overlay: (any) => void,
|
||||||
mobileUi: (any) => void,
|
mobileUi: (any) => void,
|
||||||
|
|
|
@ -76,6 +76,7 @@ function VideoViewer(props: Props) {
|
||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
const [showAutoplayCountdown, setShowAutoplayCountdown] = useState(false);
|
const [showAutoplayCountdown, setShowAutoplayCountdown] = useState(false);
|
||||||
const [isEndededEmbed, setIsEndededEmbed] = useState(false);
|
const [isEndededEmbed, setIsEndededEmbed] = useState(false);
|
||||||
|
const vjsCallbackDataRef: any = React.useRef();
|
||||||
|
|
||||||
/* isLoading was designed to show loading screen on first play press, rather than completely black screen, but
|
/* isLoading was designed to show loading screen on first play press, rather than completely black screen, but
|
||||||
breaks because some browsers (e.g. Firefox) block autoplay but leave the player.play Promise pending */
|
breaks because some browsers (e.g. Firefox) block autoplay but leave the player.play Promise pending */
|
||||||
|
@ -93,6 +94,16 @@ function VideoViewer(props: Props) {
|
||||||
}
|
}
|
||||||
}, [uri, previousUri]);
|
}, [uri, previousUri]);
|
||||||
|
|
||||||
|
// Update vjsCallbackDataRef (ensures videojs callbacks are not using stale values):
|
||||||
|
useEffect(() => {
|
||||||
|
vjsCallbackDataRef.current = {
|
||||||
|
embedded: embedded,
|
||||||
|
muted: muted,
|
||||||
|
volume: volume,
|
||||||
|
videoPlaybackRate: videoPlaybackRate,
|
||||||
|
};
|
||||||
|
}, [embedded, muted, volume, videoPlaybackRate]);
|
||||||
|
|
||||||
function doTrackingBuffered(e: Event, data: any) {
|
function doTrackingBuffered(e: Event, data: any) {
|
||||||
fetch(source, { method: 'HEAD' }).then((response) => {
|
fetch(source, { method: 'HEAD' }).then((response) => {
|
||||||
data.playerPoweredBy = response.headers.get('x-powered-by');
|
data.playerPoweredBy = response.headers.get('x-powered-by');
|
||||||
|
@ -137,12 +148,17 @@ function VideoViewer(props: Props) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function restoreSavedSettings(player) {
|
||||||
|
if (!vjsCallbackDataRef.current.embedded) {
|
||||||
|
player.muted(vjsCallbackDataRef.current.muted);
|
||||||
|
player.volume(vjsCallbackDataRef.current.volume);
|
||||||
|
player.playbackRate(vjsCallbackDataRef.current.videoPlaybackRate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const onPlayerReady = useCallback(
|
const onPlayerReady = useCallback(
|
||||||
(player: Player) => {
|
(player: Player) => {
|
||||||
if (!embedded) {
|
if (!embedded) {
|
||||||
player.muted(muted);
|
|
||||||
player.volume(volume);
|
|
||||||
player.playbackRate(videoPlaybackRate);
|
|
||||||
addTheaterModeButton(player, toggleVideoTheaterMode);
|
addTheaterModeButton(player, toggleVideoTheaterMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +186,12 @@ function VideoViewer(props: Props) {
|
||||||
|
|
||||||
setIsLoading(shouldPlay); // if we are here outside of an embed, we're playing
|
setIsLoading(shouldPlay); // if we are here outside of an embed, we're playing
|
||||||
|
|
||||||
|
// PR: #5535; Commit: "vjs: Fix 'Video-setting persistence broken'"
|
||||||
|
// Move the restoration to a later `loadedmetadata` phase to counter the
|
||||||
|
// delay from the header-fetch. This is a temp change until the next
|
||||||
|
// re-factoring.
|
||||||
|
player.on('loadedmetadata', () => restoreSavedSettings(player));
|
||||||
|
|
||||||
player.on('tracking:buffered', doTrackingBuffered);
|
player.on('tracking:buffered', doTrackingBuffered);
|
||||||
player.on('tracking:firstplay', doTrackingFirstPlay);
|
player.on('tracking:firstplay', doTrackingFirstPlay);
|
||||||
player.on('ended', onEnded);
|
player.on('ended', onEnded);
|
||||||
|
@ -191,7 +213,12 @@ function VideoViewer(props: Props) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
player.on('ratechange', () => {
|
player.on('ratechange', () => {
|
||||||
if (player) {
|
const HAVE_NOTHING = 0; // https://docs.videojs.com/player#readyState
|
||||||
|
if (player && player.readyState() !== HAVE_NOTHING) {
|
||||||
|
// The playbackRate occasionally resets to 1, typically when loading a fresh video or when 'src' changes.
|
||||||
|
// Videojs says it's a browser quirk (https://github.com/videojs/video.js/issues/2516).
|
||||||
|
// [x] Don't update 'videoPlaybackRate' in this scenario.
|
||||||
|
// [ ] Ideally, the controlBar should be hidden to prevent users from changing the rate while loading.
|
||||||
setVideoPlaybackRate(player.playbackRate());
|
setVideoPlaybackRate(player.playbackRate());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue