use video elem as source of truth
This commit is contained in:
@@ -90,18 +90,6 @@ export function VideoPlayer({
|
|||||||
const ref = useRef<HTMLVideoElement>(null)
|
const ref = useRef<HTMLVideoElement>(null)
|
||||||
const [focused, setFocused] = useState(false)
|
const [focused, setFocused] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (ref.current) {
|
|
||||||
if (ref.current.canPlayType('application/vnd.apple.mpegurl')) {
|
|
||||||
ref.current.src = source
|
|
||||||
} else if (Hls.isSupported()) {
|
|
||||||
hls.loadSource(source)
|
|
||||||
} else {
|
|
||||||
// TODO: fallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [source, hls])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
ref.current &&
|
ref.current &&
|
||||||
@@ -116,6 +104,18 @@ export function VideoPlayer({
|
|||||||
}
|
}
|
||||||
}, [hls])
|
}, [hls])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (ref.current) {
|
||||||
|
if (ref.current.canPlayType('application/vnd.apple.mpegurl')) {
|
||||||
|
ref.current.src = source
|
||||||
|
} else if (Hls.isSupported()) {
|
||||||
|
hls.loadSource(source)
|
||||||
|
} else {
|
||||||
|
// TODO: fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [source, hls])
|
||||||
|
|
||||||
const enterFullscreen = useCallback(() => {
|
const enterFullscreen = useCallback(() => {
|
||||||
if (containerRef.current) {
|
if (containerRef.current) {
|
||||||
containerRef.current.requestFullscreen()
|
containerRef.current.requestFullscreen()
|
||||||
@@ -324,7 +324,6 @@ function useVideoUtils(ref: React.RefObject<HTMLVideoElement>) {
|
|||||||
const [muted, setMuted] = useState(true)
|
const [muted, setMuted] = useState(true)
|
||||||
const [currentTime, setCurrentTime] = useState(0)
|
const [currentTime, setCurrentTime] = useState(0)
|
||||||
const [duration, setDuration] = useState(0)
|
const [duration, setDuration] = useState(0)
|
||||||
const [canPlay, setCanPlay] = useState(false)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ref.current) return
|
if (!ref.current) return
|
||||||
@@ -333,7 +332,6 @@ function useVideoUtils(ref: React.RefObject<HTMLVideoElement>) {
|
|||||||
// Initial values
|
// Initial values
|
||||||
setCurrentTime(current.currentTime || 0)
|
setCurrentTime(current.currentTime || 0)
|
||||||
setDuration(current.duration || 0)
|
setDuration(current.duration || 0)
|
||||||
setCanPlay(current.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA)
|
|
||||||
setMuted(current.muted)
|
setMuted(current.muted)
|
||||||
setPlaying(!current.paused)
|
setPlaying(!current.paused)
|
||||||
|
|
||||||
@@ -363,10 +361,6 @@ function useVideoUtils(ref: React.RefObject<HTMLVideoElement>) {
|
|||||||
setMuted(false)
|
setMuted(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCanPlay = () => {
|
|
||||||
setCanPlay(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
ref.current.addEventListener('timeupdate', handleTimeUpdate)
|
ref.current.addEventListener('timeupdate', handleTimeUpdate)
|
||||||
ref.current.addEventListener('durationchange', handleDurationChange)
|
ref.current.addEventListener('durationchange', handleDurationChange)
|
||||||
ref.current.addEventListener('play', handlePlay)
|
ref.current.addEventListener('play', handlePlay)
|
||||||
@@ -375,7 +369,6 @@ function useVideoUtils(ref: React.RefObject<HTMLVideoElement>) {
|
|||||||
ref.current.addEventListener('unmute', handleUnmute)
|
ref.current.addEventListener('unmute', handleUnmute)
|
||||||
ref.current.addEventListener('ended', handlePause)
|
ref.current.addEventListener('ended', handlePause)
|
||||||
ref.current.addEventListener('error', handlePause)
|
ref.current.addEventListener('error', handlePause)
|
||||||
ref.current.addEventListener('canplay', handleCanPlay)
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
current.removeEventListener('timeupdate', handleTimeUpdate)
|
current.removeEventListener('timeupdate', handleTimeUpdate)
|
||||||
@@ -386,56 +379,53 @@ function useVideoUtils(ref: React.RefObject<HTMLVideoElement>) {
|
|||||||
current.removeEventListener('unmute', handleUnmute)
|
current.removeEventListener('unmute', handleUnmute)
|
||||||
current.removeEventListener('ended', handlePause)
|
current.removeEventListener('ended', handlePause)
|
||||||
current.removeEventListener('error', handlePause)
|
current.removeEventListener('error', handlePause)
|
||||||
current.removeEventListener('canplay', handleCanPlay)
|
|
||||||
}
|
}
|
||||||
}, [ref])
|
}, [ref])
|
||||||
|
|
||||||
// to explain why I'm doing this in an effect - if you call play()
|
const play = useCallback(() => {
|
||||||
// before it's loaded, at least on firefox, it'll throw when you then
|
|
||||||
// later go to pause/unload the video. Therefore we should keep
|
|
||||||
// play state outside of the video, and then only call it when
|
|
||||||
// playing === true and canPlay === true
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ref.current) return
|
if (!ref.current) return
|
||||||
|
|
||||||
if (playing) {
|
const promise = ref.current.play()
|
||||||
if (canPlay) {
|
if (promise !== undefined) {
|
||||||
ref.current.play()
|
promise.catch(error => {
|
||||||
|
console.error('Error playing video:', error)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} else {
|
}, [ref])
|
||||||
|
|
||||||
|
const pause = useCallback(() => {
|
||||||
|
if (!ref.current) return
|
||||||
|
|
||||||
ref.current.pause()
|
ref.current.pause()
|
||||||
}
|
}, [ref])
|
||||||
}, [playing, ref, canPlay])
|
|
||||||
|
|
||||||
useEffect(() => {
|
const togglePlayPause = useCallback(() => {
|
||||||
if (!ref.current) return
|
if (!ref.current) return
|
||||||
|
|
||||||
ref.current.muted = muted
|
if (ref.current.paused) {
|
||||||
}, [muted, ref])
|
play()
|
||||||
|
} else {
|
||||||
const play = () => {
|
pause()
|
||||||
setPlaying(true)
|
|
||||||
}
|
}
|
||||||
|
}, [ref, play, pause])
|
||||||
|
|
||||||
const pause = () => {
|
const mute = useCallback(() => {
|
||||||
setPlaying(false)
|
if (!ref.current) return
|
||||||
}
|
|
||||||
|
|
||||||
const togglePlayPause = () => {
|
ref.current.muted = true
|
||||||
setPlaying(p => !p)
|
}, [ref])
|
||||||
}
|
|
||||||
|
|
||||||
const mute = () => {
|
const unmute = useCallback(() => {
|
||||||
setMuted(true)
|
if (!ref.current) return
|
||||||
}
|
|
||||||
|
|
||||||
const unmute = () => {
|
ref.current.muted = false
|
||||||
setMuted(false)
|
}, [ref])
|
||||||
}
|
|
||||||
|
|
||||||
const toggleMute = () => {
|
const toggleMute = useCallback(() => {
|
||||||
setMuted(m => !m)
|
if (!ref.current) return
|
||||||
}
|
|
||||||
|
ref.current.muted = !ref.current.muted
|
||||||
|
}, [ref])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
play,
|
play,
|
||||||
|
|||||||
Reference in New Issue
Block a user