视频相关代码

This commit is contained in:
liux 2025-06-27 14:55:09 +08:00
parent 896fa85865
commit e78d475cc1
45 changed files with 11863 additions and 41 deletions

View File

@ -226,49 +226,49 @@
<systemPath>${project.basedir}/lib/arcsoft-sdk-face-3.0.0.0-windows.jar</systemPath>
</dependency>
<!-- &lt;!&ndash; groovy-all &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.apache.groovy</groupId>-->
<!-- <artifactId>groovy</artifactId>-->
<!-- <version>4.0.21</version>-->
<!-- <scope>system</scope>-->
<!-- <systemPath>${project.basedir}/src/main/resources/lib/groovy-4.0.21.jar-->
<!-- </systemPath>-->
<!-- </dependency>-->
<!-- groovy-all -->
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
<version>4.0.21</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/groovy-4.0.21.jar
</systemPath>
</dependency>
<!-- &lt;!&ndash;HK SDK&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>examples-1.0</groupId>-->
<!-- <artifactId>examples</artifactId>-->
<!-- <version>1.3.0</version>-->
<!-- <scope>system</scope>-->
<!-- <systemPath>${project.basedir}/src/main/resources/lib/examples.jar-->
<!-- </systemPath>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>jna-1.3.0</groupId>-->
<!-- <artifactId>jna</artifactId>-->
<!-- <version>1.3.0</version>-->
<!-- <scope>system</scope>-->
<!-- <systemPath>${project.basedir}/src/main/resources/lib/jna.jar-->
<!-- </systemPath>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.infiniteautomation</groupId>-->
<!-- <artifactId>modbus4j</artifactId>-->
<!-- <version>3.1.0</version>-->
<!-- <scope>system</scope>-->
<!-- <systemPath>${project.basedir}/src/main/resources/lib/modbus4j-3.0.3.jar</systemPath>-->
<!-- </dependency>-->
<!--HK SDK-->
<dependency>
<groupId>examples-1.0</groupId>
<artifactId>examples</artifactId>
<version>1.3.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/examples.jar
</systemPath>
</dependency>
<dependency>
<groupId>jna-1.3.0</groupId>
<artifactId>jna</artifactId>
<version>1.3.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/jna.jar
</systemPath>
</dependency>
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
<version>3.1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/modbus4j-3.0.3.jar</systemPath>
</dependency>
<!-- <dependency>-->
<!-- <groupId>artemis-http-client</groupId>-->
<!-- <artifactId>secutil</artifactId>-->
<!-- <version>1.1.3</version>-->
<!-- <scope>system</scope>-->
<!-- <systemPath>${project.basedir}/src/main/resources/lib/artemis-http-client-1.1.3.jar-->
<!-- </systemPath>-->
<!-- </dependency>-->
<dependency>
<groupId>artemis-http-client</groupId>
<artifactId>secutil</artifactId>
<version>1.1.3</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/artemis-http-client-1.1.3.jar
</systemPath>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,61 @@
package com.bonus.canteen.core.video.controller;
import com.bonus.canteen.core.video.dto.PlaybackURLsDTO;
import com.bonus.canteen.core.video.dto.PreviewDTO;
import com.bonus.canteen.core.video.entity.VideoRequestBean;
import com.bonus.canteen.core.video.service.VideoService;
import com.bonus.common.core.web.controller.BaseController;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.log.annotation.SysLog;
import com.bonus.common.log.enums.OperaType;
import com.bonus.system.api.domain.SysAddress;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 地址信息Controller
*
* @author xsheng
* @date 2025-04-14
*/
@Api(tags = "地址信息接口")
@RestController
@RequestMapping("/video")
public class VideoController extends BaseController {
@Resource
private VideoService videoService;
@ApiOperation(value = "视频下载")
@SysLog(title = "视频下载", businessType = OperaType.DELETE, logType = 1,module = "视频管理->视频下载")
@PostMapping("/download")
public AjaxResult download(@RequestBody VideoRequestBean videoRequestBean) {
return success(videoService.download(videoRequestBean));
}
@ApiOperation(value = "实时视频流")
@SysLog(title = "实时视频流", businessType = OperaType.DELETE, logType = 1,module = "视频管理->实时视频流")
@PostMapping("/previewURLs")
public AjaxResult previewURLs(@RequestBody PreviewDTO previewDTO) {
return success(videoService.previewURLs(previewDTO));
}
@ApiOperation(value = "历史视频流")
@SysLog(title = "历史视频流", businessType = OperaType.DELETE, logType = 1,module = "视频管理->历史视频流")
@PostMapping("/playbackURLs")
public AjaxResult playbackURLs(@RequestBody PlaybackURLsDTO playbackURLsDTO) {
return success(videoService.playbackURLs(playbackURLsDTO));
}
@ApiOperation(value = "根据位置分类摄像头")
@SysLog(title = "根据位置分类摄像头", businessType = OperaType.DELETE, logType = 1,module = "视频管理->根据位置分类摄像头")
@PostMapping("/getCameraByPlace")
public AjaxResult getCameraByPlace(@RequestBody PlaybackURLsDTO playbackURLsDTO) {
return success(videoService.playbackURLs(playbackURLsDTO));
}
}

