From 9958bc1501d0daee954d9bba383475e55e24ebab Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Thu, 14 May 2026 08:18:07 +0800
Subject: [PATCH] 优化
---
ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java | 221 +++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 156 insertions(+), 65 deletions(-)
diff --git a/ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java b/ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java
index 9cca6f5..e4e7991 100644
--- a/ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java
+++ b/ard-modules/ard-modules-work/src/main/java/com/ard/work/sdk/hik/service/AbstractHikVisionSDK.java
@@ -5,6 +5,7 @@
import com.ard.common.core.exception.ServiceException;
import com.ard.common.core.exception.device.CameraSDKException;
import com.ard.common.core.utils.StringUtils;
+import com.ard.common.core.utils.file.FileMultipartFile;
import com.ard.common.core.utils.file.FileUtils;
import com.ard.common.core.utils.file.MimeTypeUtils;
import com.ard.common.redis.service.RedisService;
@@ -30,7 +31,6 @@
import com.ard.work.sdk.model.PtzScope;
import com.ard.work.sdk.service.CameraSDK;
import com.ard.work.utils.FFmpegUtils;
-import com.ard.work.utils.file.MultipartFileUtil;
import com.ard.work.utils.gis.GisUtil;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
@@ -1561,6 +1561,7 @@
String type = cmd.getType() == null ? "other" : cmd.getType();
String bucketName = cmd.getBucketName() == null ? "pic" : cmd.getBucketName();
int userId = cmd.getLoginId().intValue();
+
//图片信息
NET_DVR_JPEGPARA jpeg = new NET_DVR_JPEGPARA();
//设置图片分辨率
@@ -1570,8 +1571,9 @@
IntByReference a = new IntByReference();
//设置图片大小
ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);
- // 抓图到内存,单帧数据捕获并保存成JPEG存放在指定的内存空间中
+ // 抓图到内存
boolean bool = hCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(userId, chanNo, jpeg, jpegBuffer, 1024 * 1024, a);
+
if (!bool) {
int errorCode = hCNetSDK.NET_DVR_GetLastError();
String errorDesc = SdkErrorCodeEnum.getDescByCode(errorCode);
@@ -1579,19 +1581,46 @@
log.warn(errorMsg);
return "";
}
+
log.debug("hikSdk(抓图)-结果状态值(0表示成功):{}", hCNetSDK.NET_DVR_GetLastError());
- byte[] array = jpegBuffer.array();
- //存储到minio
- String objectName = cameraId + "_" + chanNo + ".jpeg";
- InputStream inputStream = new ByteArrayInputStream(array);
- String url = "";
- MultipartFile multipartFile = MultipartFileUtil.inputStreamToMultipartFile(inputStream, objectName,
- MimeTypeUtils.IMAGE_JPEG);
- R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
- if (sysFileR.getCode() == R.SUCCESS) {
- url = sysFileR.getData().getUrl();
- log.debug("上传文件成功:{}", url);
+
+ // 获取实际图片数据
+ int actualLength = a.getValue();
+ byte[] imageBytes;
+ if (actualLength > 0 && actualLength < 1024 * 1024) {
+ imageBytes = new byte[actualLength];
+ System.arraycopy(jpegBuffer.array(), 0, imageBytes, 0, actualLength);
+ } else {
+ imageBytes = jpegBuffer.array();
}
+
+ // 存储到minio
+ String objectName = cameraId + "_" + chanNo + ".jpeg";
+ String url = "";
+ File tempFile = null;
+
+ try {
+ // 创建临时文件
+ tempFile = File.createTempFile("snap_", ".jpeg");
+ java.nio.file.Files.write(tempFile.toPath(), imageBytes);
+
+ // 使用 FileMultipartFile 转换
+ MultipartFile multipartFile = new FileMultipartFile(tempFile, objectName, MimeTypeUtils.IMAGE_JPEG);
+
+ R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
+ if (sysFileR.getCode() == R.SUCCESS) {
+ url = sysFileR.getData().getUrl();
+ log.debug("上传文件成功:{}", url);
+ }
+ } catch (Exception e) {
+ log.error("上传失败", e);
+ } finally {
+ // 删除临时文件
+ if (tempFile != null && tempFile.exists()) {
+ tempFile.delete();
+ }
+ }
+
return url;
}
@@ -1602,6 +1631,7 @@
Integer chanNo = cmd.getChanNo();
String type = cmd.getType() == null ? "other" : cmd.getType();
Integer userId = cmd.getLoginId().intValue();
+
//图片信息
NET_DVR_JPEGPARA jpeg = new NET_DVR_JPEGPARA();
//设置图片分辨率
@@ -1613,6 +1643,7 @@
ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);
// 抓图到内存,单帧数据捕获并保存成JPEG存放在指定的内存空间中
boolean bool = hCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(userId, chanNo, jpeg, jpegBuffer, 1024 * 1024, a);
+
if (!bool) {
int errorCode = hCNetSDK.NET_DVR_GetLastError();
String errorDesc = SdkErrorCodeEnum.getDescByCode(errorCode);
@@ -1620,22 +1651,50 @@
log.warn(errorMsg);
return "";
}
- byte[] array = jpegBuffer.array();
- InputStream inputStream = new ByteArrayInputStream(array);
- String url = "";
- MultipartFile multipartFile = MultipartFileUtil.inputStreamToMultipartFile(inputStream, objectName,
- MimeTypeUtils.IMAGE_JPEG);
- R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
- if (sysFileR.getCode() == R.SUCCESS) {
- url = sysFileR.getData().getUrl();
- log.debug("上传文件成功:{}", url);
+
+ // 获取实际图片数据(只复制有效长度)
+ int actualLength = a.getValue();
+ byte[] imageBytes;
+ if (actualLength > 0 && actualLength < 1024 * 1024) {
+ imageBytes = new byte[actualLength];
+ System.arraycopy(jpegBuffer.array(), 0, imageBytes, 0, actualLength);
+ } else {
+ imageBytes = jpegBuffer.array();
}
+
+ String url = "";
+ File tempFile = null;
+
+ try {
+ // 创建临时文件
+ tempFile = File.createTempFile("snap_", ".jpeg");
+ java.nio.file.Files.write(tempFile.toPath(), imageBytes);
+
+ // 使用 FileMultipartFile 转换
+ MultipartFile multipartFile = new FileMultipartFile(tempFile, objectName, MimeTypeUtils.IMAGE_JPEG);
+
+ R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
+ if (sysFileR.getCode() == R.SUCCESS) {
+ url = sysFileR.getData().getUrl();
+ log.debug("上传文件成功:{}", url);
+ }
+ } catch (Exception e) {
+ log.error("上传失败", e);
+ } finally {
+ if (tempFile != null && tempFile.exists()) {
+ tempFile.delete();
+ }
+ }
+
return url;
}
//短时录像
@Override
public String record(CameraCmd cmd) {
+ String url = "";
+ File tempFile = null;
+
try {
String cameraId = cmd.getCameraId();
Integer chanNo = cmd.getChanNo();
@@ -1644,29 +1703,32 @@
String path = FileUtils.createFile(tempDir + "/record/" + name + ".mp4");
boolean enable = cmd.isEnable();
Integer userId = cmd.getLoginId().intValue();
+
//强制I帧结构体对象
- NET_DVR_I_FRAME netDvrIFrame = new NET_DVR_I_FRAME(); //新建结构体对象
+ NET_DVR_I_FRAME netDvrIFrame = new NET_DVR_I_FRAME();
netDvrIFrame.read();
- netDvrIFrame.dwChannel = chanNo;//因为上文代码中设置了通道号,按照上文中的设置
+ netDvrIFrame.dwChannel = chanNo;
netDvrIFrame.byStreamType = 0;
netDvrIFrame.dwSize = netDvrIFrame.size();
netDvrIFrame.write();
+
if (!hCNetSDK.NET_DVR_RemoteControl(userId, 3402, netDvrIFrame.getPointer(), netDvrIFrame.dwSize)) {
log.error("强制I帧 错误码为:{}", hCNetSDK.NET_DVR_GetLastError());
}
+
//预览参数
NET_DVR_PREVIEWINFO previewInfo = new NET_DVR_PREVIEWINFO();
previewInfo.read();
previewInfo.lChannel = chanNo;
- previewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-三码流,3-虚拟码流,以此类推
- previewInfo.dwLinkMode = 0;//连接方式:0-TCP方式,1-UDP方式,2-多播方式,3-RTP方式,4-RTP/RTSP,5-RTP/HTTP,6-HRUDP(可靠传输),7
- // -RTSP/HTTPS,8-NPQ
- previewInfo.hPlayWnd = null;//播放窗口的句柄,为NULL表示不解码显示。
- previewInfo.bBlocked = 0;//0- 非阻塞取流,1-阻塞取流
- previewInfo.byNPQMode = 0;//NPQ模式:0-直连模式,1-过流媒体模式
+ previewInfo.dwStreamType = 0;
+ previewInfo.dwLinkMode = 0;
+ previewInfo.hPlayWnd = null;
+ previewInfo.bBlocked = 0;
+ previewInfo.byNPQMode = 0;
previewInfo.write();
- String url = "";
+
if (enable) {
+ // 开始录像
if (!GlobalVariable.previewMap.containsKey(name)) {
int lRealHandle = hCNetSDK.NET_DVR_RealPlay_V40(userId, previewInfo, null, null);
if (lRealHandle == -1) {
@@ -1676,6 +1738,7 @@
log.debug("取流成功");
GlobalVariable.previewMap.put(name, lRealHandle);
}
+
if (!hCNetSDK.NET_DVR_SaveRealData_V30((int) GlobalVariable.previewMap.get(name), 2, path)) {
log.error("保存视频文件到临时文件夹失败 错误码为:{}", hCNetSDK.NET_DVR_GetLastError());
return "";
@@ -1683,24 +1746,40 @@
log.debug("录像开始");
} else {
+ // 停止录像
if (GlobalVariable.previewMap.containsKey(name)) {
Integer lRealHandle = (Integer) GlobalVariable.previewMap.get(name);
hCNetSDK.NET_DVR_StopRealPlay(lRealHandle);
GlobalVariable.previewMap.remove(name);
}
log.debug("录像停止");
- //存入minio
+
+ // 检查录像文件是否存在
+ File videoFile = new File(path);
+ if (!videoFile.exists() || videoFile.length() == 0) {
+ log.error("录像文件不存在或为空: {}", path);
+ return "";
+ }
+
+ // 存入minio - 使用 FileMultipartFile
String bucketName = "record";
- String objectName = cameraId + "_" + chanNo;
- MultipartFile multipartFile = MultipartFileUtil.filePathToMultipartFile(path, objectName,
- MimeTypeUtils.VIDEO_MP4);
+ String objectName = cameraId + "_" + chanNo + ".mp4";
+
+ // 创建临时文件对象(实际上 path 已经是文件路径)
+ tempFile = new File(path);
+
+ // 使用 FileMultipartFile 转换
+ MultipartFile multipartFile = new FileMultipartFile(tempFile, objectName, MimeTypeUtils.VIDEO_MP4);
+
R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName);
if (sysFileR.getCode() == R.SUCCESS) {
url = sysFileR.getData().getUrl();
log.debug("上传文件成功:{}", url);
}
}
+
return url;
+
} catch (Exception ex) {
log.error("录像异常:{}", ex.getMessage());
return "";
@@ -1763,69 +1842,81 @@
return false;
}
}
-
@Override
public String recordStop(CameraCmd cmd) {
String url = "";
+ File videoFile = null;
+ File transcodeFile = null;
+
try {
String cameraId = cmd.getCameraId();
Integer chanNo = cmd.getChanNo();
String name = cameraId + "_" + chanNo;
// 本地临时录像地址
String path = FileUtils.createFile(tempDir + "/record/" + name + ".mp4");
- Integer userId = cmd.getLoginId().intValue();
- //region 强制I帧
- NET_DVR_I_FRAME netDvrIFrame = new NET_DVR_I_FRAME(); //新建结构体对象
- netDvrIFrame.read();
- netDvrIFrame.dwChannel = chanNo;//因为上文代码中设置了通道号,按照上文中的设置
- netDvrIFrame.byStreamType = 0;
- netDvrIFrame.dwSize = netDvrIFrame.size();
- netDvrIFrame.write();
- if (!hCNetSDK.NET_DVR_RemoteControl(userId, 3402, netDvrIFrame.getPointer(), netDvrIFrame.dwSize)) {
- log.error("强制I帧 错误码为:{}", hCNetSDK.NET_DVR_GetLastError());
- }
- //endregion
- //region 预览参数
- NET_DVR_PREVIEWINFO previewInfo = new NET_DVR_PREVIEWINFO();
- previewInfo.read();
- previewInfo.lChannel = chanNo;
- previewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-三码流,3-虚拟码流,以此类推
- previewInfo.dwLinkMode = 0;//连接方式:0-TCP方式,1-UDP方式,2-多播方式,3-RTP方式,4-RTP/RTSP,5-RTP/HTTP,6-HRUDP(可靠传输),7
- // -RTSP/HTTPS,8-NPQ
- previewInfo.hPlayWnd = null;//播放窗口的句柄,为NULL表示不解码显示。
- previewInfo.bBlocked = 0;//0- 非阻塞取流,1-阻塞取流
- previewInfo.byNPQMode = 0;//NPQ模式:0-直连模式,1-过流媒体模式
- previewInfo.write();
- //endregion
+
+ // 停止录像
if (GlobalVariable.previewMap.containsKey(name)) {
Integer lRealHandle = (Integer) GlobalVariable.previewMap.get(name);
hCNetSDK.NET_DVR_StopRealPlay(lRealHandle);
GlobalVariable.previewMap.remove(name);
}
log.debug("录像停止");
- //ffmpeg转码
+
+ // 检查原录像文件是否存在
+ videoFile = new File(path);
+ if (!videoFile.exists() || videoFile.length() == 0) {
+ log.error("录像文件不存在或为空: {}", path);
+ return "";
+ }
+
+ // ffmpeg转码
StopWatch watchStop = new StopWatch();
watchStop.start();
String newpath = FileUtils.createFile(tempDir + "/record/" + name + "_c.mp4");
+ transcodeFile = new File(newpath);
FFmpegUtils.transcodeToMP4(path, newpath);
watchStop.stop();
log.warn("转码耗时:{}", watchStop.getTotalTimeMillis());
- //存入minio
+
+ // 检查转码后的文件是否存在
+ if (!transcodeFile.exists() || transcodeFile.length() == 0) {
+ log.error("转码文件不存在或为空: {}", newpath);
+ return "";
+ }
+
+ // 存入minio - 使用 FileMultipartFile
String bucketName = "record";
- String objectName = cameraId + "_" + chanNo;
+ String objectName = cameraId + "_" + chanNo + ".mp4";
String type = cmd.getType();
- MultipartFile multipartFile = MultipartFileUtil.filePathToMultipartFile(newpath, objectName,
- MimeTypeUtils.VIDEO_MP4);
+
+ MultipartFile multipartFile = new FileMultipartFile(transcodeFile, objectName, MimeTypeUtils.VIDEO_MP4);
R<SysFile> sysFileR = remoteFileService.upload(multipartFile, bucketName, type);
+
if (sysFileR.getCode() == R.SUCCESS) {
url = sysFileR.getData().getUrl();
log.info("上传文件成功:{}", url);
}
return url;
+
} catch (Exception ex) {
log.error("录像异常:{}", ex.getMessage());
return "";
+ } finally {
+ // 清理临时文件
+ try {
+ if (videoFile != null && videoFile.exists()) {
+ videoFile.delete();
+ log.debug("删除原录像文件: {}", videoFile.getPath());
+ }
+ if (transcodeFile != null && transcodeFile.exists()) {
+ transcodeFile.delete();
+ log.debug("删除转码文件: {}", transcodeFile.getPath());
+ }
+ } catch (Exception e) {
+ log.warn("删除临时文件失败", e);
+ }
}
}
--
Gitblit v1.9.3