赞
踩
这是一套拿到手就能直接用的根据海康提供的摄像机节点实时预览和回放的全步骤代码,开箱即用。
我的是基于vue2写的,vue3可以看我下一篇文章。
因我已经从上家公司离职,而我当时的项目还在跑,说明这一套代码还是可以使用的。
很多人在开发vue项目的时候,不知道怎么去开发视频实时预览和回放功能,然后一直查文档,再去看别人写的项目,就是无从下手。这篇文章是我刚开始接触到这个项目的时候从头到尾写下来的,功能已经实现希望有用。
首先去海康开放平台下载海康提供的Demo,这里面有项目需要用到的播放器插件和js文件。
我使用的是V1.6.1版本。
上面的海康地址好像是打不开了,具体地址需要官网的可以自行去查。
下面我附上我阿里网盘的下载地址:网盘链接
然后下载这一个,首次下载需要登录,没有的直接手机号注册一个就行了。
然后安装视频播放插件,如下图。
在vue项目中的public目录下新建文件夹,把刚才下载好的js复制到这个文件夹里面,然后再在public目录下的index.html文件里面引入sj文件。
代码如下(示例):
这里是template部分,只给一个盒子,然后给个宽和高就行了,插件会自适应盒子大小和位置的。
ref对应的名字在初始化插件的时候会用到。
- <div class="videoMain" ref="playWndBox">
- <div
- id="playWnd"
- class="playWnd"
- :style="{
- height: playWndHeight + 'px',
- width: playWndWidth + 'px',
- }"
- ></div>
- </div>
这是data里面的数据,可根据自己需求修改。
- data() {
- return {
- // 视频盒子的高度
- playWndHeight: "",
- // 视频盒子的宽度
- playWndWidth: "",
- oWebControl: null,
- initCount: 0,
- pubKey: "",
- cameraIndexCode: "", // 这里面是监控点编号
- objData: {
- appkey: "", //海康平台提供的appkey
- ip: "", //平台地址
- secret: "", //海康平台提供的secret
- port: 443,
- playMode: 0, // 0 预览 1回放
- layout: "1x1", //页面展示的模块数【16】
-
- },
- }
- },
这是monted里面的代码,组件加载后先获取视频盒子的高度和宽度
- // 首次加载时的到父容器的高度
- this.playWndHeight = this.$refs.playWndBox.clientHeight;
- // 首次加载时的到父容器的宽度
- this.playWndWidth = this.$refs.playWndBox.clientWidth;
-
- // 初始化播放器插件
- this.$nextTick(() => {
- this.initPlugin();
- });
-
- // 监听scroll事件,使插件窗口尺寸跟随DIV窗口变化
- window.addEventListener("scroll", () => {
- if (this.oWebControl != null) {
- this.oWebControl.JS_Resize(
- this.$refs.playWndBox.clientWidth,
- this.$refs.playWndBox.clientHeight
- );
- this.setWndCover();
- }
- });
-
- // 监听resize事件,使插件窗口尺寸跟随DIV窗口变化
- window.addEventListener("resize", (e) => {
- if (this.oWebControl != null) {
- this.oWebControl.JS_Resize(
- this.$refs.playWndBox.clientWidth,
- this.$refs.playWndBox.clientHeight
- );
- this.setWndCover();
- }
- });
组件销毁的时候要调用插件销毁方法,要不然页面会有插件残留。
- destroyed () {
- if (this.oWebControl != null) {
- // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
- this.oWebControl.JS_HideWnd();
- // 销毁当前播放的视频
- this.oWebControl.JS_RequestInterface({ funcName: "destroyWnd" });
- // 断开与插件服务连接
- this.oWebControl.JS_Disconnect();
- }
- },
下面是methods方法里面的函数,自己定义点击事件函数,把监控点编号发送到previewVideo(data)函数里面。前提是得先安装播放插件!!!
- // 创建播放实例
- initPlugin() {
- let that = this;
- this.oWebControl = null;
- that.oWebControl = new WebControl({
- szPluginContainer: "playWnd", // 指定容器id
- iServicePortStart: 15900, // 指定起止端口号,建议使用该值
- iServicePortEnd: 15909,
- szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsid
- cbConnectSuccess: () => {
- // 创建WebControl实例成功
- that.oWebControl
- .JS_StartService("window", {
- // WebControl实例创建成功后需要启动服务
- // 值"./VideoPluginConnect.dll"写死
- dllPath: "./VideoPluginConnect.dll",
- })
- .then(
- function () {
- // 设置消息回调
- that.oWebControl.JS_SetWindowControlCallback({
- cbIntegrationCallBack: that.cbIntegrationCallBack,
- });
- //JS_CreateWnd创建视频播放窗口,宽高可设定
- that.oWebControl
- .JS_CreateWnd("playWnd", 2040, 945, { bEmbed: true })
- //注:2040,945这是我本人项目视频盒子的大小,你们要根据自己视频盒子的大小进行修改,不然初始化插件的时候会有空白闪烁。
- .then(function () {
- // 创建播放实例成功后初始化
- that.init();
- });
- },
- function () {
- // 启动插件服务失败
- }
- );
- },
- // 创建WebControl实例失败
- cbConnectError: function () {
- that.oWebControl = null;
- // alert('插件未启动,正在尝试启动,请稍候...')
- // that.$message.warning("插件未启动,正在尝试启动,请稍候...");
- // 程序未启动时执行error函数,采用wakeup来启动程序
- window.WebControl.JS_WakeUp("VideoWebPlugin://");
- that.initCount++;
- if (that.initCount < 3) {
- setTimeout(function () {
- that.initPlugin();
- }, 3000);
- } else {
- // that.messageBox = true
- // alert('插件启动失败,请安装插件并重新启动!')
- // that.downloadHikVideo()
- // setTimeout(function () {
- // that.messageBox = false
- // }, 5000)
- // setTimeout(function () {
- // alert('插件启动失败,请检查插件是否安装!')
- // that.$message({
- // message: '插件启动失败,请检查插件是否安装! \n 插件下载地址:https://www.baidu.com',
- // type: 'warning'
- // });
- // }, 5000)
- }
- },
- cbConnectClose: () => {
- // 异常断开:bNormalClose = false
- // JS_Disconnect正常断开:bNormalClose = true
- // console.log("cbConnectClose");
- that.oWebControl = null;
- },
- });
- },
- // 初始化
- init(callback) {
- let that = this;
- that.getPubKey(() => {
- let appkey = that.objData.appkey; //综合安防管理平台提供的appkey,必填
- let secret = that.setEncrypt(that.objData.secret); //综合安防管理平台提供的secret,必填
- let ip = that.objData.ip; //综合安防管理平台IP地址,必填
- let playMode = that.objData.playMode; //初始播放模式:0-预览,1-回放
- let port = that.objData.port; //综合安防管理平台端口,若启用HTTPS协议,默认443
- let snapDir = "D:\\SnapDir"; //抓图存储路径
- let videoDir = "D:\\VideoDir"; //紧急录像或录像剪辑存储路径
- let layout = that.objData.layout; //playMode指定模式的布局
- let enableHTTPS = 1; //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1
- let encryptedFields = "secret"; //加密字段,默认加密领域为secret
- let showToolbar = 1; //是否显示工具栏,0-不显示,非0-显示
- let showSmart = 1; //是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示
- let buttonIDs = "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769"; //自定义工具条按钮
- // var toolBarButtonIDs = "2049,2304" // 工具栏上自定义按钮
- that.oWebControl
- .JS_RequestInterface({
- funcName: "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, //自定义工具条按钮
- }),
- })
- .then(function (oData) {
- that.oWebControl.JS_Resize(that.playWndWidth, that.playWndHeight); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
- if (callback) {
- callback();
- }
- // 隐藏
- // that.oWebControl.JS_HideWnd()
- });
- });
- },
- // 获取公钥
- getPubKey(callback) {
- let that = this;
- this.oWebControl
- .JS_RequestInterface({
- funcName: "getRSAPubKey",
- argument: JSON.stringify({
- keyLength: 1024,
- }),
- })
- .then(function (oData) {
- if (oData.responseMsg.data) {
- that.pubKey = oData.responseMsg.data;
- callback();
- }
- });
- },
- // RSA 加密
- setEncrypt(value) {
- let that = this;
- let encrypt = new window.JSEncrypt();
- encrypt.setPublicKey(that.pubKey);
- return encrypt.encrypt(value);
- },
- // 回调的消息
- cbIntegrationCallBack(oData) {
- let { responseMsg: type } = oData;
- if (type === "error") {
- } else {
- }
- },
- // 视频预览功能
- previewVideo(data) {
- let that = this;
- let cameraIndexCode = data; // 获取输入的监控点编号值,必填
- let streamMode = 0; // 主子码流标识:0-主码流,1-子码流
- let transMode = 0; // 传输协议:0-UDP,1-TCP
- let gpuMode = 0; // 是否启用GPU硬解,0-不启用,1-启用
- let wndId = -1; // 播放窗口序号(在2x2以上布局下可指定播放窗口)
- // console.log(cameraIndexCode, "-------cameraIndexCode-");
-
- that.oWebControl.JS_RequestInterface({
- funcName: "startPreview",
- argument: JSON.stringify({
- cameraIndexCode: cameraIndexCode.trim(), // 监控点编号
- streamMode: streamMode, // 主子码流标识
- transMode: transMode, // 传输协议
- gpuMode: gpuMode, // 是否开启GPU硬解
- wndId: wndId, // 可指定播放窗口
- }),
- });
- },
- // 停止全部预览
- stopAllPreview() {
- this.oWebControl.JS_RequestInterface({
- funcName: "stopAllPreview",
- });
- },
- // 格式化时间
- dateFormat(oDate, fmt) {
- let o = {
- "M+": oDate.getMonth() + 1, //月份
- "d+": oDate.getDate(), //日
- "h+": oDate.getHours(), //小时
- "m+": oDate.getMinutes(), //分
- "s+": oDate.getSeconds(), //秒
- "q+": Math.floor((oDate.getMonth() + 3) / 3), //季度
- S: oDate.getMilliseconds(), //毫秒
- };
- if (/(y+)/.test(fmt)) {
- fmt = fmt.replace(
- RegExp.$1,
- (oDate.getFullYear() + "").substr(4 - RegExp.$1.length)
- );
- }
- for (let k in o) {
- if (new RegExp("(" + k + ")").test(fmt)) {
- fmt = fmt.replace(
- RegExp.$1,
- RegExp.$1.length == 1
- ? o[k]
- : ("00" + o[k]).substr(("" + o[k]).length)
- );
- }
- }
- return fmt;
- },
-
- // 设置窗口裁剪,当因滚动条滚动导致窗口需要被遮住的情况下需要JS_CuttingPartWindow部分窗口
- 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;
-
- this.oWebControl.JS_RepairPartWindow(0, 0, 2041, 946); // 多1个像素点防止还原后边界缺失一个像素条
- if (iCoverLeft != 0) {
- this.oWebControl.JS_CuttingPartWindow(0, 0, iCoverLeft, 946);
- }
- if (iCoverTop != 0) {
- this.oWebControl.JS_CuttingPartWindow(0, 0, 2041, iCoverTop); // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条
- }
- if (iCoverRight != 0) {
- this.oWebControl.JS_CuttingPartWindow(2041 - iCoverRight, 0, iCoverRight, 946);
- }
- if (iCoverBottom != 0) {
- this.oWebControl.JS_CuttingPartWindow(0, 946 - iCoverBottom, 2041, iCoverBottom);
- }
- },
后期如果需要对监控点位进行多窗口预览,多窗口预览实现原理是先定义要预览的窗口数量,然后把要调用的窗口数据按照海康的格式进行存放到数组里面,在窗口数量改变之后再统一调用,下面是我简单调用的不是很牛的例子。
- // 对多点位监控监控进行查看
- lookPresetVideoHandler(presetDataArray) {
- //这里对要查看的监控点位按照海康的格式进行封装
- //presetDataArray是我自己监控的cameraIndexCode存放的数组,可按照自己的需求进行命名
- presetDataArray.forEach((item, index) => {
- let NowObj = {
- cameraIndexCode: item,
- ezvizDirect: 0,
- gpuMode: 0,
- streamMode: 1,
- transMode: 1,
- wndId: index + 1,
- };
- //在data里面创建一个videoList的数组
- this.videoList.push(NowObj);
- });
-
- let VideoListLength = presetDataArray.length;
- //利用switch 进行判断窗口的数量然后来调用初始化窗口的函数
- switch (true) {
- case VideoListLength == 1:
- this.objData.layout = "1x1";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 2:
- this.objData.layout = "1x2";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 3:
- this.objData.layout = "1+2";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 4:
- this.objData.layout = "2x2";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 5:
- this.objData.layout = "1+5";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 6:
- this.objData.layout = "1+5";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 7:
- this.objData.layout = "3+4";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 8:
- this.objData.layout = "1+7";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 9:
- this.objData.layout = "3x3";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 10:
- this.objData.layout = "1+9";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 11:
- this.objData.layout = "3x4";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 12:
- this.objData.layout = "3x4";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 13:
- this.objData.layout = "1+12";
- this.initLayout(this.objData.layout);
- break;
- case VideoListLength == 14:
- this.objData.layout = "1+1+12";
- this.initLayout(this.objData.layout);
- break;
- }
- //这里直接调用lookVideoListHandler这个函数来进行多窗口预览
- this.lookVideoListHandler(this.videoList);
- },
- //初始化播放窗口
- initLayout(data) {
- let that = this;
- that.oWebControl.JS_RequestInterface({
- funcName: "setLayout",
- argument: JSON.stringify({ layout: data }),
- });
- },
- //点击查看监控列表监控
- lookVideoListHandler(data) {
- let that = this;
- that.oWebControl.JS_RequestInterface({
- funcName: "startMultiPreviewByCameraIndexCode",
- argument: JSON.stringify({ list: data }),
- });
- //回调函数
- // .then(function () {
- // that.oWebControl.JS_SetWindowControlCallback({
- // cbIntegrationCallBack: function (oData) {
- // // let responseMsg = JSON.stringify(oData)
- // that.ooooo.push(oData.responseMsg.msg.cameraIndexCode)
- // }
- // });
- // console.log(that.ooooo);
-
- // });
- },
- //把视频预览中的playMode修改成1,插件就会自动调用回放功能
- // playMode: 1, // 0 预览 1回放
- //然后点击事件调用 backVideo(VideoIndex)这个函数,可以实现预览功能
-
-
- // 视频回放
- backVideo(VideoIndex) {
- //我这是查询三天前的数据,可以根据直接需求自行修改。
- //逻辑可能写的比较垃圾,我这是写死的,对着开发文档根据自己需求修改
- let cameraIndexCode = VideoIndex;
- let months = new Date().getMonth() + 1
- let end = new Date().getFullYear() + '/' + months + '/' + new Date().getDate() + ' 23:59:59'
- let endT = String(parseInt(new Date(end).getTime() / 1000));
- let star = String(parseInt(new Date(end).getTime() / 1000 - 3 * 24 * 60 * 60))
- this.oWebControl.JS_RequestInterface({
- funcName: "startPlayback",
- argument: JSON.stringify({
- cameraIndexCode: cameraIndexCode.trim(), // 监控点编号
- startTimeStamp: star, // 录像查询开始时间戳,单位:秒
- endTimeStamp: endT, // 录像查询结束时间戳,单位:秒
- recordLocation: 0, // 录像存储类型 0-中心存储 1-设备存储
- transMode: 0, // 传输协议 ,0-UDP 1-TCP
- gpuMode: 0, // 是否开启 GPU 硬解,0-不开启 1-开启
- wndId: -1 //可指定播放窗口
- })
- });
- },
HikDemo:直接点击进入这个地址,可以拿下来直接使用,里面为可以直接运行的demo。https://gitee.com/yyyyong/hik.git
海康开发平台只提供了原生JS的语法,这里是vue2的语法,有不懂的可以私信留言。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。