keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
parent
affac606b4
commit
64966e942e
@ -0,0 +1,73 @@ |
|||||||
|
import type { RefObject } from 'react' |
||||||
|
import { |
||||||
|
useMemo, |
||||||
|
useState, |
||||||
|
useEffect, |
||||||
|
useCallback, |
||||||
|
} from 'react' |
||||||
|
import ReactPlayer from 'react-player' |
||||||
|
|
||||||
|
import Hls from 'hls.js' |
||||||
|
|
||||||
|
import map from 'lodash/map' |
||||||
|
import find from 'lodash/find' |
||||||
|
import uniqBy from 'lodash/uniqBy' |
||||||
|
import orderBy from 'lodash/orderBy' |
||||||
|
|
||||||
|
const getVideoQualities = (hls: Hls | null) => { |
||||||
|
const qualities = map(hls?.levels, (level, i) => ({ |
||||||
|
level: i, |
||||||
|
quality: String(level.height), |
||||||
|
})) |
||||||
|
const sorted = orderBy( |
||||||
|
qualities, |
||||||
|
Number, |
||||||
|
'desc', |
||||||
|
) |
||||||
|
return uniqBy(sorted, 'quality') |
||||||
|
} |
||||||
|
|
||||||
|
export const useVideoQuality = (ref: RefObject<ReactPlayer>) => { |
||||||
|
const hls = ref.current?.getInternalPlayer('hls') as Hls | null |
||||||
|
const videoQualities = useMemo(() => getVideoQualities(hls), [hls]) |
||||||
|
const [selectedQuality, setSelectedQuality] = useState('') |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
const initialQuality = find(videoQualities, { level: hls?.currentLevel }) |
||||||
|
if (initialQuality) { |
||||||
|
setSelectedQuality(initialQuality.quality) |
||||||
|
} |
||||||
|
}, [hls, videoQualities]) |
||||||
|
|
||||||
|
// подписываемся на изменение качества,
|
||||||
|
// тк плеер может сам подбирать качество пользователю
|
||||||
|
// на основе скорости интернета
|
||||||
|
useEffect(() => { |
||||||
|
if (!hls) return undefined |
||||||
|
|
||||||
|
const listener = (event: string, { level }: Hls.levelSwitchedData) => { |
||||||
|
const item = find(videoQualities, { level }) |
||||||
|
if (item) { |
||||||
|
setSelectedQuality(item.quality) |
||||||
|
} |
||||||
|
} |
||||||
|
hls.on(Hls.Events.LEVEL_SWITCHED, listener) |
||||||
|
|
||||||
|
return () => { |
||||||
|
hls.off(Hls.Events.LEVEL_SWITCHED, listener) |
||||||
|
} |
||||||
|
}, [hls, videoQualities]) |
||||||
|
|
||||||
|
const onQualitySelect = useCallback((quality: string) => { |
||||||
|
const item = find(videoQualities, { quality }) |
||||||
|
if (hls && item) { |
||||||
|
hls.currentLevel = item.level |
||||||
|
} |
||||||
|
}, [hls, videoQualities]) |
||||||
|
|
||||||
|
return { |
||||||
|
onQualitySelect, |
||||||
|
selectedQuality, |
||||||
|
videoQualities: map(videoQualities, 'quality'), |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue