当前位置:首页 » 《关注互联网》 » 正文

WebSDK_V3.3.0 植入Vue2 项目

28 人参与  2024年04月22日 17:14  分类 : 《关注互联网》  评论

点击全文阅读


1.公司需要展示海康摄像头的预览画面

2.经过我两天的搜索资料加尝试,几种方式

2.1后端转码,前端调接口取太麻烦,对服务器负荷大

2.2 vlc插件对rtsp取流 高版本的各种浏览器不支持了vlc插件

2.3 WEB无插件开发包 V3.2  需要支持websocket,不是所有海康设备都支持,而且要自己去开启这个配置

2.4 WEB3.0控件开发包 V3.0  这个原理和vlc插件一模一样,谁会特意下个低版本谷歌

2.5 WEB3.3控件开发包 V3.3 从海康描述来说,非常适合,然后开始钻研,用了一个三天左右,成功迁移到vue项目,并实现预览,本来还要实现在预览画面上配置smart事件的区域,但是这个画面层级太高,我完全无法在画面上加个canvas,然后在canvas上作图.最终效果如下,切换通道可以切换画面

海康插件下载地址海康开放平台

1.把压缩包解压后,把

webVideoCtrl.js   
jsVideoPlugin-1.0.0.min.js
jquery-1.7.1.min.js三个文件拷贝到自己项目的src/utils文件夹下,然后你准备在哪个页面做预览效果,就在这个页面引入这三个js文件,webVideoCtrl.js的代码是需要改动的(改动是因为它本身是针对html也就是压缩包那样的结构去做的,现在为了适配我的vue,需要改代码,如果你直接使用原html页面,那本文章就不需要参考,你可以demo文件夹直接放在public下,然后vue中跳转,地址就是/demo/index.html,最终会指向public/demo/index.html,然后把除了画面以外的所有样式都改为不可见,注意不能把多余的登陆预览回放组件删掉,否则会有很多调不通的报错),jsVideoPlugin-1.0.0.min.js的代码不需要改动,jquery-1.7.1.min.js也不需要改动

这边我为了修改webVideoCtrl.js先用idea打开然后格式化了这个文件,格式化之后,里面会有if else导致的报错 比如if(a) b  else c;把它换行成

if(a) b 

else c  就是如果不用大括号包起来,if和else代码不能在同一行

vue页面代码如下

