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.
493 lines
20 KiB
493 lines
20 KiB
import React, { useState, useEffect, useRef } from "react";
|
|
import { connect } from "react-redux";
|
|
import screenfull from 'screenfull';
|
|
import moment from "moment";
|
|
import request from 'superagent'
|
|
import { VideoServeApi, IotVideoServerRequest, checkAudioVideo } from '$utils'
|
|
import { Button, ToastFactory, } from '@douyinfe/semi-ui';
|
|
import VideoHeader from './voiceHeader'
|
|
import VideoOperation from './videoOperation'
|
|
import './videoPlay.less';
|
|
import EZUIKit from 'ezuikit-js'
|
|
import { done } from "nprogress";
|
|
|
|
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,
|
|
global,
|
|
videoStyle,
|
|
changeData,
|
|
videoObj,
|
|
sizeWh,
|
|
slideDown, //视频下方操作是否滑动
|
|
IsSize, //是否按照16:9的比例播放
|
|
// videoObj = {
|
|
// type: 'yingshi',
|
|
// audio: false,
|
|
// serialNo: 'G75922040', // 设备序列号 必须
|
|
// channelNo: 1, //
|
|
// yingshiToken: 'at.6nn6duwz8g8gbd919as9a6ea82bmn31x-709fnp7s3k-13q3v7e-mlov7lysf', // 萤石必须
|
|
// 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.hd.local.rec',
|
|
// },
|
|
// videoObj = {
|
|
// type: 'yingshi',
|
|
// audio: false,
|
|
// serialNo: 'G56385051', // 设备序列号 必须
|
|
// channelNo: 1, //
|
|
// yingshiToken: 'at.6nn6duwz8g8gbd919as9a6ea82bmn31x-709fnp7s3k-13q3v7e-mlov7lysf', // 萤石必须
|
|
// playUrlSd: 'ezopen://open.ys7.com/G56384814/1.live', // 必须
|
|
// // playUrl: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000003',
|
|
// playUrlHd: 'ezopen://open.ys7.com/G56384814/1.hd.live',
|
|
// replayUrl: 'ezopen://open.ys7.com/G56384814/1.hd.local.rec',
|
|
// },
|
|
|
|
// videoObj = {
|
|
// type: 'cascade',
|
|
// audio: false,
|
|
// serialNo: '34020000001310000001', // 设备序列号 必须
|
|
// topSerialNo: '34020000001110000077', // 设备顶级序列号 必须
|
|
// playUrlSd: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000001', // 必须
|
|
// // playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live',
|
|
// // replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec',
|
|
// },
|
|
|
|
//
|
|
iotVideoServer,
|
|
local, //是否本地调用视频
|
|
}) => {
|
|
console.log(sizeWh);
|
|
const [jessibuca, setjessibuca] = useState(null)
|
|
const [player, setPlayer] = 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 [roll, setRoll] = useState()//滚动备注
|
|
const [photo, setPhoto] = useState(1)//滚动备注
|
|
const [size, setSize] = useState({ parentWidth: sizeWh?.parentWidth, parentHeight: sizeWh?.parentHeight, width: width || sizeWh?.parentWidth, height: height || sizeWh?.parentHeight }) //视频本身和父级尺寸
|
|
const [resolution, setResolution] = useState('sd') // 标清 sd 高清 hd
|
|
const [videoMask, setVideoMask] = useState(true) // 标清 sd 高清 hd
|
|
|
|
|
|
// 标记萤石操作中,等待ifream返回信息后清空
|
|
const [yingshiPrepare, setYingshiPrepare] = useState('')
|
|
|
|
const operationRef = useRef(null)
|
|
const Begain = useRef()
|
|
const playBackTime = useRef([])
|
|
const quanp = useRef()
|
|
const processChangeTimeoutRef = useRef(null)
|
|
// 标记萤石操作中,等待ifream返回信息后清空
|
|
const yingshiPrepareRef = useRef(null)
|
|
const playState = useRef(false) //播放状态
|
|
|
|
useEffect(() => {
|
|
setRoll(false)
|
|
}, [resolution,]);
|
|
|
|
|
|
useEffect(() => {
|
|
setResolution(changeData?.hdChecked ? 'hd' : 'sd')
|
|
}, [changeData?.hdChecked])
|
|
|
|
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([])
|
|
playBackTime.current = []
|
|
}
|
|
|
|
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)])
|
|
playBackTime.current = [moment().subtract(72, 'hours').format(timeFormat), moment().format(timeFormat)]
|
|
}
|
|
setoperationState(nextOperationState)
|
|
}
|
|
|
|
// 实时播放左下方操作栏内容
|
|
const operation = [{
|
|
key: 'control',
|
|
click: () => {
|
|
changeSelectState('control')
|
|
}
|
|
}, {
|
|
key: 'talk',
|
|
hide: !(videoObj.type == 'yingshi'),
|
|
click: (e) => {
|
|
console.log(e);
|
|
changeSelectState('talk')
|
|
}
|
|
}, {
|
|
key: 'fullScreen',
|
|
click: () => {
|
|
changeSelectState('fullScreen')
|
|
let videoplay = document.getElementById('vcmp_videoplay')
|
|
if (screenfull.isEnabled) {
|
|
screenfull.toggle(videoplay);
|
|
if (videoObj?.type == 'yingshi') {
|
|
console.log(operationRef.current);
|
|
if (operationRef.current?.fullScreen.select) {
|
|
player.reSize(screen.width, screen.height);
|
|
} else {
|
|
player.reSize(size?.width, size?.height);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}, {
|
|
key: 'histroy',
|
|
hide: !Boolean(videoObj.replayUrl),
|
|
click: () => {
|
|
changeSelectState('histroy')
|
|
player.stop().then(() => {
|
|
if (operationRef.current?.histroy?.select && Begain.current) {
|
|
player.play({ url: `${videoObj.replayUrl}?begin=${moment(Begain.current).format("YYYYMMDDHHmmss")}&end=${moment(playBackTime.current[1]).format("YYYYMMDDHHmmss")}` })
|
|
}
|
|
playState.current = false
|
|
})
|
|
}
|
|
},]
|
|
|
|
// useEffect(() => {
|
|
// createPlay()
|
|
// }, [quanp.current])
|
|
|
|
useEffect(() => {
|
|
createPlay()
|
|
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')
|
|
}
|
|
});
|
|
// const resize_ = () => {
|
|
// const VideoLocal = document.getElementById('vcmp_videoplay')
|
|
// setSize({ parentWidth: VideoLocal?.clientWidth, parentHeight: VideoLocal?.clientHeight, width: VideoLocal?.clientWidth, height: VideoLocal?.clientHeight })
|
|
|
|
// }
|
|
// if (local) {
|
|
// window.addEventListener('resize', resize_); //只要窗口殴大小发生像素变化就会触发
|
|
// }
|
|
return () => {
|
|
if (jessibuca) {
|
|
jessibuca.destroy()
|
|
}
|
|
if (player && videoObj.type == 'yingshi' && player) {
|
|
console.log(11111111111);
|
|
player.stop()
|
|
}
|
|
// if (local) {
|
|
// window.removeEventListener('resize', resize_);
|
|
// }
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (histroyTime.length) {
|
|
setHistroyBegain(histroyTime[0])
|
|
Begain.current = histroyTime[0]
|
|
document.getElementById('process_point').style.left = 0 + 'px'; // 重置进度条的位置
|
|
if (videoObj.type == 'yingshi') {
|
|
// yingshiPrepareRef.current = 'play'
|
|
// setYingshiPrepare('play')
|
|
}
|
|
} else {
|
|
setHistroyBegain(null)
|
|
Begain.current == 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)
|
|
)
|
|
Begain.current = 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)
|
|
|
|
player.stop().then(() => {
|
|
player.play({ url: `${videoObj.replayUrl}?begin=${moment(Begain.current).format("YYYYMMDDHHmmss")}&end=${moment(playBackTime.current[1]).format("YYYYMMDDHHmmss")}` })
|
|
playState.current = false
|
|
})
|
|
} else {
|
|
// 随播放时间变化更新进度条
|
|
document.getElementById('process_point').style.left = processDisX - 4.5 + 'px'
|
|
}
|
|
|
|
}
|
|
}, [processDisX])
|
|
|
|
const createPlay = async () => {
|
|
console.log(size);
|
|
if (videoObj.type != 'yingshi') {
|
|
try {
|
|
// const inviteRes = await IotVideoServerRequest.get(VideoServeApi.invite, {
|
|
// id: '36011200002002021114',
|
|
// channel: '36011200581314002900'
|
|
// }).then(res => {
|
|
// console.log(res);
|
|
// }, err => {.
|
|
// console.log(err);
|
|
// })
|
|
|
|
const inviteRes_ = await request.get(`${iotVideoServer}/api/gb28181/invite?id=${videoObj.topSerialNo}&channel=${videoObj.serialNo}`)
|
|
} catch (error) {
|
|
console.log(error.response);
|
|
}
|
|
|
|
|
|
let $container = document.getElementById(containerId);
|
|
const jessibuca = new window.Jessibuca({
|
|
container: $container,
|
|
videoBuffer: 0.2, // 缓存时长
|
|
isResize: false,
|
|
text: "",
|
|
loadingText: "加载中",
|
|
debug: true,
|
|
showBandwidth: false, // 显示网速
|
|
operateBtns: {
|
|
fullscreen: true,
|
|
screenshot: false,
|
|
play: false,
|
|
audio: false,
|
|
},
|
|
forceNoOffscreen: false,
|
|
isNotMute: false,
|
|
});
|
|
setjessibuca(jessibuca)
|
|
play({ jessibuca })
|
|
} else {
|
|
const player = new EZUIKit.EZUIKitPlayer({
|
|
id: containerId, // 视频容器ID
|
|
accessToken: videoObj?.yingshiToken,
|
|
url: videoObj.playUrlSd,
|
|
width: size?.width,
|
|
height: size?.height,
|
|
handleSuccess: () => { //播放成功
|
|
setRoll(true)
|
|
setVideoMask(false)
|
|
playState.current = true
|
|
},
|
|
handleError: (e) => { //播放失败
|
|
console.log(e, '播放失败');
|
|
},
|
|
})
|
|
setPlayer(player)
|
|
}
|
|
}
|
|
|
|
const play = (params) => {
|
|
if (videoObj.type == 'yingshi') {
|
|
|
|
} else if ((params.jessibuca || jessibuca) && videoObj.playUrlSd) {
|
|
const jes = params.jessibuca || jessibuca
|
|
jes.play(videoObj.playUrlSd);
|
|
setIsPlaying(true)
|
|
}
|
|
}
|
|
|
|
const pause = () => {
|
|
if (videoObj.type == 'yingshi' && player) {
|
|
5
|
|
} 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)
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (!operationRef.current?.fullScreen.select) {
|
|
setSize({ parentWidth: sizeWh?.parentWidth, parentHeight: sizeWh?.parentHeight, width: width || sizeWh?.parentWidth, height: height || sizeWh?.parentHeight })
|
|
if (videoObj.type == 'yingshi' && player && IsSize == !'true') {
|
|
console.log(11111111111);
|
|
player.stop().then(() => {
|
|
player.play().then(() => {
|
|
player.reSize(width || sizeWh?.parentWidth, height || sizeWh?.parentHeight)
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
}
|
|
}, [sizeWh])
|
|
|
|
// useEffect(() => {
|
|
// if (IsSize == 'true') {
|
|
// console.log(size?.parentWidth >= size?.width && size?.parentHeight >= size?.height);
|
|
// if (size?.parentWidth >= size?.width && size?.parentHeight >= size?.height) {
|
|
// if (size?.height / size?.width >= 0.55 && size?.height / size?.width <= 0.57) {
|
|
|
|
// } else {
|
|
// console.warn('宽高不符合尺寸要求,故返回合适的尺寸')
|
|
// if (size?.width / 16 > size?.height / 9) {
|
|
// setSize({ ...size, width: (size?.height / 9) * 16, })
|
|
// } else {
|
|
// setSize({ ...size, height: (size?.width / 16) * 9 })
|
|
// }
|
|
// }
|
|
// } else {
|
|
// console.warn('传递宽高参数有误,请确认容器大小范围内')
|
|
// if (size?.parentWidth / 16 > size?.parentHeight / 9) {
|
|
// setSize({ ...size, width: (size?.parentHeight / 9) * 16, height: size?.parentHeight })
|
|
// } else {
|
|
// setSize({ ...size, width: size?.parentWidth, height: (size?.parentWidth / 16) * 9 })
|
|
// }
|
|
// }
|
|
// }
|
|
// }, [sizeWh])
|
|
return (
|
|
<>
|
|
<div className="vcmp_videoplay" style={{ width: size?.parentWidth || '100%', height: size?.parentHeight || '100%', backgroundColor: 'black', overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center', }}>
|
|
<div id="vcmp_videoplay" style={{ position: 'relative', height: size?.height || '100%', width: size?.width || '100%', minWidth: 240, minHeight: 135, overflow: 'hidden' }}>
|
|
{/* 顶部信息 */}
|
|
{size?.parentWidth > 320 ? <VideoHeader
|
|
operationState={operationState} changeSelectState={changeSelectState}
|
|
histroyTime={histroyTime}
|
|
setoperationState={setoperationState} name={name}
|
|
roll={roll}
|
|
videoObj={videoObj}
|
|
showTime={histroyBegain || moment()}
|
|
setProcessDisX={setProcessDisX}
|
|
content={videoObj.content}
|
|
videoStyle={videoStyle}
|
|
player={player}
|
|
resolution={resolution}
|
|
playState={playState.current}
|
|
/> : ""}
|
|
{/* 视频内容 */}
|
|
|
|
{
|
|
// <iframe
|
|
// frameBorder="0"
|
|
// allowFullScreen='true'
|
|
// 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%'}
|
|
// wmode="transparent"
|
|
// style={{ pointerEvents: 'none' }}
|
|
// />
|
|
}
|
|
<div id={containerId} style={{ height: '100%', width: '100%', }}></div>
|
|
{videoMask ? <div style={{ height: size?.height || '100%', width: size?.width || '100%', minWidth: 400, minHeight: 225, overflow: 'hidden', position: 'absolute', top: '0', left: '0', zIndex: 99, backgroundColor: 'red' }}>hhktyjr6tyr5</div> : ''}
|
|
|
|
|
|
{/* 下方操作栏 */}
|
|
{/* 显示操作功能条件(宽高) */}
|
|
{size?.parentWidth > 320 ?
|
|
<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}
|
|
slideDown={slideDown}
|
|
setPlayer={setPlayer}
|
|
player={player}
|
|
playState={playState.current}
|
|
/> : ""
|
|
}
|
|
</div>
|
|
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function mapStateToProps (state) {
|
|
const { auth, global } = state;
|
|
console.log(global);
|
|
return {
|
|
user: auth.user,
|
|
iotVideoServer: global.iotVideoServer,
|
|
};
|
|
}
|
|
|
|
export default connect(mapStateToProps)(VideoPlay);
|