|
|
|
|
@ -1,18 +1,27 @@ |
|
|
|
|
import type { MouseEvent } from 'react' |
|
|
|
|
import { |
|
|
|
|
useCallback, |
|
|
|
|
useState, |
|
|
|
|
useMemo, |
|
|
|
|
} from 'react' |
|
|
|
|
import { useCallback, useMemo } from 'react' |
|
|
|
|
|
|
|
|
|
import once from 'lodash/once' |
|
|
|
|
|
|
|
|
|
import { useObjectState } from 'hooks' |
|
|
|
|
|
|
|
|
|
import { useVolume } from 'features/VideoPlayer/hooks/useVolume' |
|
|
|
|
|
|
|
|
|
import { useHlsPlayer } from './useHlsPlayer' |
|
|
|
|
import { useVideoQuality } from './useVideoQuality' |
|
|
|
|
import { useFullscreen } from './useFullscreen' |
|
|
|
|
|
|
|
|
|
const toMilliSeconds = (seconds: number) => seconds * 1000 |
|
|
|
|
|
|
|
|
|
const initialState = { |
|
|
|
|
duration: 0, |
|
|
|
|
loadedProgress: 0, |
|
|
|
|
playedProgress: 0, |
|
|
|
|
playing: false, |
|
|
|
|
ready: false, |
|
|
|
|
seek: 0, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export type Props = { |
|
|
|
|
onPlayingChange: (playing: boolean) => void, |
|
|
|
|
onProgressChange: (seconds: number) => void, |
|
|
|
|
@ -20,8 +29,6 @@ export type Props = { |
|
|
|
|
url: string, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const toMilliSeconds = (seconds: number) => seconds * 1000 |
|
|
|
|
|
|
|
|
|
export const useVideoPlayer = ({ |
|
|
|
|
onPlayingChange, |
|
|
|
|
onProgressChange: progressChangeCallback, |
|
|
|
|
@ -29,37 +36,34 @@ export const useVideoPlayer = ({ |
|
|
|
|
url, |
|
|
|
|
}: Props) => { |
|
|
|
|
const { hls, videoRef } = useHlsPlayer(url) |
|
|
|
|
const [ready, setReady] = useState(false) |
|
|
|
|
const [playing, setPlaying] = useState(false) |
|
|
|
|
const [duration, setDuration] = useState(0) |
|
|
|
|
const [seek, setSeek] = useState(resumeFrom) |
|
|
|
|
const [loadedProgress, setLoadedProgress] = useState(0) |
|
|
|
|
const [playedProgress, setPlayedProgress] = useState(toMilliSeconds(resumeFrom)) |
|
|
|
|
const [{ |
|
|
|
|
duration, |
|
|
|
|
loadedProgress, |
|
|
|
|
playedProgress, |
|
|
|
|
playing, |
|
|
|
|
ready, |
|
|
|
|
seek, |
|
|
|
|
}, setPlayerState] = useObjectState({ |
|
|
|
|
...initialState, |
|
|
|
|
playedProgress: toMilliSeconds(resumeFrom), |
|
|
|
|
seek: resumeFrom, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
const startPlaying = useMemo(() => once(() => { |
|
|
|
|
setReady(true) |
|
|
|
|
|
|
|
|
|
setPlaying(true) |
|
|
|
|
setPlayerState({ playing: true, ready: true }) |
|
|
|
|
onPlayingChange(true) |
|
|
|
|
}), [onPlayingChange]) |
|
|
|
|
}), [onPlayingChange, setPlayerState]) |
|
|
|
|
|
|
|
|
|
const togglePlaying = () => { |
|
|
|
|
if (ready) { |
|
|
|
|
setPlaying(!playing) |
|
|
|
|
setPlayerState({ playing: !playing }) |
|
|
|
|
onPlayingChange(!playing) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const onReady = useCallback(() => { |
|
|
|
|
if (ready) return |
|
|
|
|
|
|
|
|
|
setReady(true) |
|
|
|
|
setPlaying(true) |
|
|
|
|
}, [ready]) |
|
|
|
|
|
|
|
|
|
const onError = useCallback(() => { |
|
|
|
|
setPlaying(false) |
|
|
|
|
}, []) |
|
|
|
|
setPlayerState({ playing: false }) |
|
|
|
|
}, [setPlayerState]) |
|
|
|
|
|
|
|
|
|
const onPlayerClick = (e: MouseEvent<HTMLDivElement>) => { |
|
|
|
|
if (e.target === videoRef.current) { |
|
|
|
|
@ -68,22 +72,19 @@ export const useVideoPlayer = ({ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const onDuration = (durationSeconds: number) => { |
|
|
|
|
setDuration(toMilliSeconds(durationSeconds)) |
|
|
|
|
setPlayerState({ duration: toMilliSeconds(durationSeconds) }) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const onProgressChange = useCallback((progress: number) => { |
|
|
|
|
const progressMs = progress * duration |
|
|
|
|
setPlayedProgress(progressMs) |
|
|
|
|
setSeek(progressMs / 1000) |
|
|
|
|
}, [ |
|
|
|
|
duration, |
|
|
|
|
setSeek, |
|
|
|
|
setPlayedProgress, |
|
|
|
|
]) |
|
|
|
|
setPlayerState({ playedProgress: progressMs, seek: progressMs / 1000 }) |
|
|
|
|
}, [duration, setPlayerState]) |
|
|
|
|
|
|
|
|
|
const onLoadedProgress = setLoadedProgress |
|
|
|
|
const onLoadedProgress = (loadedMs: number) => { |
|
|
|
|
setPlayerState({ loadedProgress: loadedMs }) |
|
|
|
|
} |
|
|
|
|
const onPlayedProgress = (playedMs: number) => { |
|
|
|
|
setPlayedProgress(playedMs) |
|
|
|
|
setPlayerState({ playedProgress: playedMs }) |
|
|
|
|
progressChangeCallback(playedMs / 1000) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -96,12 +97,10 @@ export const useVideoPlayer = ({ |
|
|
|
|
onPlayedProgress, |
|
|
|
|
onPlayerClick, |
|
|
|
|
onProgressChange, |
|
|
|
|
onReady, |
|
|
|
|
playedProgress, |
|
|
|
|
playing, |
|
|
|
|
ready, |
|
|
|
|
seek, |
|
|
|
|
setReady, |
|
|
|
|
startPlaying, |
|
|
|
|
togglePlaying, |
|
|
|
|
videoRef, |
|
|
|
|
|