diff --git a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoOperation.jsx b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoOperation.jsx index 8b34ad3..6c0b225 100644 --- a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoOperation.jsx +++ b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoOperation.jsx @@ -20,8 +20,10 @@ const VideoOperation = ({ resolution, setResolution, histroyTime, setHistroyTime, histroyBegain, - play, pause, isPlaying, - videoObj + play, pause, closeSound, openSound, + isPlaying, + videoObj, + setYingshiPrepare, yingshiPrepareRef }) => { const [showTimeSelect, setShowTimeSelect] = useState(false) @@ -32,6 +34,13 @@ const VideoOperation = ({ } const changeResolution = () => { + if (yingshiPrepareRef.current) { + return + } + if (videoObj.type == 'yingshi') { + yingshiPrepareRef.current = 'yingshi' + setYingshiPrepare('play') + } setResolution(resolution == 'sd' ? 'hd' : 'sd') } @@ -73,17 +82,23 @@ const VideoOperation = ({ <>
{ - isPlaying ? - - : + videoObj.type != 'yingshi' ? + isPlaying ? + + : + : '' } {histroyTime.length ? `${moment(histroyTime[0]).format(timeFormat)} / ${moment(histroyTime[1]).format(timeFormat)}` : ''}
- - + + { + videoObj.type != 'yingshi' ? + + : '' + }
{ setShowTimeSelect(!showTimeSelect) }}>时间设置
@@ -95,6 +110,7 @@ const VideoOperation = ({ { operationState ? operation.map(p => { + if (p.hide) return null; return { const [timeRangeS, setTimeRangeS] = useState(0) - const [processDisXRatio, setProcessDisXRatio] = useState(0) + + const pointParentWidthRef = useRef(null) + useEffect(() => { + pointParentWidthRef.current = document.getElementById('process_point').parentElement.offsetWidth + }, []) useEffect(() => { if (histroyTime.length) { @@ -57,24 +61,37 @@ const videoOperationHistroyProcess = ({ processDisX, setProcessDisX, histroyTime x = parentWidth } setProcessDisX(x) - setProcessDisXRatio(x / parentWidth) - point.style.left = x + 'px'; + point.style.left = x - 4.5 + 'px'; prev = Date.now(); } }; }} > - {/*
pointParentWidthRef.current - 4.5 ? + -38 - (38 - (pointParentWidthRef.current - 4.5 - processDisX)) : + -38 + , }}> - {moment(histroyTime[0]).add(timeRangeS * processDisXRatio, 'seconds').format(timeFormat)} -
*/} + { + moment(histroyTime[0]) + .add( + timeRangeS * (processDisX / pointParentWidthRef.current), + 'second' + ) + .format(timeFormat) + } +
- + ) } diff --git a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoOperationVoice.jsx b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoOperationVoice.jsx index 0859952..4239359 100644 --- a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoOperationVoice.jsx +++ b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoOperationVoice.jsx @@ -1,65 +1,73 @@ import React, { useState, useEffect, useRef } from "react"; import { connect } from "react-redux"; -import { IconVolume2, } from '@douyinfe/semi-icons'; +import { IconVolume2, IconVolumnSilent } from '@douyinfe/semi-icons'; import './videoPlay.less'; -const VideoOperationVoice = ({ voiceDisY, setVoiceDisY }) => { +const VideoOperationVoice = ({ voiceDisY, setVoiceDisY, videoObj, closeSound, openSound }) => { return (
-
-
- {Math.abs(voiceDisY)} -
{ console.log('object'); }}> -
{ - ev.stopPropagation(); - ev.preventDefault(); + { + videoObj.type == 'yingshi' ? + '' : +
+
+ {Math.abs(voiceDisY)} +
{ console.log('object'); }}> +
{ + ev.stopPropagation(); + ev.preventDefault(); - let oevent = ev; - let distanceY = oevent.clientY - let prev = Date.now(); - const point = document.getElementById('voice_point') - document.onmousemove = function (ev) { - ev.stopPropagation(); - ev.preventDefault(); - // 节流 - let now = Date.now(); - if (now - prev >= 0) { let oevent = ev; - let y = voiceDisY + oevent.clientY - distanceY - if (y < -100) { - y = -100 - } else if (y > 0) { - y = 0 - } - setVoiceDisY(y) - point.style.bottom = -94 - y + 'px'; - prev = Date.now(); - } - }; - document.onmouseup = function () { - document.onmousemove = null; - document.onmouseup = null; - }; - }} - /> + let distanceY = oevent.clientY + let prev = Date.now(); + const point = document.getElementById('voice_point') + document.onmousemove = function (ev) { + ev.stopPropagation(); + ev.preventDefault(); + // 节流 + let now = Date.now(); + if (now - prev >= 0) { + let oevent = ev; + let y = voiceDisY + oevent.clientY - distanceY + if (y < -100) { + y = -100 + } else if (y > 0) { + y = 0 + } + setVoiceDisY(y) + point.style.bottom = -94 - y + 'px'; + prev = Date.now(); + } + }; + document.onmouseup = function () { + document.onmousemove = null; + document.onmouseup = null; + }; + }} + /> +
+
-
-
- + } + { + voiceDisY ? + + : + }
) } diff --git a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx index 894d4a1..b63a263 100644 --- a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx +++ b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx @@ -8,18 +8,23 @@ 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 = { type: 'yingshi', - audio: true, - yingshiToken: 'at.3j6eyqbn0g5xvcut73v0rzdu1nh0gnxx-4ua03m82o9-12u1t9g-rtzndpyds', - playUrlSd: 'ezopen://open.ys7.com/G75922040/1.live', + 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', + playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live', + // replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec', }, }) => { const [jessibuca, setjessibuca] = useState(null) @@ -32,10 +37,18 @@ const VideoPlay = ({ 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) { // 取消历史播放 @@ -71,7 +84,9 @@ const VideoPlay = ({ }, { key: 'fullScreen', click: () => { - + if (yingshiPrepareRef.current) { + return + } changeSelectState('fullScreen') let player = document.getElementById('vcmp_videoplay') if (screenfull.isEnabled) { @@ -80,14 +95,21 @@ const VideoPlay = ({ } }, { key: 'histroy', + hide: !Boolean(videoObj.replayUrl), click: () => { - changeSelectState('histroy') + yingshiPrepareRef.current = 'play' + setYingshiPrepare('play') } },] useEffect(() => { - create() + if (videoObj.type == 'yingshi') { + yingshiPrepareRef.current = 'play' + setYingshiPrepare('play') + } else { + createJessibuca() + } let nextOperationState = {} for (let p of operation) { nextOperationState[p.key] = { @@ -108,29 +130,42 @@ const VideoPlay = ({ }); // 萤石 ifream 信息监听 - // const listenYingshiMessage = async (e) => { - // const { data, origin } = e - // console.log(e); - // if (origin !== 'https://open.ys7.com') return - // if (data.type == 'stop' && data.code == 1) { - // setIsPlaying(false) - // } - // if (data.type == 'stop' && data.code == 1) { - // setIsPlaying(false) - // } - // } - // if (videoObj.type == 'yingshi') { - // window.addEventListener('message', listenYingshiMessage); - // } - // return () => { - // window.removeEventListener('message', listenYingshiMessage); - // } + 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) } @@ -138,6 +173,7 @@ const VideoPlay = ({ useEffect(() => { if (operationState && operationState.histroy.select) { if (isAdjustProcess) { + // 调整进度条 更新播放开始时间 if (processChangeTimeoutRef.current) { clearTimeout(processChangeTimeoutRef.current) } @@ -150,14 +186,19 @@ const VideoPlay = ({ ) .format(timeFormat) ) + if (videoObj.type == 'yingshi') { + yingshiPrepareRef.current = 'play' + setYingshiPrepare('play') + } }, 300) } else { - document.getElementById('process_point').style.left = processDisX + 'px' + // 随播放时间变化更新进度条 + document.getElementById('process_point').style.left = processDisX - 4.5 + 'px' } } }, [processDisX]) - const create = () => { + const createJessibuca = () => { if (videoObj.type != 'yingshi') { let $container = document.getElementById('container'); const jessibuca = new window.Jessibuca({ @@ -183,9 +224,8 @@ const VideoPlay = ({ } const yingshiOperation = (operation) => { - let a = document.getElementById(containerId).contentWindow.postMessage(operation, yingshiUrl) - console.log(a); - setIsPlaying(operation == 'play') + document.getElementById(containerId).contentWindow.postMessage(operation, yingshiUrl) + // setIsPlaying(operation == 'play') } const play = () => { @@ -199,13 +239,29 @@ const VideoPlay = ({ const pause = () => { if (videoObj.type == 'yingshi') { - yingshiOperation('stop') + // 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 ( <>
@@ -215,7 +271,10 @@ const VideoPlay = ({ operationState={operationState} changeSelectState={changeSelectState} histroyTime={histroyTime} setoperationState={setoperationState} name={name} - showTime={histroyBegain} + showTime={ + videoObj.type == 'yingshi' && yingshiPrepare == 'play' ? + null : (histroyBegain || moment()) + } setProcessDisX={setProcessDisX} /> {/* 视频内容 */} @@ -225,7 +284,7 @@ const VideoPlay = ({ frameBorder="0" id={containerId} src={ - `${yingshiUrl}?audio=${videoObj.audio ? '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}` + `${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;} @@ -252,10 +311,11 @@ const VideoPlay = ({ resolution={resolution} setResolution={setResolution} histroyTime={histroyTime} setHistroyTime={setHistroyTime} histroyBegain={histroyBegain} - play={play} - pause={pause} + play={play} pause={pause} closeSound={closeSound} openSound={openSound} isPlaying={isPlaying} videoObj={videoObj} + setYingshiPrepare={setYingshiPrepare} + yingshiPrepareRef={yingshiPrepareRef} />
diff --git a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlayModal.jsx b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlayModal.jsx index a096279..46d570b 100644 --- a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlayModal.jsx +++ b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlayModal.jsx @@ -5,7 +5,7 @@ import { Button, Modal, } from "@douyinfe/semi-ui"; import VideoPlay from './videoPlay.jsx' import './videoPlayModal.less'; -const VideoPlayModal = ({ visible, close }) => { +const VideoPlayModal = ({ visible, close, videoObj, name }) => { return ( { onCancel={() => { close() }} className="videoModal" > - + ) } diff --git a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/voiceHeader.jsx b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/voiceHeader.jsx index 1c90e1f..e40f470 100644 --- a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/voiceHeader.jsx +++ b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/voiceHeader.jsx @@ -11,9 +11,14 @@ const timeFormat = 'YYYY-MM-DD HH:mm:ss' const VideoHeader = ({ operationState, changeSelectState, setProcessDisX, name, showTime, histroyTime }) => { const time = useRef(moment(showTime || undefined)) const upTimeInterval = useRef(null) - const [showTime_, setShowTime] = useState(time.current.format(timeFormat)) + const [showTime_, setShowTime] = useState(' ') const updateTime = () => { + if (!showTime) { + setShowTime('') + clearInterval(upTimeInterval.current) + return + } time.current = moment(showTime || undefined) if (upTimeInterval.current) { clearInterval(upTimeInterval.current) @@ -22,6 +27,9 @@ const VideoHeader = ({ operationState, changeSelectState, setProcessDisX, name, time.current.add(1, 's') if (operationState && operationState.histroy.select) { // setProcessDisX(Math.random() * 300 + 100) + if (time.current.isSameOrAfter(histroyTime[1])) { + clearInterval(upTimeInterval.current) + } setProcessDisX( time.current.diff(moment(histroyTime[0]), 'seconds') / moment(histroyTime[1]).diff(moment(histroyTime[0]), 'seconds') * document.getElementById('process_point').parentElement.offsetWidth ) @@ -70,7 +78,7 @@ const VideoHeader = ({ operationState, changeSelectState, setProcessDisX, name,
- +
diff --git a/code/VideoAccess-VCMP/web/client/src/layout/index.jsx b/code/VideoAccess-VCMP/web/client/src/layout/index.jsx index 1fff8a4..7620186 100644 --- a/code/VideoAccess-VCMP/web/client/src/layout/index.jsx +++ b/code/VideoAccess-VCMP/web/client/src/layout/index.jsx @@ -153,8 +153,8 @@ const Root = props => { // IOT system cross window.addEventListener('message', async function (e) { // 监听 message 事件 - const { data } = e - console.log(e); + const { data, origin } = e + if (origin == 'https://open.ys7.com') return if (data && data.action) { if (data.action == 'initUser') { await store.dispatch(actions.auth.initAuth(data.user))