海康威视-按时间下载录像文件

目录

1、流程图

1.1、录像查找

1.2、录下下载 

2、按时间下载

2.1、开启下载 

2.2、后台下载

2.2.1、方式一

2.2.2、方式二

3、问题整理

3.1、错误码34

3.2、错误码10

3.3、下载的文件大小为0kb

4、错误码


由于没有在官方文档中找到通过ISAPI协议透传实现按时间下载文件的方式。所以采取了SDK本地调用方式。

1、流程图

按照官方文档中描述的流程,下载文件分为按文件名和时间两种方式。本文仅以按时间段下载录像文件。

1.1、录像查找

 

1.2、录下下载 

在官方的设备网络SDK使用手册_V6.1版本中,用例代码使用C++语法实现录像下载功能。实际上使用Java改写,调用时存在错误。

2、按时间下载

前期准备的初始化,登录模块请参考之前文章 的后半部分海康威视-NVR使用及ISAPI协议透传接入-CSDN博客

以下是核心代码:

public static void main(String[] args) {
        boolean flag = init();
        if(!flag){
            return ;
        }
        // 登录
        String sDeviceIP = "192.168.1.1";//登录设备IP地址
        String sUsername = "admin";//设备用户名
        String sPassword = "admin";//设备密码
        flag = loginByV40(sDeviceIP, sUsername, sPassword);
        if(!flag){
            log.info("登录nvr失败");
            return ;
        }

        // 设置查找范围
        Calendar start = Calendar.getInstance();
        start.setTime(DateUtil.parse("2024-06-15 08:00:00", DatePattern.NORM_DATETIME_PATTERN));
        Calendar end = Calendar.getInstance();
        end.setTime(DateUtil.parse("2024-06-15 08:00:10", DatePattern.NORM_DATETIME_PATTERN));
        downloadVideoByRangeTime(1, start, end , "D:\\1.mp4");
        logout();
    }

2.1、开启下载 

/**
     * 下载指定时间段内的视频
     * @param channel 通道号
     * @param startTime
     * @param endTime
     * @param savePath  保存视频的绝对路径,mp4格式
     */
    public static boolean downloadVideoByRangeTime(int channel, Calendar startTime, Calendar endTime, String savePath){
        // NET_DVR_GetFileByTime_V40
        HCNetSDK.NET_DVR_PLAYCOND playcond = new HCNetSDK.NET_DVR_PLAYCOND();
        playcond.read();
        //通道号 NVR设备路数小于32路的起始通道号从33开始,依次增加
        playcond.dwChannel = channel + 32;
        playcond.struStartTime.dwYear = startTime.get(Calendar.YEAR);
        playcond.struStartTime.dwMonth = startTime.get(Calendar.MONTH)+1;
        playcond.struStartTime.dwDay =  startTime.get(Calendar.DAY_OF_MONTH);
        playcond.struStartTime.dwHour = startTime.get(Calendar.HOUR_OF_DAY);
        playcond.struStartTime.dwMinute = startTime.get(Calendar.MINUTE);
        playcond.struStartTime.dwSecond = startTime.get(Calendar.SECOND);

        //HCNetSDK.NET_DVR_TIME ed = new HCNetSDK.NET_DVR_TIME();
        playcond.struStopTime.dwYear = endTime.get(Calendar.YEAR);
        playcond.struStopTime.dwMonth = endTime.get(Calendar.MONTH)+1;
        playcond.struStopTime.dwDay =  endTime.get(Calendar.DAY_OF_MONTH);
        playcond.struStopTime.dwHour = endTime.get(Calendar.HOUR_OF_DAY);
        playcond.struStopTime.dwMinute = endTime.get(Calendar.MINUTE);
        playcond.struStopTime.dwSecond = endTime.get(Calendar.SECOND);
        playcond.write();

        int code = hCNetSDK.NET_DVR_GetFileByTime_V40(lUserID, savePath, playcond);
        if(code < 0){
            log.info("初始化下载失败 channel={},playcond={}, code={}", channel, playcond, hCNetSDK.NET_DVR_GetLastError());
            return false;
        }
        return playBackControl(code);
    }

2.2、后台下载

2.2.1、方式一

通过循环检查Pos状态判断是否下载完成

