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

目录

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_NOERROR0没有错误。NET_DVR_PASSWORD_ERROR1用户名密码错误。注册时输入的用户名或者密码错误。NET_DVR_NOINIT3SDK未初始化。NET_DVR_OVER_MAXLINK5连接到设备的用户个数超过最大。NET_DVR_NETWORK_FAIL_CONNECT7连接设备失败。设备不在线或网络原因引起的连接超时等。NET_DVR_NETWORK_SEND_ERROR8向设备发送失败。NET_DVR_NETWORK_RECV_ERROR9从设备接收数据失败。NET_DVR_NETWORK_RECV_TIMEOUT10从设备接收数据超时。NET_DVR_COMMANDTIMEOUT14设备命令执行超时。NET_DVR_PARAMETER_ERROR17参数错误。SDK接口中给入的输入或输出参数为空。NET_DVR_CREATEFILE_ERROR34创建文件出错。本地录像、保存图片、获取配置文件和远程下载录像时创建文件失败。NET_DVR_ALLOC_RESOURCE_ERROR41SDK资源分配错误。NET_DVR_NOENOUGH_BUF43缓冲区太小。接收设备数据的缓冲区或存放图片缓冲区不足。NET_DVR_CREATESOCKET_ERROR44创建SOCKET出错。NET_DVR_USERNOTEXIST47用户不存在。注册的用户ID已注销或不可用。NET_DVR_BINDSOCKET_ERROR72绑定套接字失败。NET_DVR_SOCKETCLOSE_ERROR73socket连接中断,此错误通常是由于连接中断或目的地不可达。