View File

@ -0,0 +1,82 @@
package com.bonus.canteen.core.video.dto;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author xliu
* @date 2025/6/25 17:43
*/
@Data
public class PlaybackURLsDTO {
@NotNull
private String cameraIndexCode; // 摄像头索引码
/**
* 存储类型,0中心存储
* 1设备存储
* 默认为中心存储
*/
private String recordLocation;
/**
* 取流协议应用层协议)
* hik:HIK私有协议使用视频SDK进行播放时传入此类型
* rtsp:RTSP协议rtmp:RTMP协议hls:HLS协议hls:HLS协议HLS协议只支持海康SDK协议EHOME协议ONVIF协议接入的设备只支持H264视频编码和AAC音频编码云存储版本要求v2.2.4及以上的2.x版本或v3.0.5及以上的3.x版本ISC版本要求v1.2.0版本及以上需在运管中心-视频联网共享中切换成启动平台外置VOD
* ws:Websocket协议一般用于H5视频播放器取流播放
* 参数不填默认为HIK协议
*/
private String protocol;
/**
* 传输协议传输层协议0:UDP
* 1:TCP
* 默认为tcp在protocol设置为rtsp或者rtmp时有效
* EHOME设备回放只支持TCP传输
* GB28181 2011及以前版本只支持UDP传输
*/
private Integer transmode;
/**
* 开始查询时间IOS8601格式yyyy-MM-ddTHH:mm:ss.SSSXXX
* 例如北京时间
* 2017-06-14T00:00:00.000+08:00参考附录BISO8601时间格式说明
*/
@NotNull
private String beginTime;
/**
* 结束查询时间开始时间和结束时间相差不超过三天
* IOS8601格式yyyy-MM-ddTHH:mm:ss.SSSXXX例如北京时间
* 2017-06-15T00:00:00.000+08:00参考附录BISO8601时间格式说明
*/
@NotNull
private String endTime;
/**
* 分页查询id,上一次查询返回的uuid用于继续查询剩余片段默认为空字符串当存储类型为设备存储时该字段生效中心存储会一次性返回全部片段
*/
private String uuid;
/**
* 扩展内容格式key=value
* 调用方根据其播放控件支持的解码格式选择相应的封装类型
* 支持的内容详见附录F%20expand扩展内容说明
*/
private String expand;
/**
* 输出码流转封装格式ps:PS封装格式rtp:RTP封装协议当protocol=rtsp时生效且不传值时默认为RTP封装协议
*/
private String streamform;
/**
查询录像的锁定类型0-查询全部录像1-查询未锁定录像2-查询已锁定录像不传默认值为0通过录像锁定与解锁接口来进行录像锁定与解锁
*/
private Integer lockType;
}

View File

@ -0,0 +1,60 @@
package com.bonus.canteen.core.video.dto;
import io.swagger.models.auth.In;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author xliu
* @date 2025/6/25 16:59
*/
@Data
public class PreviewDTO {
/**
* 监控点唯一标识分页获取监控点资源接口获取返回参数cameraIndexCode
*/
@NotNull(message = "cameraIndexCode不能为空")
private String cameraIndexCode; // 摄像头索引码
/**
* 码流类型0:主码流
* 1:子码流
* 2:第三码流
* 参数不填默认为主码流
*/
private Integer streamType; // 流类型mainsub
/**
* 取流协议应用层协议hik:HIK私有协议使用视频SDK进行播放时传入此类型rtsp:RTSP协议rtmp:RTMP协议
* hls:HLS协议HLS协议只支持海康SDK协议EHOME协议ONVIF协议接入的设备只支持H264视频编码和AAC音频编码
* ws:Websocket协议一般用于H5视频播放器取流播放
* 参数不填默认为HIK协议
*/
private String protocol;
/**
* 传输协议传输层协议0:UDP
* 1:TCP
* 默认是TCP
*
* GB28181 2011及以前版本只支持UDP传输
*/
private Integer transmode;
/**
* 标识扩展内容格式key=value
* 调用方根据其播放控件支持的解码格式选择相应的封装类型
* 支持的内容详见附录F%20expand扩展内容说明
*/
private String expand;
/**
* 出码流转封装格式ps:PS封装格式rtp:RTP封装协议当protocol=rtsp时生效且不传值时默认为RTP封装协议
*/
private String streamform;
}

View File

@ -0,0 +1,20 @@
package com.bonus.canteen.core.video.dto;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author xliu
* @date 2025/6/24 16:39
*/
@Data
public class VideoMqSendDTO {
private Long userId;
private String videoPath;
private LocalDateTime createTime;
}

View File

