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