<template>  <div class='app-container'>      <el-form ref='ruleForm' :model='ruleForm' :rules='ruleFormRules' label-width='80px' >        <el-form-item label='通道' prop='enabled'>          <template slot-scope="scope">          <el-select            v-model="ruleForm.monitorPointId"            placeholder="请选择通道"            filterable            size="small"            @change="regetRule"          >            <el-option              v-for="cameraChannel in points"              :key="cameraChannel.id"              :label="cameraChannel.name"              :value="cameraChannel.id"            />          </el-select>          </template>        </el-form-item>        <el-tabs v-model="algorithmId" @tab-click="handleClick">          <el-tab-pane :label="item.name" :name="item.id" v-for="(item,index) in algorithms" :key="index" ></el-tab-pane>        </el-tabs>        <el-form-item label='是否启用' prop='enabled'>          <el-switch            v-model="ruleForm.enabled"            active-color="#13ce66"            inactive-color="#ff4949">          </el-switch>        </el-form-item>        <el-form-item label='区域规则' class="plugin" prop='coordinates'>          <div style="position: relative">            <div id="divPlugin" width="250" height="250" class="plugin"  style="position: relative;top: 0; left: 250px;z-index:-1;pointer-events: none"></div>               <canvas ref="canvas0" class="plugin"  width="250" height="250" @mousedown="mouseDown" style="pointer-events: none;z-index:3;position: absolute;top: 0; left: 0;background-color: rgba(255, 255, 255, 0.5);border: 1px solid rgb(255, 204, 0);  cursor: default;"></canvas>          </div>        </el-form-item>        <el-form-item label='绘制' prop='screenSize'>          <el-button type="info" @click="startDraw">开始绘制</el-button>          <el-button type="info" @click="stopDraw">停止绘制</el-button>          <el-button type="info" @click="clearDraw">清除绘制</el-button>        </el-form-item>        <el-form-item label='目标检测' prop='detectionTarget'>            <el-checkbox name="human" v-model="humanCheck">人类</el-checkbox>            <el-checkbox name="vehicle" v-model="vehicleCheck">车辆</el-checkbox>        </el-form-item>        <el-form-item label='方向' prop='directionSensitivity' v-if="algCode==='LineDetection'">          <el-select v-model="ruleForm.directionSensitivity" placeholder="请选择">            <el-option              v-for="item in directionList"              :key="item.value"              :label="item.label"              :value="item.value">            </el-option>          </el-select>        </el-form-item>        <el-form-item label='灵敏度' prop='sensitivityLevel'>          <el-slider v-model="ruleForm.sensitivityLevel" :min="1" show-input></el-slider>        </el-form-item>        <el-form-item label='时间阈值' prop='timeThreshold' v-if="algCode==='FieldDetection'||algCode==='LineDetection'">          <el-slider v-model="ruleForm.timeThreshold" show-input :max="10"></el-slider>        </el-form-item>      </el-form>      <div slot='footer' class='dialog-footer'>        <el-button :loading='buttonLoading' type='primary' @click='submitRuleForm'>确 定</el-button>        <el-button @click='rulecancel'>取 消</el-button>      </div>  </div></template><script>    import { addByServerIdAndAlgId,addByServerIdAndPointId,deleteByServerIdAndPointId,deleteByServerIdAndAlgId,setRule,addAlgorithmServer, delAlgorithmServer, getAlgorithmServer, listAlgorithmServer, updateAlgorithmServer,getRuleByServerIdAndAlgIdAndPointId } from '@/api/alg/algorithmServer'    import { listMonitorPointAll } from '@/api/alg/monitorPoint';    import { listAlgorithmAll } from '@/api/alg/algorithm';    import $ from '@/utils/webVideoCtrl';    import a from '@/utils/jsVideoPlugin-1.0.0.min';    import b from '@/utils/jquery-1.7.1.min';    import axios from "axios";export default {  name: 'smartEvent',  data() {    return {      points:[],      algorithms:[],      directionList:[{label:'左->右',value:"left-right"},{label:'左<->右',value:"any"},{label:'左<-右',value:"right-left"}],      algCode:'',      humanCheck:false,      vehicleCheck:false,      id:null,      algorithmId:'',      activeName:0,      channelFilterValue:'',      algFilterValue:'',      AllPointList:[],      ShowPointList:[],      AllAlgList:[],      ShowAlgList:[],      // 按钮loading      buttonLoading: false,      // 遮罩层      loading: true,      // 导出遮罩层      exportLoading: false,      // 选中数组      ids: [],      // 非单个禁用      single: true,      // 非多个禁用      multiple: true,      // 显示搜索条件      showSearch: true,      // 总条数      total: 0,      // 算法服务器表格数据      algorithmServerList: [],      // 弹出层标题      title: '',      // 是否显示弹出层      open: false,      // 查询参数      queryParams: {        pageNum: 1,        pageSize: 10,        name: undefined,        ip: undefined,      },      // 表单参数      form: {        id: undefined,        name: undefined,        ip: undefined,        port: undefined,        username: undefined,        password: undefined,        updateTime: undefined,        createTime: undefined,        updateBy: undefined,        createBy: undefined,        delFlag: undefined,        algorithms: [],        points:[],      },      actionArr: [],      ruleForm:{        sensitivityLevel:50,        monitorPointId:undefined,        detectionTarget:undefined,        screenSize: undefined,        timeThreshold: 5,        coordinates: undefined,        enabled:false      },      drawFlag:false,      openRule:false,      ruleFormRules:{        monitorPointId: [          { required: true, message: '通道不能为空', trigger: 'blur' }        ],      },      // 表单校验      rules: {        id: [          { required: true, message: '不能为空', trigger: 'blur' }        ],        name: [          { required: true, message: '名称不能为空', trigger: 'blur' }        ],        ip: [          { required: true, message: 'ip不能为空', trigger: 'blur' }        ],        port: [          { required: true, message: 'port不能为空', trigger: 'blur' }        ],        username: [          { required: true, message: '账号不能为空', trigger: 'blur' }        ],        password: [          { required: true, message: '密码不能为空', trigger: 'blur' }        ],      }    }  },  created() {  },  destroyed(){    WebVideoCtrl.I_DestroyPlugin();  },  mounted(){    this.serverId=this.$route.query.serverId;    getAlgorithmServer({id:this.serverId}).then((res)=>{      this.points=res.data.points;      this.algorithms=res.data.algorithms;      if (res.data.points.length!=0){        this.ruleForm.monitorPointId=res.data.points[0].id;      }      if(res.data.algorithms.length!=0){        this.algorithmId=res.data.algorithms[0].id;      }      this.$forceUpdate;      WebVideoCtrl.I_InitPlugin({        bWndFull: false,     //是否支持单窗口双击全屏,默认支持 true:支持 false:不支持        iWndowType: 1,        bDebugMode: true,        cbInitPluginComplete: function () {          WebVideoCtrl.I_InsertOBJECTPlugin("divPlugin").then(() => {            console.log("插件初始化")            // 检查插件是否最新            WebVideoCtrl.I_CheckPluginVersion().then((bFlag) => {              if (bFlag) {                alert("检测到新的插件版本,双击开发包目录里的HCWebSDKPlugin.exe升级!");              }            });          }, () => {            alert("插件初始化失败,请确认是否已安装插件;如果未安装,请双击开发包目录里的HCWebSDKPlugin.exe安装!");            axios.get('/file/HCWebSDKPlugin.exe',{              responseType: 'blob'            }).then(res => {              console.log(res);              const url = window.URL.createObjectURL(new Blob([res.data]));              const link = document.createElement('a');              link.href = url;              link.setAttribute('download', 'HCWebSDKPlugin.exe');              document.body.appendChild(link);              link.click();            })          });        }      });      if (this.algorithmId&&this.ruleForm.monitorPointId){        console.log("预览初始化")        this.getRule();      };    })  },  methods: {    handleClick(tab, event){      for(let i =0;i<this.algorithms.length;i++){        let item=this.algorithms[i];        if (item.id==this.algorithmId){          this.algCode=item.code;          break;        }      }    this.getRule();    },    startDraw(){      console.log("开启绘制")      this.drawFlag=true;     // this.rtsp();    },    clearDraw(){      const canvasDraw0 = this.$refs.canvas0;      const ctx=canvasDraw0.getContext('2d');      ctx.clearRect(0, 0, canvasDraw0.width, canvasDraw0.height);      this.actionArr=[];    },    stopDraw(){      if (this.drawFlag){        console.log(this.actionArr);        console.log(this.algCode);        if(this.actionArr.length!==2&&this.algCode==='LineDetection'){          alert("越界告警需要两个坐标");          return;        }else if(this.actionArr.length!==4&&this.algCode!=='LineDetection'){          alert("区域需要四个坐标点");          return;        }      }      this.drawFlag=false;    },    drawCircle(x, y){    },    mouseDown(e){      console.log(e);      if(e.buttons==1&&this.drawFlag){        if(this.actionArr.length>=4){          return;        }        this.actionArr.push({x:e.offsetX,y:e.offsetY})        this.drawActionArr();      }    },    mouseMove(e){      console.log(e);    },    filterAlg(){      this.ShowAlgList=this.AllAlgList.filter(function (element,index,array){        return element.name.search(e)!=-1;      })    },    filterChannel(e){      this.ShowPointList=this.AllPointList.filter(function (element,index,array){        return element.name.search(e)!=-1;      })    },    handleAlgAdd(index){      let element = this.ShowAlgList[index];      let find=this.form.algorithms.find((value => value.id==element.id));      if (!find){        addByServerIdAndAlgId({algorithmId:element.id,serverId:this.id}).then(response=>{          this.form.algorithms.push(element);        })      }    },    handleChannelAdd(index){      let element = this.ShowPointList[index];      let find=this.form.points.find((value => value.id==element.id));      if (!find){        addByServerIdAndPointId({pointId:element.id,serverId:this.id}).then(response=>{        this.form.points.push(element);        })      }    },    drawActionArr(){      if (this.actionArr.length>0){        const canvasDraw0 = this.$refs.canvas0;        const ctx=canvasDraw0.getContext('2d');        ctx.fillStyle="black";        ctx.clearRect(0, 0, canvasDraw0.width, canvasDraw0.height)        for (let i = 0; i <this.actionArr.length ; i++) {          ctx.beginPath();          ctx.arc(this.actionArr[i].x,this.actionArr[i].y,5,0,2*Math.PI,true);          ctx.fill();          ctx.closePath();          ctx.font="20px Georgia";          ctx.fillText(i+1,this.actionArr[i].x,this.actionArr[i].y)        }        ctx.beginPath();        ctx.moveTo(this.actionArr[0].x,this.actionArr[0].y);        for (let i = 1; i <this.actionArr.length ; i++) {          ctx.lineTo(this.actionArr[i].x,this.actionArr[i].y);          ctx.moveTo(this.actionArr[i].x,this.actionArr[i].y);          if (i==this.actionArr.length-1){            ctx.lineTo(this.actionArr[0].x,this.actionArr[0].y);          }        }        ctx.stroke()        ctx.closePath();      }    },    regetRule(e){      this.getRule();    },    getRule(){      getRuleByServerIdAndAlgIdAndPointId({serverId:this.serverId,algorithmId:this.algorithmId,pointId:this.ruleForm.monitorPointId}).then(response => {        this.clearDraw();        this.humanCheck=false;        this.vehicleCheck=false;        if (response.data){          this.ruleForm = response.data;          this.actionArr=this.ruleForm.coordinates?this.ruleForm.coordinates.map(function(value) {            return {x:parseInt(value.x)/4,y:parseInt(value.y)/4}          }):[];          this.drawActionArr();          if (response.data.detectionTarget) {            if (response.data.detectionTarget === 'human') {              this.humanCheck = true;              this.vehicleCheck = false;            } else if (response.data.detectionTarget === 'vehicle') {              this.humanCheck = false;              this.vehicleCheck = true;            } else if (response.data.detectionTarget === 'human,vehicle') {              this.humanCheck = true;              this.vehicleCheck = true;            }          }          this.$forceUpdate();          console.log("ruleForm")          console.log(this.ruleForm)          this.startView(response.data.point);        }else {          console.log("没返回值")          this.ruleForm ={            monitorPointId:this.ruleForm.monitorPointId,            serverId:this.serverId,            algorithmId:this.algorithmId,            sensitivityLevel:50,            detectionTarget:undefined,            screenSize: undefined,            timeThreshold: 5,            coordinates: undefined,            enabled:false          };        }      });    },    startView(option){      console.log("走到预览方法里")      if (!option||!option.username||!option.password||!option.ip){        alert("监控点数据不全,无法预览")        return;      }      //获取预览画面      var oLiveView = {        iProtocol: 1,            // protocol 1:http, 2:https        szIP: option.ip,    // protocol ip        szPort: "80",            // protocol port        szUsername: option.username,     // device username        szPassword: option.password, // device password        iStreamType: 1,          // stream 1:main stream  2:sub-stream  3:third stream  4:transcode stream        iChannelID: option.channelId?option.channelId:1,           // channel no        bZeroChannel: false      // zero channel      };      let isExists = WebVideoCtrl.findDeviceIndexByIP(option.ip);      console.log("是否登陆过")      console.log(isExists!==-1)      if (isExists!==-1){        var szDeviceIdentify = oLiveView.szIP + "_" + oLiveView.szPort;        var oWndInfo = WebVideoCtrl.I_GetWindowStatus(0);        console.log("窗口是否在播放")        console.log(oWndInfo != null)        if (oWndInfo != null) {// 已经在播放了,先停止          WebVideoCtrl.I_Stop({iWndIndex:0,            success: function () {            console.log("停止成功")              setTimeout(function () {                WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {                  iWndIndex:0,                  iStreamType: oLiveView.iStreamType,                  iChannelID: oLiveView.iChannelID,                  bZeroChannel: oLiveView.bZeroChannel                });              }, 1000);            }          });        } else {          setTimeout(function () {            WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {              iWndIndex:0,              iStreamType: oLiveView.iStreamType,              iChannelID: oLiveView.iChannelID,              bZeroChannel: oLiveView.bZeroChannel            });          }, 1000);        }        return;      }      WebVideoCtrl.I_Login(oLiveView.szIP, oLiveView.iProtocol, oLiveView.szPort, oLiveView.szUsername, oLiveView.szPassword, {        success: function (xmlDoc) {          console.log("登陆成功")          // 开始预览          var szDeviceIdentify = oLiveView.szIP + "_" + oLiveView.szPort;          var oWndInfo = WebVideoCtrl.I_GetWindowStatus(0);          console.log("窗口是否在播放")          console.log(oWndInfo != null)          if (oWndInfo != null) {// 已经在播放了,先停止            WebVideoCtrl.I_Stop({iWndIndex:0,              success: function () {                console.log("停止播放")                setTimeout(function () {                  WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {                    iWndIndex:0,                    iStreamType: oLiveView.iStreamType,                    iChannelID: oLiveView.iChannelID,                    bZeroChannel: oLiveView.bZeroChannel                  });                }, 1000);              }            });          } else {            setTimeout(function () {              WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {                iWndIndex:0,                iStreamType: oLiveView.iStreamType,                iChannelID: oLiveView.iChannelID,                bZeroChannel: oLiveView.bZeroChannel              });            }, 1000);          }        },        error: function (oError) {        if (2001 === status) {          var szDeviceIdentify = oLiveView.szIP + "_" + oLiveView.szPort;          var oWndInfo = WebVideoCtrl.I_GetWindowStatus(0);          if (oWndInfo != null) {// 已经在播放了,先停止            WebVideoCtrl.I_Stop({iWndIndex:0,              success: function () {                console.log("停止播放成功")                setTimeout(function () {                  WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {                    iWndIndex:0,                    iStreamType: oLiveView.iStreamType,                    iChannelID: oLiveView.iChannelID,                    bZeroChannel: oLiveView.bZeroChannel,                  });                }, 1000);              }            });          } else {            setTimeout(function () {              WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {                iWndIndex:0,                iStreamType: oLiveView.iStreamType,                iChannelID: oLiveView.iChannelID,                bZeroChannel: oLiveView.bZeroChannel              });            }, 1000);          }        }else {          console.log("登陆失败")          console.log(oLiveView)          console.log(oError);          console.log(status);        }      }      });    },    handleAlgRemove(index){      this.form.algorithms.splice(index,1);    },    handlePointRemove(index){      this.form.points.splice(index,1);    },    showPointers(row){      this.algCode=row.code?row.code:"";      this.algorithmId=row.id;      this.openRule=true;      this.rulereset();    },    // 取消按钮    cancel() {      this.open = false      this.reset()    },    // 取消按钮    rulecancel() {      this.rulereset()      this.openRule = false    },    // 表单重置    reset() {      this.form = {        id: undefined,        name: undefined,        ip: undefined,        port: undefined,        username: undefined,        password: undefined,        updateTime: undefined,        createTime: undefined,        updateBy: undefined,        createBy: undefined,        delFlag: undefined,        algorithms: [],        points:[],      }      this.resetForm('form')    },    rulereset() {      this.ruleForm = {        sensitivityLevel:50,        monitorPointId:undefined,        detectionTarget:undefined,        screenSize: undefined,        timeThreshold: 5,        coordinates: undefined,        enabled:false      }      this.clearDraw();      this.resetForm('ruleForm')    },    /** 修改按钮操作 */    handleUpdate(row) {      this.id=row.id;      this.loading = true      this.reset()      const id = row.id || this.ids      getAlgorithmServer({ id: id }).then(response => {        this.loading = false        this.form = response.data        this.open = true        this.title = '修改算法服务器'      })    },    /** 提交按钮 */    submitForm() {      this.$refs['form'].validate(valid => {        if (valid) {          this.buttonLoading = true          if (this.form.id != null) {            updateAlgorithmServer(this.form).then(response => {              this.$modal.msgSuccess('修改成功')              this.open = false              this.getList()            }).finally(() => {              this.buttonLoading = false            })          } else {            addAlgorithmServer(this.form).then(response => {              this.$modal.msgSuccess('新增成功')              this.open = false              this.getList()            }).finally(() => {              this.buttonLoading = false            })          }        }      })    },    submitRuleForm() {      if(this.drawFlag){        alert("请先完成绘制");        return;      }      this.$refs['ruleForm'].validate(valid => {        if (valid) {          this.buttonLoading = true            if (!this.humanCheck&&!this.vehicleCheck){              this.ruleForm.detectionTarget='all'            } else if(this.humanCheck&&!this.vehicleCheck){              this.ruleForm.detectionTarget='human'            }else if(!this.humanCheck&&this.vehicleCheck){              this.ruleForm.detectionTarget='vehicle'            }else {              this.ruleForm.detectionTarget='human,vehicle'            }            if (this.actionArr.length!==0){              this.ruleForm.coordinates= this.actionArr.map(function(value) {                return {x:4*value.x,y:4*value.y}              })            }            setRule(this.ruleForm).then(response => {              this.$modal.msgSuccess('新增成功')              this.openRule = false              this.getList()            }).finally(() => {              this.buttonLoading = false            })        }      })    },    /** 导出按钮操作 */    handleExport() {        this.$download.excel('/alg/algorithmServer/export', this.queryParams)    }  }}</script><style scoped>.hide {  display: none;}.item {  height: 30px;  line-height: 30px;  margin: 0 15px;}.plugin {  width: 250px;  height: 250px;}.channel-list {  max-height: 660px;  overflow: scroll;}::-webkit-scrollbar {  width: 5px;  height: 5px;}::-webkit-scrollbar-track {  width: 6px;  background: none;  -webkit-border-radius: 2em;  -moz-border-radius: 2em;  border-radius: 2em;}::-webkit-scrollbar-thumb {  background-color: rgba(144, 147, 153, .5);  background-clip: padding-box;  min-height: 28px;  -webkit-border-radius: 2em;  -moz-border-radius: 2em;  border-radius: 2em;  transition: background-color .3s;  cursor: pointer;}::-webkit-scrollbar-thumb:hover {  background-color: rgba(144, 147, 153, .3);}.view {  min-width: 1120px;  padding: 10px 15px;}</style>

webVideoCtrl.js主要修改初始化插件的代码,原先有个获取dirName方法就是获取webVideoCtrl.js自己的文件路径前缀,通过这个路径拼接再去找到jsVideoPlugin.js,但是vue结构下打包后这个文件路径获取肯定不对,所有我把webVideoCtrl.js和jsVideoPlugin.js放到utils里,然后通过require([./xxx.js])的方法在webVideoCtrl.js中引入jsVideoPlugin.js,注意它是把整个jsVideoPlugin.js存到了自身的window.JSvideoPlugin变量中,方便之后调用,然后它这边还有个值得注意的是窗口号,因为我只需要单窗口,所有我的窗口号传的都0;

this.I_InitPlugin = function(options) {      m_utilsInc.extend(m_options, options)                  if ('object' === typeof exports && typeof module !== 'undefined') {          require([ './jsVideoPlugin-1.0.0.min.js'], function(o) {            window.JSVideoPlugin = o.JSVideoPlugin            if (options.cbInitPluginComplete) {              options.cbInitPluginComplete()            }          })        } else if ('function' === typeof define && define.amd) {          require([ './jsVideoPlugin-1.0.0.min.js'], function(o) {            window.JSVideoPlugin = o.JSVideoPlugin            if (options.cbInitPluginComplete) {              options.cbInitPluginComplete()            }          })        } else {          m_utilsInc.loadScript( './jsVideoPlugin-1.0.0.min.js', function() {            if (options.cbInitPluginComplete) {              options.cbInitPluginComplete()            }          })        }          window.addEventListener('resize', function() {        if (m_pluginOBJECT !== null) {          var oElem = $('#' + m_options.szContainerID)          m_pluginOBJECT.JS_Resize(oElem.width(), oElem.height())        }      })      window.addEventListener('unload', function() {      })      window.addEventListener('scroll', function() {      })    }


点击全文阅读


本文链接:http://zhangshiyu.com/post/98810.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1