@ -0,0 +1,22 @@
package com.bonus.canteen.core.video.entity;
public class FileNameBean {
String currentFileName;
String returnPath;
public String getCurrentFileName() {
return currentFileName;
}
public void setCurrentFileName(String currentFileName) {
this.currentFileName = currentFileName;
}
public String getReturnPath() {
return returnPath;
}
public void setReturnPath(String returnPath) {
this.returnPath = returnPath;
}
}

View File

@ -0,0 +1,44 @@
package com.bonus.canteen.core.video.entity;
import lombok.Data;
/**
* 包名称com.bonus.boot.rear.screen.video.entity
* 类名称VideoBean
* 类描述视频bean
* 创建人@author tqzhang
* 创建时间2023年08月11日 15:21
*/
@Data
public class VideoBean {
private String id;
/**
* 父id
*/
private String pId;
/**
* 球机名称
*/
private String name;
/**
* 球机编码
*/
private String code;
/**
* puid
*/
private String puid;
/**
* 球机下表 0 球机
*/
private String ballIndex;
/**
* 建筑名称 :经研院 A楼 一层
*/
private String building;
/**
* 球机是否在线
*/
private String onLine;
}

View File

@ -0,0 +1,13 @@
package com.bonus.canteen.core.video.entity;
import lombok.Data;
@Data
public class VideoRequestBean {
private String startTime;
private String endTime;
private String channelId;
private String videoType;
private String ip; // IP address of the video source
}

View File

@ -0,0 +1,18 @@
package com.bonus.canteen.core.video.service;
import com.bonus.canteen.core.video.dto.PlaybackURLsDTO;
import com.bonus.canteen.core.video.dto.PreviewDTO;
import com.bonus.canteen.core.video.entity.VideoRequestBean;
/**
* @author xliu
* @date 2025/6/23 15:27
*/
public interface VideoService {
String download(VideoRequestBean videoRequestBean);
String previewURLs(PreviewDTO previewDTO);
String playbackURLs(PlaybackURLsDTO playbackURLsDTO);
}

View File

@ -0,0 +1,60 @@
package com.bonus.canteen.core.video.service.impl;
import com.alibaba.fastjson2.JSON;
import com.bonus.canteen.core.video.dto.PlaybackURLsDTO;
import com.bonus.canteen.core.video.dto.PreviewDTO;
import com.bonus.canteen.core.video.entity.VideoRequestBean;
import com.bonus.canteen.core.video.service.VideoService;
import com.bonus.canteen.core.video.utils.HCNetVedio;
import com.bonus.canteen.core.video.utils.HKRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
/**
* @author xliu
* @date 2025/6/23 15:27
*/
@Service
public class VideoServiceImpl implements VideoService {
public static Logger logger = LoggerFactory.getLogger(VideoServiceImpl.class);
@Override
public String download(VideoRequestBean bean) {
String fileName = "";
logger.error("check_download_bean="+bean.toString());
int userId = -1;
userId = getUserId(bean, userId);
System.err.println("userId=" + userId);
if (userId > -1) {
fileName = new HCNetVedio().downloadByTime(userId, bean);
// new HCNetVedio().getRealPlayStream(userId,bean);
}
System.err.println("download_fileName=" + fileName);
return fileName;
}
private int getUserId(VideoRequestBean bean, int userId) {
// if ("CVR".equals(bean.getVideoType())) {
// userId = HCNetVedio.login_V40("192.168.1.10", (short) 8000, "admin", "hzx12345"); //CVR
// } else if ("NVR1".equals(bean.getVideoType())) {
// userId = HCNetVedio.login_V40("192.168.1.10", (short) 8000, "admin", "hzx12345"); //NVR1
// } else if ("NVR2".equals(bean.getVideoType())) {
// userId = HCNetVedio.login_V40("192.168.1.10", (short) 8000, "admin", "hzx12345"); //NVR2
// }
userId = HCNetVedio.login_V40(bean.getIp(), (short) 8000, "admin", "hzx12345");
return userId;
}
@Override
public String previewURLs(PreviewDTO previewDTO) {
String result = HKRequest.sendHttp(HKRequest.GET_VIDEO_URL, JSON.toJSONString(previewDTO));
return result;
}
@Override
public String playbackURLs(PlaybackURLsDTO playbackURLsDTO) {
String result = HKRequest.sendHttp(HKRequest.GET_VIDEO_HISTORY_URL, JSON.toJSONString(playbackURLsDTO));
return result;
}
}

View File

