iot-ui-app/pages/video/video-detail.vue

484 lines
12 KiB
Vue

<template>
<view class="video-detail">
<!-- <nav-bar :is-back="true" title="视频监控"></nav-bar> -->
<view class="video-box">
<!-- <video id="myVideo" :src="url" autoplay v-if="showVideo" show-mute-btn="true" vslide-gesture="true" :controls="btnToggle"> -->
<!-- #ifdef APP-PLUS -->
<video id="myVideo" :src="dataObj.flvUrl" autoplay show-fullscreen-btn v-if="showVideo" :controls="false">
<cover-view class="btn-toggle" v-if="btnToggle" @click="quitFullScreen">
退出全屏
</cover-view>
<view class="btn-toggle" v-if="btnToggle" @click="quitFullScreen">
退出全屏
</view>
</video>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<video id="myVideo" class="video-content" :src="dataObj.m3u8Url" :autoplay="true" :direction="0"
:muted="true" :controls="true" :is-live="true" object-fit="contain" @binderror="error" :custom-cache="false"
title="放大后会显示的标题" show-fullscreen-btn>
</video>
<!--<video id="myVideo" :src="dataObj.m3u8Url" autoplay show-fullscreen-btn v-if="showVideo" :controls="false">
<cover-view class="btn-toggle" v-if="btnToggle" @click="quitFullScreen">
退出全屏
</cover-view> -->
<!-- <view class="btn-toggle" v-if="btnToggle" @click="quitFullScreen">
退出全屏
</view>
</video> -->
<!-- #endif -->
<!-- #ifdef MP-WEIXIN
<live-player id="live-video" :src="dataObj.url" v-if="showVideo" autoplay @statechange="statechange"
@netstatus="netstatus">
<cover-view class="btn-toggle" v-if="btnToggle" @click="quitFullScreen">
退出全屏
</cover-view>
</live-player>
#endif -->
</view>
<view class="video-title">
{{dataObj.name}}
</view>
<view class="channe-name">
通道名称:{{dataObj.channeName}}
</view>
<!-- #ifdef MP-WEIXIN -->
<view class="slider-box">
<!-- <view class="title">
推流状态
</view> -->
<view class="net-status">
<text>速度:{{netStatus.netSpeed==undefined?'':netStatus.netSpeed}}</text>
<text>网络抖动:{{netStatus.netJitter==undefined?'':netStatus.netJitter}}</text>
<text>视频帧率:{{netStatus.videoFPS==undefined?'':netStatus.videoFPS}}</text>
<text>状态码:{{videoStatus}}</text>
</view>
</view>
<!-- #endif -->
<!-- <view class="slider-box">
<view class="title">
速度
</view>
<slider v-model="speed" step="10" @change="sliderChange" max="200" show-value />
</view> -->
<view class="title">
云台控制
</view>
<view class="btn-box">
<view class="btn">
<view class="btn-top-bottom" @touchstart="PTZcontrol(ptzType.up)"
@touchcancel="PTZcontrol(ptzType.stop)" @touchend="PTZcontrol(ptzType.stop)">
<view class="iconfont icon-fangxiang-shang"></view>
</view>
<view class="btn-center">
<view class="btn-left-right" @touchstart="PTZcontrol(ptzType.left)"
@touchcancel="PTZcontrol(ptzType.stop)" @touchend="PTZcontrol(ptzType.stop)">
<view class="iconfont icon-fangxiang-zuo"></view>
</view>
<view class="btn-center-center">
<!-- <view class="iconfont iconluyin" @touchstart="startRecording()" @touchcancel="endRecording()" @touchend="endRecording()"></view> -->
</view>
<view class="btn-left-right" @touchstart="PTZcontrol(ptzType.right)"
@touchcancel="PTZcontrol(ptzType.stop)" @touchend="PTZcontrol(ptzType.stop)">
<view class="iconfont icon-fangxiang-you"></view>
</view>
</view>
<view class="btn-top-bottom" @touchstart="PTZcontrol(ptzType.down)"
@touchcancel="PTZcontrol(ptzType.stop)" @touchend="PTZcontrol(ptzType.stop)">
<view class="iconfont icon-fangxiang-xia"></view>
</view>
</view>
</view>
<view class="display-box">
<view class="title">
显示
</view>
<button class="zoom-btn" type="default" @click="fullScreen()">全屏</button>
</view>
<u-toast ref="uToast" />
</view>
</template>
<script>
import {
getPTZCmd,
PTZ_TYPE
} from '@/static/common/js/video/ptz-cmd.js'
export default {
data() {
return {
title: '',
url: '',
speed: 100,
btnToggle: false,
dataObj: {
flvUrl: '',
m3u8Url: '',
id:'',
name: '',
channeId:'',
channeName:'',
},
refreshdata: 11,
showVideo: true,
// 时间
// 录音地址
videoStatus: '',
netStatus: {
netSpeed: '',
netJitter: '',
videoFPS: '',
},
videoObj: {
url: '',
id: '',
channel: '',
},
// 平台控制头
ptzTypeUrl:'',
ptzType: {}
};
},
onLoad(option) {
console.log("option",option)
this.ptzType = PTZ_TYPE;
console.log("PTZ_TYPE", PTZ_TYPE)
console.log("option: ", option);
let deviceObj = JSON.parse(decodeURIComponent(option.deviceObj));
let channeObj = JSON.parse(decodeURIComponent(option.channeObj));
this.videoObj.url = channeObj.hlsUrl;
this.dataObj.flvUrl = channeObj.hdlUrl;
this.dataObj.m3u8Url = channeObj.hlsUrl;
this.dataObj.id = channeObj.devId;
this.dataObj.name = deviceObj.name;
this.dataObj.channeId = channeObj.channelId;
this.dataObj.channeName = channeObj.name;
this.ptzTypeUrl = channeObj.baseUrl;
// if (obj.siteM7sHost && obj.siteM7sPort && obj.devId && obj.devChannel) {
// if (obj.https) {
// this.videoObj = {
// url: 'https://' + obj.siteM7sHost + ':' + obj.siteM7sPort,
// id: obj.devId,
// channel: obj.devChannel,
// }
// this.pullVideoList('https://' + obj.siteM7sHost + ':' + obj.siteM7sPort, obj.devId, obj.devChannel)
// this.dataObj.url = 'https://' + obj.siteM7sHost + ':' + obj.siteM7sPort + '/hdl/' + obj.devId + '/' +
// obj.devChannel + '.flv'
// } else {
// this.videoObj = {
// url: 'http://' + obj.siteM7sHost + ':' + obj.siteM7sPort,
// id: obj.devId,
// channel: obj.devChannel,
// }
// this.pullVideoList('http://' + obj.siteM7sHost + ':' + obj.siteM7sPort, obj.devId, obj.devChannel)
// this.dataObj.url = 'http://' + obj.siteM7sHost + ':' + obj.siteM7sPort + '/hdl/' + obj.devId + '/' +
// obj.devChannel + '.flv'
// }
// } else {
// this.$u.toast('摄像头参数错误!');
// }
console.log("当前flv地址:" + this.videoObj.url)
// 为了防止苹果手机静音无法播放
// uni.setInnerAudioOption({
// obeyMuteSwitch: false
// })
},
watch: {
refreshdata() {
this.$nextTick(() => {
this.showVideo = true
})
}
},
methods: {
statechange(e) {
// console.log('live-player code:', e)
this.videoStatus = e.detail.code;
if (e.detail.code == -2301) {
this.$u.toast('网络断连,且经多次重连抢救无效,更多重试请自行重启播放')
}
},
netstatus(e) {
// console.log('live-player netstatus:', e)
this.netStatus = e.detail.info;
},
pullVideoList(url, id, channel) {
// console.log("开启推流",url,id,channel)
let params = {
id: id,
channel: channel,
// startTime:1657165870,
// endTime:1657770669,
}
let DefaultOpts = {
url: url + '/api/gb28181/invite',
data: params,
method: "GET",
}
uni.request(DefaultOpts).then(
(res) => {
console.log("pullVideoList", res);
}
).catch(
(response) => {
console.log("pullVideoList错误", res);
}
)
},
// 进入全屏
fullScreen() {
// #ifdef APP-PLUS
// const subNvue=uni.getSubNVueById('popup'); //获取
// subNvue.show() // 显示
this.videoContext = uni.createVideoContext('myVideo');
// 进入全屏状态
this.videoContext.requestFullScreen();
this.btnToggle = true;
// #endif
// #ifdef MP-WEIXIN
this.videoContext = uni.createLivePlayerContext('live-video');
this.videoContext.requestFullScreen({
direction: 90
});
this.btnToggle = true;
// #endif
},
// 退出全屏
quitFullScreen() {
// #ifdef APP-PLUS
this.videoContext = uni.createVideoContext('myVideo');
// 进入全屏状态
this.videoContext.exitFullScreen();
this.btnToggle = false;
// const subNvue=uni.getSubNVueById('popup');
// subNvue.hide() //隐藏
// #endif
// #ifdef MP-WEIXIN
this.videoContext = uni.createLivePlayerContext('live-video');
this.videoContext.exitFullScreen();
this.btnToggle = false;
// #endif
},
// 滑动速度滚动条
sliderChange(e) {
console.log(e);
this.speed = e.detail.value;
},
// 云台控制
PTZcontrol(type) {
console.log("type", type);
let ptzcmd = getPTZCmd({
type: type
});
console.log("ptzcmd", ptzcmd)
this.btnToast(type);
let params = {
id: this.dataObj.id,
channel: this.dataObj.channeId,
ptzcmd: ptzcmd
}
let DefaultOpts = {
url: this.ptzTypeUrl + '/gb28181/api/control',
data: params,
method: "GET",
}
uni.request(DefaultOpts).then(
(res) => {
console.log("PTZcontrol", res);
}
).catch(
(response) => {
console.log("PTZcontrol错误", res);
}
)
},
error(e){
console.log("播放错误",error)
},
btnToast(type) {
if (type == this.ptzType.up) {
this.$refs.uToast.show({
title: '向上移动!',
type: 'success',
})
} else if (type == this.ptzType.left) {
this.$refs.uToast.show({
title: '向左移动!',
type: 'success',
})
} else if (type == this.ptzType.right) {
this.$refs.uToast.show({
title: '向右移动!',
type: 'success',
})
} else if (type == this.ptzType.down) {
this.$refs.uToast.show({
title: '向下移动!',
type: 'success',
})
} else if (type == this.ptzType.stop) {
this.$refs.uToast.show({
title: '停止移动!',
type: 'error',
})
}
}
}
}
</script>
<style lang="less" scoped>
.video-detail {
background-color: #fff;
height: 100%;
height: 100%;
.video-box {
width: 750rpx;
height: 422rpx;
video,
live-player {
width: 100%;
height: 100%;
}
.btn-toggle {
position: fixed;
top: 60rpx;
right: 80rpx;
z-index: 9999;
padding: 10rpx;
background: rgba(0, 0, 0, 0.5);
color: #fff;
font-size: 28rpx;
line-height: 36rpx;
}
}
.video-title {
font-weight: bold;
font-size: 36rpx;
line-height: 100rpx;
text-indent: 30rpx;
}
.channe-name{
font-size: 28rpx;
line-height: 60rpx;
margin: 0 30rpx 0 20rpx;
}
.title {
font-size: 26rpx;
font-weight: bold;
margin: 0 30rpx 0 20rpx;
}
.btn-box {
display: flex;
justify-content: center;
margin: 30rpx;
.btn {
width: 336rpx;
height: 336rpx;
border-radius: 50%;
background-color: #f2f3f7;
display: flex;
flex-direction: column;
align-items: center;
color: #7d90ab;
font-size: 56rpx;
overflow: hidden;
.btn-top-bottom {
width: 141rpx;
height: 98rpx;
display: flex;
justify-content: center;
align-items: center;
}
.btn-center {
display: flex;
align-items: center;
.btn-left-right {
width: 98rpx;
height: 141rpx;
display: flex;
justify-content: center;
align-items: center;
}
.btn-center-center {
width: 141rpx;
height: 141rpx;
background-color: #dde1ea;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
}
.btn-top-bottom:active,
.btn-left-right:active {
background-color: #dde1ea;
color: #7d90ab;
}
.btn-center-center:active {
background-color: #7d90ab;
color: #dde1ea;
}
}
}
.slider-box {
display: flex;
align-items: center;
margin: 30rpx;
slider {
width: 536rpx;
}
}
.zoom-box,
.display-box {
margin: 30rpx;
display: flex;
align-items: center;
.zoom-btn {
margin: 0;
line-height: 2;
border-color: #8293ab;
color: #8293ab;
}
}
}
/deep/.u-position-center{
top: calc(var(--status-bar-height) + 470rpx + 45px) !important;
}
.net-status {
text {
margin-right: 10rpx;
display: block;
}
}
</style>