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:
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:
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):
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):
Efecto de vista previa