@ -0,0 +1,65 @@
package com.bonus.canteen.core.video.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class FixMP4 {
private static String ffmpegEXE = "D:\\workSoftware\\ffmpeg\\ffmpeg-2025-01-20-git-504df09c34-full_build\\ffmpeg-2025-01-20-git-504df09c34-full_build\\bin\\ffmpeg.exe";
private static String ffmpegLinux = "/usr/local/ffmpeg/bin/ffmpeg";
public static void main(String[] args) {
try {
convert("D:\\projects_out\\jyyhq\\rearServiceScreen\\src\\main\\resources\\static\\download\\playBackByTime_origin.mp4","D:\\projects_out\\jyyhq\\rearServiceScreen\\src\\main\\resources\\static\\download\\playBackByTime.mp4");
} catch (Exception e) {
e.printStackTrace();
}
}
//ffmpeg -i demo.mp4 -c copy -an demp_enc.mp4
public static void convert(String videoInputPath, String videoOutPath) {
List<String> command = new ArrayList<String>();
System.out.println("video convert finished!");
if (osSelect.isWindows()) {
command.add(ffmpegEXE);
} else if (osSelect.isLinux()) {
command.add(ffmpegLinux);
}
command.add("-i");
command.add(videoInputPath);
command.add("-c");
command.add("copy");
command.add("-an");
command.add(videoOutPath);
ProcessBuilder builder = new ProcessBuilder(command);
Process process = null;
try {
File outputFile = new File(videoOutPath);
outputFile.delete();
process = builder.start();
// 使用这种方式会在瞬间大量消耗CPU和内存等系统资源所以这里我们需要对流进行处理
InputStream errorStream = process.getErrorStream();
InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
BufferedReader br = new BufferedReader(inputStreamReader);
String line = "";
while ((line = br.readLine()) != null) {
}
if (br != null) {
br.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (errorStream != null) {
errorStream.close();
}
System.out.println("video convert finished!");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,465 @@
package com.bonus.canteen.core.video.utils;
import com.bonus.canteen.core.common.utils.MqUtil;
import com.bonus.canteen.core.video.dto.VideoMqSendDTO;
import com.bonus.canteen.core.video.entity.FileNameBean;
import com.bonus.canteen.core.video.entity.VideoRequestBean;
import com.bonus.common.houqin.mq.constant.LeMqConstant;
import com.bonus.common.security.utils.SecurityUtils;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.IntByReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Timer;
public class HCNetVedio {
private static final Logger logger = LoggerFactory.getLogger(HCNetVedio.class);
static String JAVA_LIB_FOLDER = "/home/sdk/lib/";
static String RECORDING_TEMP_FOLDER = "/opt/tomcat/webapps/witDisplay/download/";
// 载入sdk库文件
static HCNetSDK hCNetSDK; // = HCNetSDK.INSTANCE;
static PlayCtrl playControl = null;
static int lUserID = -1;//用户句柄
static int lDChannel; //预览通道号
static boolean bSaveHandle = false;
static int m_lLoadHandle;
static FExceptionCallBack_Imp fExceptionCallBack;
static int iPlayBack; //回放句柄
static File file;
static boolean palybackFlay = false;
static playDataCallBack playBackCallBack; //回放码流回调
static Timer downloadtimer;//下载用定时器
static Timer Playbacktimer;//回放用定时器
static FileOutputStream outputStream;
static {
init();
}
static class FExceptionCallBack_Imp implements HCNetSDK.FExceptionCallBack {
public void invoke(int dwType, int lUserID, int lHandle, Pointer pUser) {
System.out.println("异常事件类型:" + dwType);
return;
}
}
static class playDataCallBack implements HCNetSDK.FPlayDataCallBack {
public void invoke(int lPlayHandle, int dwDataType, Pointer pBuffer, int dwBufSize, int dwUser) {
System.out.println("回放码流回调...");
//将设备发送过来的回放码流数据写入文件
long offset = 0;
ByteBuffer buffers = pBuffer.getByteBuffer(offset, dwBufSize);
byte[] bytes = new byte[dwBufSize];
buffers.rewind();
buffers.get(bytes);
try {
if (outputStream == null) {
try {
HCNetVedio.outputStream = new FileOutputStream(HCNetVedio.file);
} catch (FileNotFoundException e) {
System.out.println("再次创建HCNetVedio.outputStream出错");
e.printStackTrace();
}
}
outputStream.write(bytes);
} catch (IOException e) {
System.out.println("HCNetVedio.playDataCallBack出错");
e.printStackTrace();
}
}
}
static void init() {
if (hCNetSDK == null && playControl == null) {
if (!createSDKInstance()) {
System.out.println("Load SDK fail");
return;
}
if (!createPlayInstance()) {
System.out.println("Load PlayCtrl fail");
return;
}
}
//linux系统建议调用以下接口加载组件库
if (osSelect.isLinux()) {
HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
//这里是库的绝对路径请根据实际情况修改注意改路径必须有访问权限
String strPath1 = JAVA_LIB_FOLDER + "libcrypto.so.1.1";
String strPath2 = JAVA_LIB_FOLDER + "libssl.so.1.1";
System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
ptrByteArray1.write();
hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());
System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
ptrByteArray2.write();
hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());
String strPathCom = JAVA_LIB_FOLDER;
HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
struComPath.write();
hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());
}
//SDK初始化一个程序只需要调用一次
boolean initSuc = hCNetSDK.NET_DVR_Init();
//异常消息回调
if (fExceptionCallBack == null) {
fExceptionCallBack = new FExceptionCallBack_Imp();
}
Pointer pUser = null;
if (!hCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, 0, fExceptionCallBack, pUser)) {
return;
}
System.out.println("设置异常消息回调成功");
//启动SDK写日志
hCNetSDK.NET_DVR_SetLogToFile(3, "./sdkLog", false);
}
private static boolean createSDKInstance() {
if (hCNetSDK == null) {
synchronized (HCNetSDK.class) {
String strDllPath = "";
try {
if (osSelect.isWindows()) {
//win系统加载库路径
strDllPath = System.getProperty("user.dir") + "\\bonus-modules\\bonus-smart-canteen\\src\\main\\resources\\lib\\HCNetSDK.dll";
}
else if (osSelect.isLinux()) {
//Linux系统加载库路径
strDllPath = JAVA_LIB_FOLDER + "libhcnetsdk.so";
}
hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);
} catch (Exception ex) {
System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
return false;
}
}
}
return true;
}
/**
* 播放库加载
*
* @return
*/
private static boolean createPlayInstance() {
if (playControl == null) {
synchronized (PlayCtrl.class) {
String strPlayPath = "";
try {
if (osSelect.isWindows()) {
//win系统加载库路径
strPlayPath = System.getProperty("user.dir") + "\\bonus-modules\\bonus-smart-canteen\\src\\main\\resources\\lib\\PlayCtrl.dll";
}
else if (osSelect.isLinux()) {
//Linux系统加载库路径
strPlayPath = JAVA_LIB_FOLDER + "libPlayCtrl.so";
}
playControl = (PlayCtrl) Native.loadLibrary(strPlayPath, PlayCtrl.class);
} catch (Exception ex) {
System.out.println("loadLibrary: " + strPlayPath + " Error: " + ex.getMessage());
return false;
}
}
}
return true;
}
public static int login_V40(String ip, short port, String user, String psw) {
//初始化
init();
//注册
HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息
HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息
String m_sDeviceIP = ip;//设备ip地址
m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
String m_sUsername = user;//设备用户名
m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
String m_sPassword = psw;//设备密码
m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
m_strLoginInfo.wPort = port;
m_strLoginInfo.bUseAsynLogin = false; //是否异步登录0- 1-
m_strLoginInfo.byLoginMode = 0; //0- SDK私有协议1- ISAPI协议
m_strLoginInfo.write();
lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
if (lUserID == -1) {
System.out.println("登录失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());
} else {
System.out.println(ip + ":设备登录成功!");
//相机一般只有一个通道号热成像相机有2个通道号通道号为1或1,2
//byStartDChan为IP通道起始通道号, 预览回放NVR的IP通道时需要根据起始通道号进行取值
if ((int) m_strDeviceInfo.struDeviceV30.byStartDChan == 1 && (int) m_strDeviceInfo.struDeviceV30.byStartDChan == 33) {
//byStartDChan为IP通道起始通道号, 预览回放NVR的IP通道时需要根据起始通道号进行取值,NVR起始通道号一般是33或者1开始
lDChannel = (int) m_strDeviceInfo.struDeviceV30.byStartDChan;
System.out.println("预览起始通道号:" + lDChannel);
}
}
return lUserID;
}
/**
* 注销
*
* @param lUserID 设备注册成功唯一标识符
*/
public static void logout(int lUserID) {
// 注销
hCNetSDK.NET_DVR_Logout(lUserID);
// 释放sdk资源
hCNetSDK.NET_DVR_Cleanup();
}
public static void logout() {
try {
Thread.sleep(5 * 1000); //sleep 5 seconds
//退出程序时调用每一台设备分别注销
if (hCNetSDK.NET_DVR_Logout(lUserID)) {
System.out.println("注销成功");
}
//SDK反初始化释放资源只需要退出时调用一次
hCNetSDK.NET_DVR_Cleanup();
} catch (Exception e) {
e.printStackTrace();
}
}
/*************************************************
: DownloadTask
类描述: 下载定时器响应函数
*************************************************/
static class downloadTask extends java.util.TimerTask {
int userId;
String filePath;
downloadTask(int userId, String filePath) {
this.userId = userId;
this.filePath = filePath;
}
//定时器函数
@Override
public void run() {
IntByReference nPos = new IntByReference(0);
hCNetSDK.NET_DVR_PlayBackControl(m_lLoadHandle, HCNetSDK.NET_DVR_PLAYGETPOS, 0, nPos);
System.out.println("下载开始..., nPos.getValue()="+ nPos.getValue());
if (nPos.getValue() > 100) {
m_lLoadHandle = -1;
downloadtimer.cancel();
System.out.println("由于网络原因或DVR忙,下载异常终止!");
}
if (nPos.getValue() == 100) {
Date nowTime = new Date(System.currentTimeMillis());
SimpleDateFormat sdFormatter = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
System.out.println("结束下载时间:" + sdFormatter.format(nowTime));
m_lLoadHandle = -1;
downloadtimer.cancel();
HCNetVedio.logout(userId);
System.out.println("按时间下载结束!");
//修复MP4
String outPutFullPath = filePath.replace("_origin", "");
FixMP4.convert(filePath, outPutFullPath);
System.out.println("修复mp4结束,"+filePath+"->"+outPutFullPath);
// VideoMqSendDTO bean = new VideoMqSendDTO();
// bean.setUserId(SecurityUtils.getUserId());
// bean.setVideoPath(filePath.replace("_origin", ""));
// bean.setCreateTime(LocalDateTime.now());
// MqUtil.pushToTenantAllDevice(bean, LeMqConstant.Topic.VIDEO_UPLOAD);
}
}
}
//获取视频流
public void getRealPlayStream(int userID, VideoRequestBean bean) {
HCNetSDK.NET_DVR_PLAYCOND playCond = new HCNetSDK.NET_DVR_PLAYCOND();
playCond.dwChannel = Integer.parseInt(bean.getChannelId());
playCond.struStartTime = parseTime(bean.getStartTime());
playCond.struStopTime = parseTime(bean.getEndTime());
playCond.byStreamType=2;
playCond.byDrawFrame=1; // 0-不解码1-解码
int lPlayHandle = hCNetSDK.NET_DVR_PlayBackByTime_V40(new NativeLong(userID), playCond);
System.out.println("获取视频流成功,句柄为: " + lPlayHandle);
if (lPlayHandle < 0) {
System.out.println("获取视频流失败: " + hCNetSDK.NET_DVR_GetLastError());
return;
} else {
System.out.println("获取视频流成功,句柄为: " + lPlayHandle);
new StreamCallback().invoke(lPlayHandle, 0, null, 0, null);
}
}
// 时间格式转换示例20250624120000
private static HCNetSDK.NET_DVR_TIME parseTime(String timeStr) {
System.err.println("传入时间为:"+timeStr);
timeStr = timeStr.replaceAll("-", "").replaceAll(":", "").replaceAll(" ", "");
System.err.println("传入时间为:"+timeStr);
HCNetSDK.NET_DVR_TIME dvrTime = new HCNetSDK.NET_DVR_TIME();
dvrTime.dwYear = Integer.parseInt(timeStr.substring(0,4));
dvrTime.dwMonth = Integer.parseInt(timeStr.substring(4,6));
dvrTime.dwDay = Integer.parseInt(timeStr.substring(6,8));
dvrTime.dwHour = Integer.parseInt(timeStr.substring(8,10));
dvrTime.dwMinute = Integer.parseInt(timeStr.substring(10,12));
dvrTime.dwSecond = Integer.parseInt(timeStr.substring(12,14));
System.out.println("时间:"+timeStr.substring(0,4));
System.out.println("时间:"+timeStr.substring(4,6));
System.out.println("时间:"+timeStr.substring(6,8));
System.out.println("时间:"+timeStr.substring(8,10));
System.out.println("时间:"+timeStr.substring(10,12));
System.out.println("时间:"+timeStr.substring(12,14));
return dvrTime;
}
// 回调函数处理视频流数据
public static class StreamCallback implements HCNetSDK.FRealDataCallBack_V30 {
@Override
public void invoke(int lRealHandle, int dwDataType, ByteByReference pBuffer, int dwBufSize, Pointer pUser) {
// 处理视频流数据需配合解码库使用
System.out.println("Received data size: " + dwBufSize);
}
}
//按时间下载录像(不支持转码3GP格式)
public String downloadByTime(int userID, VideoRequestBean bean) {
cancelLastDownloadSchedule(); //先清除上次的下载
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime startDateTime = LocalDateTime.parse(bean.getStartTime(), formatter);
LocalDateTime endDateTime = LocalDateTime.parse(bean.getEndTime(), formatter);
int lChannel = Integer.parseInt(bean.getChannelId());
HCNetSDK.NET_DVR_PLAYCOND net_dvr_playcond = new HCNetSDK.NET_DVR_PLAYCOND();
net_dvr_playcond.read();
net_dvr_playcond.dwChannel=lChannel;
//开始时间
net_dvr_playcond.struStartTime.dwYear=startDateTime.getYear();
net_dvr_playcond.struStartTime.dwMonth=startDateTime.getMonthValue();
net_dvr_playcond.struStartTime.dwDay=startDateTime.getDayOfMonth();
net_dvr_playcond.struStartTime.dwHour=startDateTime.getHour();
net_dvr_playcond.struStartTime.dwMinute=startDateTime.getMinute();
net_dvr_playcond.struStartTime.dwSecond=startDateTime.getSecond();
//停止时间
net_dvr_playcond.struStopTime.dwYear=endDateTime.getYear();
net_dvr_playcond.struStopTime.dwMonth=endDateTime.getMonthValue();
net_dvr_playcond.struStopTime.dwDay=endDateTime.getDayOfMonth();
net_dvr_playcond.struStopTime.dwHour=endDateTime.getHour();
net_dvr_playcond.struStopTime.dwMinute=endDateTime.getMinute();
net_dvr_playcond.struStopTime.dwSecond=endDateTime.getSecond();
net_dvr_playcond.write();
FileNameBean fileNameBean = getFileNameBean(bean);
m_lLoadHandle = hCNetSDK.NET_DVR_GetFileByTime_V40(userID,fileNameBean.getCurrentFileName(),net_dvr_playcond);
if (m_lLoadHandle >= 0)
{
hCNetSDK.NET_DVR_PlayBackControl(m_lLoadHandle, 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));
downloadtimer = new Timer();//新建定时器
downloadtimer.schedule(new downloadTask(userID, fileNameBean.getCurrentFileName()), 0, 5000);//0秒后开始响应函数
return fileNameBean.getReturnPath();
} else
{
System.out.println("按时间下载失败: " + hCNetSDK.NET_DVR_GetLastError());
return null;
}
}
public static FileNameBean getFileNameBean(VideoRequestBean bean) {
StringBuilder fileNameBuild = new StringBuilder();
fileNameBuild.append(bean.getChannelId()).append("_").append(System.currentTimeMillis());
String fileName = fileNameBuild.toString();
System.out.println("传入起始时间为:"+bean.getStartTime()+",传入结束时间为:"+bean.getEndTime());
String windowsFileFullPath = System.getProperty("user.dir") + "\\bonus-modules\\bonus-smart-canteen\\src\\main\\resources\\static\\download\\"+fileName+"_origin.mp4";
String linuxFileFullPath = RECORDING_TEMP_FOLDER + fileName + "_origin.mp4";
String returnPath = "download/" + fileName + ".mp4";
if (osSelect.isWindows()) {
fileName = windowsFileFullPath;
} else if (osSelect.isLinux()) {
fileName = linuxFileFullPath;
}
FileNameBean fileNameBean = new FileNameBean();
fileNameBean.setCurrentFileName(fileName);
fileNameBean.setReturnPath(returnPath);
return fileNameBean;
}
public static void cancelLastDownloadSchedule() {
try {
if (downloadtimer != null) {
downloadtimer.cancel();
System.out.println("结束上次download定时器成功");
Thread.sleep(5 * 1000); //sleep 5 seconds
}
if (Playbacktimer != null) {
Playbacktimer.cancel();
System.out.println("结束上次playback定时器成功");
Thread.sleep(5 * 1000); //sleep 5 seconds
}
//删除文件
String windowsFileFullPath = System.getProperty("user.dir") + "\\bonus-modules\\bonus-smart-canteen\\src\\main\\resources\\static\\download";
String linuxFileFullPath = RECORDING_TEMP_FOLDER;
File directory = null;
if (osSelect.isWindows()) {
directory = new File(windowsFileFullPath);
} else if (osSelect.isLinux()) {
directory = new File(linuxFileFullPath);
}
deleteAllFiles(directory);
System.out.println("删除上次文件成功");
} catch (Exception e) {
System.out.println("取消上次下载计划失败");
e.printStackTrace();
}
}
public static void deleteAllFiles(File file) {
// 如果是目录则遍历目录下的所有文件并递归调用该方法
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
deleteAllFiles(f);
}
}
} else {
// 如果是文件则直接删除
boolean isDeleted = file.delete();
if (isDeleted) {
System.out.println("成功删除文件:" + file.getAbsolutePath());
} else {
System.out.println("无法删除文件:" + file.getAbsolutePath());
}
}
}
}

