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_OB

Hikvison对接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流媒体服务

海康大华视频监控在浏览器端无插件低延时播放解决方案

移动端安卓IOS对接H5项目遇到的坑

移动端WEBAPP开发遇到的坑,以及填坑方案!持续更新~~~~

EasyNVR无法对接新版海康平台RTSP取流机制怎么解决?