尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

基于JNA的海康威视SDK二次开发:摄像头与门禁联动实战

发布时间:2026/9/23 20:16:04

资讯中心
01
ARTICLE

基于JNA的海康威视SDK二次开发:摄像头与门禁联动实战

基于JNA的海康威视SDK二次开发:摄像头与门禁联动实战
简介面向毕业设计、课程设计及实际项目开发基于Java与海康威视SDK二次开发实现网络摄像头与门禁系统整合方案覆盖设备注册登录、局域网发现扫描、门禁人员列表与存储人脸获取、下发门禁卡与门禁人脸、门禁事件布防及上传含照片、设备当前帧抓取、摄像机RTSP推流与SDK推流等完整流程帮助开发者快速搭建可演示、可扩展的安防应用。压缩包共186个文件主体为174个Java源码包含HCNetSDK底层封装以及门禁、报警、设备、卡片、用户等服务实现类辅以xml/yml配置、jar依赖、Dockerfile、md说明文档、license等文件整体仅1.5MB目录结构紧凑便于导入工程参考和二次改造。已有554人学习浏览代码经严格测试文档对接口调用与二次开发要点说明清晰适合需对接海康设备协议并希望在此基础上延展功能的Java工程师。1. 为什么毕设选海康威视SDK做摄像头与门禁联合管理很多课程设计和毕业设计一提到“网络摄像头”第一反应是调个网页播放插件或者用OpenCV读个RTSP流就交差。但真正拿到答辩现场老师一句“你的门禁和摄像头是怎么联动的”就能问住。摄像头和门禁在安防项目里从来不是两个独立产品而是同一套设备SDK下的两个业务面预览、抓图、云台控制是一类接口人员授权、刷卡回调、远程开门是另一类接口。如果项目选Java作为开发语言海康威视SDK是绕不开的选择。校园机房、宿舍楼、实验室里大量部署的是海康设备SDK覆盖网络摄像机、球机、门禁一体机、报警主机而且官方提供的Demo直接给了C版本Java工程师要做的是用JNA把这套C接口桥接过来。这篇博文按“摄像头取流 门禁联动 Web管理端”的完整链路拆解代码可以直接抄进你的毕设或课程设计里。适合正在找Java课程设计案例源码、想快速上手设备SDK二次开发以及准备在面试里把项目讲出技术深度的读者。2. 搭建Java工程与海康SDK的JNA桥接层2.1 SDK目录结构与Java依赖清单海康威视的设备网络SDK压缩包解开之后核心文件是HCNetSDK.dllWindows或libhcnetsdk.soLinux另外还有一堆头文件、Demo和配套的动态库如HCCore.dll、HCPreview.dll等。Java项目里不直接写JNI而是用JNA在运行时把动态库里的导出函数映射成Java接口省去生成C头文件对应Java类的繁琐步骤。需要在pom.xml里引入两个基础依赖其他像Spring Boot、MyBatis-Plus、JavaCV按后续模块再加。dependency groupIdnet.java.dev.jna/groupId artifactIdjna/artifactId version5.13.0/version /dependency dependency groupIdnet.java.dev.jna/groupId artifactIdjna-platform/artifactId version5.13.0/version /dependencyJNA依赖本身很小jna-platform里封装了Win32 API和部分系统接口海康SDK登录时会用到系统级调用直接一起引入省心。版本号选择5.13.0是因为它对Windows和Linux的Structure对齐处理都比较稳定如果你已经在用Spring Boot 2.7及以上版本没有任何冲突。2.2 用JNA定义HCNetSDK核心接口新建一个HCNetSDK接口继承Library用Native.load加载动态库然后把要用的C函数声明成Java方法。import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.ptr.IntByReference; public interface HCNetSDK extends Library { HCNetSDK INSTANCE Native.load(HCNetSDK, HCNetSDK.class); boolean NET_DVR_Init(); boolean NET_DVR_Cleanup(); int NET_DVR_Login_V40(NET_DVR_USER_LOGIN_INFO loginInfo, NET_DVR_DEVICEINFO_V40 deviceInfo); boolean NET_DVR_Logout(int userId); int NET_DVR_GetLastError(); boolean NET_DVR_SetDVRMessageCallBack_V31( fMessCallBack cb, Object userData); }Native.load(HCNetSDK, ...)在Windows下会自动去找HCNetSDK.dllLinux下找libhcnetsdk.so。NET_DVR_Init对应SDK初始化进程里只能调用一次NET_DVR_Login_V40是现在海康推荐的登录接口返回的userId是后续所有操作的句柄NET_DVR_GetLastError在任何接口返回false或负数时都能拿到错误码这是排查问题最重要的入口。2.3 登录信息结构体的JNA映射C结构体在Java里要继承Structure类字段顺序必须和头文件完全一致这是JNA最容易踩的坑之一。public static class NET_DVR_USER_LOGIN_INFO extends Structure { public byte[] sDeviceAddress new byte[129]; public byte[] sUserName new byte[64]; public byte[] sPassword new byte[64]; public short wPort 8000; public int bUseAsynLogin 0; public Pointer pUser null; Override protected ListString getFieldOrder() { return Arrays.asList(sDeviceAddress, sUserName, sPassword, wPort, bUseAsynLogin, pUser); } } public static class NET_DVR_DEVICEINFO_V40 extends Structure { public byte[] sSerialNumber new byte[48]; // 其他字段按头文件补全 }sDeviceAddress是设备IPsUserName和sPassword对应设备web登录的账号密码wPort默认8000。getFieldOrder决定了JNA把Java字节数组映射到C内存块的顺序字段顺序、数组长度哪怕差一个字节登录就会报错或者返回乱码。2.4 设备登录与注销封装类把这些接口封装成一个DeviceService后面摄像头和门禁模块共用同一个登录句柄。public class DeviceService { private HCNetSDK sdk HCNetSDK.INSTANCE; private int userId -1; public boolean init() { return sdk.NET_DVR_Init(); } public int login(String ip, short port, String username, String password) { HCNetSDK.NET_DVR_USER_LOGIN_INFO loginInfo new HCNetSDK.NET_DVR_USER_LOGIN_INFO(); loginInfo.sDeviceAddress ip.getBytes(); loginInfo.sUserName username.getBytes(); loginInfo.sPassword password.getBytes(); loginInfo.wPort port; HCNetSDK.NET_DVR_DEVICEINFO_V40 deviceInfo new HCNetSDK.NET_DVR_DEVICEINFO_V40(); userId sdk.NET_DVR_Login_V40(loginInfo, deviceInfo); if (userId -1) { throw new RuntimeException(登录失败错误码 sdk.NET_DVR_GetLastError()); } return userId; } public void logout() { if (userId ! -1) { sdk.NET_DVR_Logout(userId); userId -1; } } }login方法里把Java字符串直接转成byte数组写入结构体注意海康C接口里char数组默认不带结尾符但如果数组长度足够JNA会自动处理。登录失败时NET_DVR_GetLastError返回的错误码值得背几个常用的26是用户名或密码错误17是内存不足29是未登录就调用其他接口23是设备不支持该功能。项目调试阶段看到错误码先查SDK手册不要盲目重启设备。3. 网络摄像头实战RTSP取流、实时预览与抓图录像3.1 取流方案对比私有预览通道还是RTSPJavaCV摄像头接入Java后端有两条路线。第一条是用SDK的NET_DVR_RealPlay_V40在Windows上能直接弹出预览窗口但换到Linux服务器就没界面可用第二条是用RTSP协议拉流再交给JavaCV的FFmpeg解码。两条路线各有取舍下面表格列了我在实际项目里的选型依据。方案延迟表现跨平台Web集成难度是否占用SDK通道NET_DVR_RealPlay_V40低200ms左右差依赖窗口句柄需要转码再推流占用预览通道RTSP JavaCV300-500ms好纯Java直接输出帧或转HLS/WebRTC几乎不占毕设和课程设计我建议直接走RTSPJavaCV。海康设备默认开启RTSP服务不用额外配通道而且群晖Surveillance Station这类第三方平台能管理萤石摄像头靠的也是RTSP而不是私有协议。SDK真正的价值在门禁和云台控制取流这种通用能力用标准协议更省事。3.2 基于JavaCV的RTSP实时预览先确认设备RTSP地址格式海康摄像机一般是rtsp://admin:密码192.168.1.64:554/Streaming/Channels/101路径里101表示第一通道主码流102是第一通道子码流201是第二通道主码流。预览页用子码流降低带宽需要抓细节截图时再切主码流。FFmpegFrameGrabber grabber new FFmpegFrameGrabber(rtspUrl); grabber.setOption(rtsp_transport, tcp); grabber.setOption(stimeout, 5000000); grabber.start(); while (running) { Frame frame grabber.grabImage(); if (frame ! null) { Java2DFrameConverter converter new Java2DFrameConverter(); BufferedImage image converter.convert(frame); // 在这里把BufferedImage推给WebSocket或者写入视频流 } } grabber.stop();rtsp_transport设为tcp是因为默认的UDP模式在跨网段预览时掉流严重stimeout是5秒拉流超时设备不在线时快速报错而不是卡死线程。grabImage()拿到的Frame转成BufferedImage后配合WebSocket每200ms推一帧浏览器端用Canvas渲染就能做到接近实时预览。3.3 通过SDK抓图与录像抓图直接走SDK比截取视频帧清晰因为抓图是设备端编码输出JPEG。HCNetSDK.NET_DVR_JPEGPARA jpegPara new HCNetSDK.NET_DVR_JPEGPARA(); jpegPara.wPicSize 2; // 图片尺寸2表示高清 jpegPara.wPicQuality 0; // 画质等级0最高 boolean result sdk.NET_DVR_CaptureJPEGPicture( userId, 1, // 通道号从1开始 jpegPara, D:/snapshot/20240801_103000.jpg);wPicSize和wPicQuality会在门禁刷卡瞬间抓拍时用到配合人员照片对比就是一套实打实的考勤记录。录像的话用JavaCV更灵活FFmpegFrameRecorder可以直接复用Grabber的帧。FFmpegFrameRecorder recorder new FFmpegFrameRecorder(D:/record/1.mp4, 1280, 720); recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); recorder.setFormat(mp4); recorder.setFrameRate(25); recorder.setVideoBitrate(2000000); recorder.start(); Frame frame; while ((frame grabber.grab()) ! null) { recorder.record(frame); } recorder.stop();录像的码率至少给到2Mbps码率太低会导致运动物体画面出现马赛克。这几个参数在答辩演示录像证据时一定要提前调好。3.4 球机云台控制与预置点联动海康球机摄像头在课堂上很少演示但门禁报警后球机自动转到对应预置点是全场最能体现工程能力的点。// 0-上 1-下 2-左 3-右speed范围1-7 boolean up sdk.NET_DVR_PTZControlWithSpeed(userId, 1, 0, 0, 5); Thread.sleep(2000); boolean stopUp sdk.NET_DVR_PTZControlWithSpeed(userId, 1, 0, 1, 5);控制动作和停止动作必须成对调用NET_DVR_PTZControlWithSpeed最后一个参数是停止标记0表示开始转动1表示停止。做联动时序时先让球机转会再触发抓图否则照片里是空的。预置点用NET_DVR_PTZPreset设置比如1号预置点对准门禁读卡器2号预置点对准大厅这样门禁报警时根据事件源切预置点。4. 门禁系统业务落地人员授权、刷卡事件与远程开关门4.1 门禁设备选型与网络拓扑门禁部分先明确设备类型。海康门禁产品线里常见两类一类是独立门禁控制器接读卡器和电锁适合大项目另一类是门禁一体机刷卡面板、读卡器、控制模块集成在一起适合实验室和办公区。毕设场景绝大多数选一体机。校园里另一种常见方案是Arduino加RDM6300射频模块自己搭门禁能读出卡号但做不了人员权限管理和远程下发更别说和摄像头联动。海康设备SDK的优势在于门禁事件通过HTTP或SDK回调主动上报项目里只要监听事件、写数据库、触发抓图就完成了一个完整门禁系统。网络拓扑很简单门禁一体机通过网线接入实验室交换机IP设为192.168.1.80电脑端TCP访问设备的8000端口。如果设备出厂默认的SDK端口不是8000用SADP工具改一下再登录。4.2 人员档案与卡片号下发人员信息下发是门禁管理的第一步。海康SDK里这类操作通常走远程配置通道先打开配置会话再写入人员信息最后把卡号绑定到人员。// 伪码风格具体结构体以SDK头文件为准 NET_DVR_START_REMOTECONFIG start new NET_DVR_START_REMOTECONFIG(); start.lCommand NET_DVR_CMD_ACS_USER_INFO_ADD; start.lUserID userId; start.dwSize 0; start.pInBuffer Pointer.NULL; int configHandle sdk.NET_DVR_StartRemoteConfig(start, null, null);NET_DVR_StartRemoteConfig返回的handle是远程配置句柄后面下发、修改、删除人员都靠它。写人员信息时注意卡号是指定还是自动生成门禁卡通常是Mifare卡的扇区内容在PC端读卡器上读出10位卡号后再通过这套接口写入。统一卡号格式很重要否则后续查通行记录做Excel导出时会对不上。4.3 门禁事件实时监听与回调门禁最重要的事件是刷卡记录。海康SDK注册报警回调后设备端的合法卡、非法卡、门磁异常、按钮开门都会异步上报到Java层。public interface fMessCallBack extends StdCallCallback { boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser); }监听线程的注册代码要单独写HCNetSDK.fMessCallBack callback (command, alarmer, info, len, user) - { // 用线程池处理不要阻塞回调线程 executor.submit(() - handleAccessEvent(command, info)); return true; }; sdk.NET_DVR_SetDVRMessageCallBack_V31(callback, null); // 布置报警通道才能收到门禁事件 int alarmHandle sdk.NET_DVR_SetupAlarmChan_V41(userId);回调接口lCommand为COMM_ALARM_ACS门禁主机报警时pAlarmInfo指向门禁报警信息结构体里面能解析出读卡器号、卡号、事件类型和事件时间。NET_DVR_SetDVRMessageCallBack_V31注册的回调对象必须存在强引用否则JVM垃圾回收会把回调回收掉表现为项目跑几分钟后突然收不到事件。常见门禁事件类型如下表不同系列的设备返回值可能有差异以头文件注释为准。事件类型含义业务动作2001合法卡通行记录通行时间正常放行2002非法卡刷卡告警联动抓拍2003门磁异常记录并通知管理员2004按钮开门记录为手动开门2005胁迫报警输出告警并隐藏提示事件回调里不能直接执行数据库写入或者调用其他SDK接口因为回调线程被阻塞会把设备端的事件队列堵死。我一般是在回调里把原始数据丢进线程池再用Spring的Async去落库保证回调返回速度在几十毫秒内。4.4 远程开关门与异常联动远程开门是门禁系统的管理功能管理员在网页端点击“开门”请求通过后端发到门禁设备。海康门禁除SDK外还开放ISAPI接口调试时用HTTP请求最直观。curl -X PUT http://192.168.1.80/ISAPI/AccessControl/RemoteControl/door/1 \ -H Content-Type: application/xml \ -u admin:password \ -d RemoteControlDoorcmd1/cmd/RemoteControlDoorbody里cmd为1表示开门0表示关门。后端用Java的HttpClient封装这个方法后门禁联动逻辑就清晰了收到门磁异常事件时先调球机转到对应预置点抓拍再通过ISAPI接口把门磁对应门关闭最后把事件写入记录表并推送告警到前端。5. 数据库与Web管理端把摄像头和门禁串成一个管理系统5.1 核心表结构与权限模型设备层跑通后需要一套表把人员和设备关联起来。毕设阶段用MySQL加MyBatis-Plus足够核心表就五张。CREATE TABLE person ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(64) NOT NULL, id_card_no VARCHAR(32) UNIQUE, department VARCHAR(128), photo_url VARCHAR(255), created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE card ( id BIGINT PRIMARY KEY AUTO_INCREMENT, card_no VARCHAR(32) NOT NULL UNIQUE, person_id BIGINT NOT NULL, status TINYINT DEFAULT 1, FOREIGN KEY (person_id) REFERENCES person(id) ); CREATE TABLE door ( id BIGINT PRIMARY KEY AUTO_INCREMENT, door_name VARCHAR(64) NOT NULL, device_ip VARCHAR(32), device_port INT DEFAULT 8000, channel_no INT DEFAULT 1 ); CREATE TABLE authority ( id BIGINT PRIMARY KEY AUTO_INCREMENT, person_id BIGINT NOT NULL, door_id BIGINT NOT NULL, time_start TIME, time_end TIME ); CREATE TABLE access_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, person_id BIGINT, card_no VARCHAR(32), door_id BIGINT, event_type INT, result TINYINT, snapshot_url VARCHAR(255), event_time DATETIME );access_record表是整套系统的核心event_type和result两个字段联合起来能回答“谁在什么时间刷了哪扇门”。表设计上access_record的person_id可以为空因为非法卡刷卡时查不到人员记录仍然要落库。5.2 Spring Boot接口设计与实现管理端接口按资源划分最常用的三个是设备状态查询、人员下发、通行记录分页。RestController RequestMapping(/api/access) public class AccessRecordController { Autowired private AccessRecordService recordService; GetMapping(/records) public PageResultAccessRecordVO page( RequestParam(defaultValue 1) int page, RequestParam(defaultValue 20) int size, RequestParam(required false) String cardNo, RequestParam(required false) LocalDate startDate, RequestParam(required false) LocalDate endDate) { // 按卡号、日期范围过滤通行记录 return recordService.queryPage(page, size, cardNo, startDate, endDate); } PostMapping(/door/{doorId}/open) public RString openDoor(PathVariable Long doorId) { // 调用ISAPI远程开门 return deviceClient.remoteOpenDoor(doorId); } }分页查询要连表把人员姓名、部门、门名称带出来直接用MyBatis-Plus的Page对象配合自定义SQL。remoteOpenDoor里封装4.4节的HTTP调用并在开门前记录一条操作日志这样审计时能区分“刷卡开门”和“管理员远程开门”。5.3 通行记录与异常检索SQL答辩时老师大概率会问“怎么查某个人的出入记录”和“怎么统计异常次数”这两条SQL直接背下来用。SELECT p.name, p.department, d.door_name, r.event_time, IF(r.result 1, 正常, 异常) AS status FROM access_record r LEFT JOIN person p ON r.person_id p.id LEFT JOIN door d ON r.door_id d.id WHERE r.card_no 1234567890 AND r.event_time 2025-06-01 00:00:00 ORDER BY r.event_time DESC LIMIT 50; SELECT d.door_name, COUNT(*) AS abnormal_count FROM access_record r LEFT JOIN door d ON r.door_id d.id WHERE r.event_type IN (2002, 2003, 2005) AND r.event_time DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY d.door_name;第二条SQL统计一周内异常事件数量可以做成前端大屏的告警柱状图。DATE_SUB(NOW(), INTERVAL 7 DAY)是MySQL原生函数避免了在Java代码里拼时间字符串。5.4 定时任务巡检设备在线状态摄像头和门禁设备都可能离线值得加一个定时任务每30秒检查一遍设备状态。这里在登录时记录设备句柄利用心跳机制判断设备是否在线。Scheduled(fixedDelay 30000) public void checkDeviceStatus() { devicePool.forEach(device - { if (device.isLogin()) { boolean alive sdk.NET_DVR_GetDVRWorkState(device.getUserId()) 0; if (!alive) { deviceService.reLogin(device); } } }); }NET_DVR_GetDVRWorkState返回0表示设备已经断开重连时先logout再login注意到NET_DVR_Cleanup不能随便调用否则会杀掉整个进程里所有设备连接。6. 从课程设计到面试加分常见坑位、现场演示与问答框架6.1 三个容易卡住的坑第一个坑是JNA找不到动态库。报错UnsatisfiedLinkError时检查项目启动目录下有没有HCNetSDK.dll或者启动参数里有没有加-Djna.library.pathD:/sdk/libs。第二个坑是Structure字段顺序错位登录返回错误码27多半是NET_DVR_USER_LOGIN_INFO里字段声明顺序和头文件不一致用getFieldOrder逐字段核对。第三个坑是回调收不到事件先确认NET_DVR_SetupAlarmChan_V41返回值大于0再检查回调对象是否被GC回收把回调对象声明成Spring容器的单例Bean最保险。6.2 三分钟现场演示脚本演示顺序建议做成“先看效果后看代码”。第一步打开管理界面展示设备在线列表、实时预览画面第二步掏出一张已授权卡片刷门禁浏览器页面上实时弹出人员信息、照片和通行记录第三步刷非法卡页面出现告警弹窗同时球机自动转向并抓拍最后展示数据库里access_record表新插入的记录。整个流程控制在三分钟每一步结束用一句话点出对应技术点不要主动去翻代码。6.3 面试问答框架面试官对海康SDK项目最常见的追问集中在三处为什么用JNA不用JNI回答“JNA避免手写JNI头文件转换开发效率高而且海康SDK是C接口JNA天然适配C结构体”RTSP延迟怎么优化回答“子码流预览、TCP传输、降低帧率、延迟从1秒压到400ms”并发设备接入怎么扩展回答“设备连接池加线程池每台设备独立会话调度层用一致性哈希把设备请求分发到不同节点”。和UG二次开发、Catia二次开发这类CAD领域的二次开发相比海康SDK更关注网络通信和事件回调在简历项目里要突出的是“网络编程、多线程回调、设备协议理解”这三项能力。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。