View File

@ -0,0 +1,97 @@
package com.bonus.canteen.core.video.utils;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import org.apache.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;
/**
* 海康车库闸机http接口
*
* @author bonus
*/
public class HKRequest {
private static final String host = "127.0.0.1:443";
private static final String appKey = "21775939";
private static final String appSecret = "jRUGavASM5qolzEDrJ5w";
private static final String ARTEMIS_PATH = "/artemis";//设置OpenAPI接口的上下文
public static final String GET_VIDEO_URL = "/api/video/v2/cameras/previewURLs";//获取视频预览地址接口
public static final String GET_VIDEO_HISTORY_URL = "/api/video/v2/cameras/playbackURLs";//获取视频预览地址接口
/**
* 发送http请求
*
* @param apiUrl api地址
* @param body 参数
* @return
*/
public static String sendHttp(String apiUrl, String body) {
ArtemisConfig.host = host; // artemis网关服务器ip端口
ArtemisConfig.appKey = appKey; // 秘钥appkey
ArtemisConfig.appSecret = appSecret;// 秘钥appSecret
final String previewURLsApi = ARTEMIS_PATH + apiUrl;
Map<String, String> path = new HashMap<String, String>(2) {
{
put("https://", previewURLsApi);//根据现场环境部署确认是http还是https
}
};
String contentType = "application/json";
String result = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, contentType, null);// post请求a pplication/json类型参数
return result;
}
/**
* 发送http请求
*
* @param apiUrl api地址
* @param body 参数
* @return
*/
public static String sendHttpTagId(String apiUrl, String body) {
ArtemisConfig.host = host; // artemis网关服务器ip端口
ArtemisConfig.appKey = appKey; // 秘钥appkey
ArtemisConfig.appSecret = appSecret;// 秘钥appSecret
final String previewURLsApi = ARTEMIS_PATH + apiUrl;
Map<String, String> path = new HashMap<String, String>(2) {
{
put("https://", previewURLsApi);//根据现场环境部署确认是http还是https
}
};
Map<String, String> tagId = new HashMap<String, String>(2) {
{
put("tagId", "frs");//根据现场环境部署确认是http还是https
}
};
String contentType = "application/json";
String result = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, contentType, tagId);// post请求a pplication/json类型参数
return result;
}
public static HttpResponse sendHttpImg(String apiUrl, String body) {
ArtemisConfig.host = "10.138.106.66:443"; // artemis网关服务器ip端口
ArtemisConfig.appKey = "21775939"; // 秘钥appkey
ArtemisConfig.appSecret = "jRUGavASM5qolzEDrJ5w";// 秘钥appSecret
final String previewURLsApi = ARTEMIS_PATH + apiUrl;
Map<String, String> path = new HashMap<String, String>(2) {
{
put("https://", previewURLsApi);//根据现场环境部署确认是http还是https
}
};
String contentType = "application/json";
HttpResponse result = ArtemisHttpUtil.doPostStringImgArtemis(path, body, null, null, contentType, null);// post请求a pplication/json类型参数
return result;
}
}

