feat: 添加自动播放
This commit is contained in:
parent
58ace4514b
commit
983b35f914
@ -51,7 +51,7 @@ export const VideoListItem = (
|
|||||||
className={`video-item-info flex gap-2 flex-1 bg-gray-100 h-[80px] overflow-hidden rounded-lg p-3 shadow-blue-500 ${active ? 'video-item-shadow' : ''}`}>
|
className={`video-item-info flex gap-2 flex-1 bg-gray-100 h-[80px] overflow-hidden rounded-lg p-3 shadow-blue-500 ${active ? 'video-item-shadow' : ''}`}>
|
||||||
<div className={'video-title leading-7 flex-1'}>{video.title || video.video_title}</div>
|
<div className={'video-title leading-7 flex-1'}>{video.title || video.video_title}</div>
|
||||||
<div className={'video-item-cover bg-white rounded-md overflow-hidden'}>
|
<div className={'video-item-cover bg-white rounded-md overflow-hidden'}>
|
||||||
<img className="w-[100px] h-[56px] object-cover" src={video.cover_url || video.cover || ImageCover} alt={video.video_title}/>
|
<img className="w-[100px] h-[56px] object-cover" src={video.cover || ImageCover} alt={video.video_title}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="operation flex items-center ml-2 gap-3 text-lg text-gray-400">
|
<div className="operation flex items-center ml-2 gap-3 text-lg text-gray-400">
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
import React, {useEffect, useState} from "react";
|
import React, {useEffect, useRef, useState} from "react";
|
||||||
import {Button, message, Modal} from "antd";
|
import {Button, Modal} from "antd";
|
||||||
import {SortableContext, arrayMove} from '@dnd-kit/sortable';
|
import {SortableContext, arrayMove} from '@dnd-kit/sortable';
|
||||||
import {DndContext} from "@dnd-kit/core";
|
import {DndContext} from "@dnd-kit/core";
|
||||||
|
|
||||||
import {VideoListItem} from "@/components/video/video-list-item.tsx";
|
import {VideoListItem} from "@/components/video/video-list-item.tsx";
|
||||||
import {deleteByIds, getList, modifyOrder, playState} from "@/service/api/live.ts";
|
import {deleteByIds, getList, modifyOrder, playState} from "@/service/api/live.ts";
|
||||||
|
|
||||||
import styles from './style.module.scss'
|
|
||||||
import {set} from "lodash";
|
|
||||||
import {showErrorToast, showToast} from "@/components/message.ts";
|
import {showErrorToast, showToast} from "@/components/message.ts";
|
||||||
import ButtonBatch from "@/components/button-batch.tsx";
|
import ButtonBatch from "@/components/button-batch.tsx";
|
||||||
|
import FlvJs from "flv.js";
|
||||||
|
|
||||||
|
const cache: { flvPlayer?: FlvJs.Player } = {}
|
||||||
export default function LiveIndex() {
|
export default function LiveIndex() {
|
||||||
|
const videoRef = useRef<HTMLVideoElement | null>(null)
|
||||||
const [videoData, setVideoData] = useState<LiveVideoInfo[]>([])
|
const [videoData, setVideoData] = useState<LiveVideoInfo[]>([])
|
||||||
const [modal, contextHolder] = Modal.useModal()
|
const [modal, contextHolder] = Modal.useModal()
|
||||||
const [checkedIdArray, setCheckedIdArray] = useState<number[]>([])
|
const [checkedIdArray, setCheckedIdArray] = useState<number[]>([])
|
||||||
@ -54,12 +55,57 @@ export default function LiveIndex() {
|
|||||||
// 找到对应video item 并显示在视图可见区域
|
// 找到对应video item 并显示在视图可见区域
|
||||||
showVideoItem(activeIndex)
|
showVideoItem(activeIndex)
|
||||||
}
|
}
|
||||||
|
const playVideo = (video: LiveVideoInfo, state: 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() // 重新获取播放状态
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (/mp4$/i.test(video.video_oss_url)) {
|
||||||
|
videoRef.current!.src = video.video_oss_url
|
||||||
|
videoRef.current!.currentTime = playedTime
|
||||||
|
videoRef.current!.play()
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (FlvJs.isSupported()) {
|
||||||
|
|
||||||
|
// 已经有播放实例 则销毁
|
||||||
|
if (cache.flvPlayer) {
|
||||||
|
cache.flvPlayer.pause()
|
||||||
|
cache.flvPlayer.unload()
|
||||||
|
}
|
||||||
|
cache.flvPlayer = FlvJs.createPlayer({
|
||||||
|
type: 'flv',
|
||||||
|
url: video.video_oss_url
|
||||||
|
})
|
||||||
|
|
||||||
|
cache.flvPlayer.on('ended', () => {
|
||||||
|
//activeToNext()
|
||||||
|
initPlayingState()
|
||||||
|
})
|
||||||
|
cache.flvPlayer.attachMediaElement(videoRef.current!)
|
||||||
|
cache.flvPlayer.load()
|
||||||
|
cache.flvPlayer.currentTime = playedTime
|
||||||
|
cache.flvPlayer.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const initPlayingState = (videoList?: LiveVideoInfo[] | null) => {
|
const initPlayingState = (videoList?: LiveVideoInfo[] | null) => {
|
||||||
const list = videoList || videoData || []
|
const list = videoList || videoData || []
|
||||||
playState().then(ret => {
|
playState().then(state => {
|
||||||
setState({
|
const video = list.find(v => v.id === state.id)
|
||||||
activeIndex: list.findIndex(v => v.id === ret.id)
|
if (video) {
|
||||||
})
|
activeToNext(list.findIndex(v => v.id === state.id))
|
||||||
|
playVideo(video, state)
|
||||||
|
} else {
|
||||||
|
setState({activeIndex: -1})
|
||||||
|
setTimeout(() => {
|
||||||
|
initPlayingState()
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const loadList = () => {
|
const loadList = () => {
|
||||||
@ -74,8 +120,8 @@ export default function LiveIndex() {
|
|||||||
useEffect(loadList, [])
|
useEffect(loadList, [])
|
||||||
|
|
||||||
const processDeleteVideo = async (ids: number[]) => {
|
const processDeleteVideo = async (ids: number[]) => {
|
||||||
deleteByIds(ids).then(()=>{
|
deleteByIds(ids).then(() => {
|
||||||
showToast('删除成功!','success')
|
showToast('删除成功!', 'success')
|
||||||
loadList()
|
loadList()
|
||||||
}).catch(showErrorToast)
|
}).catch(showErrorToast)
|
||||||
}
|
}
|
||||||
@ -115,6 +161,8 @@ export default function LiveIndex() {
|
|||||||
<div className="text-center text-base">数字人直播间</div>
|
<div className="text-center text-base">数字人直播间</div>
|
||||||
<div className="video-player flex justify-center flex-1 mt-5">
|
<div className="video-player flex justify-center flex-1 mt-5">
|
||||||
<div className="live-player rounded overflow-hidden w-[360px] h-[700px]">
|
<div className="live-player rounded overflow-hidden w-[360px] h-[700px]">
|
||||||
|
<video ref={videoRef} controls autoPlay
|
||||||
|
className="w-[360px] rounded overflow-hidden h-full object-contain"></video>
|
||||||
{/*<iframe src="https://fm.gachafun.com/" className="border-0 w-full h-full max-h-full"></iframe>*/}
|
{/*<iframe src="https://fm.gachafun.com/" className="border-0 w-full h-full max-h-full"></iframe>*/}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -155,22 +203,11 @@ export default function LiveIndex() {
|
|||||||
const {active, over} = e;
|
const {active, over} = e;
|
||||||
if (over && active.id !== over.id) {
|
if (over && active.id !== over.id) {
|
||||||
let oldIndex = -1, newIndex = -1;
|
let oldIndex = -1, newIndex = -1;
|
||||||
// const originArr = [...videoData]
|
|
||||||
setVideoData((items) => {
|
setVideoData((items) => {
|
||||||
oldIndex = items.findIndex(s => s.id == active.id);
|
oldIndex = items.findIndex(s => s.id == active.id);
|
||||||
newIndex = items.findIndex(s => s.id == over.id);
|
newIndex = items.findIndex(s => s.id == over.id);
|
||||||
return arrayMove(items, oldIndex, newIndex);
|
return arrayMove(items, oldIndex, newIndex);
|
||||||
});
|
});
|
||||||
// modal.confirm({
|
|
||||||
// title: '提示',
|
|
||||||
// content: '是否要移动到指定位置',
|
|
||||||
// onCancel: () => {
|
|
||||||
// setVideoData(originArr);
|
|
||||||
// },
|
|
||||||
// onOk: () => {
|
|
||||||
// setVideoData([...videoData])
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
<SortableContext items={videoData}>
|
<SortableContext items={videoData}>
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import {post} from "@/service/request.ts";
|
import {post} from "@/service/request.ts";
|
||||||
|
|
||||||
export function playState() {
|
export function playState() {
|
||||||
return post<{
|
return post<LiveState>({url: '/room/playing'})
|
||||||
id: number;
|
|
||||||
start_time?: number;
|
|
||||||
}>({url: '/room/playing'})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getList() {
|
export function getList() {
|
||||||
|
8
src/types/api.d.ts
vendored
8
src/types/api.d.ts
vendored
@ -83,7 +83,7 @@ declare interface ListCrawlerNewsItem extends BasicArticleInfo {
|
|||||||
declare interface VideoInfo {
|
declare interface VideoInfo {
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
cover?: string;
|
cover: string;
|
||||||
oss_video_url: string;
|
oss_video_url: string;
|
||||||
duration: number;
|
duration: number;
|
||||||
article_id: number;
|
article_id: number;
|
||||||
@ -94,10 +94,14 @@ declare interface LiveVideoInfo {
|
|||||||
id: number;
|
id: number;
|
||||||
video_id: number;
|
video_id: number;
|
||||||
video_title: string;
|
video_title: string;
|
||||||
cover_url: string;
|
cover: string;
|
||||||
video_duration: number;
|
video_duration: number;
|
||||||
video_oss_url: string;
|
video_oss_url: string;
|
||||||
status: number;
|
status: number;
|
||||||
order_no: string;
|
order_no: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare interface LiveState{
|
||||||
|
id: number;
|
||||||
|
start_time?: number;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user