zhgdyunapp/pages/videoManage/playVideo.vue
2025-12-17 15:10:03 +08:00

1744 lines
45 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="fullHeight">
<headers :showBack="true" :themeType="true">
<view class="headerName">
{{videoInfo.videoName}}
</view>
</headers>
<!-- <video class="videoBox" id="myVideo" :custom-cache="false" :src="url" controls autoplay></video> -->
<template v-if="videoConfig.enableNotPlugin != 1">
<!-- APP环境使用web-view -->
<!-- #ifdef APP-PLUS -->
<video v-if="!isYsy" class="videoBox" id="myVideo" :custom-cache="false" :src="playUrlFilter" controls
autoplay></video>
<!-- #endif -->
<!-- H5环境使用ezuikit -->
<!-- #ifdef H5 -->
<my-player-m3u8 v-if="!isYsy && playUrlFilter" :showMask="true" :src="playUrlFilter" :autoplay="true" />
<!-- #endif -->
<view v-if="isYsy && playUrlFilter && accessToken" :style="{width: '100%', height: '225px'}">
<!-- H5环境使用ezuikit -->
<!-- #ifdef H5 -->
<iframe :src="ysyPlayUrl" :style="webviewStyles" frameborder="0" :scrolling="'no'"></iframe>
<!-- #endif -->
<!-- APP环境使用web-view -->
<!-- #ifdef APP-PLUS -->
<web-view :src="ysyPlayUrl" :style="webviewStyles" :webview-styles="webviewConfig"></web-view>
<!-- #endif -->
</view>
<view v-else class="webview-container" :style="{width: '100%', height: '225px'}">
<!-- #ifdef H5 -->
<!-- <iframe :src="webURL" :style="webviewStyles" ref="webViewRef" @onPostMessage="postMessage"
:scrolling="'no'" frameborder="0" /> -->
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<!-- ios语音对讲去 -->
<web-view :src="webURL" :style="{
width: '10',
height: '10',
}" :webview-styles="{
position: 'static',
}" :fullscreen="false" @message="postMessage"></web-view>
<!-- #endif -->
</view>
</template>
<template v-else>
<div id="playerId"></div>
</template>
<view class="video-box">
<view class="videoName">
<view class="view-set" @click="setSpeed">
<image src="@/static/videoControlIcon/view-set.png" class="bg"></image>
<text>球机转速</text>
</view>
<!-- {{videoInfo.videoName}} -->
<button v-if="videoInfo.videoType==3" type="primary" class="changeBtn btn"
@click="changeStreamFn">{{streamType==1?'切换到主码流':'切换到子码流'}}</button>
</view>
<view class="videoOperateBox">
<!-- <text class="desc">当前云台速度:{{ this.opSize }}</text> -->
<view class="box">
<image src="@/static/videoControlIcon/bg1.png" class="bg"></image>
<view class="pic top" :class="{'topActive': typeName == 'UP' && videoFlag}"
@touchstart="controlVideoMouse('UP', 0)" @touchend="controlVideoMouse('UP', 1)"></view>
<view class="pic left" :class="{'leftActive': typeName == 'LEFT' && videoFlag}"
@touchstart="controlVideoMouse('LEFT', 0)" @touchend="controlVideoMouse('LEFT', 1)"></view>
<view class="pic bottom" :class="{'bottomActive': typeName == 'DOWN' && videoFlag}"
@touchstart="controlVideoMouse('DOWN', 0)" @touchend="controlVideoMouse('DOWN', 1)"></view>
<view class="pic right" :class="{'rightActive': typeName == 'RIGHT' && videoFlag}"
@touchstart="controlVideoMouse('RIGHT', 0)" @touchend="controlVideoMouse('RIGHT', 1)"></view>
<!-- <view class="pic center" @click="stop()"></view> -->
</view>
<!-- <view class="box2">
<view class="zoom zoomin"
:style="{backgroundImage: typeName == 'ZOOM_OUT' && videoFlag?'url(@/static/videoControlIcon/2.png)':'url(@/static/videoControlIcon/1.png)'}"
@click="controlVideoFn(0,0,-0.2,'ZOOM_OUT')"></view>
<view class="zoom zoomout"
:style="{backgroundImage: typeName == 'ZOOM_IN' && videoFlag?'url(@/static/videoControlIcon/4.png)':'url(@/static/videoControlIcon/3.png)'}"
@click="controlVideoFn(0,0,0.2,'ZOOM_IN')"></view>
</view> -->
<view @touchstart="controlVideoMouse('ZOOM_OUT', 0)" @touchend="controlVideoMouse('ZOOM_OUT', 1)"
class="box-left box-main">
<u-icon name="minus" color="#EFEFEF" size="60"></u-icon>
</view>
<view @touchstart="controlVideoMouse('ZOOM_IN', 0)" @touchend="controlVideoMouse('ZOOM_IN', 1)"
class="box-right box-main">
<u-icon name="plus" color="#EFEFEF" size="60"></u-icon>
</view>
<!-- <view class="video-playback" v-if="videoConfig.videoType != 1" @click="toBackList">
视频回放
</view> -->
<!-- <view class="set-speed">
<u-button @click="setSpeed" type="primary">设置球机转动速度</u-button>
</view> -->
</view>
<!-- #ifdef H5 -->
<!-- <view class="voice-icon" @click="btnStart"></view> -->
<view class="voice-icon" @click="handleAuthRecord"></view>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<view class="voice-icon" @click="handleAuthRecord"></view>
<!-- #endif -->
</view>
<u-tabbar :value="tabActive" @change="handleChangeTab" :list="tabList" activeColor="#498CEC"
inactiveColor="#4D4D4D"></u-tabbar>
<uni-popup ref="speedPopup" type="center">
<view class="speed_wrap">
<text class="s_title">设置球机转动速度</text>
<UNumberBox :value="opSize" :inputHeight="70" @change="changeSpeed" />
<u-button class="s_btn" @click="handleSaveSpeed">确认</u-button>
</view>
</uni-popup>
<audio id="html_audio_remote" autoPlay />
<u-popup mode="bottom" :mask-close-able="false" v-model="voiceShow" :closeable="false">
<view class="voice-main">
<view class="voice-header">
正在对讲
</view>
<view class="voice-image">
<view class="voice-icon_left"></view>
<view class="voice-icon_center"></view>
<view class="voice-icon_left"></view>
</view>
<view class="voice-text">
{{formattedTime}}
</view>
<!-- #ifdef H5 -->
<view @click="btnStop" class="footer-btn footer-btn1">
结束对讲
</view>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<view @click="btnTalkbackStop" class="footer-btn footer-btn1">
结束对讲
</view>
<!-- #endif -->
<!-- <view class="footer-btn footer-btn2">
<view>取消</view>
<view>发送</view>
</view> -->
</view>
</u-popup>
</view>
</template>
<script>
// #ifdef H5
import "@/utils/sos-v1.0.17.js";
// #endif
// 引入h5player
// import '@/utils/monitor/h5player.min.js'
import moment from "moment";
// const SOS = require('@/utils/sos-v1.0.17.js');
import headers from '@/components/headers/headers.vue'
import UNumberBox from "@/components/u-number-box/u-number-box.vue"
import MyPlayerM3u8 from '@/components/my-player-m3u8/my-player-m3u8.vue';
import previewIcon from '@/static/videoControlIcon/previewIcon.png'
import previewActiveIcon from '@/static/videoControlIcon/previewIcon-active.png'
import playbackIcon from '@/static/videoControlIcon/playbackIcon.png'
import playbackActiveIcon from '@/static/videoControlIcon/playbackIcon-active.png';
import permission from "@/common/permission";
export default {
components: {
headers,
UNumberBox,
MyPlayerM3u8
},
data() {
return {
url: '', //rtsp://admin:jxj12345@192.168.0.64:554/h264/ch1/main/av_stream
videoInfo: {
videoName: '',
videoType: null
},
streamType: 1, //1是子码流 2是主码流
opSize: 20,
videoResponseInfo: {},
videoFlag: false,
typeName: "",
videoConfig: {},
projectSn: "",
tempSpeed: 20,
tabList: [{
text: '实时预览',
iconPath: previewIcon,
selectedIconPath: previewActiveIcon
},
{
text: '视频回放',
iconPath: playbackIcon,
selectedIconPath: playbackActiveIcon
}
],
tabActive: 0,
voiceShow: false,
sosSDK: null,
taskCode: [], // 对讲任务码
useConfigInfo: {},
webURL: "",
webviewStyles: {
width: "100%",
height: "100%",
},
// 播放器对象
playerVideo: null,
numCount: 1,
iWndIndex: 0,
maxWindows: 16, // 最大窗口数
recordingBegin: false,
muted: true,
talkbackBegin: false,
playback: {
startTime: "2023-08-16T00:00:00",
endTime: "2023-08-16T23:00:00",
valueFormat: moment.HTML5_FMT.DATETIME_LOCAL_SECONDS,
seekStart: "2023-08-16T10:00:00",
rate: "",
},
isFullScreen: false,
isFullScreenAll: false,
h5Url: "",
H5Player: null,
seconds: 0,
secondsTime: null,
testModule: null,
};
},
onLoad(options) {
// #ifdef H5
this.H5Player = require('@/static/monitor/h5player.min.js');
// console.log(888888, this.H5Player)
// #endif
this.testModule = uni.requireNativePlugin("DCTestUniPlugin-TestModule");
//videoType 1萤石云2乐橙3ISC4大华5宇视6国标
// this.url = options.url
this.tabActive = options.tabActive;
this.videoInfo = uni.getStorageSync('videoInfo');
if (options.sn) {
this.projectSn = options.sn;
} else {
this.projectSn = JSON.parse(uni.getStorageSync('projectDetail')).projectSn;
}
this.opSize = Number(uni.getStorageSync('videoOpSize') || 20);
this.streamType = this.videoInfo.defaultStreamType;
console.log(7777, this.videoInfo)
if (this.videoInfo.videoType == 2) {
this.url = this.videoInfo.liveRadioUrl
} else {
this.getPlayUrl()
}
this.getUseProjectVideoConfig();
this.getUseConfig();
},
onReady() {
this.$nextTick(() => {
// #ifdef APP-PLUS
this.setHeight()
// #endif
})
},
onUnload() {
this.cleanup()
},
computed: {
playUrlFilter() {
//
// let url = "";
// if(this.videoConfig && this.videoConfig.videoType == 1) {
// url = this.url
// } else if (this.url) {
// url = 'rtsp://42.180.188.17' + this.url.substring(20);
// }
console.log(88888, this.url);
return this.url
},
isYsy() {
console.info(this.videoInfo?.videoType, '======')
return this.videoInfo?.videoType == 1
},
ysyPlayUrl() {
// 萤石云播放地址
return `https://open.ys7.com/ezopen/h5/iframe?url=${this.playUrlFilter}&template=simple&autoplay=1&accessToken=${this.accessToken}`
},
formattedTime() {
return this.$dayjs.duration(this.seconds, 'seconds').format('HH:mm:ss');
},
},
methods: {
setHeight() {
let height = 0; //定义动态的高度变量,如高度为定值,可以直接写
let statusbar = 0
uni.getSystemInfo({
//成功获取的回调函数,返回值为系统信息
success: (sysinfo) => {
statusbar = sysinfo.statusBarHeight;
height = sysinfo.windowHeight; //自行修改,自己需要的高度 此处如底部有其他内容,可以直接---(-50)这种
},
complete: () => {}
});
this.pageTop = statusbar + 44 + 'px'
// #ifdef APP-PLUS
let currentWebview = this.$scope.$getAppWebview(); //获取当前web-view
setTimeout(function() {
let wv = currentWebview.children()[0];
wv.setStyle({ //设置web-view距离顶部的距离以及自己的高度单位为px
top: statusbar + 44, //此处是距离顶部的高度,页面的头部
height: 1, //webview的高度
scalable: false, //webview的页面是否可以缩放双指放大缩小,
position: "static",
})
}, 500); //如页面初始化调用需要写延迟
// #endif
},
// 接收h5页面发来的键值判断需要执行的操作
postMessage(res) {
console.log("postMessage: ", res)
let {
err,
msg
} = res.detail.data[0];
uni.hideLoading()
if (msg == 'success') {
this.voiceShow = true;
this.secondsTime = setInterval(() => {
this.seconds += 1;
}, 1000);
} else {
uni.showToast({
title: "对讲连接失败",
icon: 'none'
})
}
// uni.showModal({
// title:"提示",
// content:evt.detail.data[0].msg
// })
},
async handleAuthRecord() {
let that = this;
// #ifdef APP-PLUS
const appAuthorizeSetting = uni.getAppAuthorizeSetting()
console.log(appAuthorizeSetting.microphoneAuthorized)
if (appAuthorizeSetting.microphoneAuthorized === 'authorized') {
this.btnTalkbackStart()
} else {
uni.showToast({
title: '未授权麦克风权限,请开启权限',
icon: 'none'
})
if (plus.os.name === 'iOS') {
const AVAudioSession = plus.ios.import('AVAudioSession');
const session = AVAudioSession.sharedInstance();
session.requestRecordPermission(function(granted) {
plus.ios.deleteObject(session);
console.log(3344, granted)
if (granted) {
that.btnTalkbackStart()
}
});
} else {
setTimeout(() => {
console.log(1122334455)
permission.gotoAppPermissionSetting()
}, 1000)
}
}
// #endif
// #ifdef H5
that.btnTalkbackStart();
// #endif
},
btnTalkbackStart() {
const that = this;
console.log(1111, this.videoInfo);
let requestData = {
protocol: "wss",
projectSn: this.projectSn,
serialNumber: this.videoInfo.serialNumber,
}
if (this.secondsTime) clearInterval(this.secondsTime);
this.seconds = 0;
// 获取系统信息
const systemInfo = uni.getSystemInfoSync();
console.log(334455, systemInfo)
if (systemInfo.platform === 'ios') {
this.sendRequest({
url: "xmgl/videoItem/getTalkURLs",
data: {
...requestData,
protocol: "rtsp",
},
method: "POST",
success(res) {
console.log("我进来了", that.testModule)
const res2 = JSON.parse(res.result);
if (!res2.data) {
uni.showToast({
title: '获取url失败',
icon: 'none'
})
return
}
const url = res2.data.url;
that.testModule.startTalk({
talkUrl: url
},
(res) => {
console.log(88888, res)
if (res.status == "SUCCESS") {
that.voiceShow = true;
that.secondsTime = setInterval(() => {
that.seconds += 1;
}, 1000);
} else if(res.status == "EXCEPTION" || res.status == "FAILED") {
uni.showToast({
title: '连接失败!',
icon: 'none'
});
}
}
);
}
})
return
}
// #ifdef APP-PLUS
let currentWebview = this.$scope.$getAppWebview();
const wv = currentWebview.children()[0];
console.log(2222, wv)
// #endif
this.sendRequest({
url: "xmgl/videoItem/getTalkURLs",
data: requestData,
method: "POST",
success(res) {
console.log(res.result)
const res2 = JSON.parse(res.result);
if (!res2.data) {
uni.showToast({
title: '获取url失败',
icon: 'none'
})
return
}
// uni.showToast({
// title: '开始对讲!',
// icon: 'none'
// });
// that.voiceShow = true;
// that.secondsTime = setInterval(() => {
// that.seconds += 1;
// }, 1000);
// .replace("hrdl.zhgdyun.com", "sp.szjxj.com")
const url = res2.data.url;
const data = {
url: url,
type: 'start'
}
console.log('获取talkUrl', res2)
// #ifdef H5
that.h5Url = url.replace("hrdl.zhgdyun.com", "sp.szjxj.com");
that.talkbackStart();
// #endif
// #ifdef APP-PLUS
that.$nextTick(() => {
uni.showLoading({
title: "连接中"
})
})
if (plus.os.name === 'iOS') {
const encodedData = encodeURIComponent(JSON.stringify(data));
console.log(111, encodedData)
wv.evalJS(`handleMessage(decodeURIComponent('${encodedData}'))`);
} else {
wv.evalJS(`handleMessage('${JSON.stringify(data)}')`);
}
// #endif
// if (process.env.VUE_APP_PLATFORM === 'h5') {
// const iframe = that.$refs.webViewRef.contentWindow;
// console.info(iframe, 'iframe')
// iframe.handleMessage(JSON.stringify(data))
// // iframe.postMessage(JSON.stringify(data), 'https://example.com');
// }
}
})
},
btnTalkbackStop() {
const that = this;
const systemInfo = uni.getSystemInfoSync();
if (systemInfo.platform === 'ios') {
this.testModule.stopTalk();
clearInterval(this.secondsTime);
this.voiceShow = false;
return
}
// #ifdef APP-PLUS
let currentWebview = this.$scope.$getAppWebview();
const wv = currentWebview.children()[0];
// #endif
console.log(1111, this.videoInfo)
let requestData = {
projectSn: this.projectSn,
serialNumber: this.videoInfo.serialNumber,
}
this.sendRequest({
url: "xmgl/videoItem/stopTalkURLs",
data: requestData,
method: "POST",
success(res) {
uni.showToast({
title: '结束对讲!',
icon: 'none'
});
that.voiceShow = false;
clearInterval(that.secondsTime);
const data = {
url: null,
type: 'end'
}
// #ifdef APP-PLUS
wv.evalJS(`handleMessage('${JSON.stringify(data)}')`);
// #endif
if (process.env.VUE_APP_PLATFORM === 'h5') {
const iframe = this.$refs.webViewRef.contentWindow;
console.info(iframe, 'iframe')
iframe.handleMessage(JSON.stringify(data))
}
}
})
},
// 开始对讲
talkbackStart() {
if (this.secondsTime) clearInterval(this.secondsTime);
this.seconds = 0;
console.log(11122, this.h5Url, this.playerVideo)
// uni.showToast({
// title: '进来!',
// icon: 'none'
// });
this.playerVideo.JS_SetConnectTimeOut(0, 1000);
this.playerVideo.JS_StartTalk(this.h5Url).then(
() => {
uni.showToast({
title: '开始对讲!',
icon: 'none'
});
this.playerVideo.JS_OpenSound(0).then(
() => {
console.info('JS_OpenSound success');
},
(err) => {
console.info('JS_OpenSound failed');
}
);
this.voiceShow = true;
this.secondsTime = setInterval(() => {
this.seconds += 1;
}, 1000)
console.log("record start ...");
},
(e) => {
uni.showToast({
title: e,
icon: 'none'
})
console.error(e);
this.voiceShow = false;
}
);
},
// 结束对讲
talkbackStop() {
let playerVideo = this.playerVideo;
playerVideo.JS_StopTalk().then(
(res) => {
console.log("record stoped, saving ...", res);
clearInterval(this.secondsTime);
this.voiceShow = false;
this.playerVideo.JS_CloseSound(0).then(
() => {
console.info('JS_CloseSound success');
},
(err) => {
console.info('JS_CloseSound failed');
}
);
},
(e) => {
console.error(e);
}
);
},
btnStart() {
console.log("start on click");
if (this.videoConfig.enableNotPlugin == 1) {
this.talkbackStart();
return;
}
this.voiceShow = true;
this.taskCode = [];
if (this.sosSDK) {
const broadcastDevs = this.videoInfo.broadcastDevs.split(',');
console.log(124545, broadcastDevs)
broadcastDevs.forEach(item => {
// 开始音频对讲
this.sosSDK.audioSpeakStart({
// 必填参数
DeviceId: Number(item),
AudioDomId: 'html_audio_remote',
}, (speakResult) => {
if (speakResult && speakResult.success) {
this.taskCode.push(speakResult.TaskCode);
console.log('开始对讲成功')
}
})
})
} else {
uni.showToast({
title: '对讲失败!',
icon: 'none'
})
}
},
btnStop() {
console.log("stop on click");
// 获取系统信息
const systemInfo = uni.getSystemInfoSync();
console.log(334455, systemInfo)
// if (systemInfo.platform === 'ios') {
// const message = {
// action: "stopTalk",
// data: {
// timestamp: new Date().getTime(),
// reason: "用户手动停止"
// }
// };
// try {
// // window.webkit.messageHandlers.talkHandler.postMessage(message);
// window.postMessage(message);
// clearInterval(this.secondsTime);
// this.voiceShow = false;
// } catch (error) {
// uni.showLoading({
// title: "结束失败"
// })
// }
// return
// }
if (this.videoConfig.enableNotPlugin == 1) {
this.talkbackStop();
return;
}
if (this.sosSDK) {
const promises = [];
this.taskCode.forEach(item => {
promises.push(this.sosSDK.audioSpeakStop({
TaskCode: item
}));
})
console.log(1111, promises)
Promise.all(promises)
.then((res) => {
console.log(res)
}).catch((error) => {
console.log(error)
}).finally(() => {
this.voiceShow = false;
});
} else {
uni.showToast({
title: '对讲停止失败!',
icon: 'none'
})
}
},
getUseConfig() {
var that = this
let requestData = {
projectSn: this.projectSn
}
this.sendRequest({
url: "xmgl/smartBroadcastConfig/getUseConfig",
data: requestData,
method: "POST",
success(res) {
this.useConfigInfo = res.result;
// that.initSOS();
}
})
},
initSOS() {
try {
// 加载SOS uniapp包装器
const sosModule = require('@/utils/sos-uniapp-wrapper.js')
// 创建SDK实例
this.sosSDK = new sosModule.SDK({
// AppId: "f6ebb2d01c864a788d1a82ac7afa50e4", // 这里填写appid
// AppCode: "82b8816f27424d68b4ec0078fd478685", // 这里填写appCode
Account: "13192278390", // 这里填写account
AppId: this.useConfigInfo.appId, // 这里填写appid
AppCode: this.useConfigInfo.appCode, // 这里填写appCode
})
// 初始化SDK
this.sosSDK.init().then(() => {
console.log('SOS SDK初始化成功', this.sosSDK.version())
this.setupEventListeners()
}).catch(error => {
console.error('SOS SDK初始化失败:', error)
})
} catch (error) {
console.error('SOS SDK加载失败:', error)
}
},
setupEventListeners() {
// 添加事件监听器
this.sosSDK.addEventListener('sdk::event::state', (event) => {
console.log('SDK状态变化:', event)
})
},
cleanup() {
if (this.sosSDK) {
this.sosSDK.destroy()
this.sosSDK = null
}
},
handleChangeTab(val) {
console.info(val, 'val')
this.tabActive = val;
if (this.tabActive == 1) {
this.toBackList();
}
},
handleSaveSpeed() {
this.opSize = this.tempSpeed
this.$refs.speedPopup.close()
uni.setStorageSync('videoOpSize', this.opSize)
},
changeSpeed(data) {
console.info(data, this.opSize)
this.tempSpeed = data.value
},
setSpeed() {
this.tempSpeed = this.opSize
this.$refs.speedPopup.open()
},
getUseProjectVideoConfig() {
var that = this
let requestData = {
projectSn: this.projectSn
}
this.sendRequest({
url: "xmgl/projectVideoConfig/getUseProjectVideoConfig",
data: requestData,
method: "POST",
success(res) {
console.log('找封面', res)
that.videoConfig = res.result;
// #ifdef H5
that.videoConfig.enableNotPlugin = 1;
if (that.videoConfig.enableNotPlugin == 1) {
that.$nextTick(() => {
that.initPlayer();
})
}
// #endif
// #ifdef APP-PLUS
that.videoConfig.enableNotPlugin = -1;
// #endif
}
})
},
/**
* 初始化播放器
*/
initPlayer() {
const _this = this;
const parmas = {
// 需要英文字母开头 必填
szId: "playerId",
// 必填,引用H5player.min.js的js相对路径
szBasePath: "/app/static/monitor/",
iMaxSplit: 4,
openDebug: true,
mseWorkerEnable: false, //是否开启多线程解码分辨率大于1080P建议开启否则可能卡顿
bSupporDoubleClickFull: true, //是否支持双击全屏true-双击是全屏false-双击无响应
// 分屏播放默认最大分屏4*4
// iMaxSplit: 16,
iCurrentSplit: 1,
// 样式
oStyle: {
border: "#343434",
borderSelect: "#FFCC00",
background: "#000",
},
};
this.playerVideo = new this.H5Player.JSPlugin(parmas);
// 事件回调绑定
this.playerVideo.JS_SetWindowControlCallback({
windowEventSelect: function(iWndIndex) {
//插件选中窗口回调
console.log("windowSelect callback: ", iWndIndex);
},
pluginErrorHandler: function(iWndIndex, iErrorCode, oError) {
//插件错误回调
console.log("pluginError callback: ", iWndIndex, iErrorCode, oError);
},
performanceLack: function(iWndIndex) {
//性能不足回调
console.log("performanceLack callback: ", iWndIndex);
},
StreamEnd: function(iWndIndex) {
//性能不足回调
console.log("recv StreamEnd: ", iWndIndex);
},
talkPluginErrorHandler: (iErrorCode, oErrorInfo) => { //对讲错误回调
console.log('recv talkPluginErrorHandler: ' + iErrorCode);
},
});
this.play(this.videoInfo, this.iWndIndex);
},
play(row, index) {
const _this = this;
// this.stopPlay(index + 1, "delete");
let tempCode = row.serialNumber;
const param = {
cameraIndexCode: tempCode,
streamType: this.streamType == 2 ? 0 : this.streamType,
type: this.url_config.includes("https") ? "wss" : "ws",
// type: "wss",
transmode: 1,
itemId: row.itemId,
};
this.sendRequest({
url: "xmgl/videoItem/getVideoItemInfo",
data: param,
method: "post",
success(res) {
if (res.code != 200) {
uni.showToast({
title: '获取视频流失败!',
icon: 'none'
})
return;
}
let isProd = process.env.NODE_ENV === 'development' ? "" : "" // '/mlh5'
switch (_this.videoInfo.videoType) {
case 1:
_this.url = res.result.videoInfo.hdFlvAddress
_this.accessToken = res.result.accessToken;
break;
default:
_this.url = res.result.videoInfo.url;
break;
}
// console.log(_this.url,res.result.videoInfo.hdFlvAddress,_this.videoInfo.videoType,res.result.projectVideoConfig.videoType)
_this.videoResponseInfo = {
...res.result.projectVideoConfig,
...res.result.videoInfo
};
for (let i in _this.videoResponseInfo) {
if (!_this.videoResponseInfo[i]) {
delete _this.videoResponseInfo[i]
}
}
// 视频添加加载中图片
const id = "player-container-" + index;
var d1 = document.getElementById(id); //获取div元素
d1.childNodes.forEach((item) => {
if (item.nodeName == "" || item.nodeName == "IMG") {
d1.removeChild(item);
}
});
var im = document.createElement("img"); //创建图片
im.src = require("@/static/iscImage/loading.gif");
//图片设置成和div一样大小
const divHeightNum = d1.style.height.slice(
0,
d1.style.height.length - 2
);
// const imgHeightNum = divHeightNum * 0.2
const imgHeightNum = 256;
im.style.width = imgHeightNum + "px";
im.style.height = imgHeightNum + "px";
im.style.position = "absolute";
im.style.top = "50%";
im.style.left = "50%";
const positionNum = imgHeightNum / 2 - imgHeightNum;
im.style.marginLeft = positionNum + "px";
im.style.marginTop = positionNum + "px";
d1.appendChild(im); //图片挂载到div上
let preUrl = res.result.videoInfo.url;
_this.h5Url = res.result.videoInfo.url;
const param = {
playURL: preUrl,
// 1高级模式 0普通模式高级模式支持所有
mode: 0,
};
// 索引默认0
if (!index) {
index = 0;
}
const findIndex = Array.from(d1.childNodes).findIndex((item) => item
.localName ==
'img');
_this.playerVideo.JS_Play(preUrl, param, index).then(
() => {
console.log(d1.childNodes);
if (findIndex !== -1) {
d1.removeChild(d1.childNodes[findIndex]);
console.log("播放成功", findIndex);
}
},
(err) => {
console.log("播放失败");
// im.src = require("@/static/iscImage/text-to-image.png");
// const imgHeightNum = 20;
// const imgWidthNum = 150;
// im.style.width = imgWidthNum + "px";
// im.style.height = imgHeightNum + "px";
// const positionNum = imgHeightNum / 2 - imgHeightNum;
// const positionWidthNum = imgWidthNum / 2 - imgWidthNum;
// im.style.marginLeft = positionWidthNum + "px";
// im.style.marginTop = positionNum + "px";
if (findIndex !== -1) {
d1.removeChild(d1.childNodes[findIndex]);
let ndiv = document.createElement("div"); //创建图片
const reloadBtn = document.createElement("div");
// 创建图片元素
const reloadIcon = document.createElement("img");
reloadIcon.src = require("@/static/iscImage/reload.png");; // 替换为你的图片路径
reloadBtn.textContent = "重新加载";
reloadBtn.addEventListener("click", (e) => {
e.stopPropagation();
_this.onReload(row.id);
});
// 将图片添加到按钮
reloadBtn.appendChild(reloadIcon);
ndiv.innerHTML = `预览失败,请检查设备网络`;
ndiv.style.position = "absolute";
ndiv.style.top = "50%";
ndiv.style.left = "50%";
ndiv.style.transform = "translate(-50%, -50%)";
ndiv.className = "classImg";
ndiv.appendChild(reloadBtn);
d1.appendChild(ndiv); //图片挂载到div上
}
}
);
_this.playerVideo.JS_SetConnectTimeOut(index, 60).then(
() => {
console.info("JS_SetConnectTimeOut success");
// do you want...
},
(err) => {
console.info("JS_SetConnectTimeOut failed", err);
// do you want...
}
);
}
})
},
onReload(id) {
console.log("重新加载", id);
// 这里添加重新加载的逻辑
this.play(this.videoInfo, this.iWndIndex);
},
// 跳转到录像回放列表
toBackList() {
uni.redirectTo({
url: `./playBackList?obj=${JSON.stringify({
...this.videoResponseInfo,
...this.videoInfo
})}&tabActive=${this.tabActive}&sn=${this.projectSn}`
})
},
changeStreamFn() {
if (this.streamType == 1) {
this.streamType = 2
} else {
this.streamType = 1
}
if (this.videoConfig.enableNotPlugin == 1) {
this.play(this.videoInfo, this.iWndIndex);
} else {
this.getPlayUrl();
}
},
getPlayUrl() {
var that = this
var json = {
itemId: this.videoInfo.itemId
}
if (this.videoInfo.videoType == 3) {
json.streamType = this.streamType;
// json.type = 'rtsp' //rtsp或者hls
// json.type = this.url_config.includes("https") ? "wss" : "ws"; //rtsp或者hls
}
// #ifdef H5
// this.sendRequest({
// url: "xmgl/videoItem/getVideoItemInfo",
// data: {
// ...json,
// type: this.url_config.includes("https") ? "wss" : "ws",
// },
// method: "post",
// success(res) {
// let isProd = process.env.NODE_ENV === 'development' ? "" : "" // '/mlh5'
// switch (that.videoInfo.videoType) {
// case 1:
// that.url = res.result.videoInfo.hdFlvAddress
// that.accessToken = res.result.accessToken;
// break;
// default:
// that.url = res.result.videoInfo.url;
// break;
// }
// // console.log(that.url,res.result.videoInfo.hdFlvAddress,that.videoInfo.videoType,res.result.projectVideoConfig.videoType)
// that.videoResponseInfo = {
// ...res.result.projectVideoConfig,
// ...res.result.videoInfo
// };
// for (let i in that.videoResponseInfo) {
// if (!that.videoResponseInfo[i]) {
// delete that.videoResponseInfo[i]
// }
// }
// }
// });
// #endif
// #ifdef APP-PLUS
this.sendRequest({
url: "xmgl/videoItem/getVideoItemInfo",
data: {
...json,
type: "rtsp",
},
method: "post",
success(res) {
let isProd = process.env.NODE_ENV === 'development' ? "" : "" // '/mlh5'
switch (that.videoInfo.videoType) {
case 1:
that.url = res.result.videoInfo.hdFlvAddress
that.accessToken = res.result.accessToken;
break;
default:
that.url = res.result.videoInfo.url;
break;
}
// console.log(that.url,res.result.videoInfo.hdFlvAddress,that.videoInfo.videoType,res.result.projectVideoConfig.videoType)
that.videoResponseInfo = {
...res.result.projectVideoConfig,
...res.result.videoInfo
};
for (let i in that.videoResponseInfo) {
if (!that.videoResponseInfo[i]) {
delete that.videoResponseInfo[i]
}
}
}
});
this.sendRequest({
url: "xmgl/videoItem/getVideoItemInfo",
data: {
...json,
type: "wss", //rtsp或者hls
},
method: "post",
success(res) {
let isProd = process.env.NODE_ENV === 'development' ? "" : "" // '/mlh5'
switch (that.videoInfo.videoType) {
case 1:
that.webURL = isProd + '/static/monitor/player.html?cameraUrl=' + res.result
.videoInfo
.hdFlvAddress
break;
default:
that.webURL = isProd + '/static/monitor/player.html?cameraUrl=' + res.result
.videoInfo
.url
break;
}
}
})
// #endif
},
controlVideoMouse(opType, action) {
if (this.videoInfo.deviceType != 2) {
this.$message.warning("该设备不是球机,不支持此操作");
return false;
}
if (this.videoInfo.videoType != 3 && this.videoInfo.videoType != 4) {
uni.showToast({
title: '暂不支持',
icon: 'none'
})
return
}
if (this.videoInfo.videoType == 4) {
const objDh = {
'UP': {
pan: 0,
tilt: 0.2,
zoom: 0,
},
'LEFT': {
pan: -0.2,
tilt: 0,
zoom: 0,
},
'DOWN': {
pan: 0,
tilt: -0.2,
zoom: 0,
},
'RIGHT': {
pan: 0.2,
tilt: 0,
zoom: 0,
},
'ZOOM_OUT': {
pan: 0,
tilt: 0,
zoom: -0.2,
},
'ZOOM_IN': {
pan: 0,
tilt: 0,
zoom: 0.2,
}
}
this.controlVideoFn_dh(objDh[opType]);
return
}
this.typeName = opType
if (action == 0) {
this.videoFlag = true;
}
const json = {
itemId: this.videoInfo.itemId,
opType: opType,
action: action,
opSize: this.opSize,
opCode: 1,
};
var that = this
this.sendRequest({
url: "xmgl/videoItem/setHikPtzControl",
data: json,
method: "post",
hideLoading: true,
success(res) {
// uni.showToast({
// title: '控制成功',
// icon: 'none'
// })
},
complete() {
if (action == 1) {
that.videoFlag = false;
}
}
})
},
controlVideoFn(pan, tilt, zoom, opType) {
this.typeName = opType
if (this.videoFlag) {
uni.showToast({
title: '不要重复点击',
icon: 'none'
})
return
}
if (this.videoInfo.deviceType != 2) {
uni.showToast({
title: '该设备不是球机,不支持此操作',
icon: 'none'
})
return false
}
switch (this.videoInfo.videoType) {
case 3:
this.videoFlag = true;
this.controlVideoFn_isc(opType)
break;
case 4:
this.videoFlag = true;
this.controlVideoFn_dh(pan, tilt, zoom)
break;
default:
uni.showToast({
title: '暂不支持',
icon: 'none'
})
break;
}
},
controlVideoFn_isc(opType) {
let json = {
// cameraId: this.videoInfo.deviceSerial,
itemId: this.videoInfo.itemId,
opType: opType,
opSize: this.opSize,
opCode: 1
};
var that = this
this.sendRequest({
url: "xmgl/videoItem/getHikPtzControl",
data: json,
method: "post",
success(res) {
uni.showToast({
title: '控制成功',
icon: 'none'
})
},
complete() {
that.videoFlag = false;
}
})
},
controlVideoFn_dh(objDh) {
var code = '';
var jsonStr = {
pan: objDh.pan,
tilt: objDh.tilt,
zoom: objDh.zoom,
duration: 100
};
let json = {
ip: this.videoInfo.ip,
port: this.videoInfo.port,
username: this.videoInfo.username,
password: this.videoInfo.password,
chnnelcode: this.videoInfo.chnnelcode,
jsonStr: JSON.stringify(jsonStr),
data: new Date()
};
var that = this
this.sendRequest({
url: "xmgl/video/putPTZ",
data: json,
method: "get",
success(res) {
uni.showToast({
title: '控制成功',
icon: 'none'
})
},
complete() {
that.videoFlag = false;
}
})
}
}
}
</script>
<style lang="scss" scoped>
/deep/.classImg {
color: rgba(255, 255, 255, 0.5);
font-size: 32rpx;
width: calc(100% - 48rpx);
text-align: center;
padding: 0 24rpx;
z-index: 101;
>div {
color: rgb(255, 255, 255);
font-size: 24rpx;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
margin-top: 12rpx;
>img {
width: 32rpx;
height: 32rpx;
margin-left: 16rpx;
}
}
}
.webview-container {
position: relative;
overflow: visible;
display: none;
width: 0 !important;
height: 0 !important;
/deep/ uni-web-view {
height: 100% !important;
iframe {
position: absolute !important;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}
}
#playerId {
width: 100% !important;
height: 420rpx !important;
}
.video-box {
position: relative;
height: 900rpx;
background-color: #F4F5FD;
}
.voice-main {
padding: 36rpx 26rpx 18rpx;
height: 400rpx;
background: #FFFFFF;
box-shadow: 0rpx -8rpx 8rpx 0rpx rgba(0, 0, 0, 0.05);
display: flex;
flex-direction: column;
align-items: center;
.voice-header {
font-weight: 500;
font-size: 28rpx;
color: #808080;
margin-bottom: 24rpx;
}
.voice-image {
display: flex;
justify-content: center;
align-items: center;
.voice-icon_left {
width: 92rpx;
height: 92rpx;
background-image: url("@/static/videoControlIcon/voice-icon_left.gif");
background-repeat: no-repeat;
background-size: 100% 100%;
}
.voice-icon_center {
width: 118rpx;
height: 118rpx;
background-image: url("@/static/videoControlIcon/voice-icon_center.png");
background-repeat: no-repeat;
background-size: 100% 100%;
margin: 0 20rpx;
}
}
.voice-text {
font-weight: 500;
font-size: 28rpx;
color: #4D4D4D;
margin-top: 12rpx;
}
.footer-btn {
margin-top: 36rpx;
width: 100%;
height: 76rpx;
border-radius: 6rpx;
font-weight: 500;
font-size: 28rpx;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
}
.footer-btn1 {
background-color: #5181F6;
}
.footer-btn2 {
>view {
width: 50%;
height: 100%;
}
>view:first-child {
background: rgba(81, 129, 246, 0.1);
color: #5181F6;
display: flex;
align-items: center;
justify-content: center;
}
>view:last-child {
background-color: #5181F6;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
}
}
.voice-icon {
width: 118rpx;
height: 118rpx;
background-image: url("@/static/videoControlIcon/voice-icon.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
left: 50%;
// bottom: 186rpx;
bottom: 0;
transform: translateX(-50%);
}
/deep/ .u-tabbar {
height: 152rpx;
.u-tabbar__content {
height: 152rpx !important;
.u-tabbar__content__item__button {
margin-top: 18rpx;
}
.u-tabbar__content__item__text {
margin-bottom: 18rpx;
}
}
}
/deep/ .m3u8-player,
.player-m3u8 {
width: 100%;
height: 420rpx;
}
/* #ifdef H5 */
.fullHeight {
background-color: #F4F5FD;
min-height: 100vh;
}
/* #endif */
/* #ifdef MP-WEIXIN */
.fullHeight {
background-color: #F4F5FD;
min-height: 100vh;
}
/* #endif */
/* #ifdef APP-PLUS */
.fullHeight {
background-color: #F4F5FD;
// height: auto;
// padding-bottom: 60rpx;
min-height: 100vh;
}
/* #endif */
.videoBox {
width: 100%;
}
.videoName {
font-size: 16px;
color: $uni-text-color;
font-weight: bold;
margin: 10px 15px;
position: relative;
.view-set {
width: 120rpx;
height: 120rpx;
padding: 20rpx 12rpx 10rpx;
background: #FFFFFF;
border-radius: 8rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
>image {
width: 48rpx;
height: 48rpx;
}
>text {
margin-top: 8rpx;
font-weight: 500;
font-size: 24rpx;
color: #498CEC;
}
}
.changeBtn {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
font-size: 24rpx;
}
}
.set-speed {
margin: 48rpx 96rpx;
height: 108rpx;
}
.video-playback {
width: 454rpx;
height: 108rpx;
background: #FFFFFF;
border-radius: 31rpx;
text-align: center;
line-height: 108rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 40rpx;
color: #8D8D8D;
margin: 0 auto;
margin-top: 80rpx;
// position: fixed;
// bottom: 80rpx;
// left: 145rpx;
}
.videoOperateBox {
position: relative;
text-align: center;
padding-top: 10px;
.box-main {
width: 118rpx;
height: 118rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.05);
border-radius: 50%;
border: 2rpx solid rgba(175, 175, 177, 0.2);
position: absolute;
top: 50%;
transform: translateY(-50%);
display: flex;
align-items: center;
justify-content: center;
}
.box-right {
right: 28rpx;
}
.box-left {
left: 28rpx;
}
.bg {
width: 220px;
height: 220px;
}
}
.videoOperateBox .box {
position: relative;
display: inline-block;
margin: auto;
height: 220px;
}
.videoOperateBox .pic {
position: absolute;
cursor: pointer;
}
.videoOperateBox .zoom {
width: 106px;
height: 69px;
display: inline-block;
cursor: pointer;
}
.videoOperateBox .zoomin:hover {
background: url("@/static/videoControlIcon/4.png");
}
.videoOperateBox .zoomout:hover {
background: url("@/static/videoControlIcon/2.png");
}
.videoOperateBox .zoomin {
background: url("@/static/videoControlIcon/3.png");
}
.videoOperateBox .zoomout {
background: url("@/static/videoControlIcon/1.png");
}
.videoOperateBox .left {
width: 20rpx;
height: 28rpx;
background-image: url("@/static/videoControlIcon/left.png");
background-repeat: no-repeat;
background-size: 100% 100%;
left: 25px;
top: 50%;
transform: translateY(-50%);
}
.videoOperateBox .left:hover {
background-image: url("@/static/videoControlIcon/left-active.png");
}
.videoOperateBox .right:hover {
background-image: url("@/static/videoControlIcon/right-active.png");
}
.videoOperateBox .top:hover {
background-image: url("@/static/videoControlIcon/top-active.png");
}
.videoOperateBox .bottom:hover {
background-image: url("@/static/videoControlIcon/bottom-active.png");
}
.topActive {
background-image: url("@/static/videoControlIcon/top-active.png");
}
.leftActive {
background-image: url("@/static/videoControlIcon/left-active.png");
}
.rightActive {
background-image: url("@/static/videoControlIcon/right-active.png");
}
.bottomActive {
background-image: url("@/static/videoControlIcon/bottom-active.png");
}
// .videoOperateBox .center:hover {
// background: url("@/static/videoControlIcon/center-active.png");
// }
.videoOperateBox .right {
width: 20rpx;
height: 28rpx;
background-image: url("@/static/videoControlIcon/right.png");
background-repeat: no-repeat;
background-size: 100% 100%;
right: 25px;
top: 50%;
transform: translateY(-50%);
}
.videoOperateBox .top {
width: 28rpx;
height: 20rpx;
background-image: url("@/static/videoControlIcon/top.png");
background-repeat: no-repeat;
background-size: 100% 100%;
top: 25px;
left: 50%;
transform: translateX(-50%);
}
.videoOperateBox .bottom {
width: 28rpx;
height: 20rpx;
background-image: url("@/static/videoControlIcon/bottom.png");
background-repeat: no-repeat;
background-size: 100% 100%;
bottom: 25px;
left: 50%;
transform: translateX(-50%);
}
// .videoOperateBox .center {
// width: 44px;
// height: 40px;
// background: url("@/static/videoControlIcon/center.png");
// left: 50%;
// top: 50%;
// margin-top: -20px;
// margin-left: -22px;
// }
.desc {
text-align: right;
position: absolute;
top: -12rpx;
font-size: 32rpx;
left: 28rpx;
}
.speed_wrap {
width: 550rpx;
height: 300rpx;
background-color: #FFFFFF;
border-radius: 16rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
.s_title {
color: #000;
font-weight: 600;
line-height: 40rpx;
font-size: 36rpx;
margin: 24rpx 0;
}
.s_btn {
width: 100%;
&:after {
border-radius: 0;
}
}
}
</style>