@ -0,0 +1,22 @@ |
|||
'use strict'; |
|||
const mqtt = require('mqtt'); |
|||
|
|||
module.exports = async function factory (app, opts) { |
|||
// const client = mqtt.connect(opts.mqtt.mqttVideoServer);
|
|||
|
|||
// client.on('connect', function () {
|
|||
// console.info(`mqtt connect success ${opts.mqtt.mqttVideoServer}`);
|
|||
// })
|
|||
// client.on('error', function (e) {
|
|||
// console.error(`mqtt connect failed ${opts.mqtt.mqttVideoServer}`);
|
|||
// app.fs.logger.error('info', '[FS-AUTH-MQTT]', `mqtt connect failed ${opts.mqtt.mqttVideoServer}`);
|
|||
// })
|
|||
|
|||
// client.subscribe('test', { qos: 2 });//订阅主题为test的消息
|
|||
|
|||
// client.on('message', function (top, message) {
|
|||
// console.log(message.toString());
|
|||
// });
|
|||
|
|||
// app.mqttVideoServer = client
|
|||
} |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 906 B |
After Width: | Height: | Size: 671 B |
After Width: | Height: | Size: 632 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1012 B |
@ -0,0 +1,48 @@ |
|||
import React, { useRef, useEffect, useState } from 'react' |
|||
import moment from 'moment' |
|||
import './textScroll.less' |
|||
|
|||
function TextScroll (props) { |
|||
const { content, duration } = props |
|||
const [showContent, setShowContent] = useState('1231231') |
|||
|
|||
useEffect(() => { |
|||
let repeatTime = moment() |
|||
let refreshTime = moment() |
|||
const scroll = () => { |
|||
let contentParent = document.getElementById('marquee_box') |
|||
document.getElementById('contentPMakeUp').style.width = contentParent.clientWidth + 'px' |
|||
// 控制频率 |
|||
if (moment().diff(refreshTime) > 1000 / 60) { |
|||
const contentP = document.getElementById('contentP') |
|||
// 静态等待时间 |
|||
if (moment().diff(repeatTime) > 1000 * 1.5) { |
|||
contentP.style.visibility = 'visible' |
|||
} |
|||
if (moment().diff(repeatTime) > 1000 * 3) { |
|||
contentParent.scrollLeft = contentParent.scrollLeft + 1 |
|||
} |
|||
if (contentParent.scrollLeft >= contentP.clientWidth + 24) { |
|||
contentParent.scrollLeft = 0 |
|||
repeatTime = moment() |
|||
setShowContent('asdasd' + Math.random()) |
|||
contentP.style.visibility = 'hidden' |
|||
} |
|||
refreshTime = moment() |
|||
} |
|||
window.requestAnimationFrame(scroll) |
|||
} |
|||
window.requestAnimationFrame(scroll) |
|||
}, []) |
|||
|
|||
return ( |
|||
<div className="marquee_box" id='marquee_box' style={{ overflow: 'hidden' }} > |
|||
<p style={{ position: 'relative', left: 24 }}> |
|||
<p id='contentP' style={{ display: 'inline-block', visibility: 'hidden' }}>{showContent}</p> |
|||
<p id='contentPMakeUp' style={{ width: 0, display: 'inline-block' }}></p> |
|||
</p> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default React.memo(TextScroll) |
@ -0,0 +1,19 @@ |
|||
.marquee_box { |
|||
width: 100%; |
|||
height: 100%; |
|||
word-break: keep-all; |
|||
white-space: nowrap; |
|||
// display: flex; |
|||
// align-items: center; |
|||
} |
|||
|
|||
.marquee_box p { |
|||
// display: inline-block; |
|||
padding: 0; |
|||
margin: 0; |
|||
} |
|||
|
|||
.marquee_box:hover p { |
|||
animation-play-state: paused; |
|||
cursor: default; |
|||
} |
@ -0,0 +1,143 @@ |
|||
import React, { useState, useEffect, useRef } from "react"; |
|||
import { connect } from "react-redux"; |
|||
import moment from 'moment' |
|||
import { Button, Modal, Col, Row, Space } from "@douyinfe/semi-ui"; |
|||
import TextScroll from './textScroll' |
|||
import './videoPlay.less'; |
|||
|
|||
const VideoPlay = ({ height, width }) => { |
|||
const [jessibuca, setjessibuca] = useState(null) |
|||
const [playUrl, setPlayUrl] = useState('http://flv.bdplay.nodemedia.cn/live/bbb.flv') |
|||
const [isPlaying, setIsPlaying] = useState(false) |
|||
const [operationState, setoperationState] = useState() |
|||
const operation = [{ |
|||
key: 'control', |
|||
click: () => { console.log(121212); } |
|||
}, { |
|||
key: 'talk', |
|||
click: () => { console.log(121212); } |
|||
}, { |
|||
key: 'fullScreen', |
|||
click: () => { console.log(121212); } |
|||
}, { |
|||
key: 'histroy', |
|||
click: () => { console.log(121212); } |
|||
},] |
|||
useEffect(() => { |
|||
create() |
|||
let nextOperationState = {} |
|||
for (let p of operation) { |
|||
nextOperationState[p.key] = { |
|||
select: false |
|||
} |
|||
} |
|||
setoperationState(nextOperationState) |
|||
}, []) |
|||
|
|||
const create = () => { |
|||
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) |
|||
} |
|||
|
|||
useEffect(() => { |
|||
play() |
|||
}, [jessibuca]) |
|||
|
|||
const play = () => { |
|||
if (jessibuca && playUrl) { |
|||
jessibuca.play(playUrl); |
|||
setIsPlaying(true) |
|||
} |
|||
} |
|||
|
|||
const pause = () => { |
|||
if (jessibuca) { |
|||
jessibuca.pause(); |
|||
setIsPlaying(false) |
|||
} |
|||
} |
|||
|
|||
const butStyle = { |
|||
border: '1px solid #fff', display: 'inline-block', color: '#fff', padding: '0 10px', |
|||
display: 'flex', alignItems: 'center', height: '64%', marginLeft: 12 |
|||
} |
|||
|
|||
return ( |
|||
<> |
|||
<div style={{ height: height || '100%', width: width || '100%' }}> |
|||
|
|||
<div style={{ position: 'relative', }}> |
|||
<div style={{ |
|||
height: 42, lineHeight: '42px', background: '#00000026', |
|||
position: 'absolute', width: '100%', zIndex: 99, |
|||
color: '#fff' |
|||
}}> |
|||
<Row > |
|||
<Col span={9} style={{ |
|||
backgroundImage: 'url(/assets/images/background/videoPlayBg.png)', |
|||
backgroundSize: '100% 100%', |
|||
backgroundRepeat: 'no-repeat', |
|||
textAlign: 'center' |
|||
}}>123</Col> |
|||
<Col span={15} style={{}}> |
|||
<div style={{ paddingRight: 12 }}> |
|||
<TextScroll content={['asdadasdasdasdasdasd','123123']} duration={6} /> |
|||
</div> |
|||
</Col> |
|||
</Row> |
|||
</div> |
|||
<div id="container" style={{ height: height || '100%', width: width || '100%' }}></div> |
|||
<div style={{ |
|||
height: 42, lineHeight: '42px', background: 'linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%)', padding: '0 12px', |
|||
display: 'flex', justifyContent: 'space-between', |
|||
position: 'absolute', bottom: 0, width: '100%', zIndex: 99 |
|||
}}> |
|||
<div style={{ display: 'flex', alignItems: 'center' }}> |
|||
{ |
|||
operationState ? |
|||
operation.map(p => { |
|||
return <img |
|||
src={`/assets/images/background/video-icon-${p.key}-${operationState[p.key].select ? 'select' : 'unselect'}.png`} |
|||
height={26} |
|||
style={{ marginRight: 24 }} |
|||
/> |
|||
}) : '' |
|||
} |
|||
</div> |
|||
<div style={{ display: 'flex', alignItems: 'center' }}> |
|||
<div style={butStyle}>标清</div> |
|||
<div style={butStyle}>高清</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
</> |
|||
) |
|||
} |
|||
|
|||
function mapStateToProps (state) { |
|||
const { auth } = state; |
|||
return { |
|||
user: auth.user, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(VideoPlay); |
@ -0,0 +1,32 @@ |
|||
import React, { useState, useEffect, useRef } from "react"; |
|||
import { connect } from "react-redux"; |
|||
import moment from 'moment' |
|||
import { Button, Modal, } from "@douyinfe/semi-ui"; |
|||
import VideoPlay from './videoPlay' |
|||
import './videoPlayModal.less'; |
|||
|
|||
const VideoPlayModal = ({ visible }) => { |
|||
|
|||
return ( |
|||
<Modal |
|||
visible={visible} |
|||
header={null} |
|||
footer={null} |
|||
size={'large'} |
|||
style={{}} |
|||
bodyStyle={{}} |
|||
className="videoModal" |
|||
> |
|||
<VideoPlay height={460} /> |
|||
</Modal> |
|||
) |
|||
} |
|||
|
|||
function mapStateToProps (state) { |
|||
const { auth } = state; |
|||
return { |
|||
user: auth.user, |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(VideoPlayModal); |
@ -0,0 +1,5 @@ |
|||
.videoModal { |
|||
.semi-modal-content { |
|||
padding: 0; |
|||
} |
|||
} |