diff --git a/src/pages/live/index.tsx b/src/pages/live/index.tsx index 34abbb6..aac671d 100644 --- a/src/pages/live/index.tsx +++ b/src/pages/live/index.tsx @@ -1,4 +1,4 @@ -import React, {useEffect, useRef, useState} from "react"; +import React, {useEffect, useMemo, useRef, useState} from "react"; import {Button, Modal} from "antd"; import {SortableContext, arrayMove} from '@dnd-kit/sortable'; import {DndContext} from "@dnd-kit/core"; @@ -9,8 +9,11 @@ import {deleteByIds, getList, modifyOrder, playState} from "@/service/api/live.t import {showErrorToast, showToast} from "@/components/message.ts"; import ButtonBatch from "@/components/button-batch.tsx"; import FlvJs from "flv.js"; +import {formatDuration} from "@/util/strings.ts"; +import {useSetState} from "ahooks"; +import {set} from "lodash"; -const cache: { flvPlayer?: FlvJs.Player } = {} +const cache: { flvPlayer?: FlvJs.Player,timerPlayNext?:any,timerLoadState?:any } = {} export default function LiveIndex() { const videoRef = useRef(null) const [videoData, setVideoData] = useState([]) @@ -18,9 +21,14 @@ export default function LiveIndex() { const [checkedIdArray, setCheckedIdArray] = useState([]) const [editable, setEditable] = useState(false) - const [state, setState] = useState({ + const [state, setState] = useSetState({ activeIndex: -1, + muted: true, }) + const activeIndex = useRef(state.activeIndex) + useEffect(()=>{ + activeIndex.current = state.activeIndex + },[state.activeIndex]) const showVideoItem = (index: number) => { // 找到对应video item 并显示在视图可见区域 @@ -42,29 +50,28 @@ export default function LiveIndex() { } const activeToNext = (index?: number) => { - const endToFirst = index != undefined && index > -1 ? false : state.activeIndex >= videoData.length - 1 - const activeIndex = index != undefined && index > -1 ? index : (endToFirst ? 0 : state.activeIndex + 1) - setState(() => { - return { - activeIndex - } - }) + const endToFirst = index != undefined && index > -1 ? false : activeIndex.current >= videoData.length - 1 + const _activeIndex = index != undefined && index > -1 ? index : (endToFirst ? 0 : activeIndex.current + 1) + setState({activeIndex:_activeIndex}) if (endToFirst) { showToast('即将播放第一条视频'); } // 找到对应video item 并显示在视图可见区域 - showVideoItem(activeIndex) + showVideoItem(_activeIndex) + return _activeIndex; } - const playVideo = (video: LiveVideoInfo, state: LiveState) => { + const playVideo = (video: LiveVideoInfo, liveState: LiveState) => { if (videoRef.current && video.video_oss_url) { - const playedTime = Date.now() / 1000 >> 0 - state.start_time - if (playedTime < 0 || playedTime > video.video_duration) { // 已播放时间大于总时长了 - initPlayingState() // 重新获取播放状态 + if(cache.timerPlayNext) clearTimeout(cache.timerPlayNext) + const duration = Math.ceil(video.video_duration / 1000) + const playedTime =( Date.now() / 1000 >> 0) - liveState.live_start_time + if (playedTime < 0 || playedTime > duration) { // 已播放时间大于总时长了 + //initPlayingState() // 重新获取播放状态 return; } if (/mp4$/i.test(video.video_oss_url)) { videoRef.current!.src = video.video_oss_url - videoRef.current!.currentTime = playedTime + if(liveState.live_start_time > 0 && playedTime > 0) videoRef.current!.currentTime = playedTime videoRef.current!.play() return; } @@ -80,44 +87,56 @@ export default function LiveIndex() { url: video.video_oss_url }) - cache.flvPlayer.on('ended', () => { - //activeToNext() - initPlayingState() - }) cache.flvPlayer.attachMediaElement(videoRef.current!) cache.flvPlayer.load() - cache.flvPlayer.currentTime = playedTime + + if(liveState.live_start_time > 0 && playedTime > 0) videoRef.current!.currentTime = playedTime + cache.flvPlayer.play() + cache.timerPlayNext = setTimeout(()=>{ + const index = activeToNext(),nextVideo = videoData[index] + playVideo(nextVideo,{live_start_time:(Date.now() / 1000 >> 0),id:nextVideo.id}) + },(duration - playedTime) * 1000) } } } - const initPlayingState = (videoList?: LiveVideoInfo[] | null) => { - const list = videoList || videoData || [] - playState().then(state => { - const video = list.find(v => v.id === state.id) + const initPlayingState = () => { + if(cache.timerLoadState) clearTimeout(cache.timerLoadState) + if(videoData.length == 0) { + cache.timerLoadState = setTimeout(initPlayingState, 1000) + return; + } + playState().then(liveState => { + const video = videoData.find(v => v.id === liveState.id) if (video) { - activeToNext(list.findIndex(v => v.id === state.id)) - playVideo(video, state) + activeToNext(videoData.findIndex(v => v.id === liveState.id)) + playVideo(video, liveState) } else { setState({activeIndex: -1}) - setTimeout(() => { - initPlayingState() - }, 5000) + cache.timerLoadState = setTimeout(initPlayingState, 5000) } - - }); } + const clearAllTimer = ()=>{ + + if(cache.timerPlayNext) clearTimeout(cache.timerPlayNext) + if(cache.timerLoadState) clearTimeout(cache.timerLoadState) + } + const loadList = () => { + clearAllTimer(); getList().then(res => { - console.log('origin list', res.list.map(s => s.id)) - setVideoData(res.list || []) + // console.log('origin list', res.list.map(s => s.id)) + setVideoData(()=>(res.list || [])) setCheckedIdArray([]) - initPlayingState(res.list) }); } - useEffect(loadList, []) + useEffect(()=>{ + loadList() + initPlayingState(); + return clearAllTimer; + }, []) const processDeleteVideo = async (ids: number[]) => { deleteByIds(ids).then(() => { @@ -154,18 +173,32 @@ export default function LiveIndex() { }) } + const totalDuration = useMemo(() => { + if (!videoData || videoData.length == 0) return 0; + // 计算总时长 + return videoData.reduce((sum, v) => sum + v.video_duration, 0); + }, [videoData]) + return (
{contextHolder}
数字人直播间
-
-
+
+ 视频时长: {formatDuration(totalDuration)} +
diff --git a/src/types/api.d.ts b/src/types/api.d.ts index 3a53c41..3658646 100644 --- a/src/types/api.d.ts +++ b/src/types/api.d.ts @@ -103,5 +103,5 @@ declare interface LiveVideoInfo { declare interface LiveState{ id: number; - start_time?: number; + live_start_time?: number; }