场景

Vue中预览HIKVSION海康威视的NVR(网络硬盘录像机)中多个通道(摄像机)的视频:

Vue中预览HIKVSION海康威视的NVR(网络硬盘录像机)中多个通道(摄像机)的视频_霸道流氓气质的博客-CSDN博客_海康nvr网页预览

在上面进行NVR视频预览时采用的是WEB控件开发包,需要电脑安装插件,并且需要浏览器在

兼容模式下预览。

除此之外,还有另一种无插件开发包的方式

截止目前是WEB无插件开发包V3.2

WEB3.2无插件版本开发包,支持高版本谷歌、火狐浏览器,同时需要设备支持Websocket取流。无插件版本需要使用nginx代理服务器。

按照说明可知,需要NVR支持websocket取流。

验证NVR是否支持websocket取流

这里的NVR型号为:DS-8664n-k16

登录到NVR的web页面-配置-系统设置-网络-高级配置-启用websocket

如果有启用WebSokcet选项,则代表可以,为了进一步验证,下载上面的官方demo。

按照官方提供的说明,运行nginx的代理

修改nginx目录下的配置文件

这里只是简单修改了端口号为8000

然后点击start.bat启动nginx,访问

http://127.0.0.1:8000/cn/demo.html

输入NVR对应的地址、用户名、密码等信息,然后点击登录和开始预览

如果官方demo能预览成功,那么就可以使用无插件开发包了。

注:

博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

1、在demo.html中能实现预览的基础上,只需要根据自己的需要改造即可,

对应的demo以及接口文档说的很清楚。

那么怎么将demo的示例与现有项目进行结合,比如前后端分离的SpringBoot+Vue的项目。

若依前后端分离版本地搭建开发环境并运行项目的教程:

若依前后端分离版手把手教你本地搭建环境并运行项目_霸道流氓气质的博客-CSDN博客_前后端分离项目本地运行

在基于Vue的项目上进行代码改造

后台存储摄像头的相关信息,最需要的就是通道号,拿其来进行预览时传参用

选中摄像头时点击预览按钮,传递通道号参数至预览页面。

前面流程可参考

SpringBoot+Vue+HIKVSION实现摄像头多选并多窗口预览(插件版):

SpringBoot+Vue+HIKVSION实现摄像头多选并多窗口预览(插件版)_霸道流氓气质的博客-CSDN博客_websocket取流

然后根据官方demo引入需要的js等文件

下面主要是预览页面的代码