private static boolean playBackControl(int hPlayback){
        hCNetSDK.NET_DVR_PlayBackControl(hPlayback, HCNetSDK.NET_DVR_PLAYSTART, 0, null);

        Date nowTime = new Date(System.currentTimeMillis());
        SimpleDateFormat sdFormatter = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        System.out.println("开始下载时间:"+sdFormatter.format(nowTime));
        while(true){
            IntByReference nPos = new IntByReference(0);
            hCNetSDK.NET_DVR_PlayBackControl(hPlayback, HCNetSDK.NET_DVR_PLAYGETPOS, 0, nPos);
            if (nPos.getValue() > 100)
            {
                System.out.println( "由于网络原因或DVR忙,下载异常终止!");
                break;
            }
            if (nPos.getValue() == 100)
            {
                System.out.println("结束下载时间:"+sdFormatter.format(nowTime));
                System.out.println("按时间下载结束!");
                break;
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
}

2.2.2、方式二

结合Pos状态,记录下载进度,主要针对大文件反馈结果。

/**
     * 控制后台下载过程
     */
    private static boolean playBackControl(int hPlayback){

        boolean flag = hCNetSDK.NET_DVR_PlayBackControl_V40(hPlayback, HCNetSDK.NET_DVR_PLAYSTART, null, 0, null, null);
        if(!flag) {
            log.info("Play back control failed code=" +  hCNetSDK.NET_DVR_GetLastError());
            return false;
        }

        int nPos = 0;
        for(nPos = 0; nPos < 100&&nPos>=0; nPos = hCNetSDK.NET_DVR_GetDownloadPos(hPlayback))
        {
            log.info("Be downloading... " + nPos);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if(!hCNetSDK.NET_DVR_StopGetFile(hPlayback))
        {
            log.info("failed to stop get file " + hCNetSDK.NET_DVR_GetLastError());
            return false;
        }
        if(nPos<0||nPos>100)
        {
            log.info("download err "  + hCNetSDK.NET_DVR_GetLastError());
            return false;
        }
        log.info("Be downloading..." + nPos);
        return true;
    }

3、问题整理

3.1、错误码34

描述:创建文件出错。本地录像、保存图片、获取配置文件和远程下载录像时创建文件失败。

原因:由于windows下,存储的文件路径指定到了C盘,造成无法写入。

解决:选择其他盘符即可

3.2、错误码10

描述:从设备接收数据超时。

原因:由于传入的channelID 设备通道号错误

解决:与ISAPI调用传入的channelID不同,在NVR设备路数小于32路的起始通道号从33开始,依次增加

// channel 为原始的 1、2、3...

playcond.dwChannel = channel + 32;

3.3、下载的文件大小为0kb

原因:传入的起止日期值错误,导致无法查找对应通道的回放录像

解决:由于我在代码中使用了java.util.Calendar 类,该类在查询日期字段值存在差异。

其中 Calendar.MONTH 以0为起点,需要+1

// 以下是年月日,时分秒的查询

playcond.struStartTime.dwYear = startTime.get(Calendar.YEAR);
playcond.struStartTime.dwMonth = startTime.get(Calendar.MONTH)+1;
playcond.struStartTime.dwDay =  startTime.get(Calendar.DAY_OF_MONTH);
playcond.struStartTime.dwHour = startTime.get(Calendar.HOUR_OF_DAY);
playcond.struStartTime.dwMinute = startTime.get(Calendar.MINUTE);
playcond.struStartTime.dwSecond = startTime.get(Calendar.SECOND);

4、错误码

以下错误码仅代表 NET_DVR_GetFileByTime_V40 方法

错误类型 错误值 错误信息
NET_DVR_NOERROR 0 没有错误。
NET_DVR_PASSWORD_ERROR 1 用户名密码错误。注册时输入的用户名或者密码错误。
NET_DVR_NOINIT 3 SDK未初始化。
NET_DVR_OVER_MAXLINK 5 连接到设备的用户个数超过最大。
NET_DVR_NETWORK_FAIL_CONNECT 7 连接设备失败。设备不在线或网络原因引起的连接超时等。
NET_DVR_NETWORK_SEND_ERROR 8 向设备发送失败。
NET_DVR_NETWORK_RECV_ERROR 9 从设备接收数据失败。
NET_DVR_NETWORK_RECV_TIMEOUT 10 从设备接收数据超时。
NET_DVR_COMMANDTIMEOUT 14 设备命令执行超时。
NET_DVR_PARAMETER_ERROR 17 参数错误。SDK接口中给入的输入或输出参数为空。
NET_DVR_CREATEFILE_ERROR 34 创建文件出错。本地录像、保存图片、获取配置文件和远程下载录像时创建文件失败。
NET_DVR_ALLOC_RESOURCE_ERROR 41 SDK资源分配错误。
NET_DVR_NOENOUGH_BUF 43 缓冲区太小。接收设备数据的缓冲区或存放图片缓冲区不足。
NET_DVR_CREATESOCKET_ERROR 44 创建SOCKET出错。
NET_DVR_USERNOTEXIST 47 用户不存在。注册的用户ID已注销或不可用。
NET_DVR_BINDSOCKET_ERROR 72 绑定套接字失败。
NET_DVR_SOCKETCLOSE_ERROR 73 socket连接中断,此错误通常是由于连接中断或目的地不可达。

最近更新

  1. TCP协议是安全的吗?

    2024-06-15 17:06:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-15 17:06:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-15 17:06:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-15 17:06:01       18 阅读

热门阅读

  1. 低代码开发:智能财务系统开发应用

    2024-06-15 17:06:01       10 阅读
  2. Web 品质样式表

    2024-06-15 17:06:01       6 阅读
  3. 论徐州高防IP的作用有哪些?

    2024-06-15 17:06:01       8 阅读
  4. postgresql 创建函数

    2024-06-15 17:06:01       8 阅读
  5. 观察者模式

    2024-06-15 17:06:01       8 阅读
  6. WebSocket定时前端推送:深度解析与实战挑战

    2024-06-15 17:06:01       6 阅读