智慧工地前端
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.

450 lines
23 KiB

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./lib/WSPlayer/player.css">
<link rel="stylesheet" href="./lib/WSPlayer/window.division.css">
<link rel="stylesheet" href="./bootstrap.min.css">
<!-- 滚动进度条样式,按需引入 -->
<link rel="stylesheet" href="./scroll_style.css">
<title>wsplayer简易demo</title>
<style>
.platform-info {
display: flex;
margin-bottom: 20px;
flex-wrap: wrap;
padding: 20px;
}
.container {
display: flex;
6 days ago
padding: 0 10px !important;
margin: 0!important;
max-width: none;
}
.real-container,
.record-container {
width: 45%;
margin-left: 50px;
display: flex;
flex-direction: column;
}
.has-success .valid-feedback{
display: unset;
}
.cursor-pointer {
cursor: pointer;
}
.list-group a {
text-decoration: none;
color: #13425c;
}
</style>
</head>
<body>
<div class="alert alert-dismissible alert-primary" style="display: none;">
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
<span id="notify"></span>
</div>
<!-- 右侧固定小弹窗 -->
<div style="position: fixed; right: 0; top: 60px; width: 250px;display: none;">
<p style="font-size: 20px;">
<button type="button" class="btn btn-outline-secondary"><a href="/demo_api.html">点击跳转到功能api-demo页面</a></button>
</p>
<div class="platform-info">
大华平台信息
<div class="form-floating mb-3">
<input type="text" value="59.47.183.182" class="form-control" id="ip" placeholder="10.10.10.10">
<label for="floatingInput">平台IP:</label>
</div>
<div class="form-floating mb-3">
<input type="text" value="9443" class="form-control" id="platform_port" placeholder="443">
<label for="floatingInput">平台端口:</label>
</div>
<div class="form-floating mb-3">
<input type="text" class="form-control" id="real_port" placeholder="443">
<label id="real_port_label" for="floatingInput">实时预览拉流端口:</label>
</div>
<div class="form-floating mb-3">
<input type="text" class="form-control" id="record_port" placeholder="443">
<label id="record_port_label" for="floatingInput">录像回放拉流端口:</label>
</div>
<button type="button" class="btn btn-outline-secondary btn-sm" id="open-icc-info">一键填写开放平台联调环境</button>
<button type="button" class="btn btn-outline-secondary btn-sm" id="submit-platform">确认信息自动生成 wsUrl</button>
<span id="certificate-message" style="color: red;"></span>
</div>
</div>
<!-- 中间内容部分 -->
<div class="container">
<div class="real-container">
6 days ago
<span id="real-title">实时预览:</span>
<div id="ws-real-player" style="height: 500px; margin-bottom: 20px;"></div>
6 days ago
<div id="real-btn-box">
<button type="button" class="btn btn-outline-primary" id="real-btn">实时预览</button>
<button type="button" class="btn btn-outline-primary" id="close-real">关闭预览</button>
<!-- <button type="button" class="btn btn-outline-primary" id="talk-btn">开始对讲</button> -->
<!-- <button type="button" class="btn btn-outline-primary" id="talk-close-btn">关闭对讲</button> -->
</div>
</div>
<div class="record-container">
录像回放:
<div id="ws-record-player" style="height: 500px; margin-bottom: 20px;"></div>
<div style="display: flex;">
<!-- 日期 -->
<input style="width:140px;" type="date" id="date" class="form-control" id="record-date" value="2024-09-17"/>
<button style="margin:0 5px" type="button" class="btn btn-outline-primary" id="record-btn">录像回放</button>
<button type="button" class="btn btn-outline-primary" id="close-record">关闭录像</button>
<!-- <button type="button" class="btn btn-outline-primary" id="close-record">录像下载接口</button> -->
</div>
</div>
</div>
<script type="text/javascript" src="/dahua/lib/WSPlayer/PlaySDKInterface.js"></script>
<script type="text/javascript" src="/dahua/lib/WSPlayer/WSPlayer.js"></script>
<script type="module">
6 days ago
//获取参数real
let isReal = window.location.href.indexOf('real') !== -1 ? true : false;
if(isReal){
document.getElementsByClassName('record-container')[0].style.display = 'none';
document.getElementById('real-title').style.display = 'none';
document.getElementById('real-btn-box').style.display = 'none';
let readDom = document.getElementsByClassName('real-container')[0];
readDom.style.width = '100%';
}
// record-date默认今日
document.getElementById('date').value = new Date().toISOString().split('T')[0];
let cameraInfo;
let recordInfo;
//接收消息
window.addEventListener('message', function(event) {
console.log('接收到消息:', event.data);
if (event.data === 'reload') {
location.reload()
}else if (event.data.type ==='startVideo') {
cameraInfo = event.data.data;
playReal()
}
else if (event.data.type ==='playRecord') {
recordInfo = event.data.data;
playRecord()
}
});
function isMobile() {
// 正则表达式匹配常见的移动端平台关键字
return /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec)/i.test(navigator.userAgent);
}
// 判断移动端/PC端
if (isMobile()) {
window.location.href = './mobile.html'
}
function getDom(selector) {
return document.querySelector(selector)
}
let ipDom = getDom('#ip')
let platformDom = getDom('#platform_port')
let realPortDom = getDom('#real_port')
let recordPortDom = getDom('#record_port')
let isHttp = window.location.protocol === 'http:'
let wsplayerParam = JSON.parse(localStorage.getItem('wsplayerParam')) || {
ip: '',
platform: '',
realPort: isHttp ? '9100' : '9102',
recordPort: isHttp ? '9320' : '9322',
real_wsUrl: '',
record_wsUrl: '',
}
ipDom.value = wsplayerParam.ip
platformDom.value = wsplayerParam.platform
realPortDom.value = wsplayerParam.realPort
recordPortDom.value = wsplayerParam.recordPort
renderDom()
import PlayerManager from './icc/PlayerManager.js'
// 初始化播放器
var realPlayer = new PlayerManager({
el: "ws-real-player", /** 实时预览容器id,创建多个播放器,传入不同的容器id即可 **/
type: 'real', /** real - 实时预览 record - 录像回放 **/
maxNum: 25, /** 一个播放器上限能播放的路数,可根据实际情况设置,支持 1 4 9 16 25 **/
num: 1, /** 初始化,页面显示的路数 **/
showControl: true, /** 是否显示工具栏,默认显示 **/
prefixUrl: 'dahua/lib', /** 解码库所在位置的前缀 **/
receiveMessageFromWSPlayer: (methods, data, err) => { /* 回调函数,可以在以下回调函数里面做监听 */
switch(methods) {
case 'initializationCompleted':
console.log('初始化完成')
realPlayer.setPlayerAdapter("stretching")
6 days ago
if(isReal) window.parent.postMessage({type: 'startVideo'}, '*')
// playReal()
// 初始化完成,可调用播放方法(适用于动态加载解码库)
// 若回调未触发时就使用实时预览/录像回放,则无法播放。
// 此时我们可以调用一个
break;
case "changeStreamType": // 主/辅码流切换回调
console.log(data.channelData) // 通道数据
console.log(data.streamType) // 码流类型 0-主码流 1-辅码流1 2-辅码流2
console.log(data.selectIndex) // 窗口序号,从 0
break;
case "realSuccess": // 实时预览成功
console.log("实时预览成功")
break;
case "realError": // 实时预览失败
console.log("实时预览失败", err)
break;
case "notifyTalk":
// 点击窗口上的对讲按钮触发的事件回调
console.log("notifyTalk", data)
case "talkError": // 对讲失败
console.log("对讲失败");
break;
case 'selectWindowChanged': // 选中的窗口发生改变
console.log(data, "返回窗口信息")
break;
case 'windowNumChanged': // 播放器显示的路数发生改变
console.log(data, "返回显示的窗口数量")
break;
case 'closeVideo': // 视频关闭回调
// 点击关闭按钮引发的视频关闭进行提示
// 切换视频引发的视频关闭不进行提示
if(!data.changeVideoFlag) {
console.log(`窗口${data.selectIndex}的视频已关闭`)
}
break;
case 'statusChanged': // 视频状态发生改变
break;
case 'errorInfo': // 错误信息汇总
console.log(data, "可打印查看错误消息");
}
}
})
// 流地址方式播放实时预览
function playReal() {
let wsURL = `ws://59.47.183.182:9100`
let rtspURL = `${cameraInfo.url}?token=${cameraInfo.token}`.replace(/\$/g, "%24").replace(/&/g, "%26");
let streamType = 1
let channelId = cameraInfo.channelId
console.log('params :>> ', {
wsURL,
rtspURL,
streamType,
channelId
});
realPlayer.realByUrl({
rtspURL, // 必传
wsURL, // 必传
selectIndex: 0, // 必传, 播放窗口号
channelId, // 必传, 通道id
streamType, // 必传, 码流类型,
playerAdapter: 'stretching', // 选传, selfAdaption 自适应 | stretching 拉伸
channelData: { // 建议传, 通道树信息
// id: channelCode, // {String} 通道编码
// deviceCode: deviceCode, // {String} 设备编码
// deviceType: deviceType, // {String} 设备类型
// channelSeq: channelSeq, // {String|Number} 通道序号
}, // 选传
})
}
// 流地址方式对讲
function startTalk() {
let wsURL = getDom('#real-ws').value
let rtspURL = getDom('#talk-rtsp').value
let channelId = getDom('#real-channelId').value
let audioType = getDom('#audioType').value
let gbDevice = getDom('#gbDevice').value
realPlayer.talkByUrl({
selectIndex: 0, //
rtspURL,
wsURL,
audioType,
gbDevice: Boolean(Number(gbDevice)), // 广播
channelId
})
}
// 停止对讲
function stopTalk() {
// 此处调用停止对讲接口
}
// 初始化播放器
var recordPlayer = new PlayerManager({
el: "ws-record-player", /** 实时预览容器id,创建多个播放器,传入不同的容器id即可 **/
type: 'record', /** real - 实时预览 record - 录像回放 **/
maxNum: 4, /** 一个播放器上限能播放的路数,可根据实际情况设置,支持 1 4 9 16 25 **/
num: 1, /** 初始化,页面显示的路数 **/
showControl: true, /** 是否显示工具栏,默认显示 **/
prefixUrl: 'dahua/lib', /** 解码库所在位置的前缀 **/
receiveMessageFromWSPlayer: (methods, data, err) => { /* 回调函数,可以在以下回调函数里面做监听 */
switch(methods) {
case 'initializationCompleted':
// 初始化完成,可以调用拉流方法,实现播放器加载后立即显示画面
break;
case "recordSuccess": // 录像回放成功
console.log("录像回放成功")
break;
case "recordError": // 录像回放失败
console.log("录像回放失败", err)
break;
case "recordFinish": // 录像回放完成
console.log("录像回放完成");
break;
// 拖拽时间戳的回调
case 'switchStartTime':
// data.timeStamp 时间戳
// data.channelData 通道信息
// {timeStamp, channelData: player.options.channelData, hasVideoRecord: true}
// palyerManager.recordByUrl(recordPlayer.recordByUrl({
// wsURL: '', // ws地址
// rtspURL: '', // 重新请求后的rtsp
// channelId , // 必传, 通道id
// records: records, // 录像列表
// selectIndex: 0, // 必传
// playRecordByTime: true // 必传false
// }))
break;
case 'selectWindowChanged': // 选中的窗口发生改变
console.log(data, "返回窗口信息")
break;
case 'windowNumChanged': // 播放器显示的路数发生改变
console.log(data, "返回显示的窗口数量")
break;
case 'closeVideo': // 视频关闭回调
// 点击关闭按钮引发的视频关闭进行提示
// 切换视频引发的视频关闭不进行提示
if(!data.changeVideoFlag) {
console.log(`窗口${data.selectIndex}的视频已关闭`)
}
break;
case 'statusChanged': // 视频状态发生改变
break;
case 'errorInfo': // 错误信息汇总
console.log(data, "可打印查看错误消息");
}
}
})
// 流地址方式播放录像回放
const playRecord = () => {
let records = recordInfo.records;
let wsURL = `ws://59.47.183.182:9320`
let rtspURL = `${recordInfo.url}?token=${recordInfo.token}`;
let channelId = recordInfo.channelId
console.log('params :>> ', {
wsURL,
rtspURL,
channelId: channelId, // 必传, 通道id
records: records || [], // 录像列表
selectIndex: 0, // 必传
playRecordByTime: true, // 默认不传,拖拽异常时请传入false
channelData: {
records: records || []
}, // 选传, 通道信息
});
recordPlayer.recordByUrl({
wsURL,
rtspURL,
channelId: channelId, // 必传, 通道id
records: records || [], // 录像列表
selectIndex: 0, // 必传
playRecordByTime: true, // 默认不传,拖拽异常时请传入false
// startTime: records[0].startTime, // 建议传,不传则会通过records数组中截取, 格式 // new Date().getTime() / 1000 【到秒时间戳】
// endTime: records[0].endTime, // 建议传,不传则会通过records数组中截取, 格式 // new Date().getTime() / 1000 【到秒时间戳】
// playerAdapter: opt.playerAdapter, // 选传, , selfAdaption 自适应 | stretching 拉伸
channelData: {
records: records || []
}, // 选传, 通道信息
})
}
getDom('.btn-close').addEventListener('click', () => {
getDom('.alert-dismissible').style.display = 'none'
})
getDom('#real-btn').addEventListener('click', () => {
//向父窗口发送消息
window.parent.postMessage({type: 'startVideo'}, '*')
// playReal()
})
// getDom('#talk-btn').addEventListener('click', () => {
// startTalk()
// })
// 关闭对讲,此功能需调用关闭对讲接口
// getDom('#talk-close-btn').addEventListener('click', () => {
// stopTalk()
// })
getDom('#record-btn').addEventListener('click', () => {
let date = getDom('#date').value;
window.parent.postMessage({type:'playRecord',date}, '*')
// playRecord()
})
getDom('#close-real').addEventListener('click', e => {
realPlayer && realPlayer.close(0)
})
getDom('#close-record').addEventListener('click', e => {
recordPlayer && recordPlayer.close(0)
})
// 一键生成icc联调环境信息
getDom('#open-icc-info').addEventListener('click', (e) => {
wsplayerParam = {
ip: '124.160.33.135',
platform: '4077',
realPort: isHttp ? '4079' : '4081',
recordPort: isHttp ? '4080' : '4082',
real_wsUrl: `${isHttp ? 'ws': 'wss'}://124.160.33.135:${isHttp ? '4079' : '4081'}`, // 实时预览ws地址
record_wsUrl: `${isHttp ? 'ws': 'wss'}://124.160.33.135:${isHttp ? '4080' : '4082'}`
}
ipDom.value = wsplayerParam.ip
platformDom.value = wsplayerParam.platform
realPortDom.value = wsplayerParam.realPort
recordPortDom.value = wsplayerParam.recordPort
localStorage.wsplayerParam = JSON.stringify(wsplayerParam)
renderDom()
})
// 生成拉流socket信息
getDom('#submit-platform').addEventListener('click', (e) => {
wsplayerParam = {
ip: ipDom.value,
platform: platformDom.value,
realPort: realPortDom.value,
recordPort: recordPortDom.value,
real_wsUrl: `${isHttp ? 'ws://': 'wss://'}${ipDom.value}:${realPortDom.value}`, // 实时预览ws地址
record_wsUrl: `${isHttp ? 'ws://': 'wss://'}${ipDom.value}:${recordPortDom.value}`
}
localStorage.wsplayerParam = JSON.stringify(wsplayerParam)
renderDom()
})
function renderDom() {
return;
!isHttp && (getDom('#certificate-message').innerHTML = `如果平台未配置证书,请先临时访问 <a target="_blank" href="${window.location.protocol}//${ipDom.value}:${realPortDom.value}" >${window.location.protocol}//${ipDom.value}:${realPortDom.value}</a> 浏览器安全访问该地址,否则无法拉流`)
getDom('#real-ws').value = wsplayerParam.real_wsUrl
getDom('#record-ws').value = wsplayerParam.record_wsUrl
getDom('#real-ws').placeholder = `${isHttp ? 'ws' : 'wss'}://10.10.10.10:${realPortDom.value}`
getDom('#record-ws').placeholder = `${isHttp ? 'ws' : 'wss'}://10.10.10.10:${recordPortDom.value}`
getDom('#real-rtsp').placeholder = `rtsp://10.10.10.10:${realPortDom.value}/dss/monitor/param/cameraid=1000000%240%26substream=1?token=1`
getDom('#record-rtsp').placeholder = `rtsp://10.10.10.10:${recordPortDom.value}/playback/pu/1?token=1`
getDom('#talk-rtsp').placeholder = `rtsp://10.10.10.10:${realPortDom.value}/talk/pu/1?token=1`
}
getDom('#notify').innerHTML = isHttp ? `注:当前是${window.location.protocol}服务, 如果你是集成在 https 项目中,请 启动 node https.cjs 进行查看` : `注:当前是${window.location.protocol}服务, 如果你是集成在 http 项目中,请 启动 node http.cjs 进行查看。 https服务,需要在大华的平台上配置https证书,否则无法拉流<a href="https://open-icc.dahuatech.com/iccdoc/openfaq/wiki/iccfaq/question/admin.html#WSPlayer%E6%8B%89%E6%B5%81wss%E9%85%8D%E7%BD%AE%EF%BC%9B%E8%A7%86%E9%A2%91%E5%BA%94%E7%94%A8"" target="_blank">跳转到证书说明</a>`
getDom('#real_port_label').innerHTML = window.location.protocol + '实时预览拉流端口:'
getDom('#record_port_label').innerHTML = window.location.protocol + '录像回放拉流端口:'
// getDom('#is-support-talk').innerHTML = isHttp ? '(当前为http协议,不支持对讲)' : ''
// if(isHttp) {
// getDom('#talk-rtsp').disabled = true
// getDom('#audioType').disabled = true
// getDom('#gbDevice').disabled = true
// }
</script>
</body>
</html>