<template><el-dialogtitle="视频监控":visible.sync="videoOpen"width="800px":append-to-body=false@close="videoClose"class="video_box":modal=false><!-- 摄像头 --><!--视频窗口展示--><div id="playWnd" class="playWnd" ref="playWnd"></div></el-dialog>
</template><script>
const g_iWndIndex = 0; //可以不用设置这个变量,有窗口参数的接口中,不用传值,开发包会默认使用当前选择窗口
export default {name: "HkVideo1",components: {},props: {channelId: "",},watch: {},data() {return {isLogin: false,videoOpen: false,szDeviceIdentify: "", // 设备标识(IP_Port)ip: "NVR的ip",port: "80",username: "NVR的用户名",password: "NVR的密码",};},created() {},mounted() {},destroyed() {},methods: {// 创建播放实例async initPlugin() {let iRet = window.WebVideoCtrl.I_CheckPluginInstall();if (-1 == iRet) {alert("您还未安装过插件,请安装WebComponentsKit.exe!");this.$confirm("是否下载WebComponentsKit.exe插件?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {window.location.href = "/static/HK_3.2/WebComponentsKit.exe";});return;}// 初始化插件参数及插入插件window.WebVideoCtrl.I_InitPlugin(800, 600, {bWndFull: true, //是否支持单窗口双击全屏,默认支持 true:支持 false:不支持iPackageType: 2,//szColorProperty:"plugin-background:0000ff; sub-background:0000ff; sub-border:00ffff; sub-border-select:0000ff",   //2:PS 11:MP4iWndowType: 1,bNoPlugin: true,// 窗口选中事件回调cbSelWnd: (xmlDoc) => {var szInfo = "当前选择的窗口编号:" + g_iWndIndex;console.log(szInfo);},// 窗口双击事件回调cbDoubleClickWnd: (iWndIndex, bFullScreen) => {var szInfo = "当前放大的窗口编号:" + iWndIndex;if (!bFullScreen) {szInfo = "当前还原的窗口编号:" + iWndIndex;}console.log(szInfo);},// 插件事件回调cbEvent: (iEventType, iParam1, iParam2) => {if (2 == iEventType) {// 回放正常结束console.log("窗口" + iParam1 + "回放结束!");} else if (-1 == iEventType) {console.log("设备" + iParam1 + "网络错误!");} else if (3001 == iEventType) {this.clickStopRecord(g_szRecordType, iParam1);}},cbRemoteConfig: () => {console.log("关闭远程配置库!");},// 插件初始化完成回调cbInitPluginComplete: () => {this.$nextTick(() => {console.log('窗口', this.$refs.playWnd)let isInit = window.WebVideoCtrl.I_InsertOBJECTPlugin('playWnd');console.log('isInit', isInit)// 检查插件是否最新if (-1 == window.WebVideoCtrl.I_CheckPluginVersion()) {alert("检测到新的插件版本,请对WebComponentsKit.exe进行升级!");return;} else this.clickLogin();})},});},// 登录clickLogin() {let { ip, port, username, password } = this;if ("" == ip || "" == port) {return;}this.szDeviceIdentify = ip + "_" + port;let iRet = window.WebVideoCtrl.I_Login(ip, 1, port, username, password, {success: (xmlDoc) => {setTimeout(() => {this.getChannelInfo();this.getDevicePort();}, 10);},error: (status, xmlDoc) => {console.log(" 登录失败!", status, xmlDoc);},});if (-1 == iRet) {this.clickStartRealPlay();}},// 获取通道getChannelInfo() {if (null == this.szDeviceIdentify) {return;}// 模拟通道window.WebVideoCtrl.I_GetAnalogChannelInfo(this.szDeviceIdentify, {async: false,success: (xmlDoc) => {},error: (status, xmlDoc) => {console.log(" 获取模拟通道失败!");},});// 数字通道window.WebVideoCtrl.I_GetDigitalChannelInfo(this.szDeviceIdentify, {async: false,success: (xmlDoc) => {},error: (status, xmlDoc) => {console.log(" 获取数字通道失败!");},});// 零通道window.WebVideoCtrl.I_GetZeroChannelInfo(this.szDeviceIdentify, {async: false,success: (xmlDoc) => {},error: (status, xmlDoc) => {console.log(" 获取零通道失败!");},});},// 获取端口getDevicePort() {if (null == this.szDeviceIdentify) {return;}this.port = window.WebVideoCtrl.I_GetDevicePort(this.szDeviceIdentify);if (this.port != null) {this.clickStartRealPlay();return true} else {console.log(" 获取端口失败!");return false}},// 开始预览clickStartRealPlay(iStreamType) {let wndInfo = window.WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);let iChannelID = this.channelId; // 通道列表let bZeroChannel = false; // 是否播放零通道(下拉框)let szInfo = "";if ("undefined" === typeof iStreamType) {iStreamType = 2; // 1主码流 2子码流 3第三码流 4转码码流}if (null == this.szDeviceIdentify) {return;}let startRealPlay = () => {window.WebVideoCtrl.I_StartRealPlay(this.szDeviceIdentify, {iRtspPort: 554,iStreamType: iStreamType,iChannelID: iChannelID,bZeroChannel: bZeroChannel,success: () => {szInfo = "开始预览成功!";console.log(szInfo);},error: (status, xmlDoc) => {if (403 === status) {szInfo = "设备不支持Websocket取流!";} else {szInfo = "开始预览失败!";}this.$message.error(szInfo);},});};if (wndInfo != null) {// 已经在播放了,先停止window.WebVideoCtrl.I_Stop({success: () => {startRealPlay();},});} else {startRealPlay();}},// 停止预览clickStopRealPlay() {let oWndInfo = window.WebVideoCtrl.I_GetWindowStatus(g_iWndIndex),szInfo = "";if (oWndInfo != null) {window.WebVideoCtrl.I_Stop({success: () => {szInfo = "停止预览成功!";console.log(szInfo);},error: () => {szInfo = "停止预览失败!";console.log(szInfo);},});}},// 全屏clickFullScreen() {window.WebVideoCtrl.I_FullScreen(true);},// 停止录像clickStopRecord(szType, iWndIndex) {if ("undefined" === typeof iWndIndex) {iWndIndex = g_iWndIndex;}var oWndInfo = window.WebVideoCtrl.I_GetWindowStatus(iWndIndex),szInfo = "";if (oWndInfo != null) {window.WebVideoCtrl.I_StopRecord({success: () => {if ("realplay" === szType) {szInfo = "停止录像成功!";} else if ("playback" === szType) {szInfo = "停止剪辑成功!";}showOPInfo(oWndInfo.szDeviceIdentify + " " + szInfo);},error: () => {if ("realplay" === szType) {szInfo = "停止录像失败!";} else if ("playback" === szType) {szInfo = "停止剪辑失败!";}showOPInfo(oWndInfo.szDeviceIdentify + " " + szInfo);},});}},// 查看摄像videoChange() {this.videoOpen = true;this.$nextTick(() => {if(!this.isLogin) {this.isLogin = truethis.initPlugin()} else {this.clickStartRealPlay();}});},// 关闭摄像头弹窗videoClose() {this.videoOpen = false;console.log(this.isLogin)this.clickStopRealPlay();},},
};
</script><style scoped lang="scss">
.video_box {width: 100%;height: 100%;
}.plugin {width: 100%;height: 100%;
}.playWnd {width: 800px;height: 600px;margin: 0;
}.video_box {::v-deep .el-dialog__body {padding: 0 !important;}
}
</style>

2、关于nginx代理

查看官方示例nginx配置文件中

需要做两部分的代理。最前面的

        location / {root   "../webs";index  index.html index.htm;}

是其示例demo的静态页面的代理,对应自己的Vue的dist包的代理

对应的线上要改成

    location / {root C:\dist;try_files $uri $uri/ /index.html;index index.html index.htm;}

剩下两个代理一个是接口代理,比如调用登录接口时进行反向代理

​location ~ /ISAPI|SDK/ {if ($http_cookie ~ "webVideoCtrlProxy=(.+)") {proxy_pass http://$cookie_webVideoCtrlProxy;break;}}​

这个意思大概是如果是ISAPI或者SDK开头的请求,波浪线代表不忽略大小写,就被被代理到下面的地址。

但是这里会疑问为什么代理配置文件中没有配置任何关于nvr的ip地址的配置,那我代理时是怎么请求接口的。

这里是在中间加一个nginx进行转发,nginx通过请求中的Cookie找到NVR的Ip地址进行转发,包括预览时获取视频流

也是通过这种方式进行websocket代理并获取视频流。

类似如下这张流程图。

所以只要按照官方的nginx的配置文件将自己项目的nginx配置文件进行修改即可

下面提供一个改造之后项目的nginx的配置文件示例

​
worker_processes 1;
events {worker_connections 1024;
}
http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;map $http_upgrade $connection_upgrade {default upgrade;'' close;}server {listen 90;server_name localhost;client_max_body_size 300M;#websocket相关配置proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_set_header X-real-ip $remote_addr;proxy_set_header X-Forwarded-For $remote_addr;location / {root D:\font\dist;try_files $uri $uri/ /index.html;index index.html index.htm;}location /prod-api/ {proxy_set_header Host $http_host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header REMOTE-HOST $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://服务器ip:8888/;}location ~ /ISAPI|SDK/ {if ($http_cookie ~ "webVideoCtrlProxy=(.+)") {proxy_pass http://$cookie_webVideoCtrlProxy;break;}}location ^~ /webSocketVideoCtrlProxy {#web socketproxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_set_header Host $host;if ($http_cookie ~ "webVideoCtrlProxyWs=(.+)") {proxy_pass http://$cookie_webVideoCtrlProxyWs/$cookie_webVideoCtrlProxyWsChannel?$args;break;}if ($http_cookie ~ "webVideoCtrlProxyWss=(.+)") {proxy_pass http://$cookie_webVideoCtrlProxyWss/$cookie_webVideoCtrlProxyWsChannel?$args;break;}}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}
}​

前后端项目使用Nginx代理可以参考

若依前后端分离版本,Windows下使用Nginx代理的方式进行部署(全流程,图文教程):

若依前后端分离版本,Windows下使用Nginx代理的方式进行部署(全流程,图文教程)_霸道流氓气质的博客-CSDN博客

预览效果

Hikvison对接NVR实现WEB无插件开发包实现前端视频预览(html、vue、nginx代理)相关推荐

  1. web项目使用OpenOffice实现前端在线预览office文档(超详细)

    超详细的OpenOffice实现前端在线预览office文档记录 最近搞一个数字化共享平台,是一个java web项目,使用框架ssm,其中项目有一个需要在线预览PDF.excle.ppt.word文 ...

  2. 通过java解码web前端直接预览海康威视摄像头

    一:前言 最近进行项目开发时遇到了需要前端直接调用摄像头,并直接进行播放的需求.原本计划通过海康威视官网的<WEB无插件开发包 V3.2>直接进行控制.交互,实现摄像头直接登录以及取流预览 ...

  3. office web viewer实现office文档在线预览

    office web viewer实现office文档在线预览 office web viewer官网介绍 若要自行制作 URL,您可使用以下链接,其中 <文档位置> 是文档的 URL. ...

  4. [Office Web Apps]实现在线office文档预览

    摘要 在使用office web apps实现office文档在线预览的时候,需要注意的地方. web api web api作为owa在线预览服务回调的接口,这里面核心代码片段如下: using H ...

  5. vue引入海康监控web无插件开发的问题

    海康web版开发插件: 需要支持websocket取流的摄像头和录像机:需要本机安装nginx服务(但是使用视频录像机自带的web页面可以用高版本浏览器直接预览没有websocket的摄像头.找客服咨 ...

  6. 在web html页面中,打印、预览当前页面

    最近的项目需要简单的实现一下打印当前页面的数据,有分页打印的功能.下面的一段代码可以帮助我们实现简单的打印功能,要想实现复杂的打印那需要利用其他的打印控件.这里就不提了! <html> & ...

  7. 部署Office Web Apps Server 实现office在线编辑预览,office-online

    提示:此版本为旧版最新版本请访问部署Office Online Server服务 一:准备工作: 1.两台Windows机器我用的是[Windows Server 2012 r2]可以找度娘要下 2. ...

  8. form 表单 + HTML5(FileReader) +iframe 实现无刷新图片上传+图片预览效果

    作为一个初入前端的菜鸟,最近因为一个无刷新上传图片问题走了很多弯路,所以在这里给大家分享一下,不足之处希望谅解.无刷新上传图片一般有两种方式,一种是 form 表单+iframe ,还有一种是 aja ...

  9. 利用jquery.form.js实现Ajax无刷新图片上传及预览功能

    某些时候当我们做登记页面的时候可能需要上传图片,并实现即时预览的功能. 如果只是预览而不上传,可以使用ImagePreview来实现,方便简单.如果需要上传,那么你也可以使用uploadify无刷新上 ...

最新文章

  1. iOS 秒数转换成时间,时,分,秒
  2. POI读入excel文件到Java中
  3. Tomcat 中文路径乱码
  4. 《需求工程——软件建模与分析》阅读笔记之一
  5. 计算机算法设计与分析 最长子序列
  6. python下载可执行安装程序_如何下载并安装python
  7. OPENNLP——java的NLP工具
  8. 设计模式(二)--单例模式
  9. IDEA多款主题颜色推荐!炫酷经典!
  10. DM manager工具的使用
  11. 基于神经网络的车牌识别系统
  12. 开源ESB-ServiceMix服务总线
  13. 紫光视频平台服务器系统,紫光展锐打造操作系统生态,赋能万物互联智能时代...
  14. 《白夜行》读后感:白夜行走,暗中羁绊
  15. 深度学习【注意力机制(Attention)原理和实现】
  16. 无广告托管应用,免费的应用分发平台,提供下载次数等数据统计,Android、ios应用合并,一个二维码搞定
  17. CSS 实现文字渐变色
  18. 威尔士和英格兰同属英国,但为啥还要在世界杯上进行PK?
  19. ps2018首选项出现要求96和8之间的整数怎么办?
  20. 海伦公式计算三角形面积 C++

热门文章

  1. 恶意进程 - 挖矿程序处理
  2. STM32 串口的使用
  3. LeetCode——6. Z 字形变换
  4. KernelSU: 内核 ROOT 方案, KernelSU KernelSU KernelSU 新的隐藏root防止检测 封号方案
  5. 可清空所选时间的jquery.datetimepicker时间插件
  6. 编程入门篇之零基础入门(通用)
  7. PC端兼容问题--配置浏览器内核
  8. 如何用Jmeter发送消息到Solace JNDI
  9. HTML有2种路径的写法:绝对路径和相对路径
  10. vue qrcodejs2生成二维码实现手机APP扫码进行web网页登录