You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
346 lines
12 KiB
346 lines
12 KiB
import React, { useState, useEffect, useRef } from "react";
|
|
import { connect } from "react-redux";
|
|
import screenfull from 'screenfull';
|
|
import moment from "moment";
|
|
import VideoHeader from './voiceHeader'
|
|
import VideoOperation from './videoOperation'
|
|
import './videoPlay.less';
|
|
|
|
const timeFormat = 'YYYY-MM-DD HH:mm:ss'
|
|
const yingshiUrl = 'https://open.ys7.com/ezopen/h5/iframe'
|
|
const yingshiCloseSoundKey = 'closeSound'
|
|
const yingshiOpenSoundKey = 'openSound'
|
|
|
|
const VideoPlay = ({
|
|
height, width, containerId = 'myPlayer',
|
|
// playUrl,
|
|
name,
|
|
// videoObj,
|
|
// videoObj = {
|
|
// type: 'yingshi',
|
|
// audio: false,
|
|
// serialNo: 'G75922040', // 设备序列号 必须
|
|
// channelNo: 1, //
|
|
// yingshiToken: 'at.3j6eyqbn0g5xvcut73v0rzdu1nh0gnxx-4ua03m82o9-12u1t9g-rtzndpyds', // 萤石必须
|
|
// playUrlSd: 'ezopen://open.ys7.com/G75922040/1.live', // 必须
|
|
// // playUrl: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000003',
|
|
// playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live',
|
|
// // replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec',
|
|
// },
|
|
videoObj = {
|
|
type: 'cascade',
|
|
audio: false,
|
|
serialNo: 'G75922040', // 设备序列号 必须
|
|
topSerialNo: 'G75922040', // 设备顶级序列号 必须
|
|
playUrlSd: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000003', // 必须
|
|
// playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live',
|
|
// replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec',
|
|
},
|
|
}) => {
|
|
console.log(videoObj);
|
|
const [jessibuca, setjessibuca] = useState(null)
|
|
const [isPlaying, setIsPlaying] = useState(false)
|
|
const [operationState, setoperationState] = useState()
|
|
const [voiceDisY, setVoiceDisY] = useState(0)
|
|
const [processDisX, setProcessDisX] = useState(0)
|
|
const [isAdjustProcess, setIsAdjustProcess] = useState(false)
|
|
const [histroyTime, setHistroyTime] = useState([])
|
|
const [histroyBegain, setHistroyBegain] = useState()
|
|
const [resolution, setResolution] = useState('sd') // 标清 sd 高清 hd
|
|
|
|
// 标记萤石操作中,等待ifream返回信息后清空
|
|
const [yingshiPrepare, setYingshiPrepare] = useState('')
|
|
|
|
const operationRef = useRef(null)
|
|
const processChangeTimeoutRef = useRef(null)
|
|
// 标记萤石操作中,等待ifream返回信息后清空
|
|
const yingshiPrepareRef = useRef(null)
|
|
|
|
const changeSelectState = (key) => {
|
|
if (videoObj.type == 'yingshi' && yingshiPrepareRef.current) {
|
|
return
|
|
}
|
|
const nextOperationState = JSON.parse(JSON.stringify(operationRef.current))
|
|
if (key == 'histroy' && nextOperationState.histroy.select) {
|
|
// 取消历史播放
|
|
setProcessDisX(0)
|
|
setHistroyTime([])
|
|
}
|
|
|
|
for (let k in nextOperationState) {
|
|
if (k == key) {
|
|
nextOperationState[k].select = !nextOperationState[k].select
|
|
} else if (k !== 'fullScreen') {
|
|
nextOperationState[k].select = false
|
|
}
|
|
}
|
|
operationRef.current = nextOperationState
|
|
|
|
if (operationRef.current.histroy.select && histroyTime.length == 0) {
|
|
setHistroyTime([moment().subtract(72, 'hours').format(timeFormat), moment().format(timeFormat)])
|
|
}
|
|
setoperationState(nextOperationState)
|
|
}
|
|
|
|
const operation = [{
|
|
key: 'control',
|
|
click: () => {
|
|
changeSelectState('control')
|
|
}
|
|
}, {
|
|
key: 'talk',
|
|
click: () => {
|
|
changeSelectState('talk')
|
|
}
|
|
}, {
|
|
key: 'fullScreen',
|
|
click: () => {
|
|
if (yingshiPrepareRef.current) {
|
|
return
|
|
}
|
|
changeSelectState('fullScreen')
|
|
let player = document.getElementById('vcmp_videoplay')
|
|
if (screenfull.isEnabled) {
|
|
screenfull.toggle(player);
|
|
}
|
|
}
|
|
}, {
|
|
key: 'histroy',
|
|
hide: !Boolean(videoObj.replayUrl),
|
|
click: () => {
|
|
changeSelectState('histroy')
|
|
yingshiPrepareRef.current = 'play'
|
|
setYingshiPrepare('play')
|
|
}
|
|
},]
|
|
|
|
useEffect(() => {
|
|
if (videoObj.type == 'yingshi') {
|
|
yingshiPrepareRef.current = 'play'
|
|
setYingshiPrepare('play')
|
|
} else {
|
|
createJessibuca()
|
|
}
|
|
let nextOperationState = {}
|
|
for (let p of operation) {
|
|
nextOperationState[p.key] = {
|
|
select: false
|
|
}
|
|
}
|
|
setoperationState(nextOperationState)
|
|
operationRef.current = nextOperationState
|
|
|
|
// 全屏状态监听
|
|
screenfull.on('change', () => {
|
|
if (screenfull.isFullscreen && operationRef.current && !operationRef.current['fullScreen'].select) {
|
|
changeSelectState('fullScreen')
|
|
}
|
|
if (!screenfull.isFullscreen && operationRef.current && operationRef.current['fullScreen'].select) {
|
|
changeSelectState('fullScreen')
|
|
}
|
|
});
|
|
|
|
// 萤石 ifream 信息监听
|
|
const listenYingshiMessage = async (e) => {
|
|
const { data, origin } = e
|
|
console.log(e);
|
|
if (origin !== 'https://open.ys7.com') return
|
|
if (data.type == "handleSuccess") {
|
|
if (yingshiPrepareRef.current == 'play') {
|
|
setIsPlaying(true)
|
|
}
|
|
} else if (data.type == yingshiOpenSoundKey && data.code == 0) {
|
|
if (yingshiPrepareRef.current == yingshiOpenSoundKey) {
|
|
setVoiceDisY(30)
|
|
}
|
|
} if (data.type == yingshiCloseSoundKey && data.code == 0) {
|
|
if (yingshiPrepareRef.current == yingshiCloseSoundKey) {
|
|
setVoiceDisY(0)
|
|
}
|
|
}
|
|
yingshiPrepareRef.current = null
|
|
setYingshiPrepare(null)
|
|
}
|
|
if (videoObj.type == 'yingshi') {
|
|
window.addEventListener('message', listenYingshiMessage);
|
|
}
|
|
return () => {
|
|
window.removeEventListener('message', listenYingshiMessage);
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (histroyTime.length) {
|
|
setHistroyBegain(histroyTime[0])
|
|
document.getElementById('process_point').style.left = 0 + 'px'; // 重置进度条的位置
|
|
if (videoObj.type == 'yingshi') {
|
|
yingshiPrepareRef.current = 'play'
|
|
setYingshiPrepare('play')
|
|
}
|
|
} else {
|
|
setHistroyBegain(null)
|
|
}
|
|
}, [histroyTime])
|
|
useEffect(() => {
|
|
if (operationState && operationState.histroy.select) {
|
|
if (isAdjustProcess) {
|
|
// 调整进度条 更新播放开始时间
|
|
if (processChangeTimeoutRef.current) {
|
|
clearTimeout(processChangeTimeoutRef.current)
|
|
}
|
|
processChangeTimeoutRef.current = setTimeout(() => {
|
|
setHistroyBegain(
|
|
moment(histroyTime[0])
|
|
.add(
|
|
Math.abs(moment(histroyTime[0]).diff(moment(histroyTime[1]), 'seconds')) * (processDisX / document.getElementById('process_point').parentElement.offsetWidth),
|
|
'second'
|
|
)
|
|
.format(timeFormat)
|
|
)
|
|
if (videoObj.type == 'yingshi') {
|
|
yingshiPrepareRef.current = 'play'
|
|
setYingshiPrepare('play')
|
|
}
|
|
}, 300)
|
|
} else {
|
|
// 随播放时间变化更新进度条
|
|
document.getElementById('process_point').style.left = processDisX - 4.5 + 'px'
|
|
}
|
|
}
|
|
}, [processDisX])
|
|
|
|
const createJessibuca = async () => {
|
|
if (videoObj.type != 'yingshi') {
|
|
|
|
let $container = document.getElementById('container');
|
|
const jessibuca = new window.Jessibuca({
|
|
container: $container,
|
|
videoBuffer: 0.2, // 缓存时长
|
|
isResize: false,
|
|
text: "",
|
|
loadingText: "加载中",
|
|
debug: true,
|
|
showBandwidth: true, // 显示网速
|
|
operateBtns: {
|
|
fullscreen: true,
|
|
screenshot: true,
|
|
play: true,
|
|
audio: true,
|
|
},
|
|
forceNoOffscreen: false,
|
|
isNotMute: false,
|
|
});
|
|
setjessibuca(jessibuca)
|
|
play()
|
|
}
|
|
}
|
|
|
|
const yingshiOperation = (operation) => {
|
|
document.getElementById(containerId).contentWindow.postMessage(operation, yingshiUrl)
|
|
// setIsPlaying(operation == 'play')
|
|
}
|
|
|
|
const play = () => {
|
|
if (videoObj.type == 'yingshi') {
|
|
yingshiOperation('play')
|
|
} else if (jessibuca && videoObj.playUrlSd) {
|
|
jessibuca.play(videoObj.playUrlSd);
|
|
setIsPlaying(true)
|
|
}
|
|
}
|
|
|
|
const pause = () => {
|
|
if (videoObj.type == 'yingshi') {
|
|
// yingshiOperation('stop')
|
|
} else if (jessibuca) {
|
|
jessibuca.pause();
|
|
setIsPlaying(false)
|
|
}
|
|
}
|
|
|
|
const closeSound = () => {
|
|
if (videoObj.type == 'yingshi') {
|
|
yingshiPrepareRef.current = yingshiCloseSoundKey
|
|
setYingshiPrepare(yingshiCloseSoundKey)
|
|
yingshiOperation(yingshiCloseSoundKey)
|
|
}
|
|
}
|
|
|
|
const openSound = () => {
|
|
if (videoObj.type == 'yingshi') {
|
|
yingshiPrepareRef.current = yingshiOpenSoundKey
|
|
setYingshiPrepare(yingshiOpenSoundKey)
|
|
yingshiOperation(yingshiOpenSoundKey)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<div className="vcmp_videoplay" style={{ height: height || '100%', width: width || '100%' }}>
|
|
<div id="vcmp_videoplay" style={{ position: 'relative', display: 'flex', height: '100%', width: '100%' }}>
|
|
{/* 顶部信息 */}
|
|
<VideoHeader
|
|
operationState={operationState} changeSelectState={changeSelectState}
|
|
histroyTime={histroyTime}
|
|
setoperationState={setoperationState} name={name}
|
|
showTime={
|
|
videoObj.type == 'yingshi' && yingshiPrepare == 'play' ?
|
|
null : (histroyBegain || moment())
|
|
}
|
|
setProcessDisX={setProcessDisX}
|
|
/>
|
|
{/* 视频内容 */}
|
|
{
|
|
videoObj.type == 'yingshi' ?
|
|
<iframe
|
|
frameBorder="0"
|
|
id={containerId}
|
|
src={
|
|
`${yingshiUrl}?audio=${videoObj.audio && operationState && !operationState.histroy.select ? '1' : '0'}&url=${operationState && operationState.histroy.select && histroyBegain ? `${videoObj.replayUrl}?begin=${moment(histroyBegain).format("YYYYMMDDHHmmss")}&end=${moment(histroyTime[1]).format("YYYYMMDDHHmmss")}` : resolution == 'sd' ? videoObj.playUrlSd : videoObj.playUrlHd}&autoplay=${'1'}&accessToken=${videoObj.yingshiToken}`
|
|
}
|
|
// https://open.ys7.com/doc/zh/book/index/live_proto.html
|
|
// 单个播放器的长宽比例限制最小为{width: 400px;height: 300px;}
|
|
width={'100%'}
|
|
height={'100%'}
|
|
allowFullScreen
|
|
wmode="transparent"
|
|
style={{ pointerEvents: 'none' }}
|
|
/> :
|
|
<div id="container"
|
|
style={{
|
|
height: '100%', width: '100%'
|
|
}}>
|
|
|
|
</div>
|
|
}
|
|
|
|
{/* 下方操作栏 */}
|
|
<VideoOperation
|
|
operationState={operationState} operation={operation}
|
|
voiceDisY={voiceDisY} setVoiceDisY={setVoiceDisY}
|
|
processDisX={processDisX} setProcessDisX={setProcessDisX}
|
|
isAdjustProcess={isAdjustProcess} setIsAdjustProcess={setIsAdjustProcess}
|
|
resolution={resolution} setResolution={setResolution}
|
|
histroyTime={histroyTime} setHistroyTime={setHistroyTime}
|
|
histroyBegain={histroyBegain}
|
|
play={play} pause={pause} closeSound={closeSound} openSound={openSound}
|
|
isPlaying={isPlaying}
|
|
videoObj={videoObj}
|
|
setYingshiPrepare={setYingshiPrepare}
|
|
yingshiPrepareRef={yingshiPrepareRef}
|
|
/>
|
|
</div>
|
|
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function mapStateToProps (state) {
|
|
const { auth } = state;
|
|
return {
|
|
user: auth.user,
|
|
};
|
|
}
|
|
|
|
export default connect(mapStateToProps)(VideoPlay);
|