Hikvison se acopla con NVR para implementar un kit de desarrollo WEB sin complementos para implementar la vista previa de video frontal (html, vue, proxy nginx)

Escenas

Obtenga una vista previa del video de múltiples canales (cámara) en el NVR (grabador de disco duro de red) de HIKVSION Hikvision en Vue:

Obtenga una vista previa del video de múltiples canales (cámara) en HIKVSION NVR (grabadora de video de disco duro de red) de Hikvision en el blog Vue_A con temperamento de gángster dominante-CSDN blog_Vista previa de la página web de Hikvision nvr

Al obtener una vista previa del video NVR anterior, se utiliza el paquete de desarrollo de control WEB, que requiere que la computadora instale el complemento y el navegador.

Vista previa en modo de compatibilidad.

Además, existe otra forma de desarrollar un paquete sin complementos.

 

A partir de ahora, es el kit de desarrollo WEB sin complementos V3.2.

El kit de desarrollo de versión sin complemento WEB3.2 admite versiones superiores de los navegadores Google y Firefox, y el dispositivo debe admitir la transmisión Websocket. La versión sin complemento requiere el uso de un servidor proxy nginx.

Según las instrucciones, el NVR debe admitir la transmisión websocket.

Verifique si el NVR admite la transmisión por websocket

El modelo de NVR aquí es: DS-8664n-k16

 

Inicie sesión en la página web del NVR-Configuración-Ajustes del sistema-Red-Configuración avanzada-Habilitar websocket

 

Si hay una opción para habilitar WebSokcet, significa que está bien. Para una verificación adicional, descargue la demostración oficial arriba.

 

Siga las instrucciones oficiales para ejecutar el agente nginx.

 

Modifique el archivo de configuración en el directorio nginx

 

Aquí simplemente cambiamos el número de puerto a 8000

Luego haga clic en start.bat para iniciar nginx y visitar

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

Ingrese la dirección, nombre de usuario, contraseña y otra información correspondiente al NVR, luego haga clic en Iniciar sesión e iniciar vista previa

 

Si se puede obtener una vista previa de la demostración oficial con éxito, entonces puede utilizar el paquete de desarrollo sin complementos.

Nota:

Blog:
un blog con temperamento pícaro dominante_CSDN Blog-C #, Architecture Road, blogger SpringBoot.
Siga la cuenta pública
Domineering Programmer
para obtener libros electrónicos relacionados con la programación, tutoriales y descargas gratuitas.

lograr

1. Dado que la vista previa se puede realizar en demo.html, solo necesita modificarla según sus propias necesidades.

Los documentos de interfaz y demostración correspondientes son muy claros.

Entonces, ¿cómo combinar los ejemplos de demostración con proyectos existentes, como el proyecto SpringBoot+Vue que separa el front-end y el back-end?

Tutorial sobre cómo configurar un entorno de desarrollo y ejecutar el proyecto basado en versiones separadas del front-end y back-end:

La versión separada de front-end y back-end de Ruoyi le enseña paso a paso cómo construir el entorno y ejecutar el proyecto localmente_Un blog con temperamento dominante y pícaro-blog CSDN_Ejecución local de proyectos separados de front-end y back-end

Transformación de código en proyectos basados ​​en Vue

 

La información relacionada con la cámara se almacena en segundo plano, lo más necesario es el número de canal, que se puede utilizar como referencia al realizar una vista previa.

 

Cuando la cámara esté seleccionada, haga clic en el botón de vista previa y pase el parámetro del número de canal a la página de vista previa.

Consulte el proceso anterior.

SpringBoot+Vue+HIKVSION implementa selección múltiple de cámara y vista previa de ventanas múltiples (versión complementaria):

SpringBoot + Vue + HIKVSION implementa selección múltiple de cámara y vista previa de ventanas múltiples (versión complementaria)_Un blog con temperamento pícaro dominante-CSDN blog_websocket streaming

Luego introduzca los js requeridos y otros archivos según la demostración oficial.

 

El siguiente es principalmente el código de la página de vista previa.

<template>
  <el-dialog
    title="视频监控"
    :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:MP4
        iWndowType: 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 = true
          this.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. Acerca del proxy nginx

Ver el archivo de configuración oficial de nginx de ejemplo

 

Se requieren dos partes de la agencia. El frente

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

Es el proxy de la página estática de su demostración de ejemplo, correspondiente al proxy de su propio paquete Vue dist.

La línea correspondiente debe cambiarse a

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

Uno de los dos servidores proxy restantes es un proxy de interfaz, como un proxy inverso al llamar a la interfaz de inicio de sesión.

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

​

Esto probablemente significa que si la solicitud comienza con ISAPI o SDK, la línea ondulada significa que ese caso no se ignora y se enviará a la siguiente dirección.

Pero aquí me pregunto por qué no hay ninguna configuración sobre la dirección IP de nvr en el archivo de configuración del proxy, entonces, ¿cómo solicito la interfaz cuando soy un proxy?

Aquí, se agrega un nginx en el medio para el reenvío. nginx encuentra la dirección IP del NVR a través de la cookie en la solicitud y la reenvía, incluida la obtención de la transmisión de video durante la vista previa.

Así es también cómo realizar el proxy websocket y obtener transmisión de video.

Similar al diagrama de flujo a continuación.

 

Así que simplemente modifique el archivo de configuración nginx de su proyecto de acuerdo con el archivo de configuración oficial de nginx.

A continuación se proporciona un ejemplo del archivo de configuración nginx del proyecto después de la transformación.

​
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 socket
     proxy_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;
    }
  }
}

​

Para proyectos de front-end y back-end que utilizan el proxy Nginx, consulte

Si las versiones de front-end y back-end están separadas, implemente usando el proxy Nginx en Windows (proceso completo, tutorial gráfico):

Si confía en las versiones separadas de front-end y back-end, utilice el método de proxy Nginx para implementar en Windows (proceso completo, tutorial gráfico)_The Blog of Overbearing Rogue Temperament-CSDN Blog

Efecto de vista previa

 

Supongo que te gusta

Origin blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/127717532
Recomendado
Clasificación