web端对接海康视频3.2开发包以及遇到的坑
Posted meetAlice
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web端对接海康视频3.2开发包以及遇到的坑相关的知识,希望对你有一定的参考价值。
须知:
- 3.0开发包功能比较全,但是只支持ie浏览器,所以使用的功能相对来说较少的3.2开发包,开发包官网上可以下载,可自行下载,并按照要求引入文件。
- 我的项目需求是左侧显示摄像头树状列表,中间部分显示摄像头信息,摄像头要支持预览、截图、录像、回放、云台的功能。
- 本示例演示的是对接nvr预览通道视频,和直接对接摄像头也差不太多,可以参考。
引入3.2必要js文件
<!--web3.2控件包必要的js文件引入-->
<script src="./js/codebase/encryption/AES.js"></script>
<script src="./js/codebase/encryption/cryptico.min.js"></script>
<script src="./js/codebase/encryption/crypto-3.1.2.min.js"></script>
<script src="./js/codebase/webVideoCtrl.js"></script>
全局的config配置文件
var CONFIG_OBJ =
Video_Total:null, //web3.2插件的所有方法
NVR_Data:
ip:"192.168.12.68",
port:80,
userName:"admin",
passWord:"ht123456",
szDeviceIdentify:null, //格式:iP_port
streamType:2, //码流类型 1主码流 2子码流 3第三码流 4转码码流
rtspPort:null, //RTSP端口
currentChannel:, //当前选择的通道
allChannel:[], //已登录的全部通道
;
海康视频用到的相关方法,包括登录、预览、抓图、回放、录像、云台等功能
function showOPInfo(data,data1,data2)
console.log(data,data1,data2)
function videoFunc()
var that = this;
this.clickLogin = function clickLogin(paramObj)
var szIP = paramObj.szIP,
szPort = paramObj.szPort,
szUsername = paramObj.szUsername,
szPassword = paramObj.szPassword;
if ("" == szIP || "" == szPort)
return;
CONFIG_OBJ.NVR_Data.szDeviceIdentify = szIP + "_" + szPort;
var iRet = WebVideoCtrl.I_Login(szIP, 1, szPort, szUsername, szPassword,
success: function ()
console.log(CONFIG_OBJ.NVR_Data.szDeviceIdentify + " 登录成功!");
that.getChannelInfo();
that.getDevicePort(paramObj.iWndIndex);
,
error: function (status, xmlDoc)
console.log(CONFIG_OBJ.NVR_Data.szDeviceIdentify + " 登录失败!", status, xmlDoc);
);
if (-1 == iRet)
showOPInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify + " 已登录过!");
that.getDevicePort(paramObj.iWndIndex);
;
// 窗口分割数
this.changeWndNum = function changeWndNum(iType)
iType = parseInt(iType, 10);
WebVideoCtrl.I_ChangeWndNum(iType);
;
// 退出登录
this.clickLogout = function clickLogout()
if (null == CONFIG_OBJ.NVR_Data.szDeviceIdentify)
return;
var iRet = WebVideoCtrl.I_Logout(CONFIG_OBJ.NVR_Data.szDeviceIdentify);
if (0 == iRet)
console.log("退出成功!");
CONFIG_OBJ.NVR_Data.szDeviceIdentify = null;
CONFIG_OBJ.NVR_Data.allChannel = [];
CONFIG_OBJ.NVR_Data.currentChannel = ;
CONFIG_OBJ.NVR_Data.rtspPort = null;
else
console.log("退出失败!");
;
//销毁
this.DestroyWorker = function DestroyWorker()
WebVideoCtrl.I_DestroyWorker();
;
// 获取端口
this.getDevicePort = function getDevicePort(g_iWndIndex)
showOPInfo("开始获取端口");
if (null == CONFIG_OBJ.NVR_Data.szDeviceIdentify)
return;
var oPort = WebVideoCtrl.I_GetDevicePort(CONFIG_OBJ.NVR_Data.szDeviceIdentify);
showOPInfo(oPort);
if (oPort != null)
//默认播放第一个通道的视频
// that.clickStartRealPlay(g_iWndIndex);
CONFIG_OBJ.NVR_Data.rtspPort = oPort.iRtspPort;
;
//获取通道
this.getChannelInfo = function getChannelInfo()
// oSel = $("#channels").empty();
CONFIG_OBJ.NVR_Data.allChannel = [];
CONFIG_OBJ.NVR_Data.currentChannel = ;
if (null == CONFIG_OBJ.NVR_Data.szDeviceIdentify)
return;
// 模拟通道
WebVideoCtrl.I_GetAnalogChannelInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify,
async: false,
success: function (xmlDoc)
var oChannels = $(xmlDoc).find("VideoInputChannel");
$.each(oChannels, function (i)
var id = $(this).find("id").eq(0).text(),
name = $(this).find("name").eq(0).text();
if ("" == name)
name = "Camera " + (i < 9 ? "0" + (i + 1) : (i + 1));
CONFIG_OBJ.NVR_Data.allChannel.push(
id:id,
name:name,
bZero:false
);
// oSel.append("<option value='" + id + "' bZero='false'>" + name + "</option>");
);
//默认选中第一个通道
CONFIG_OBJ.NVR_Data.currentChannel = CONFIG_OBJ.NVR_Data.allChannel[0];
showOPInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify + " 获取模拟通道成功!");
,
error: function (status, xmlDoc)
showOPInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify + " 获取模拟通道失败!", status, xmlDoc);
);
// 数字通道
WebVideoCtrl.I_GetDigitalChannelInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify,
async: false,
success: function (xmlDoc)
var oChannels = $(xmlDoc).find("InputProxyChannelStatus");
$.each(oChannels, function (i)
var id = $(this).find("id").eq(0).text(),
name = $(this).find("name").eq(0).text(),
ipAddress = $(this).find("ipAddress").eq(0).text(),
online = $(this).find("online").eq(0).text();
if ("false" == online) // 过滤禁用的数字通道
return true;
if ("" == name)
name = "IPCamera " + (i < 9 ? "0" + (i + 1) : (i + 1));
CONFIG_OBJ.NVR_Data.allChannel.push(
id:id,
name:name,
bZero:false,
ip:ipAddress
);
// oSel.append("<option value='" + id + "' bZero='false'>" + name + "</option>");
);
//默认选中第一个通道
CONFIG_OBJ.NVR_Data.currentChannel = CONFIG_OBJ.NVR_Data.allChannel[0];
showOPInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify + " 获取数字通道成功!");
,
error: function (status, xmlDoc)
showOPInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify + " 获取数字通道失败!", status, xmlDoc);
);
// 零通道
WebVideoCtrl.I_GetZeroChannelInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify,
async: false,
success: function (xmlDoc)
var oChannels = $(xmlDoc).find("ZeroVideoChannel");
$.each(oChannels, function (i)
var id = $(this).find("id").eq(0).text(),
name = $(this).find("name").eq(0).text();
if ("" == name)
name = "Zero Channel " + (i < 9 ? "0" + (i + 1) : (i + 1));
if ("true" == $(this).find("enabled").eq(0).text()) // 过滤禁用的零通道
CONFIG_OBJ.NVR_Data.allChannel.push(
id:id,
name:name,
bZero:true
);
// oSel.append("<option value='" + id + "' bZero='true'>" + name + "</option>");
);
//默认选中第一个通道
CONFIG_OBJ.NVR_Data.currentChannel = CONFIG_OBJ.NVR_Data.allChannel[0];
showOPInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify + " 获取零通道成功!");
,
error: function (status, xmlDoc)
showOPInfo(CONFIG_OBJ.NVR_Data.szDeviceIdentify + " 获取零通道失败!", status, xmlDoc);
);
;
// 开始预览
this.clickStartRealPlay = function clickStartRealPlay(g_iWndIndex)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
if (null == CONFIG_OBJ.NVR_Data.szDeviceIdentify)
return;
var startRealPlay = function ()
WebVideoCtrl.I_StartRealPlay(CONFIG_OBJ.NVR_Data.szDeviceIdentify,
iWndIndex: g_iWndIndex,
iRtspPort: CONFIG_OBJ.NVR_Data.rtspPort,
iStreamType: CONFIG_OBJ.NVR_Data.streamType,
iChannelID: CONFIG_OBJ.NVR_Data.currentChannel.id,
bZeroChannel: CONFIG_OBJ.NVR_Data.currentChannel.bZero,
success: function ()
console.log("开始预览成功!");
that.clickEnableEZoom(g_iWndIndex);
,
error: function (status, xmlDoc)
if (403 === status)
console.log("设备不支持Websocket取流!");
else
console.log("开始预览失败!");
);
;
if (oWndInfo != null) // 已经在播放了,先停止
console.log("已经在播放了,先停止");
WebVideoCtrl.I_Stop(
success: function ()
startRealPlay();
,error:function ()
console.log("shibai")
);
else
startRealPlay();
;
//停止预览(防止多窗口预览同一视频退出登录未停止播放)
this.clickStopPreview = function clickStopPreview(windowIndex)
WebVideoCtrl.I_Stop(
iWndIndex:windowIndex,
success: function ()
console.log("停止播放成功"+windowIndex)
);
;
// 抓图
this.clickCapturePic = function clickCapturePic(g_iWndIndex,fn)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
if (oWndInfo != null)
var szPicName = oWndInfo.szDeviceIdentify + "_" + new Date().getTime() + ".jpg";
WebVideoCtrl.I2_CapturePic(szPicName,
bDateDir: true //是否生成日期文件
).then(function()
console.log("抓图成功");
fn(szPicName);
,function()
console.log("抓图失败")
);
;
// 启用电子放大
this.clickEnableEZoom = function clickEnableEZoom(g_iWndIndex)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
if (oWndInfo != null)
var iRet = WebVideoCtrl.I_EnableEZoom(g_iWndIndex);
if (0 == iRet)
console.log("启用电子放大成功");
else
console.log("启用电子放大失败");
;
// 开始录像
this.clickStartRecord = function clickStartRecord(g_iWndIndex)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
if (oWndInfo != null)
var szFileName = oWndInfo.szDeviceIdentify + "_" + new Date().getTime();
WebVideoCtrl.I_StartRecord(szFileName,
bDateDir: true, //是否生成日期文件
success: function ()
console.log("开始录像成功!")
,
error: function ()
console.log("开始录像失败!")
);
;
// 停止录像
this.clickStopRecord = function clickStopRecord(g_iWndIndex)
console.log("停止录像方法");
console.log(g_iWndIndex);
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
console.log(oWndInfo);
if (oWndInfo != null)
WebVideoCtrl.I_StopRecord(
success: function ()
console.log("停止录像成功!")
,
error: function ()
console.log("停止录像失败!")
);
;
this.g_bPTZAuto = false;
// 云台控制
this.mouseDownPTZControl = function mouseDownPTZControl(iPTZIndex,g_iWndIndex)
showOPInfo("云台操作!");
console.log(iPTZIndex,g_iWndIndex);
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex),
iPTZSpeed = 4;
console.log(oWndInfo);
if (oWndInfo != null)
if (9 == iPTZIndex && this.g_bPTZAuto)
iPTZSpeed = 0;// 自动开启后,速度置为0可以关闭自动
else
this.g_bPTZAuto = false;// 点击其他方向,自动肯定会被关闭
console.log(iPTZIndex)
WebVideoCtrl.I_PTZControl(iPTZIndex, false,
iPTZSpeed: iPTZSpeed,
success: function (xmlDoc)
if (9 == iPTZIndex && this.g_bPTZAuto)
showOPInfo(oWndInfo.szDeviceIdentify + " 停止云台成功!");
else
showOPInfo(oWndInfo.szDeviceIdentify + " 开启云台成功!");
if (9 == iPTZIndex)
this.g_bPTZAuto = !this.g_bPTZAuto;
,
error: function (status, xmlDoc)
showOPInfo(oWndInfo.szDeviceIdentify + " 开启云台失败!", status, xmlDoc);
);
;
this.mouseUpPTZControl = function mouseUpPTZControl(g_iWndIndex)
console.log("鼠标抬起")
console.log(g_iWndIndex)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
console.log(oWndInfo)
if (oWndInfo != null)
WebVideoCtrl.I_PTZControl(1, true,
success: function (xmlDoc)
console.log("成功")
showOPInfo(oWndInfo.szDeviceIdentify + " 停止云台成功!");
,
error: function (status, xmlDoc)
console.log("失败")
showOPInfo(oWndInfo.szDeviceIdentify + " 停止云台失败!", status, xmlDoc);
);
;
// 开始回放
this.clickStartPlayback = function clickStartPlayback(g_iWndIndex,startTime,endTime)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex),
szDeviceIdentify = CONFIG_OBJ.NVR_Data.szDeviceIdentify,
iRtspPort = CONFIG_OBJ.NVR_Data.rtspPort,
iStreamType = CONFIG_OBJ.NVR_Data.streamType,
bZeroChannel = CONFIG_OBJ.NVR_Data.currentChannel.bZero,
iChannelID = CONFIG_OBJ.NVR_Data.currentChannel.id,
szStartTime = startTime,
szEndTime = endTime,
bChecked = false, //不启用转码码流
iRet = -1;
if (null == szDeviceIdentify)
return;
if (bZeroChannel) // 零通道不支持回放
return;
var startPlayback = function ()
WebVideoCtrl.I_StartPlayback(szDeviceIdentify,
iRtspPort: iRtspPort,
iStreamType: iStreamType,
iChannelID: iChannelID,
szStartTime: szStartTime,
szEndTime: szEndTime,
success: function ()
console.log(szDeviceIdentify +"开始回放成功");
,
error: function (status, xmlDoc)
if (403 === status)
console.log(szDeviceIdentify +"设备不支持Websocket取流!");
else
console.log(szDeviceIdentify +"开始回放失败!");
);
;
if (oWndInfo != null) // 已经在播放了,先停止
WebVideoCtrl.I_Stop(
success: function ()
startPlayback();
);
else
startPlayback();
;
// 停止回放
this.clickStopPlayback = function clickStopPlayback(g_iWndIndex)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
if (oWndInfo != null)
WebVideoCtrl.I_Stop(
success: function ()
console.log("停止回放成功!");
,
error: function ()
console.log("停止回放失败!");
);
;
// 暂停回放
this.clickPause = function clickPause(g_iWndIndex)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
if (oWndInfo != null)
WebVideoCtrl.I_Pause(
success: function ()
console.log(oWndInfo.szDeviceIdentify + "暂停成功!");
,
error: function ()
console.log(oWndInfo.szDeviceIdentify + "暂停失败!");
);
;
//恢复回放
this.clickResume = function clickResume(g_iWndIndex)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
if (oWndInfo != null)
WebVideoCtrl.I_Resume(
success: function ()
console.log(oWndInfo.szDeviceIdentify + "恢复成功!");
,
error: function ()
console.log(oWndInfo.szDeviceIdentify + "恢复失败!");
);
;
// 慢放
this.clickPlaySlow = function clickPlaySlow(g_iWndIndex)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
if (oWndInfo != null)
WebVideoCtrl.I_PlaySlow(
success: function ()
console.log(oWndInfo.szDeviceIdentify + "慢放成功!");
,
error: function ()
console.log(oWndInfo.szDeviceIdentify + "慢放失败!");
);
;
// 快放
this.clickPlayFast = function clickPlayFast(g_iWndIndex)
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(g_iWndIndex);
if (oWndInfo != null)
WebVideoCtrl.I_PlayFast(
success: function ()
showOPInfo(oWndInfo.szDeviceIdentify + "快放成功!");
,
error: function ()
showOPInfo(oWndInfo.szDeviceIdentify + "快放失败!");
);
export videoFunc
赋值全局变量
this.$url.Video_Total = new videoFunc();
将海康视频封装一个组件,方便项目中多个位置使用到视频
<template>
<div :style="styleData">
<div class="video_warp" :id="video_warp"></div>
<el-upload
style="display: none"
:action="uploadUrl"
:data="uploadData"
accept="image/*"
:onSuccess="uploadSuccess">
<el-button id="upload_btn" size="small" type="primary">点击上传</el-button>
</el-upload>
</div>
</template>
<script>
export default
name: "hik_video",
data()
return
g_iWndIndex:0,
//截图的上传地址
uploadUrl: this.$url.MANAGE_URL + '/monScreenshot/addImage',
uploadData:
token: this.$store.state.token,
// screenshotDevice:null,
screenshotUser: this.$store.state.user.id,
region: this.$store.state.regionInfo.region,
regionId: this.$store.state.regionInfo.id
,
timer0:null,
timer1:null,
timer2:null,
timer3:null,
timer4:null,
timer5:null,
timer6:null,
timer7:null,
timer8:null,
replayArr:[], //记录当前正在回放的窗口
recordArr:[], //记录当前正在录像的窗口
,
props:
video_warp:String,
styleData:Object,
iWndowType:Number
,
methods:
//初始化视频
initPlugin()
var that = this;
// 检查插件是否已经安装过
var iRet = window.WebVideoCtrl.I_CheckPluginInstall();
if (-1 == iRet)
that.$message(
type: 'error',
message: '未安装插件,双击开发包目录里的WebComponentsKit.exe安装!'
);
return;
// 初始化插件参数及插入插件
WebVideoCtrl.I_InitPlugin("100%", "100%",
//是否支持单窗口双击全屏,默认支持 true:支持 false:不支持
bWndFull: true,
iPackageType: 2,
//分屏类型:1- 1*1,2- 2*2,3- 3*3,4- 4*4,默认值为1,单画面
iWndowType: that.iWndowType,
//是否启用无插件
bNoPlugin: true,
//窗口选中事件回调函数,只包含一个字符串参数,里面的值是XML
cbSelWnd: function (xmlDoc)
that.g_iWndIndex = parseInt($(xmlDoc).find("SelectWnd").eq(0).text(), 10);
that.$emit("changeIWndIndex",that.g_iWndIndex);
,
//插件初始化完成回调,必须要定义
cbInitPluginComplete: function ()
WebVideoCtrl.I_InsertOBJECTPlugin(that.video_warp);
that.initVideoOperate();
console.log("初始化完成");
// 检查插件是否最新
if (-1 == WebVideoCtrl.I_CheckPluginVersion())
that.$message(
type: 'error',
message: '检测到新的插件版本,双击开发包目录里的WebComponentsKit.exe升级!'
);
return;
);
,
//点击的当前窗口可能正在播放回放视频 将窗口号传递过去删除回放数组里的当前窗口号
deleteReplayWindow(data)
//如果当前窗口正在回放
if(this.replayArr.length && this.replayArr.indexOf(data) != -1)
//删除正在回放的视频
this.replayArr.splice(this.replayArr.indexOf(data),1);
,
//点击的当前窗口可能正在录制视频 将窗口号传递过去删除录制数组里的当前窗口号
deleteRecordWindow(data)
//如果当前窗口正在录像
if(this.recordArr.length && this.recordArr.indexOf(data) != -1)
//删除正在录制的视频
this.recordArr.splice(this.recordArr.indexOf(data),1);
$(".parent-wnd>div").eq(this.g_iWndIndex).find(".icon_record").attr("title","录制").removeClass("icon_record_stop");
$(".parent-wnd>div").eq(this.g_iWndIndex).find(".record_time_warp").hide(); //隐藏录像的计时器
this.$url.Video_Total.clickStopRecord(this.g_iWndIndex);
this.resetVideoTime();
,
//初始化视频的操作按钮
initVideoOperate()
var that = this;
//动态拼接每个按钮
$(".parent-wnd>div").each(function (index,item)
$(this).append('<div class="record_time_warp">'+
'<span class="record_icon"></span>'+
'<span class="record_time">00:00:00</span>'+
'</div>'+
'<div class="btn_warp">'+
'<span class="icon_control fr" title="云台控制"></span>'+
'<span class="icon_replay fr" title="回放操作栏"></span>'+
'<span class="icon_record fr" title="录制"></span>'+
'<span class="icon_carmera fr" title="抓图"></span>'+
'</div>'+
'<div class="control_btn_warp">' +
'<span class="control_lt"></span>'+
'<span class="control_t"></span>'+
'<span class="control_rt"></span>'+
'<span class="control_l"></span>'+
'<span class="control_auto"></span>'+
'<span class="control_r"></span>'+
'<span class="control_lb"></span>'+
'<span class="control_b"></span>'+
'<span class="control_rb"></span>'+
'</div>'+
'<div class="replay_warp">' +
'<input class="replay_time" type="text"
id="replay_time_'+index+'"
placeholder="请选择时间">'+
'<span class="start_replay">开始回放</span>'+
'<span class="stop_replay">停止回放</span>'+
'<span class="suspended_replay">暂停</span>'+
'<span class="restore_replay">恢复</span>'+
'<span class="slow_replay">慢放</span>'+
'<span class="fast_replay">快放</span>'+
'</div>');
laydate.render(
elem: '#replay_time_'+index,
type: 'datetime',
range: "~",
done:function ()
);
);
//video悬停事件
$(".parent-wnd>div").mouseenter(function ()
$(this).addClass("active");
);
$(".parent-wnd>div").mouseleave(function ()
$(this).removeClass("active");
);
//抓图事件
$(".icon_carmera").unbind("click").click(function ()
//截图成功后出上传截图文件弹框
that.$url.Video_Total.clickCapturePic(that.g_iWndIndex,function ()
that.$confirm('您是否将截图文件上传至服务器?', '提示',
cancelButtonText: '取消',
confirmButtonText: '确定',
type: 'warning'
).then(() =>
that.$message(
type: 'warning',
// message: '请在《下载》目录中选择截图文件!',
message: '请在目录中选择截图文件!',
duration: 6000,
offset:100
);
$("#upload_btn").click();
).catch(() =>
that.$message(
type: 'warning',
message: '取消上传至服务器可能导致文件丢失,之后可在本地目录中重新上传!',
duration: 6000,
offset:100
);
);
);
);
//云台控制按钮点击事件
$(".icon_control").unbind("click").click(function ()
//当前窗口正在进行回放操作,不支持云台
if(that.replayArr.indexOf(that.g_iWndIndex) != -1)
that.$message.warning("预览回放视频暂不支持云台控制!");
return;
//如果当前的回放操作栏处于打开状态 将它关闭
if($(this).parent().find(".icon_replay").hasClass("icon_replay_check"))
$(this).parent().find(".icon_replay").removeClass("icon_replay_check");
$(this).parent().find(".icon_replay").attr("title","回放操作栏");
$(this).parent().parent().find(".replay_warp").hide();
//关闭云台控制
if($(this).hasClass("icon_control_check"))
$(this).attr("title","云台控制");
$(this).removeClass("icon_control_check");
$(this).parent().parent().find(".control_btn_warp").hide();
//开启云台控制
else
$(this).attr("title","关闭云台控制");
$(this).addClass("icon_control_check");
$(this).parent().parent().find(".control_btn_warp").show();
);
// 云台控制左上
$(".control_lt").unbind("mousedown").mousedown(function ()
that.$url.Video_Total.mouseDownPTZControl(5,that.g_iWndIndex);
);
$(".control_lt").unbind("mouseup").mouseup(function ()
that.$url.Video_Total.mouseUpPTZControl(that.g_iWndIndex);
);
// 云台控制上
$(".control_t").unbind("mousedown").mousedown(function ()
that.$url.Video_Total.mouseDownPTZControl(1,that.g_iWndIndex);
);
$(".control_t").unbind("mouseup").mouseup(function ()
that.$url.Video_Total.mouseUpPTZControl(that.g_iWndIndex);
);
// 云台控制右上
$(".control_rt").unbind("mousedown").mousedown(function ()
that.$url.Video_Total.mouseDownPTZControl(7,that.g_iWndIndex);
);
$(".control_rt").unbind("mouseup").mouseup(function ()
that.$url.Video_Total.mouseUpPTZControl(that.g_iWndIndex);
);
// 云台控制左
$(".control_l").unbind("mousedown").mousedown(function ()
that.$url.Video_Total.mouseDownPTZControl(3,that.g_iWndIndex);
);
$(".control_l").unbind("mouseup").mouseup(function ()
that.$url.Video_Total.mouseUpPTZControl(that.g_iWndIndex);
);
// 云台控制右
$(".control_r").unbind("mousedown").mousedown(function ()
that.$url.Video_Total.mouseDownPTZControl(4,that.g_iWndIndex);
);
$(".control_r").unbind("mouseup").mouseup(function ()
that.$url.Video_Total.mouseUpPTZControl(that.g_iWndIndex);
);
// 云台控制左下
$(".control_lb").unbind("mousedown").mousedown(function ()
that.$url.Video_Total.mouseDownPTZControl(6,that.g_iWndIndex);
);
$(".control_lb").unbind("mouseup").mouseup(function ()
that.$url.Video_Total.mouseUpPTZControl(that.g_iWndIndex);
);
// 云台控制下
$(".control_b").unbind("mousedown").mousedown(function ()
that.$url.Video_Total.mouseDownPTZControl(2,that.g_iWndIndex);
);
$(".control_b").unbind("mouseup").mouseup(function ()
that.$url.Video_Total.mouseUpPTZControl(that.g_iWndIndex);
);
// 云台控制右上
$(".control_rb").unbind("mousedown").mousedown(function ()
that.$url.Video_Total.mouseDownPTZControl(8,that.g_iWndIndex);
);
$(".control_rb").unbind("mouseup").mouseup(function ()
that.$url.Video_Total.mouseUpPTZControl(that.g_iWndIndex);
);
//打开回放栏的按钮
$(".icon_replay").unbind("click").click(function ()
//关闭回放操作栏
if($(this).hasClass("icon_replay_check"))
$(this).attr("title","回放操作栏");
$(this).removeClass("icon_replay_check");
$(this).parent().parent().find(".replay_warp").hide();
// that.$url.Video_Total.clickStopPlayback(that.g_iWndIndex);
//开启回放
else
//如果当前的云台操作栏处于打开状态 将它关闭
if($(this).parent().find(".icon_control").hasClass("icon_control_check"))
$(this).parent().find(".icon_control").removeClass("icon_control_check");
$(this).parent().find(".icon_control").attr("title","云台控制");
$(this).parent().parent().find(".control_btn_warp").hide();
//当前窗口正在进行录制视频操作,询问是否停止录制
if($(this).parent().find(".icon_record").hasClass("icon_record_stop"))
that.$confirm('当前正在进行录制操作,是否停止本次录制?', '提示',
cancelButtonText: '取消',
confirmButtonText: '确定',
type: 'warning'
).then(() =>
//停止录制
$(this).parent().find(".icon_record").attr("title","录制");
$(this).parent().find(".icon_record").removeClass("icon_record_stop");
$(this).parent().siblings(".record_time_warp").hide(); //隐藏录像的计时器
that.$url.Video_Total.clickStopRecord(that.g_iWndIndex);
that.resetVideoTime();
//打开回放操作栏
// $(this).parent().parent().find(".replay_warp").css("bottom",0);
//当前窗口正在进行云台控制操作,关闭云台操作面板
if($(this).parent().find(".icon_control").hasClass("icon_control_check"))
$(this).parent().find(".icon_control").removeClass("icon_control_check");
$(this).parent().find(".icon_control").attr("title","云台控制");
$(this).parent().parent().find(".control_btn_warp").hide();
//初始化日期时间
var szCurTime = that.dateFormat(new Date(), "yyyy-MM-dd");
$(this).parent().siblings(".replay_warp").find(".replay_time").val(szCurTime + " 00:00:00 ~ " + szCurTime + " 23:59:59");
$(this).attr("title","关闭回放操作栏");
$(this).addClass("icon_replay_check");
$(this).parent().parent().find(".replay_warp").show();
);
else
//打开回放操作栏
// $(this).parent().parent().find(".replay_warp").css("bottom",0);
//当前窗口正在进行云台控制操作,关闭云台操作面板
if($(this).parent().find(".icon_control").hasClass("icon_control_check"))
$(this).parent().find(".icon_control").removeClass("icon_control_check");
$(this).parent().find(".icon_control").attr("title","云台控制");
$(this).parent().parent().find(".control_btn_warp").hide();
//初始化日期时间
var szCurTime = that.dateFormat(new Date(), "yyyy-MM-dd");
$(this).parent().siblings(".replay_warp").find(".replay_time").val(szCurTime + " 00:00:00 ~ " + szCurTime + " 23:59:59");
$(this).attr("title","关闭回放操作栏");
$(this).addClass("icon_replay_check");
$(this).parent().parent().find(".replay_warp").show();
);
//开始回放
$(".start_replay").unbind("click").click(function ()
if(!$(this).parent().find(".replay_time").val())
that.$message.warning("请选择开始时间结束时间");
return;
var startTime = $(this).parent().find(".replay_time").val().split("~")[0].trim();
var endTime = $(this).parent().find(".replay_time").val().split("~")[1].trim();
that.$url.Video_Total.clickStartPlayback(that.g_iWndIndex,startTime,endTime);
that.replayArr.push(that.g_iWndIndex); //存储正在回放的视频
);
//停止回放
$(".stop_replay").unbind("click").click(function ()
that.$url.Video_Total.clickStopPlayback(that.g_iWndIndex);
//当前窗口正在进行录制回放视频的操作,结束计时器和改变按钮
if(that.recordArr.indexOf(that.g_iWndIndex) != -1)
$(this).parent().siblings(".btn_warp").find(".icon_record").attr("title","录制");
$(this).parent().siblings(".btn_warp").find(".icon_record").removeClass("icon_record_stop");
$(this).parent().siblings(".record_time_warp").hide(); //隐藏录像的计时器
that.$url.Video_Total.clickStopRecord(that.g_iWndIndex);
that.resetVideoTime();
if(this.recordArr.length && this.recordArr.indexOf(that.g_iWndIndex) != -1)
this.recordArr.splice(this.recordArr.indexOf(that.g_iWndIndex),1);//删除正在录制的视频
if(this.replayArr.length && this.replayArr.indexOf(that.g_iWndIndex) != -1)
that.replayArr.splice(this.replayArr.indexOf(that.g_iWndIndex),1); //删除正在回放的视频
);
//暂停回放
$(".suspended_replay").unbind("click").click(function ()
that.$url.Video_Total.clickPause(that.g_iWndIndex);
);
//恢复回放
$(".restore_replay").unbind("click").click(function ()
that.$url.Video_Total.clickResume(that.g_iWndIndex);
);
//慢放
$(".slow_replay").unbind("click").click(function ()
that.$url.Video_Total.clickPlaySlow(that.g_iWndIndex);
);
//快放
$(".fast_replay").unbind("click").click(function ()
that.$url.Video_Total.clickPlayFast(that.g_iWndIndex);
);
//录制视频或停止录制
$(".icon_record").unbind("click").click(function ()
//停止录制
if($(this).hasClass("icon_record_stop"))
$(this).attr("title","录制");
$(this).removeClass("icon_record_stop");
$(this).parent().siblings(".record_time_warp").hide(); //隐藏录像的计时器
that.$url.Video_Total.clickStopRecord(that.g_iWndIndex);
that.resetVideoTime();
if(this.recordArr.length && this.recordArr.indexOf(that.g_iWndIndex) != -1)
that.recordArr.splice(this.recordArr.indexOf(that.g_iWndIndex),1); //删除正在录制的视频
//开始录制
else
$(this).attr("title","结束录制");
$(this).addClass("icon_record_stop");
$(this).parent().siblings(".record_time_warp").show(); //显示录像的计时器
that.$url.Video_Total.clickStartRecord(that.g_iWndIndex);
that['startVideoTime'+that.g_iWndIndex](); //调用计时器
that.recordArr.push(that.g_iWndIndex); //存储正在录制的视频
);
,
//选择回放时间后的回调
checkDate(index)
,
/**
* @description 文件上传成功钩子函数
* @date 2021/8/30
*/
uploadSuccess(res)
if (res.code == 1)
this.$message.success("上传成功!");
else
this.$message.closeAll();
this.$message(
type: 'error',
message: '上传失败!'
);
return;
,
/**
* @description 重置录制的时间的时分秒
* @date 2021/10/19
*/
resetVideoTime()
window.clearInterval(this["timer"+this.g_iWndIndex]);
$('.record_time')[this.g_iWndIndex].innerhtml = '00:00:00';
,
/**
* @description 录制的时间的时分秒开始
* @date 2021/10/19
*/
startVideoTime0()
var hour0 = 0;
var minute0 = 0;
var second0 = 0;
this.timer0 = setInterval(function ()
second0++;
if(second0 >= 60)
second0 = 0;
minute0 = minute0+1;
if(minute0 >= 60)
minute0 = 0;
hour0 = hour0+1;
$('.record_time')[0].innerHTML = (hour0>9?hour0:'0'+hour0)+':'+
(minute0>9?minute0:'0'+minute0)+':'+ (second0>9?second0:'0'+second0);
,1000);
,
startVideoTime1()
var hour1 = 0;
var minute1 = 0;
var second1 = 0;
this.timer1 = setInterval(function ()
second1++;
if(second1 >= 60)
second1 = 0;
minute1 = minute1+1;
if(minute1 >= 60)
minute1 = 0;
hour1 = hour1+1;
$('.record_time')[1].innerHTML = (hour1>9?hour1:'0'+hour1)+':'+
(minute1>9?minute1:'0'+minute1)+':'+ (second1>9?second1:'0'+second1);
,1000);
,
startVideoTime2()
var hour2 = 0;
var minute2 = 0;
var second2 = 0;
this.timer2 = setInterval(function ()
second2++;
if(second2 >= 60)
second2 = 0;
minute2 = minute2+1;
if(minute2 >= 60)
minute2 = 0;
hour2 = hour2+1;
$('.record_time')[1].innerHTML = (hour2>9?hour2:'0'+hour2)+':'+
(minute2>9?minute2:'0'+minute2)+':'+ (second2>9?second2:'0'+second2);
,1000);
,
startVideoTime3()
var hour3 = 0;
var minute3 = 0;
var second3 = 0;
this.timer3 = setInterval(function ()
second3++;
if(second3 >= 60)
second3 = 0;
minute3 = minute3+1;
if(minute3 >= 60)
minute3 = 0;
hour3 = hour3+1;
$('.record_time')[1].innerHTML = (hour3>9?hour3:'0'+hour3)+':'+
(minute3>9?minute3:'0'+minute3)+':'+ (second3>9?second3:'0'+second3);
,1000);
,
startVideoTime4()
var hour4 = 0;
var minute4 = 0;
var second4 = 0;
this.timer4 = setInterval(function ()
second4++;
if(second4 >= 60)
second4 = 0;
minute4 = minute4+1;
if(minute4 >= 60)
minute4 = 0;
hour4 = hour4+1;
$('.record_time')[1].innerHTML = (hour4>9?hour4:'0'+hour4)+':'+
(minute4>9?minute4:'0'+minute4)+':'+ (second4>9?second4:'0'+second4);
,1000);
,
startVideoTime5()
var hour5 = 0;
var minute5 = 0;
var second5 = 0;
this.timer5 = setInterval(function ()
second5++;
if(second5 >= 60)
second5 = 0;
minute5 = minute5+1;
if(minute5 >= 60)
minute5 = 0;
hour5 = hour5+1;
$('.record_time')[1].innerHTML = (hour5>9?hour5:'0'+hour5)+':'+
(minute5>9?minute5:'0'+minute5)+':'+ (second5>9?second5:'0'+second5);
,1000);
,
startVideoTime6()
var hour6 = 0;
var minute6 = 0;
var second6 = 0;
this.timer6 = setInterval(function ()
second6++;
if(second6 >= 60)
second6 = 0;
minute6 = minute6+1;
if(minute6 >= 60)
minute6 = 0;
hour6 = hour6+1;
$('.record_time')[1].innerHTML = (hour6>9?hour6:'0'+hour6)+':'+
(minute6>9?minute6:'0'+minute6)+':'+ (second6>9?second6:'0'+second6);
,1000);
,
startVideoTime7()
var hour7 = 0;
var minute7 = 0;
var second7 = 0;
this.timer7 = setInterval(function ()
second7++;
if(second7 >= 60)
second7 = 0;
minute7 = minute7+1;
if(minute7 >= 60)
minute7 = 0;
hour7 = hour7+1;
$('.record_time')[1].innerHTML = (hour7>9?hour7:'0'+hour7)+':'+
(minute7>9?minute7:'0'+minute7)+':'+ (second7>9?second7:'0'+second7);
,1000);
,
startVideoTime8()
var hour8 = 0;
var minute8 = 0;
var second8 = 0;
this.timer8 = setInterval(function ()
second8++;
if(second8 >= 60)
second8 = 0;
minute8 = minute8+1;
if(minute8 >= 60)
minute8 = 0;
hour8 = hour8+1;
$('.record_time')[1].innerHTML = (hour8>9?hour8:'0'+hour8)+':'+
(minute8>9?minute8:'0'+minute8)+':'+ (second8>9?second8:'0'+second8);
,1000);
,
// 格式化时间
dateFormat(oDate, fmt)
var 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 (var 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;
,
</script>
<style scoped lang="scss">
.video_warp /deep/
width: 100%;
height: 100%;
/*点击录像后右上角的计时器*/
.parent-wnd>div>.record_time_warp
/*width: 1rem;*/
padding:0 0.1rem;
line-height: 0.35rem;
background: #333;
position: absolute;
top: 0.05rem;
right: 0.05rem;
border-radius: 2px;
display: none;
.record_icon
float: left;
width: 0.15rem;
height: 0.15rem;
background: url("../../assets/icon/video/recording.png") no-repeat center;
background-size: 100% 100%;
margin-top: 0.1rem;
margin-right: 0.03rem;
.record_time
float: left;
color: #fff;
/*下方操作按钮的容器*/
.parent-wnd>div>.btn_warp
width: 100%;
height: 0.50rem;
background: #333;
position: absolute;
bottom: -0.50rem;
left: 0;
border: none;
span
float: right;
width: 0.25rem;
height:0.25rem;
margin-top: 0.13rem;
margin-right: 0.08rem;
cursor: pointer;
.icon_carmera
background: url("../../assets/icon/video/camera.png") no-repeat;
background-size: 100% 100%;
.icon_replay
background: url("../../assets/icon/video/replay.png") no-repeat;
background-size: 100% 100%;
.icon_replay.icon_replay_check
background: url("../../assets/icon/video/replay_check.png") no-repeat;
background-size: 100% 100%;
.icon_position
background: url("../../assets/icon/video/dingwei.png") no-repeat;
background-size: 100% 100%;
.icon_record
background: url("../../assets/icon/video/record.png") no-repeat;
background-size: 100% 100%;
.icon_record.icon_record_stop
background: url("../../assets/icon/video/stop_record.png") no-repeat;
background-size: 100% 100%;
.icon_control
background: url("../../assets/icon/video/control.png") no-repeat;
background-size: 100% 100%;
.icon_control.icon_control_check
background: url("../../assets/icon/video/control_check.png") no-repeat;
background-size: 100% 100%;
.parent-wnd>div.active>.btn_warp
bottom: 0;
/*云台控制操作按钮的容器*/
.parent-wnd>div>.control_btn_warp
width: 1.80rem;
overflow: hidden;
position: absolute;
bottom: 0.50rem;
right: 0.10rem;
border: none;
display: none;
span
float: left;
width: 0.50rem;
height:0.50rem;
cursor: pointer;
margin-right: 0.10rem;
margin-bottom: 0.10rem;
span:first-child
background: url("../../assets/icon/video/direction_lt.png") no-repeat center;
span:nth-child(2)
background: url("../../assets/icon/video/direction_top.png") no-repeat center;
span:nth-child(3)
background: url("../../assets/icon/video/direction_rt.png") no-repeat center;
span:nth-child(4)
background: url("../../assets/icon/video/direction_left.png") no-repeat center;
span:nth-child(5)
/*background: url("../../assets/icon/video/direction_center.png") no-repeat center;*/
span:nth-child(6)
background: url("../../assets/icon/video/direction_right.png") no-repeat center;
span:nth-child(7)
background: url("../../assets/icon/video/direction_lb.png") no-repeat center;
span:nth-child(8)
background: url("../../assets/icon/video/direction_bottom.png") no-repeat center;
span:nth-child(9)
background: url("../../assets/icon/video/direction_rb.png") no-repeat center;
/*回放操作按钮的容器*/
.parent-wnd>div>.replay_warp
width: 3rem;
overflow: hidden;
position: absolute;
bottom: 0.50rem;
right: 0.10rem;
border: none;
display: none;
select
width: 3rem;
height:0.30rem;
margin-bottom: 0.04rem;
border-color: #304e66;
background: #403f3f;
color: #fff;
input
width: 3rem;
height:0.30rem;
margin-bottom: 0.04rem;
border:1px solid #304e66;
background: #403f3f;
color: #fff;
padding: 0 0.05rem;
span
float: left;
width: 0.95rem;
height:0.33rem;
line-height: 0.33rem;
cursor: pointer;
margin-right: 0.05rem;
margin-bottom: 0.04rem;
background: #403f3f;
border: 1px solid #304e66;
color: #fff;
text-align: center;
</style>
使用视频窗口的页面(引入海康组件)
<HikVideo ref="HikVideoRef"
@changeIWndIndex="changeIWndIndex"
:iWndowType="videoParam.iWndowType"
video_warp="video_warp"
:styleData="videoParam.styleData"
v-loading="loading"
element-loading-text="视频正在加载请稍候..."
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)"/>
<div class="control_btn">
<span @click="setVideoWindow(3)"></span>
<span @click="setVideoWindow(2)"></span>
<span @click="setVideoWindow(1)"></span>
</div>
import HikVideo from "@/components/common/hik_video" //引入上面的组件
//初始化视频
initVideo()
this.$refs.HikVideoRef.initPlugin(); //初始化视频插件
//登录nvr
let obj =
szIP: CONFIG_OBJ.NVR_Data.ip,
szPort: CONFIG_OBJ.NVR_Data.port,
szUsername:CONFIG_OBHikvison对接NVR实现WEB无插件开发包实现前端视频预览(htmlvuenginx代理)
场景
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-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、关于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 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;
前后端项目使用Nginx代理可以参考
若依前后端分离版本,Windows下使用Nginx代理的方式进行部署(全流程,图文教程):
若依前后端分离版本,Windows下使用Nginx代理的方式进行部署(全流程,图文教程)_霸道流氓气质的博客-CSDN博客
预览效果
以上是关于web端对接海康视频3.2开发包以及遇到的坑的主要内容,如果未能解决你的问题,请参考以下文章
JavaCV音视频开发宝典:使用javacv读取GB28181海康大华平台和网络摄像头sdk回调视频码流并转码推流rtmp流媒体服务
JavaCV音视频开发宝典:使用javacv读取GB28181海康大华平台和网络摄像头sdk回调视频码流并转码推流rtmp流媒体服务