HikCameraServiceImpl.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. package com.sckj.camera.service;
  2. import com.sckj.camera.common.FlowUtils;
  3. import com.sckj.camera.common.HikCameraUtils;
  4. import com.sckj.camera.manager.HikCameraManager;
  5. import com.sckj.camera.model.dto.CameraDTO;
  6. import com.sckj.camera.model.dto.ResultDTO;
  7. import com.sckj.camera.model.entity.Camera;
  8. import com.sckj.camera.model.entity.CameraFile;
  9. import com.sckj.camera.model.entity.CameraFlow;
  10. import com.sckj.camera.hik.HCNetTools;
  11. import org.apache.commons.lang3.ObjectUtils;
  12. import org.apache.commons.lang3.StringUtils;
  13. import org.slf4j.Logger;
  14. import org.slf4j.LoggerFactory;
  15. import org.springframework.beans.BeanUtils;
  16. import org.springframework.beans.factory.annotation.Autowired;
  17. import org.springframework.beans.factory.annotation.Value;
  18. import org.springframework.stereotype.Service;
  19. import java.io.File;
  20. import java.time.LocalDateTime;
  21. import java.time.format.DateTimeFormatter;
  22. import java.util.Arrays;
  23. import java.util.Date;
  24. import java.util.HashMap;
  25. import java.util.List;
  26. @Service
  27. public class HikCameraServiceImpl {
  28. private final Logger logger = LoggerFactory.getLogger(HikCameraServiceImpl.class);
  29. @Autowired
  30. private DeviceServiceImpl deviceService;
  31. @Autowired
  32. private FlowServiceImpl flowService;
  33. @Autowired
  34. private FFmpegServiceImpl ffmpegService;
  35. @Autowired
  36. private CameraFileServiceImpl cameraFileService;
  37. @Autowired
  38. private HikCameraManager hikCameraManager;
  39. @Value("${app.filepath}")
  40. private String rootPath;
  41. @Value("${rtmp.rtmphost}")
  42. private String rtmpServer;
  43. @Value("${rtmp.httphost}")
  44. private String httpServer;
  45. public ResultDTO getChannel(CameraDTO cameraDTO) {
  46. ResultDTO resultDTO = new ResultDTO();
  47. StringBuilder str = new StringBuilder();
  48. for (int i = 0;i < cameraDTO.getChannelList().size();i++) {
  49. if (i == cameraDTO.getChannelList().size() - 1) {
  50. str.append(cameraDTO.getChannelList().get(i));
  51. } else {
  52. str.append(cameraDTO.getChannelList().get(i)).append("&");
  53. }
  54. }
  55. resultDTO.setMsg(str.toString());
  56. return resultDTO;
  57. }
  58. /**
  59. * 开始推流(rtsp->rtmp)
  60. * @param cameraDTO 相机信息
  61. * @return ResultDTO
  62. */
  63. public ResultDTO startTranscode(CameraDTO cameraDTO) {
  64. ResultDTO resultDTO = new ResultDTO();
  65. Camera camera = deviceService.getById(cameraDTO.getCameraId());
  66. if(ObjectUtils.isNotEmpty(camera)){
  67. BeanUtils.copyProperties(camera,cameraDTO);
  68. }
  69. cameraDTO.setChannelList(Arrays.asList("1"));
  70. if (cameraDTO != null) {
  71. String appName;
  72. int channelNumber;
  73. if (cameraDTO.getType() == 0) {
  74. //摄像机
  75. appName = cameraDTO.getAccount() + cameraDTO.getIp().replace(".","");
  76. channelNumber = HikCameraUtils.analyzeChannel(cameraDTO.getChannelList().get(0));
  77. } else {
  78. //NVR
  79. appName = cameraDTO.getAccount() + cameraDTO.getIp().replace(".","") + "to" + cameraDTO.getIpcAddress().replace(".","");
  80. channelNumber = HikCameraUtils.getIpcChannel(cameraDTO.getChannelList(),cameraDTO.getIpcAddress());
  81. }
  82. if (channelNumber == -1) {
  83. logger.info("实时流-未搜索到ip:" + cameraDTO.getIp() + ", ipc:" + cameraDTO.getIpcAddress() + " 的设备");
  84. }
  85. String rtmpUrl = "rtmp://"+ rtmpServer + "/live/" + appName; //rtmp链
  86. String flvUrl = "http://" + httpServer + "/live/" + appName + ".flv"; //http-flv链
  87. boolean runFlag = ffmpegService.taskerIsRun(appName);
  88. CameraFlow cameraFlow = flowService.findByRtmpUrl(rtmpUrl);
  89. if (cameraFlow != null && !runFlag) {
  90. flowService.removeById(cameraFlow.getId());
  91. }
  92. if (runFlag) {
  93. //已推流
  94. if (cameraFlow != null) {
  95. resultDTO.setTasker(appName);
  96. resultDTO.setMsg(HikCameraUtils.resultNames[0]);
  97. resultDTO.setRtmpUrl(rtmpUrl);
  98. resultDTO.setFlvUrl(flvUrl);
  99. cameraFlow.setClient(cameraFlow.getClient() + 1);
  100. flowService.updateById(cameraFlow);
  101. } else {
  102. //停止推流
  103. flowService.stopByTasker(appName);
  104. resultDTO.setMsg("推流失败");
  105. return resultDTO;
  106. }
  107. } else {
  108. //未推流
  109. //String channelNumberStr = "ch"+channelNumber; //旧通道(2012年之前设备)
  110. channelNumber = 1;
  111. String channelNumberStr = channelNumber + "02"; //新通道(2012年之后设备,02代表子码流)
  112. //String rtspName = cameraDTO.getAccount() + ":" + cameraDTO.getPassword() + "@" + cameraDTO.getIp() + ":554/Streaming/Channels/" + channelNumberStr + "/sub/av_stream"); //旧码流(子码流)
  113. String rtspName = cameraDTO.getAccount() + ":" + cameraDTO.getPassword() + "@" + cameraDTO.getIp() + ":554/Streaming/Channels/" + channelNumberStr + "?transportmode=unicast"; //新码流
  114. String rtmpName = rtmpServer + "/live/"; //rtmp服务器推流入口
  115. String tasker= ffmpegService.startTranscoding(appName,rtspName,rtmpName);
  116. if (StringUtils.isNotEmpty(tasker)) {
  117. resultDTO.setTasker(tasker);
  118. resultDTO.setMsg(HikCameraUtils.resultNames[0]);
  119. resultDTO.setRtmpUrl(rtmpUrl);
  120. resultDTO.setFlvUrl(flvUrl);
  121. //添加流记录
  122. cameraFlow = new CameraFlow();
  123. cameraFlow.setCameraId(cameraDTO.getCameraId());
  124. if (cameraDTO.getType() == 0) {
  125. cameraFlow.setCameraIpc(cameraDTO.getIp());
  126. } else {
  127. cameraFlow.setCameraIpc(cameraDTO.getIpcAddress());
  128. }
  129. cameraFlow.setTasker(tasker);
  130. cameraFlow.setFlowType(FlowUtils.FlowType.HIK.ordinal());
  131. cameraFlow.setRtsp("rtsp://" + rtspName);
  132. cameraFlow.setRtmp(rtmpUrl);
  133. cameraFlow.setFlv(flvUrl);
  134. cameraFlow.setClient(1);
  135. cameraFlow.setCreateTime(new Date());
  136. cameraFlow.setUpdateTime(new Date());
  137. flowService.save(cameraFlow);
  138. } else {
  139. resultDTO.setMsg("推流失败");
  140. return resultDTO;
  141. }
  142. }
  143. return resultDTO;
  144. } else {
  145. resultDTO.setMsg("未找到设备");
  146. return resultDTO;
  147. }
  148. }
  149. /**
  150. * 回放推流
  151. * @param cameraDTO 相机信息
  152. * @return ResultDTO
  153. */
  154. public ResultDTO startBackTranscode(CameraDTO cameraDTO) {
  155. ResultDTO resultDTO = new ResultDTO();
  156. if (cameraDTO != null) {
  157. String startTime,endTime;
  158. DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyyMMdd't'HHmmss'z'");
  159. if (cameraDTO.getHistoryDTO().getEndTime() != null) {
  160. startTime = sdf.format(cameraDTO.getHistoryDTO().getStartTime());
  161. endTime = sdf.format(cameraDTO.getHistoryDTO().getEndTime());
  162. } else {
  163. startTime = sdf.format(cameraDTO.getHistoryDTO().getStartTime());
  164. endTime = null;
  165. }
  166. String appName;
  167. int channelNumber;
  168. if (cameraDTO.getType() == 0) {
  169. //摄像机
  170. appName = "history" + cameraDTO.getAccount() + cameraDTO.getIp().replace(".", "") + "start" + startTime + "end" + endTime;
  171. channelNumber = HikCameraUtils.analyzeChannel(cameraDTO.getChannelList().get(0));
  172. } else {
  173. //NVR
  174. appName = "history" + cameraDTO.getAccount() + cameraDTO.getIp().replace(".", "") + "to" + cameraDTO.getIpcAddress().replace(".", "") + "start" + startTime + "end" + endTime;
  175. channelNumber = HikCameraUtils.getIpcChannel(cameraDTO.getChannelList(), cameraDTO.getIpcAddress());
  176. }
  177. if (channelNumber == -1) {
  178. logger.info("历史流-未搜索到ip:" + cameraDTO.getIp() + ", ipc:" + cameraDTO.getIpcAddress() + " 的设备");
  179. }
  180. String rtmpUrl = "rtmp://"+ rtmpServer + "/live/" + appName; //rtmp链
  181. String flvUrl = "http://" + httpServer + "/live/" + appName + ".flv"; //http-flv链
  182. boolean runFlag = ffmpegService.taskerIsRun(appName);
  183. CameraFlow cameraFlow = flowService.findByRtmpUrl(rtmpUrl);
  184. if (cameraFlow != null && !runFlag) {
  185. flowService.removeById(cameraFlow.getId());
  186. }
  187. if (runFlag) {
  188. //已推流
  189. if (cameraFlow != null) {
  190. resultDTO.setTasker(appName);
  191. resultDTO.setMsg(HikCameraUtils.resultNames[0]);
  192. resultDTO.setRtmpUrl(rtmpUrl);
  193. resultDTO.setFlvUrl(flvUrl);
  194. cameraFlow.setClient(cameraFlow.getClient() + 1);
  195. flowService.updateById(cameraFlow);
  196. } else {
  197. //停止推流
  198. flowService.stopByTasker(appName);
  199. resultDTO.setMsg("推流失败");
  200. return resultDTO;
  201. }
  202. } else {
  203. //未推流
  204. String channelNumberStr = channelNumber + "01"; //回放流只有主码流
  205. String rtspName;
  206. if (endTime != null) {
  207. rtspName = cameraDTO.getAccount() + ":" + cameraDTO.getPassword() + "@" + cameraDTO.getIp() + ":554/Streaming/tracks/" + channelNumberStr + "?starttime=" + startTime + "&endtime=" + endTime;
  208. } else {
  209. rtspName = cameraDTO.getAccount() + ":" + cameraDTO.getPassword() + "@" + cameraDTO.getIp() + ":554/Streaming/tracks/" + channelNumberStr + "?starttime=" + startTime;
  210. }
  211. String rtmpName = rtmpServer + "/live/"; //rtmp服务器推流入口
  212. String tasker= ffmpegService.startTranscoding(appName,rtspName,rtmpName);
  213. if (StringUtils.isNotEmpty(tasker)) {
  214. resultDTO.setTasker(tasker);
  215. resultDTO.setMsg(HikCameraUtils.resultNames[0]);
  216. resultDTO.setRtmpUrl(rtmpUrl);
  217. resultDTO.setFlvUrl(flvUrl);
  218. //添加流记录
  219. cameraFlow = new CameraFlow();
  220. cameraFlow.setCameraId(cameraDTO.getCameraId());
  221. if (cameraDTO.getType() == 0) {
  222. cameraFlow.setCameraIpc(cameraDTO.getIp());
  223. } else {
  224. cameraFlow.setCameraIpc(cameraDTO.getIpcAddress());
  225. }
  226. cameraFlow.setTasker(tasker);
  227. cameraFlow.setFlowType(FlowUtils.FlowType.HIK.ordinal());
  228. cameraFlow.setRtsp("rtsp://" + rtspName);
  229. cameraFlow.setRtmp(rtmpUrl);
  230. cameraFlow.setFlv(flvUrl);
  231. cameraFlow.setClient(1);
  232. cameraFlow.setCreateTime(new Date());
  233. cameraFlow.setUpdateTime(new Date());
  234. flowService.save(cameraFlow);
  235. } else {
  236. resultDTO.setMsg("推流失败");
  237. return resultDTO;
  238. }
  239. }
  240. return resultDTO;
  241. } else {
  242. resultDTO.setMsg("未找到设备");
  243. return resultDTO;
  244. }
  245. }
  246. /**
  247. * 抓图
  248. * @param cameraDTO 相机信息
  249. */
  250. public ResultDTO catchPic(CameraDTO cameraDTO) {
  251. ResultDTO resultDTO = new ResultDTO();
  252. if (cameraDTO != null) {
  253. String pathName;
  254. int channelNumber;
  255. if (cameraDTO.getType() == 0) {
  256. //摄像机
  257. pathName = cameraDTO.getIp().replace(".", "");
  258. channelNumber = HikCameraUtils.analyzeChannel(cameraDTO.getChannelList().get(0));
  259. } else {
  260. //NVR
  261. resultDTO.setMsg("NVR设备不支持抓图");
  262. return resultDTO;
  263. }
  264. HCNetTools hcTool = cameraDTO.getHcTool();
  265. DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
  266. String name = dtf.format(LocalDateTime.now()) + ".jpg";
  267. String path = "/picture/" + pathName + "/";
  268. String filePath = rootPath + path + name;
  269. cameraFileService.pathCreator(rootPath + path);
  270. boolean success = hcTool.getDVRPic(channelNumber,filePath);
  271. if (success) {
  272. long size = new File(filePath).length();
  273. CameraFile cameraFile = cameraFileService.saveFileInfo(name,path,size);
  274. resultDTO.setMsg(cameraFile.getId().toString());
  275. }
  276. return resultDTO;
  277. } else {
  278. resultDTO.setMsg("未找到设备");
  279. return resultDTO;
  280. }
  281. }
  282. /**
  283. * 视频回放下载
  284. * @param cameraDTO
  285. */
  286. public ResultDTO downloadBack(CameraDTO cameraDTO) {
  287. ResultDTO resultDTO = new ResultDTO();
  288. if (cameraDTO != null) {
  289. String pathName;
  290. int channelNumber;
  291. if (cameraDTO.getType() == 0) {
  292. //摄像机
  293. pathName = cameraDTO.getIp().replace(".", "");
  294. channelNumber = HikCameraUtils.analyzeChannel(cameraDTO.getChannelList().get(0));
  295. } else {
  296. //NVR
  297. pathName = cameraDTO.getIpcAddress().replace(".", "");
  298. channelNumber = HikCameraUtils.getIpcChannel(cameraDTO.getChannelList(), cameraDTO.getIpcAddress());
  299. channelNumber = channelNumber + 32; //远程下载的通道号从32开始
  300. }
  301. DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
  302. String name = dtf.format(cameraDTO.getHistoryDTO().getStartTime()) + "TO" + dtf.format(cameraDTO.getHistoryDTO().getEndTime()) + ".mp4";
  303. String path = "/video/" + pathName + "/";
  304. cameraFileService.pathCreator(rootPath + path);
  305. Integer fileId = cameraFileService.findByPathAndName(path,name);
  306. if (fileId > 0) {
  307. resultDTO.setMsg(fileId.toString());
  308. return resultDTO;
  309. }
  310. hikCameraManager.downloadVideoAsync(cameraDTO,path,name,channelNumber);
  311. resultDTO.setMsg("Async");
  312. return resultDTO;
  313. } else {
  314. resultDTO.setMsg("未找到设备");
  315. return resultDTO;
  316. }
  317. }
  318. /**
  319. * 获取视频列表
  320. * @param cameraDTO
  321. * @return
  322. */
  323. public ResultDTO getVideoFileList(CameraDTO cameraDTO) {
  324. ResultDTO resultDTO = new ResultDTO();
  325. if (cameraDTO != null) {
  326. int channelNumber;
  327. if (cameraDTO.getType() == 0) {
  328. //摄像机
  329. channelNumber = HikCameraUtils.analyzeChannel(cameraDTO.getChannelList().get(0));
  330. } else {
  331. //NVR
  332. channelNumber = HikCameraUtils.getIpcChannel(cameraDTO.getChannelList(), cameraDTO.getIpcAddress());
  333. channelNumber = channelNumber + 32; //远程录像的通道号从33开始
  334. }
  335. HCNetTools hcTool = cameraDTO.getHcTool();
  336. List<HashMap<String, String>> map = hcTool.getVideoFileList(cameraDTO.getHistoryDTO().getStartTime(),cameraDTO.getHistoryDTO().getEndTime(),channelNumber);
  337. resultDTO.setMsg(map);
  338. return resultDTO;
  339. } else {
  340. resultDTO.setMsg("未找到设备");
  341. return resultDTO;
  342. }
  343. }
  344. /**
  345. * 云台控制
  346. * @param cameraDTO 相机信息
  347. */
  348. public ResultDTO playControl(CameraDTO cameraDTO) {
  349. ResultDTO resultDTO = new ResultDTO();
  350. if (cameraDTO != null) {
  351. int channelNumber;
  352. if (cameraDTO.getType() == 0) {
  353. //摄像机
  354. channelNumber = HikCameraUtils.analyzeChannel(cameraDTO.getChannelList().get(0));
  355. } else {
  356. //NVR
  357. resultDTO.setMsg("NVR设备不支持云台控制");
  358. return resultDTO;
  359. }
  360. hikCameraManager.playControlAsync(cameraDTO,channelNumber);
  361. resultDTO.setMsg("Async");
  362. return resultDTO;
  363. } else {
  364. resultDTO.setMsg("未找到设备");
  365. return resultDTO;
  366. }
  367. }
  368. /**
  369. * 停止推流
  370. * @param id 相机id
  371. */
  372. public Boolean stopRtmp(Integer id) {
  373. if (id == null) {
  374. return true;
  375. }
  376. Camera camera = deviceService.getById(id);
  377. if (camera != null) {
  378. String appName = camera.getAccount() + camera.getIp().replace(".","");
  379. return ffmpegService.stopTranscoding(appName);
  380. } else {
  381. return true;
  382. }
  383. }
  384. }