监控取流过程
- 首先需要在public文件夹下引入hls
- 在vue自定义指令文件夹下创建videoPlay.js文件
import { getVideoUrl } from '@/api/login';
// 注册全局视频播放指令
const VideoPlay = {
async inserted(el, binding, vnode) {
if (!binding.value) {
return;
}
el.click();
let id = binding.value;
let data = await getVideoUrl({ id });
let url = data.code === 200 ? data.data : '';
let video = el;
let hls = new Hls();
let hlssource = url;
if (!vnode.context.hls) {
vnode.context.hls = {};
}
vnode.context.hls[id] = hls;
if (hlssource) {
hls.loadSource(hlssource);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
video.play();
el.ondblclick = () => {
if (video.requestFullscreen) {
video.requestFullscreen();
} else if (video.mozRequestFullScreen) {
video.mozRequestFullScreen();
} else if (video.webkitRequestFullScreen) {
video.webkitRequestFullScreen();
}
};
});
}
},
unbind(el, binding, vnode) {
let id = binding.value;
vnode.context.hls[id].destroy();
el.ondblclick = null;
}
};
export default {
VideoPlay
};
- 通过getVideoUrl获取取流地址
// 获取视频url
export const getVideoUrl = data => get('', data);
- 获取code
- 创建video标签
<video v-video-play="active.code" muted class="video" v-if="showVideo" controls></video>
控件使用流程
视频播放组件
<template>
<div class="creama" ref="video">
<div class="playWnd" :id="creamaWinId"></div>
</div>
</template>
<script>
import { TipsPop } from '@/utils/tool';
let oWebControl = null;
let pubKey = null;
export default {
name: 'videoPop',
props: ['code'],
data() {
return {
isLoading: false,
isFirst: true,
isTimer: null,
creamaWinId: ''
};
},
computed: {},
watch: {},
methods: {
// 初始化控件
initPlugin() {
return new Promise((resolve, reject) => {
oWebControl = new WebControl({
szPluginContainer: this.creamaWinId,
iServicePortStart: 15900,
iServicePortEnd: 15909,
szClassId: '23BF3B0A-2C56-4D97-9C03-0CB103AA8F11', // 用于IE10使用ActiveX的clsid
cbConnectSuccess: () => {
oWebControl
.JS_StartService('window', {
dllPath: './VideoPluginConnect.dll'
})
.then(() => {
oWebControl.JS_CreateWnd(this.creamaWinId).then(() => {
resolve();
});
});
},
cbConnectError: () => {
TipsPop({
message: '插件未启动,请启动插件后再进行查看',
type: 'error'
});
this.$confirm('插件是否安装? 如未安装点击确定进行下载。', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
// 自动创建下载标签
const a = document.createElement('a'); // 创建a标签
a.setAttribute('download', ''); // download属性
a.setAttribute('href', './VideoWebPlugin.exe'); // href链接
a.click(); // 自执行点击事件
})
.catch(() => {});
resolve(false);
}
});
});
},
// 反初始化
uninit() {
TipsPop({
message: '正在关闭视频请勿进行其他操作',
type: 'info'
});
oWebControl.JS_HideWnd();
return new Promise((resolve, reject) => {
oWebControl
.JS_RequestInterface({
funcName: 'uninit'
})
.then(() => {
oWebControl.JS_DestroyWnd(this.creamaWinId);
resolve();
});
});
},
// 获取pubKey
getPubKey() {
return new Promise((resolve, reject) => {
oWebControl
.JS_RequestInterface({
funcName: 'getRSAPubKey',
argument: JSON.stringify({
keyLength: 1024
})
})
.then(function(data) {
pubKey = data.responseMsg.data;
resolve();
});
});
},
// 加载控件样式
InterFace() {
return new Promise((resolve, reject) => {
let obj = {
appkey: '23844816',
buttonIDs:
'1,0,16,256,257,258,259,260,512,513,514,515,516,517,768,769',
enableHTTPS: 1,
encryptedFields: 'secret',
// ip: '192.192.100.1',
ip: '117.159.78.142',
language: 'zh_CN',
layout: '1x1',
playMode: 0,
port: 444,
secret: this.setEncrypt('oi6kh5Zc31TeLsrCExlW'),
showSmart: 1,
showToolbar: 1,
reconnectDuration: 5,
reconnectTimes: 5
};
oWebControl
.JS_RequestInterface({
funcName: 'init',
argument: JSON.stringify(obj)
})
.then(data => {
this.videoWndResize();
resolve();
});
});
},
// RSA加密
setEncrypt(value) {
var encrypt = new JSEncrypt();
encrypt.setPublicKey(pubKey);
return encrypt.encrypt(value);
},
// 调整窗口位置
videoWndResize() {
let width = parseInt(getComputedStyle(this.$refs.video).width);
let height = parseInt(getComputedStyle(this.$refs.video).height);
oWebControl.JS_Resize(width, height); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
},
// 视频播放预览
preview(code) {
return new Promise((resolve, reject) => {
let obj = {
cameraIndexCode: code,
ezvizDirect: 0,
gpuMode: 0,
streamMode: 0,
transMode: 1,
wndId: -1
};
TipsPop({
message: '正在加载监控视频,请勿关闭'
});
this.isLoading = true;
oWebControl
.JS_RequestInterface({
funcName: 'startPreview',
argument: JSON.stringify(obj)
})
.then(data => {
this.isLoading = false;
resolve();
});
});
}
},
mounted() {
this.creamaWinId = +new Date();
setTimeout(() => {
this.dialogVisible = true;
this.$nextTick(async () => {
await this.initPlugin();
await this.getPubKey();
await this.InterFace();
await this.preview(this.code);
this.isFirst = false;
window.onresize = () => {
if (this.isTimer) {
clearTimeout(this.isTimer);
}
this.isTimer = setTimeout(() => {
this.videoWndResize();
}, 50);
};
this.$once('hook:beforeDestroy', () => {
this.uninit();
window.onresize = null;
});
});
}, 0);
}
};
</script>
<style scoped lang="scss">
.creama {
width: 100%;
height: 100%;
.playWnd {
width: 100%;
height: 100%;
}
}
</style>
视频回放组件
<template>
<div class="back">
<el-dialog
title="监控回放"
:visible.sync="dialogVisible"
width="800px"
:before-close="beforeClose"
>
<div class="search">
<el-date-picker
v-model="value"
type="datetimerange"
:picker-options="pickerOptions"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
align="right"
>
</el-date-picker>
<div class="btn">
<el-button type="primary" @click="$_handlerLook">查看回放</el-button>
</div>
</div>
<div class="videobox" ref="video">
<div class="playWnd" id="playWnd"></div>
</div>
</el-dialog>
</div>
</template>
<script>
import { TipsPop } from '@/utils/tool';
let oWebControl = null;
let pubKey = null;
export default {
name: 'back',
props: ['isVideo', 'code'],
data() {
return {
dialogVisible: false,
isLoading: false,
pickerOptions: {
shortcuts: [
{
text: '最近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
},
{
text: '最近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
},
{
text: '最近三个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
}
}
]
},
value: '',
isBack: false
};
},
computed: {},
watch: {},
methods: {
// 关闭前的回调
async beforeClose(done) {
if (!this.isBack) {
done();
this.$emit('update:isVideo', false);
return;
}
if (this.isLoading) {
TipsPop({
message: '正在加载监控视频,请勿关闭',
type: 'info'
});
return;
}
await this.uninit();
done();
this.$emit('update:isVideo', false);
},
// 初始化控件
initPlugin() {
return new Promise((resolve, reject) => {
oWebControl = new WebControl({
szPluginContainer: 'playWnd',
iServicePortStart: 15900,
iServicePortEnd: 15909,
szClassId: '23BF3B0A-2C56-4D97-9C03-0CB103AA8F11', // 用于IE10使用ActiveX的clsid
cbConnectSuccess: () => {
oWebControl
.JS_StartService('window', {
dllPath: './VideoPluginConnect.dll'
})
.then(() => {
oWebControl.JS_CreateWnd('playWnd').then(() => {
resolve();
});
});
},
cbConnectError: e => {
TipsPop({
message: '插件未启动,请启动插件后再进行查看',
type: 'error'
});
resolve(false);
}
});
});
},
// 反初始化
uninit() {
TipsPop({
message: '正在关闭视频请勿进行其他操作',
type: 'info'
});
return new Promise((resolve, reject) => {
oWebControl
.JS_RequestInterface({
funcName: 'uninit'
})
.then(() => {
oWebControl.JS_DestroyWnd('playWnd');
resolve();
});
});
},
// 获取pubKey
getPubKey() {
return new Promise((resolve, reject) => {
oWebControl
.JS_RequestInterface({
funcName: 'getRSAPubKey',
argument: JSON.stringify({
keyLength: 1024
})
})
.then(function(data) {
pubKey = data.responseMsg.data;
resolve();
});
});
},
// 加载控件样式
InterFace() {
return new Promise((resolve, reject) => {
let obj = {
appkey: '23170946',
buttonIDs:
'1,0,16,256,257,258,259,260,512,513,514,515,516,517,768,769',
enableHTTPS: 1,
encryptedFields: 'secret',
ip: '192.192.100.1',
language: 'zh_CN',
layout: '1x1',
playMode: 1,
port: 443,
secret: this.setEncrypt('T4TQWOZpFXwVr6VyGE9d'),
showSmart: 1,
showToolbar: 1,
reconnectDuration: 5,
reconnectTimes: 5
};
oWebControl
.JS_RequestInterface({
funcName: 'init',
argument: JSON.stringify(obj)
})
.then(data => {
this.videoWndResize();
resolve();
});
});
},
// RSA加密
setEncrypt(value) {
var encrypt = new JSEncrypt();
encrypt.setPublicKey(pubKey);
return encrypt.encrypt(value);
},
// 调整窗口位置
videoWndResize() {
let width = parseInt(getComputedStyle(this.$refs.video).width);
let height = parseInt(getComputedStyle(this.$refs.video).height);
oWebControl.JS_Resize(width, height); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
},
// 视频播放预览
back(code) {
let [start, end] = this.value;
if (start) {
start = new Date(start).getTime();
}
if (end) {
end = new Date(end).getTime();
}
return new Promise((resolve, reject) => {
let obj = {
cameraIndexCode: code,
ezvizDirect: 0,
gpuMode: 0,
recordLocation: 0,
startTimeStamp: start,
endTimeStamp: end,
transMode: 1,
wndId: 0
};
this.isLoading = true;
oWebControl
.JS_RequestInterface({
funcName: 'startPlayback',
argument: JSON.stringify(obj)
})
.then(oData => {
this.isLoading = false;
resolve();
});
});
},
$_handlerLook() {
if (!this.value) {
TipsPop({
message: '请选择回放时间',
type: 'info'
});
return;
}
this.$nextTick(async () => {
await this.initPlugin();
await this.getPubKey();
await this.InterFace();
await this.back(this.code);
this.isBack = true;
window.onresize = () => {
this.videoWndResize();
};
this.$once('hook:beforeDestroy', () => {
window.onresize = null;
});
});
}
},
mounted() {
this.dialogVisible = true;
}
};
</script>
<style scoped lang="scss">
.back {
.videobox {
position: relative;
width: 100%;
height: 400px;
.playWnd {
position: absolute;
width: 100%;
height: 100%;
}
}
.search {
margin-bottom: 30px;
display: flex;
justify-content: space-evenly;
}
}
</style>
创建video标签并获取code
<video-preview v-if="isVideo" :isVideo.sync="isVideo" :code="videoCode"></video-preview>
<video-back v-if="isBack" :isVideo.sync="isBack" :code="videoCode"></video-back>