zhgdyunapp/pages/videoManage/playVideo.vue
2025-09-25 09:21:56 +08:00

922 lines
22 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> -->
<!-- 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 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}"
@click="controlVideoFn(0,0.2,0,'UP')"></view>
<view class="pic left" :class="{'leftActive': typeName == 'LEFT' && videoFlag}"
@click="controlVideoFn(-0.2,0,0,'LEFT')"></view>
<view class="pic bottom" :class="{'bottomActive': typeName == 'DOWN' && videoFlag}"
@click="controlVideoFn(0,-0.2,0,'DOWN')"></view>
<view class="pic right" :class="{'rightActive': typeName == 'RIGHT' && videoFlag}"
@click="controlVideoFn(0.2,0,0,'RIGHT')"></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 @click="controlVideoFn(0,0,-0.2,'ZOOM_OUT')" class="box-left box-main">
<u-icon name="minus" color="#EFEFEF" size="60"></u-icon>
</view>
<view @click="controlVideoFn(0,0,0.2,'ZOOM_IN')" 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>
<!-- #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">
00:06:03
</view>
<view @click="btnStop" class="footer-btn footer-btn1">
结束对讲
</view>
<!-- <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
// 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'
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: {},
webviewStyles: {
width: "100%",
height: "100%"
}
};
},
onLoad(options) {
//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(() => {
// this.setHeight()
// })
},
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}`
}
},
methods: {
btnStart() {
console.log("start on click");
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");
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;
}
})
},
// 跳转到录像回放列表
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
}
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
}
this.sendRequest({
url: "xmgl/videoItem/getVideoItemInfo",
data: json,
method: "post",
success(res) {
switch (that.videoInfo.videoType) {
case 1:
// that.url=res.result.videoInfo.hdFlvAddress
that.url = res.result.videoInfo
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]
}
}
}
})
},
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(pan, tilt, zoom) {
var code = '';
var jsonStr = {
pan: pan,
tilt: tilt,
zoom: 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>
.video-box {
position: relative;
height: 900rpx;
}
.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>