View File

@ -0,0 +1,116 @@
package com.bonus.canteen.core.video.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HkCameraUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(HkCameraUtil.class);
static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;
// 设备登录信息
HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
// 设备信息
public HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
// 已登录设备的IP
String m_sDeviceIP;
// 设备用户名
String m_sUsername;
// 设备密码
String m_sPassword;
// 报警回调函数实现
public HCNetSDK.FMSGCallBack_V31 fMSFCallBack_V31;
// public IQueue queue = new LinkedQueue();
/**
* sdk初始化
*
* @return
*/
public int initDevice() {
if (!hCNetSDK.NET_DVR_Init()) {
// sdk初始化失败
return 1;
}
return 0;
}
/**
* 设备注册
*
* @param ip 设备ip
* @param name 设备名
* @param password 设备密码
*/
public int deviceRegister(int lUserID, String ip, String name, String password, String port) {
// 设备注册之前先进行判断注销已注册的设备
if (lUserID > -1) {
// 先注销
hCNetSDK.NET_DVR_Logout(lUserID);
lUserID = -1;
}
// ip地址
m_sDeviceIP = ip;
m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
// 设备用户名
m_sUsername = name;
m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
// 设备密码
m_sPassword = password;
m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
m_strLoginInfo.wPort = (short) Integer.parseInt(port);
// 是否异步登录0 - 1 -
m_strLoginInfo.bUseAsynLogin = false;
m_strLoginInfo.write();
// 设备注册调用 NET_DVR_Login_V40注册成功得到唯一标识符 lUserID
// 设备注册失败调用 NET_DVR_GetLastError根据错误号判断错误类型
lUserID = HCNetSDK.INSTANCE.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
if (lUserID == -1) {
LOGGER.info("设备注册失败,错误号:", HCNetSDK.INSTANCE.NET_DVR_GetLastError());
return -1;
} else {
LOGGER.info("设备注册成功");
return lUserID;
}
}
/**
* 注销
*
* @param lUserID 设备注册成功唯一标识符
*/
public void logout(int lUserID) {
// 注销
hCNetSDK.NET_DVR_Logout(lUserID);
}
/**
* 报警撤防
*
* @param lAlarmHandle 报警处理器
*/
public int closeAlarmChan(int lAlarmHandle) {
if (lAlarmHandle > -1) {
if (hCNetSDK.NET_DVR_CloseAlarmChan_V30(lAlarmHandle)) {
LOGGER.info("撤防成功");
lAlarmHandle = -1;
return lAlarmHandle;
}
return lAlarmHandle;
}
return lAlarmHandle;
}
public Boolean onlineState(int lUserID) {
int row = initDevice();
if (row == 1) {
LOGGER.info("初始化失败");
}
// 检查设备在线状态
LOGGER.info("设备信息========={}", m_strDeviceInfo.struDeviceV30);
boolean isOnLine = HCNetSDK.INSTANCE.NET_DVR_RemoteControl(lUserID, 20005, null, 0);
LOGGER.info("checkDeviceOnLine---isOnLine============{}", isOnLine);
return isOnLine;
}
}

View File

@ -0,0 +1,16 @@
package com.bonus.canteen.core.video.utils;
/**
* @author jiangxin
* @create 2022-01-19-16:40
*/
public class osSelect {
public static boolean isLinux() {
return System.getProperty("os.name").toLowerCase().contains("linux");
}
public static boolean isWindows() {
return System.getProperty("os.name").toLowerCase().contains("windows");
}
}