135 lines
3.5 KiB
TypeScript
135 lines
3.5 KiB
TypeScript
import React, {useEffect, useState} from "react";
|
|
// import TCPlayer from 'tcplayer.js';
|
|
|
|
import flvPlayer, { VideoPlayer } from '@/components/video/VideoPlayer.ts';
|
|
import {PlayerInstance} from "@/hooks/useCache.ts";
|
|
|
|
// import 'tcplayer.js/dist/tcplayer.min.css';
|
|
|
|
type State = {
|
|
playing: boolean
|
|
muted: boolean
|
|
end?: boolean
|
|
error?: boolean
|
|
fullscreen: boolean
|
|
progress: number
|
|
playedSeconds: number
|
|
duration: number
|
|
}
|
|
type StateUpdate = Partial<State> | ((prev: State) => Partial<State>)
|
|
|
|
type Props = {
|
|
url?: string; cover?: string; showControls?: boolean; className?: string;
|
|
poster?: string;
|
|
onChange?: (state: State) => void;
|
|
onProgress?: (current:number,duration:number) => void;
|
|
onPause?: () => void;
|
|
onPlay?: () => void;
|
|
muted?: boolean;
|
|
autoPlay?: boolean;
|
|
}
|
|
export type PlayerInstance = {
|
|
play: (url: string, currentTime: number) => void;
|
|
pause: () => void;
|
|
getState: () => State;
|
|
}
|
|
|
|
export const Mp4Player = React.forwardRef<PlayerInstance, Props>((props, ref) => {
|
|
const [tcPlayer, setTcPlayer] = useState<VideoPlayer | null>(null)
|
|
const [prevUrl, setPrevUrl] = useState<string | undefined>();
|
|
|
|
const [state, _setState] = useState<State>({
|
|
playing: false,
|
|
muted: false,
|
|
// 是否全屏
|
|
fullscreen: false,
|
|
progress: 0,
|
|
playedSeconds: 0,
|
|
duration: 0
|
|
})
|
|
|
|
const setState = (data: StateUpdate) => {
|
|
_setState(prev => {
|
|
const _state = typeof (data) === 'function' ? {...prev, ...data(prev)} : {...prev, ...data}
|
|
props.onChange?.(_state)
|
|
return _state
|
|
})
|
|
}
|
|
|
|
useEffect(()=>{
|
|
if(props.url && tcPlayer){
|
|
tcPlayer.src(props.url)
|
|
}
|
|
},[props.url, tcPlayer])
|
|
|
|
useEffect(() => {
|
|
const player = flvPlayer.newInstance({className:props.className});
|
|
document.querySelector('.video-player-container-inner')!.appendChild(player.getVideo())
|
|
// const player = TCPlayer(playerVideo, {
|
|
// controls: props.showControls,
|
|
// poster: props.poster,
|
|
// autoplay: typeof(props.autoPlay) != 'undefined' ? props.autoPlay : true,
|
|
// licenseUrl: AppConfig.TCPlayerLicense
|
|
// }
|
|
// ) as TCPlayerInstance;
|
|
|
|
player.on('pause', () => {
|
|
setState({playing: false, end: false, error: false})
|
|
props.onPause?.()
|
|
})
|
|
player.on('playing', () => {
|
|
setState({playing: true, end: false, error: false})
|
|
props.onPlay?.()
|
|
})
|
|
player.on('ended', () => {
|
|
setState({end: true, playing: false, error: false})
|
|
})
|
|
player.on('timeupdate', () => {
|
|
props.onProgress?.(player.currentTime(), player.duration())
|
|
})
|
|
player.on('error', () => {
|
|
setState({end: false, playing: false, error: true})
|
|
})
|
|
setTcPlayer(() => player)
|
|
return () => {
|
|
console.log('destroy video')
|
|
try{
|
|
// player.unload();
|
|
player.dispose();
|
|
setTcPlayer(() => null)
|
|
//Array.from(document.querySelectorAll('video')).forEach(v => v.pause())
|
|
}catch (e){
|
|
console.log(e)
|
|
}
|
|
//playerVideo.parentElement?.removeChild(playerVideo)
|
|
}
|
|
}, [])
|
|
React.useImperativeHandle(ref, () => {
|
|
return {
|
|
pause(){
|
|
if (!tcPlayer) return;
|
|
tcPlayer.pause()
|
|
},
|
|
play: (url, currentTime = 0) => {
|
|
// console.log('play', url, currentTime)
|
|
url = url.replace('.flv','.mp4');
|
|
if (!tcPlayer) return;
|
|
const player = tcPlayer
|
|
if (prevUrl == url) {
|
|
player.currentTime(0)
|
|
} else {
|
|
player.src(url)
|
|
}
|
|
player.play()
|
|
setPrevUrl(url)
|
|
if (currentTime > 0) {
|
|
player.currentTime(currentTime)
|
|
}
|
|
},
|
|
getState: () => state
|
|
}
|
|
})
|
|
|
|
return <div className={`video-player relative ${props.className} video-player-container-inner`}>
|
|
</div>
|
|
}) |