|
|
|
|
@ -12,19 +12,27 @@ import Hls from 'hls.js' |
|
|
|
|
import map from 'lodash/map' |
|
|
|
|
import find from 'lodash/find' |
|
|
|
|
import uniqBy from 'lodash/uniqBy' |
|
|
|
|
import isEmpty from 'lodash/isEmpty' |
|
|
|
|
import orderBy from 'lodash/orderBy' |
|
|
|
|
|
|
|
|
|
const autoQuality = { |
|
|
|
|
label: 'Auto', |
|
|
|
|
level: -1, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const getVideoQualities = (hls: Hls | null) => { |
|
|
|
|
if (isEmpty(hls?.levels)) return [] |
|
|
|
|
|
|
|
|
|
const qualities = map(hls?.levels, (level, i) => ({ |
|
|
|
|
label: String(level.height), |
|
|
|
|
level: i, |
|
|
|
|
quality: String(level.height), |
|
|
|
|
})) |
|
|
|
|
const sorted = orderBy( |
|
|
|
|
qualities, |
|
|
|
|
Number, |
|
|
|
|
'desc', |
|
|
|
|
) |
|
|
|
|
return uniqBy(sorted, 'quality') |
|
|
|
|
return uniqBy([...sorted, autoQuality], 'label') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export const useVideoQuality = (ref: RefObject<ReactPlayer>) => { |
|
|
|
|
@ -32,42 +40,21 @@ export const useVideoQuality = (ref: RefObject<ReactPlayer>) => { |
|
|
|
|
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 }) |
|
|
|
|
const onQualitySelect = useCallback((label: string) => { |
|
|
|
|
const item = find(videoQualities, { label }) |
|
|
|
|
if (hls && item) { |
|
|
|
|
hls.currentLevel = item.level |
|
|
|
|
setSelectedQuality(item.label) |
|
|
|
|
} |
|
|
|
|
}, [hls, videoQualities]) |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
onQualitySelect(autoQuality.label) |
|
|
|
|
}, [onQualitySelect]) |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
onQualitySelect, |
|
|
|
|
selectedQuality, |
|
|
|
|
videoQualities: map(videoQualities, 'quality'), |
|
|
|
|
videoQualities: map(videoQualities, 'label'), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|