1、使用场景
pc端后端无法给到前端flv、hls、m3u8等流进行播放时,不得不采用海康的web端播放器插件进行播放时使用;
2、优劣势区分
优点:前端负责对接就行,减少了后端工作内容,因为时播放器控件-里面有相应的下载、截图、云台控制等功能;
劣势: 网页一般多人使用时-没台电脑都需要下载播放器才能进行播放,大大影响了使用体验;
3、使用步骤
1、下载海康平台web控件1.5.1等版本;
2、组件里配置好需要的基本参数;
3、引入组件放入父组件中;
4、父组件调用初始化然后调用播放即可实现;
注:没播放可以在调用回放预览时使用定时器延迟1000毫秒左右-确保已渲染;
4、基本功能
1、 组件做了自适应布局-播放器框可以注定到指定位置-控件可以随着弹框大小自适应变化;
2、采用了vue3的写法-已将初始化、预览、回放方法暴露;
5、下面就是组件完整代码
<template>
<div class="video_box" ref="playWndBox">
<div :id="`playWnd`" class="playWnd" :style="{ height: playWndHeight + 'px', width: playWndWidth + 'px' }"></div>
</div>
</template>
<script setup>
const { proxy } = getCurrentInstance()
import { onMounted, ref } from "vue"
const props = defineProps({
// 综合安防管理平台提供的appkey
appkey: {
type: String,
default: "25309621",
},
// 综合安防管理平台提供的secret
secret: {
type: String,
default: "XwUwntqpAF9DXF5A3oWr",
},
// 综合安防管理平台IP地址
playIp: {
type: String,
default: "192.168.1.43",
},
// 综合安防管理平台端口
port: {
type: Number,
default: 9901,
},
// // 获取输入的监控点编号值
// cameraIndexCode: {
// type: String,
// default: "72cacf537a4240629c494205949899dc",
// },
// 播放模式
playMode: {
type: Number,
default: 1,
},
// 是否显示控件
showToolbar: {
type: Number,
default: 1,
},
})
const initCount = ref(0)
const pubKey = ref("")
const playWndWidth = ref(null)
const playWndHeight = ref(null)
const oWebControl = ref(null)
const playWndBox = ref(null)
function monResize() {
window.addEventListener("resize", (e) => {
if (oWebControl.value != null) {
setWndCover()
}
})
}
/* 创建插件实例 */
function initPlugin() {
console.log("每次都应该创建")
oWebControl.value = new window.WebControl({
szPluginContainer: `playWnd`, // 指定容器id
iServicePortStart: 15900,
iServicePortEnd: 15909,
// szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsid
cbConnectSu***ess: () => {
oWebControl.value
.JS_StartService("window", {
dllPath: "./VideoPluginConnect.dll",
})
.then(() => {
oWebControl.value.JS_SetWindowControlCallback({
cbIntegrationCallBack: cbIntegrationCallBack(),
})
//启动插件服务成功
oWebControl.value.JS_CreateWnd(`playWnd`, playWndWidth.value, playWndHeight.value).then(() => {
//JS_CreateWnd创建视频播放窗口,宽高可设定
init() //初始化
})
})
},
// 创建WebControl实例失败
cbConnectError: function () {
oWebControl.value = null
proxy.$message.warning("插件未启动,正在尝试启动,请稍候...")
// 程序未启动时执行error函数,采用wakeup来启动程序
window.WebControl.JS_WakeUp("VideoWebPlugin://")
initCount.value++
if (initCount.value < 3) {
setTimeout(function () {
initPlugin()
}, 2000)
} else {
proxy.$message.warning("插件启动失败,请检查插件是否安装!")
proxy.$tips("是否确定下载播放插件", (done, instance) => {
const url = `${import.meta.env.VITE_APP_FILE}${proxy.$file}/software/VideoWebPlugin.exe` // 下载链接
console.log(url, "下载链接")
// 创建一个隐藏的a标签
const link = document.createElement("a")
link.href = url
link.setAttribute("download", "VideoWebPlugin.exe") // 指定下载的文件名
document.body.appendChild(link)
// 触发点击事件,弹出下载框
link.click()
done()
instance.confirmButtonLoading = false
})
}
},
cbConnectClose: () => {
oWebControl.value = null
proxy.$message.warning("插件未启动,正在尝试启动,请稍候...")
window.WebControl.JS_WakeUp("VideoWebPlugin://")
initCount.value++
if (initCount.value < 3) {
setTimeout(function () {
initPlugin()
}, 3000)
} else {
proxy.$message.warning("插件启动失败,请检查插件是否安装!")
}
},
})
}
// 初始化
function init() {
getPubKey(() => {
var appkey = props.appkey //综合安防管理平台提供的appkey,必填
var secret = setEncrypt(props.secret) //综合安防管理平台提供的secret,必填
var ip = props.playIp //综合安防管理平台IP地址,必填
var playMode = props.playMode //初始播放模式:0-预览,1-回放
var port = props.port //综合安防管理平台端口,若启用HTTPS协议,默认443
var snapDir = "D:\\SnapDir" //抓图存储路径
var videoDir = "D:\\VideoDir" //紧急录像或录像剪辑存储路径
var layout = "1x1" //playMode指定模式的布局
var enableHTTPS = 1 //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1
var encryptedFields = "secret" //加密字段,默认加密领域为secret
var showToolbar = props.showToolbar //是否显示工具栏,0-不显示,非0-显示
var showSmart = 1 //是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示
var buttonIDs = "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769" //自定义工具条按钮
//var reconnectTimes = 2; // 重连次数,回放异常情况下有效
//var reconnectTime = 4; // 每次重连的重连间隔 >= reconnectTime
// 请自行修改以上变量值
console.log("参数配置参数", appkey, secret, ip, port)
oWebControl.value
.JS_RequestInterface({
fun***ame: "init",
argument: JSON.stringify({
appkey: appkey, //API网关提供的appkey
secret: secret, //API网关提供的secret
ip: ip, //API网关IP地址
playMode: playMode, //播放模式(决定显示预览还是回放界面)
port: port, //端口
snapDir: snapDir, //抓图存储路径
videoDir: videoDir, //紧急录像或录像剪辑存储路径
layout: layout, //布局
enableHTTPS: enableHTTPS, //是否启用HTTPS协议
encryptedFields: encryptedFields, //加密字段
showToolbar: showToolbar, //是否显示工具栏
showSmart: showSmart, //是否显示智能信息
buttonIDs: buttonIDs, //自定义工具条按钮
//reconnectTimes:reconnectTimes, //重连次数
//reconnectDuration:reconnectTime //重连间隔
}),
})
.then(function (oData) {
// oWebControl.value.value.JS_SetDocOffset({
// left: 800,
// top: 500,
// });
oWebControl.value.JS_Resize(playWndWidth.value, playWndHeight.value) // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
// startPlayback(oWebControl.value);
// if (callback) {
// callback()
// }
// startPlayback()
})
})
}
/* 获取公钥 */
function getPubKey(callback) {
oWebControl.value
.JS_RequestInterface({
fun***ame: "getRSAPubKey",
argument: JSON.stringify({
keyLength: 1024,
}),
})
.then(function (oData) {
if (oData.responseMsg.data) {
pubKey.value = oData.responseMsg.data
callback()
// startPlayback(oWebControl.value);
}
})
}
/* 视频流RSA加密 */
function setEncrypt(value) {
const encrypt = new window.JSEncrypt()
encrypt.setPublicKey(pubKey.value)
return encrypt.encrypt(value)
}
// 回调的消息
function cbIntegrationCallBack(oData) {
// let { responseMsg: type } = oData
// if (type === "error") {
// } else {
// }
}
// 视频预览功能
function previewVideo(data) {
let cameraIndexCode = data // 获取输入的监控点编号值,必填
let streamMode = 0 // 主子码流标识:0-主码流,1-子码流
let transMode = 1 // 传输协议:0-UDP,1-TCP
let gpuMode = 0 // 是否启用GPU硬解,0-不启用,1-启用
let wndId = -1 // 播放窗口序号(在2x2以上布局下可指定播放窗口)
oWebControl.value
.JS_RequestInterface({
fun***ame: "startPreview",
argument: JSON.stringify({
cameraIndexCode: cameraIndexCode, // 监控点编号
streamMode: streamMode, // 主子码流标识
transMode: transMode, // 传输协议
gpuMode: gpuMode, // 是否开启GPU硬解
wndId: wndId, // 可指定播放窗口
}),
})
.then(function () {
oWebControl.value.JS_SetWindowControlCallback({})
})
}
//录像回放功能
function startPlayback(time) {
if (!time) return
var cameraIndexCode = time.cameraIndexCode //获取输入的监控点编号值,必填
var startTimeStamp = Date.parse(time.beginTime) - 300000 //回放开始时间戳,必填
var endTimeStamp = Date.parse(time.endTime) //回放结束时间戳,必填
console.log(startTimeStamp, endTimeStamp, time.endTime, "这里都没进来")
var recordLocation = 0 //录像存储位置:0-中心存储,1-设备存储
var transMode = 1 //传输协议:0-UDP,1-TCP
var gpuMode = 0 //是否启用GPU硬解,0-不启用,1-启用
var wndId = -1 //播放窗口序号(在2x2以上布局下可指定播放窗口)
oWebControl.value.JS_RequestInterface({
fun***ame: "startPlayback",
argument: JSON.stringify({
cameraIndexCode: cameraIndexCode, //监控点编号
startTimeStamp: Math.floor(startTimeStamp / 1000).toString(), //录像查询开始时间戳,单位:秒
endTimeStamp: Math.floor(endTimeStamp / 1000).toString(), //录像结束开始时间戳,单位:秒
recordLocation: recordLocation, //录像存储类型:0-中心存储,1-设备存储
transMode: transMode, //传输协议:0-UDP,1-TCP
gpuMode: gpuMode, //是否启用GPU硬解,0-不启用,1-启用
wndId: wndId, //可指定播放窗口
}),
})
}
// 停止回放
function stopAllPlayback() {
oWebControl.value.JS_RequestInterface({
fun***ame: "stopAllPlayback",
})
}
// 设置窗口裁剪,当因滚动条滚动导致窗口需要被遮住的情况下需要JS_CuttingPartWindow部分窗口
function setWndCover() {
var iWidth = $(window).width()
var iHeight = $(window).height()
var oDivRect = $("#playWnd").get(0).getBoundingClientRect()
var iCoverLeft = oDivRect.left < 0 ? Math.abs(oDivRect.left) : 0
var iCoverTop = oDivRect.top < 0 ? Math.abs(oDivRect.top) : 0
var iCoverRight = oDivRect.right - iWidth > 0 ? Math.round(oDivRect.right - iWidth) : 0
var iCoverBottom = oDivRect.bottom - iHeight > 0 ? Math.round(oDivRect.bottom - iHeight) : 0
iCoverLeft = iCoverLeft > 2041 ? 2041 : iCoverLeft
iCoverTop = iCoverTop > 945 ? 945 : iCoverTop
iCoverRight = iCoverRight > 2041 ? 2041 : iCoverRight
iCoverBottom = iCoverBottom > 945 ? 945 : iCoverBottom
oWebControl.value.JS_RepairPartWindow(0, 0, 2041, 946) // 多1个像素点防止还原后边界缺失一个像素条
if (iCoverLeft != 0) {
oWebControl.value.JS_CuttingPartWindow(0, 0, iCoverLeft, 946)
}
if (iCoverTop != 0) {
oWebControl.value.JS_CuttingPartWindow(0, 0, 2041, iCoverTop) // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条
}
if (iCoverRight != 0) {
oWebControl.value.JS_CuttingPartWindow(2041 - iCoverRight, 0, iCoverRight, 946)
}
if (iCoverBottom != 0) {
oWebControl.value.JS_CuttingPartWindow(0, 946 - iCoverBottom, 2041, iCoverBottom)
}
}
// 关闭
function closeHide() {
oWebControl.value.JS_HideWnd() // 先让窗口隐藏,规避插件窗口滞后于浏览器消失问题
if (oWebControl.value != null) {
oWebControl.value.JS_RequestInterface({
fun***ame: "stopAllPreview",
})
// oWebControl.value.JS_Disconnect().then()
}
}
function logParentSize() {
playWndWidth.value = playWndBox.value.clientWidth
playWndHeight.value = playWndBox.value.clientHeight
console.log(playWndWidth.value, playWndHeight.value, "playWndHeight.value")
}
onMounted(() => {
nextTick(() => {
logParentSize()
})
// // 监听scroll事件,使插件窗口尺寸跟随DIV窗口变化
window.addEventListener("scroll", () => {
if (oWebControl.value != null) {
oWebControl.value.JS_Resize(playWndBox.value.clientWidth, playWndBox.value.clientHeight)
}
})
window.addEventListener("resize", () => {
if (oWebControl.value != null) {
oWebControl.value.JS_Resize(playWndBox.value.clientWidth, playWndBox.value.clientHeight)
}
})
logParentSize()
initPlugin()
})
// setTimeout(() => {
// }, 2000)
defineExpose({
previewVideo,
startPlayback,
closeHide,
initPlugin,
})
</script>
<style lang="scss" scoped>
.video_box {
width: 100%;
height: 100%;
}
</style>
6、总结
直接睡觉-到处睡觉-到头就睡;