fix(1701): playing stream in between time boundaries

keep-around/fdb88b04b32b9392e76795099e2ec47c9856b38b
Mirlan 4 years ago committed by Andrei Dekterev
parent 8cf1637f14
commit 6ed39e2570
  1. 41
      src/features/MatchPage/components/LiveMatch/helpers.tsx
  2. 2
      src/features/StreamPlayer/components/ProgressBar/helpers/calculateChapterStyles/index.tsx
  3. 22
      src/features/StreamPlayer/hooks/index.tsx
  4. 3
      src/features/StreamPlayer/index.tsx
  5. 6
      src/requests/getMatchInfo.tsx

@ -1,30 +1,38 @@
import last from 'lodash/last'
import find from 'lodash/find'
import reduce from 'lodash/reduce'
import concat from 'lodash/concat'
import type { Episodes } from 'requests/getMatchPlaylists'
import type { MatchInfo } from 'requests/getMatchInfo'
import type { Chapters, Chapter } from 'features/StreamPlayer/types'
import type { MatchInfo, VideoBound } from 'requests/getMatchInfo'
import type { MatchPlaylistOption, PlaylistOption } from '../../types'
import { FULL_GAME_KEY } from '../../helpers/buildPlaylists'
export const FULL_MATCH_BOUNDARY = '0'
/**
* Формирует эпизоды плейлиста Полный матч
* API не выдает полный матч как плейлист, формируем на фронте
* */
const getFullMatchChapters = (url: string, playlist: MatchPlaylistOption) => {
const duration = (playlist.duration ?? 0) * 1000
const getFullMatchChapters = (
profile: MatchInfo,
url: string,
playlist: MatchPlaylistOption,
) => {
const bound = find(profile?.video_bounds, { h: FULL_MATCH_BOUNDARY })
const durationMs = (playlist.duration ?? 0) * 1000
return [
{
duration,
endMs: duration,
endOffsetMs: duration,
duration: durationMs,
endMs: durationMs,
endOffsetMs: bound ? Number(bound.e) * 1000 : durationMs,
index: 0,
isFullMatchChapter: true,
startMs: 0,
startOffsetMs: 0,
startOffsetMs: bound ? Number(bound.s) * 1000 : 0,
url,
},
]
@ -46,20 +54,19 @@ const getPlaylistChapters = (
) => {
if (episode.s >= episode.e) return acc
const bound = profile!.video_bounds!.filter(
(ep: VideoBound) => Number(ep.h) === Number(episode.h),
)
const bound = find(profile?.video_bounds, { h: String(episode.h) })
const boundStart = bound ? Number(bound.s) : 0
const episodeDuration = (episode.e - episode.s) * 1000
const prevVideoEndMs = (last(acc)?.endMs ?? bound[0].s * 1000) || 0
const prevVideoEndMs = last(acc)?.endMs ?? 0
const nextChapter: Chapter = {
duration: episodeDuration,
endMs: prevVideoEndMs + episodeDuration,
endOffsetMs: prevVideoEndMs + episode.e * 1000,
endOffsetMs: (boundStart + episode.e) * 1000,
index,
startMs: 0,
startOffsetMs: prevVideoEndMs + episode.s * 1000,
startMs: prevVideoEndMs,
startOffsetMs: (boundStart + episode.s) * 1000,
url,
}
return concat(acc, nextChapter)
@ -83,7 +90,11 @@ export const buildChapters = ({
}: Args): Chapters => {
if (!selectedPlaylist) return []
if (selectedPlaylist.id === FULL_GAME_KEY) {
return getFullMatchChapters(url, selectedPlaylist)
return getFullMatchChapters(
profile,
url,
selectedPlaylist,
)
}
return getPlaylistChapters(
profile,

@ -44,7 +44,7 @@ export const calculateChapterStyles = ({
})),
)(chapters)
const chapter = chapters[activeChapterIndex] ?? chapters[0]
const chapter = chapters[activeChapterIndex]
const activeChapter = {
...chapter,

@ -35,6 +35,7 @@ const toMilliSeconds = (seconds: number) => seconds * 1000
const initialState = {
activeChapterIndex: 0,
buffering: true,
chapters: [] as Chapters,
duration: 0,
loadedProgress: 0,
playedProgress: 0,
@ -54,20 +55,17 @@ export type Props = {
}
export const useVideoPlayer = ({
chapters,
chapters: chaptersProps,
isLive,
onDurationChange,
onPlayingChange,
onProgressChange: progressChangeCallback,
resumeFrom,
}: Props) => {
const { url } = chapters[0]
const numberOfChapters = size(chapters)
const { hls, videoRef } = useHlsPlayer(url, resumeFrom)
const [{
activeChapterIndex,
buffering,
chapters,
duration: fullMatchDuration,
loadedProgress,
playedProgress,
@ -75,7 +73,11 @@ export const useVideoPlayer = ({
ready,
seek,
seeking,
}, setPlayerState] = useObjectState(initialState)
}, setPlayerState] = useObjectState({ ...initialState, chapters: chaptersProps })
const { url } = chapters[0] ?? { url: '' }
const numberOfChapters = size(chapters)
const { hls, videoRef } = useHlsPlayer(url, resumeFrom)
const chaptersDuration = useDuration(chapters)
@ -90,7 +92,7 @@ export const useVideoPlayer = ({
} = usePlayingHandlers(setPlayerState, chapters)
const getActiveChapter = useCallback(
(index: number = activeChapterIndex) => chapters[index] ?? chapters[0],
(index: number = activeChapterIndex) => chapters[index],
[chapters, activeChapterIndex],
)
@ -219,10 +221,11 @@ export const useVideoPlayer = ({
useEffect(() => {
setPlayerState({
...initialState,
chapters: chaptersProps,
playing: true,
seek: chapters[0].startOffsetMs / 1000,
seek: chaptersProps[0].startOffsetMs / 1000,
})
}, [chapters, setPlayerState])
}, [chaptersProps, setPlayerState])
useEffect(() => {
if (isLive || isEmpty(chapters)) return
@ -277,6 +280,7 @@ export const useVideoPlayer = ({
allPlayedProgress: playedProgress + getActiveChapter().startMs,
backToLive,
buffering,
chapters,
duration,
isFirstChapterPlaying,
isFullscreen,

@ -36,13 +36,14 @@ import { useVideoPlayer } from './hooks'
* HLS плеер, применяется на лайв и завершенных матчах
*/
export const StreamPlayer = (props: Props) => {
const { chapters, isLive } = props
const { isLive } = props
const {
activeChapterIndex,
allPlayedProgress,
backToLive,
buffering,
chapters,
controlsVisible,
duration,
isFirstChapterPlaying,

@ -17,9 +17,9 @@ export type Team = {
}
export type VideoBound = {
e: number,
h: number,
s: number,
e: string,
h: string,
s: string,
}
type VideoBounds = Array<VideoBound>

Loading…
Cancel
Save