CameraUtil.java 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  1. package com.ozs.utils;
  2. import com.alibaba.fastjson2.JSON;
  3. import com.alibaba.fastjson2.JSONArray;
  4. import com.alibaba.fastjson2.JSONObject;
  5. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  6. import com.hikvision.artemis.sdk.ArtemisHttpUtil;
  7. import com.hikvision.artemis.sdk.config.ArtemisConfig;
  8. import com.ozs.common.config.BaseConfig;
  9. import com.ozs.common.constant.Constants;
  10. import com.ozs.common.core.domain.AjaxResult;
  11. import com.ozs.common.core.domain.entity.SysDictData;
  12. import com.ozs.common.core.redis.RedisCache;
  13. import com.ozs.common.exception.base.BaseException;
  14. import com.ozs.common.utils.DateUtils;
  15. import com.ozs.common.utils.HttpClientUtil;
  16. import com.ozs.common.utils.http.HttpUtils;
  17. import com.ozs.entity.BaseTerminal;
  18. import com.ozs.entity.MsgHeartbeatAlarmMessage;
  19. import com.ozs.entity.vo.CamerasVo;
  20. import com.ozs.entity.vo.PlaybackVo;
  21. import com.ozs.framework.config.ServerConfig;
  22. import com.ozs.service.BaseTerminalService;
  23. import com.ozs.service.MsgHeartbeatAlarmMessageService;
  24. import com.ozs.system.mapper.SysDictDataMapper;
  25. import com.ozs.system.service.ISysDictTypeService;
  26. import lombok.SneakyThrows;
  27. import lombok.extern.slf4j.Slf4j;
  28. import org.apache.commons.lang3.StringUtils;
  29. import org.springframework.beans.factory.annotation.Autowired;
  30. import org.springframework.context.annotation.Configuration;
  31. import org.springframework.util.ObjectUtils;
  32. import javax.annotation.PostConstruct;
  33. import java.io.BufferedReader;
  34. import java.io.BufferedWriter;
  35. import java.io.File;
  36. import java.io.FileFilter;
  37. import java.io.IOException;
  38. import java.io.InputStreamReader;
  39. import java.io.OutputStreamWriter;
  40. import java.io.PrintWriter;
  41. import java.text.ParseException;
  42. import java.text.SimpleDateFormat;
  43. import java.time.Instant;
  44. import java.time.LocalDateTime;
  45. import java.time.OffsetDateTime;
  46. import java.time.ZoneOffset;
  47. import java.time.format.DateTimeFormatter;
  48. import java.util.ArrayList;
  49. import java.util.Calendar;
  50. import java.util.Date;
  51. import java.util.GregorianCalendar;
  52. import java.util.HashMap;
  53. import java.util.List;
  54. import java.util.Map;
  55. import java.util.Random;
  56. import java.util.Set;
  57. import java.util.UUID;
  58. import java.util.concurrent.Callable;
  59. import java.util.concurrent.CompletableFuture;
  60. import java.util.concurrent.ExecutionException;
  61. import java.util.concurrent.ExecutorService;
  62. import java.util.concurrent.Executors;
  63. import java.util.concurrent.TimeUnit;
  64. import java.util.concurrent.TimeoutException;
  65. import java.util.stream.Collectors;
  66. /**
  67. * 相机工具
  68. */
  69. @Configuration
  70. @Slf4j
  71. public class CameraUtil {
  72. private static final ExecutorService executor = Executors.newFixedThreadPool(20);
  73. private static String historyUrl;
  74. private static String ffmpegPath;
  75. private static String filePath;
  76. private static String transcribeFilePath;
  77. private static String webUrl;
  78. private static String bakUrl;
  79. private static String bakUrlRtsp;
  80. private static String wsUrl;
  81. private static String httpUrl;
  82. private static CmdCameraUtil cUtil;
  83. private static RedisCache rc;
  84. private static ServerConfig sc;
  85. private static String recordUrl;
  86. private static String hkUrl;
  87. private static String host;
  88. private static String appKey;
  89. private static String appSecret;
  90. private static String rtmpUrl;
  91. @Autowired
  92. private CaneraConfig caneraConfig;
  93. @Autowired
  94. private CmdCameraUtil cmdCameraUtil;
  95. @Autowired
  96. private SysDictDataMapper dictDataMapper;
  97. @Autowired
  98. private RedisCache redisCache;
  99. @Autowired
  100. private ServerConfig serverConfig;
  101. @Autowired
  102. private BaseTerminalService baseTerminalService;
  103. @Autowired
  104. private MsgHeartbeatAlarmMessageService msgHeartbeatAlarmMessageService;
  105. @Autowired
  106. private ISysDictTypeService dictTypeService;
  107. @Autowired
  108. private RtspToMP4 rtspToMP4;
  109. private Map<String, Process> map = new HashMap<>();
  110. public final static String tsFilekey = "mergeVideoTsFile";
  111. /**
  112. * 历史回放
  113. *
  114. * @param fromVideoFileList
  115. * @param ph
  116. * @return
  117. * @throws IOException
  118. */
  119. public static String historyPlay(List<String> fromVideoFileList, String ph, boolean flay) {
  120. // 视频服务映射路径
  121. String NewfilePath = BaseConfig.getProfile() + "/" + ph;
  122. log.info("NewfilePath:{}", NewfilePath);
  123. log.info("fromVideoFileList:{}", fromVideoFileList);
  124. if (ObjectUtils.isEmpty(fromVideoFileList) || fromVideoFileList.size() <= 0) {
  125. throw new BaseException("当前相机无视频录像");
  126. }
  127. executor.submit(new Runnable() {
  128. @Override
  129. public void run() {
  130. try {
  131. txConvetor(fromVideoFileList, NewfilePath, flay);
  132. } catch (IOException e) {
  133. log.error(e.getMessage());
  134. e.printStackTrace();
  135. }
  136. }
  137. });
  138. // executor.shutdown();
  139. return Constants.RESOURCE_PREFIX + "/" + ph;
  140. }
  141. @SneakyThrows
  142. public static void txConvetor(List<String> fromVideoFileList,
  143. String newfilePath,
  144. boolean fly) throws IOException {
  145. /*
  146. * ffmpeg -i 20230411_155847_155947-d4c2265d-d83e-11ed-8e7f-fa163e4e1e9f.flv -c:v copy 1.ts
  147. ffmpeg -i 20230411_155948_160048-f91fea03-d83e-11ed-8e7f-fa163e4e1e9f.flv -c:v copy 2.ts
  148. ffmpeg -i "concat:1.ts|2.ts" -c copy output.mp4
  149. * */
  150. File file = new File(newfilePath);
  151. boolean flay = false;
  152. if (!file.getParentFile().exists()) {
  153. boolean mkdirs = file.getParentFile().mkdirs();
  154. log.info("创建文件夹:{}", file.getParentFile().getPath());
  155. log.info("创建文件夹结果:{}", mkdirs);
  156. flay = true;
  157. }
  158. cUtil.cmd("chomd -R 777 " + file.getParentFile().getPath());
  159. log.info("newfilePath:{}", newfilePath);
  160. StringBuffer sm = new StringBuffer(ffmpegPath + " -i \"concat:");
  161. List<String> fileTs = new ArrayList<>();
  162. for (int t = 0; t < fromVideoFileList.size(); t++) {
  163. File ft = new File(fromVideoFileList.get(t));
  164. if (ft.exists()) {
  165. log.info("file:{}", fromVideoFileList.get(t));
  166. String substring = fromVideoFileList.get(t).substring(0, fromVideoFileList.get(t).lastIndexOf("."));
  167. int x;//定义两变量
  168. Random ne = new Random();//实例化一个random的对象ne
  169. x = ne.nextInt(9999 - 1000 + 1) + 1000;//为变量赋随机值1000-9999
  170. substring = substring + x;//定义两变量
  171. String cmdstr = ffmpegPath + " -i " + fromVideoFileList.get(t) + " -c:v copy " + substring + ".ts";
  172. log.info("转换命令:{}", cmdstr);
  173. cUtil.cmd(cmdstr);
  174. fileTs.add(substring + ".ts");
  175. if (t != fromVideoFileList.size() - 1) {
  176. sm.append(substring + ".ts|");
  177. } else {
  178. sm.append(substring + ".ts\" ");
  179. }
  180. }
  181. }
  182. if (fileTs.size() > 0) {
  183. Map<String, Object> mergeVideoTsFile = rc.getCacheMap(tsFilekey);
  184. if (ObjectUtils.isEmpty(mergeVideoTsFile)) {
  185. mergeVideoTsFile = new HashMap<>();
  186. }
  187. if (!flay) {
  188. // 如果没有解除,把生成的文件放入要删除的定时任务 redis key 中
  189. fileTs.add(newfilePath);
  190. }
  191. mergeVideoTsFile.put(System.currentTimeMillis() + "", fileTs);
  192. rc.deleteObject(tsFilekey);
  193. if (mergeVideoTsFile.size() > 0) {
  194. rc.setCacheMap(tsFilekey, mergeVideoTsFile);
  195. }
  196. sm.append("-c copy " + newfilePath);
  197. log.info("合并命令:{}", sm.toString());
  198. cUtil.cmd(sm.toString());
  199. }
  200. }
  201. /**
  202. * 实时播放的拼接流
  203. *
  204. * @param cameraCode 相机编码
  205. * @param channel 相机通道
  206. * @return
  207. */
  208. public static String getPlayFlv(String cameraCode, String channel, boolean flay) {
  209. if (!flay) {
  210. return bakUrl + "/hdl/" + cameraCode + "/" + channel + ".flv";
  211. }
  212. return wsUrl + "/ws/" + cameraCode + "/" + channel + ".flv";
  213. // if (!flay) {
  214. // return bakUrl + "/ws/" + channel + "/" + cameraCode + ".flv";
  215. // }
  216. // return webUrl + "/ws/" + channel + "/" + cameraCode + ".flv";
  217. }
  218. /**
  219. * Rtsp实时播放的拼接流
  220. *
  221. * @param cameraCode 相机编码
  222. * @param channel 相机通道
  223. * @return
  224. */
  225. public static String getPlayFlvRtsp(String cameraCode, String channel, boolean flay) {
  226. if (!flay) {
  227. return bakUrlRtsp + "/" + channel + "/" + cameraCode;
  228. }
  229. return bakUrlRtsp + "/" + channel + "/" + cameraCode;
  230. // if (!flay) {
  231. // return bakUrl + "/ws/" + channel + "/" + cameraCode + ".flv";
  232. // }
  233. // return webUrl + "/ws/" + channel + "/" + cameraCode + ".flv";
  234. }
  235. public String heartbeatgetPlayFlv(String cameraCode, String channel) {
  236. List<String> pathList = new ArrayList<>();
  237. String data = HttpUtils.sendGet(webUrl + "/rtsp/api/list");
  238. log.info("data------------------>"+data);
  239. if (StringUtils.isNotEmpty(data)) {
  240. JSONArray jsonArray = JSONArray.parseArray(data);
  241. log.info("jsonArray------------------>"+jsonArray);
  242. if (!ObjectUtils.isEmpty(jsonArray)) {
  243. for (int i = 0; i < jsonArray.size(); i++) {
  244. JSONObject jsonObject = jsonArray.getJSONObject(i);
  245. String name = jsonObject.getString("Path");
  246. pathList.add(name);
  247. }
  248. boolean contains = pathList.contains(cameraCode + "/" + channel);
  249. if (!contains) {
  250. return null;
  251. } else {
  252. return getPlayFlvRtsp(cameraCode, channel, true);
  253. }
  254. }
  255. return null;
  256. }
  257. return null;
  258. }
  259. public String heartbeatgetUrl(String cameraCode, String channel) {
  260. CompletableFuture.runAsync(() -> {
  261. CamerasVo camerasVo = new CamerasVo();
  262. camerasVo.setCameraIndexCode(cameraCode);
  263. previewURLs(camerasVo, channel);
  264. });
  265. return getPlayFlvRtsp(cameraCode, channel, true);
  266. }
  267. /**
  268. * web页面实时流接口
  269. *
  270. * @param cameraCode
  271. * @param channel
  272. * @return
  273. */
  274. public static String getPlayFlv(String cameraCode, String channel) {
  275. List<String> pathList = new ArrayList<>();
  276. String data = HttpUtils.sendGet(webUrl + "/rtsp/api/list");
  277. if (StringUtils.isNotEmpty(data)) {
  278. JSONArray jsonArray = JSONArray.parseArray(data);
  279. for (int i = 0; i < jsonArray.size(); i++) {
  280. JSONObject jsonObject = jsonArray.getJSONObject(i);
  281. String name = jsonObject.getString("Path");
  282. pathList.add(name);
  283. }
  284. boolean contains = pathList.contains(cameraCode + "/" + channel);
  285. if (contains) {
  286. return getPlayFlv(cameraCode, channel, true);
  287. } else {
  288. /**
  289. * jsonBody.put("cameraIndexCode", "01ea43e6676f4e47bd6c5cd9e02aa006");
  290. * jsonBody.put("streamType", 0);
  291. * jsonBody.put("protocol","rtsp");
  292. * jsonBody.put("transmode", 1);
  293. * jsonBody.put("expand","streamform=rtp");
  294. */
  295. CamerasVo camerasVo = new CamerasVo();
  296. camerasVo.setCameraIndexCode(cameraCode);
  297. previewURLs(camerasVo, channel);
  298. return getPlayFlv(cameraCode, channel, true);
  299. }
  300. } else {
  301. CamerasVo camerasVo = new CamerasVo();
  302. camerasVo.setCameraIndexCode(cameraCode);
  303. previewURLs(camerasVo, channel);
  304. return getPlayFlv(cameraCode, channel, true);
  305. }
  306. // return getPlayFlv(cameraCode, channel, true);
  307. }
  308. public static String invite(String cameraCode, String channel) {
  309. String result = null;
  310. String url = bakUrl + "/api/gb28181/invite?id=" + cameraCode + "&channel=" + channel;
  311. try {
  312. result = HttpClientUtil.get(url);
  313. log.info("result:{}", result);
  314. } catch (Exception e) {
  315. log.info(e.getMessage());
  316. e.printStackTrace();
  317. }
  318. return result;
  319. }
  320. /**
  321. * 开启录制功能
  322. *
  323. * @param cameraCode 相机编码
  324. * @param channel 相机通道
  325. * @return
  326. */
  327. public static String startRecording(String cameraCode, String channel) {
  328. return historyUrl + "/recordpro/api/start?streamPath=" + channel + "/" + cameraCode;
  329. }
  330. /**
  331. * 关闭录制功能
  332. *
  333. * @param taskId 录像接口返回的任务ID
  334. * @return
  335. */
  336. public static String endRecording(String taskId) {
  337. return historyUrl + "/recordpro/api/stop?id=" + taskId;
  338. }
  339. /**
  340. * 历史回放流(获取)
  341. *
  342. * @param channel 相机通道
  343. * @param startTm 开始时间
  344. * @param endTm 结束时间
  345. * @return
  346. */
  347. public static String historyPlayListStr(String channel, Date startTm, Date endTm, boolean flay) {
  348. List<String> list = filterPlayList(channel, startTm, endTm, filePath);
  349. String uuid = UUID.randomUUID().toString();
  350. String ph = "record/flv/" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, new Date())
  351. + "/" + channel + "/"
  352. + uuid + ".mp4";
  353. if (!ObjectUtils.isEmpty(list)) {
  354. try {
  355. return historyPlay(list, ph, flay);
  356. } catch (Exception e) {
  357. log.error(e.getMessage());
  358. e.printStackTrace();
  359. }
  360. } else {
  361. throw new BaseException("当前相机无视频录像");
  362. }
  363. return null;
  364. }
  365. /**
  366. * 过滤符合条件的视频
  367. *
  368. * @param channel
  369. * @param startTm
  370. * @param endTm
  371. * @param mappingUrl
  372. * @return
  373. */
  374. public static List<String> filterPlayList(String channel, Date startTm, Date endTm, String mappingUrl) {
  375. if (StringUtils.isBlank(channel)
  376. || ObjectUtils.isEmpty(startTm)
  377. || ObjectUtils.isEmpty(endTm)) {
  378. return null;
  379. }
  380. List<String> ls = new ArrayList<>();
  381. Map<Date, String> m = new HashMap<>();
  382. // 调用视频服务返回参数
  383. String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, startTm);
  384. String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, endTm);
  385. String param = "channel=" + channel + "&startTime=" + startTime + "&endTime=" + endTime;
  386. String s = HttpUtils.sendGet(historyUrl + "/api/record/flv/list", param);
  387. // 视频拼接
  388. if (!StringUtils.isBlank(s) && !"null".equals(s) && !s.startsWith("<!DOCTYPE html>")) {
  389. List<Map<String, Object>> maps = JSON.parseArray(s, Map.class);
  390. if (ObjectUtils.isEmpty(maps)) {
  391. return null;
  392. }
  393. for (Map<String, Object> map : maps) {
  394. Object path = map.get("Path");
  395. if (!ObjectUtils.isEmpty(path)) {
  396. String s1 = path.toString();
  397. String substring = s1.substring(s1.lastIndexOf("/") + 1, s1.length());
  398. String substring1 = substring.substring(0, substring.indexOf("-"));
  399. String[] s2 = substring1.split("_");
  400. if (!ObjectUtils.isEmpty(s2)) {
  401. String s3 = s2[0] + s2[1];
  402. String s4 = s2[0] + s2[2];
  403. Date sdate = DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, s3);
  404. if (s2[1].startsWith("23") && s2[2].startsWith("00")) {
  405. sdate = DateUtils.addDays(sdate, -1);
  406. }
  407. Date edate = DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, s4);
  408. /* sdate |startTm| edate |endTm| */
  409. if (startTm.compareTo(sdate) >= 0
  410. && startTm.compareTo(edate) <= 0
  411. && endTm.compareTo(edate) >= 0) {
  412. m.put(sdate, mappingUrl + path.toString());
  413. /* |startTm| sdate edate |endTm| */
  414. } else if (startTm.compareTo(sdate) <= 0 && endTm.compareTo(edate) >= 0) {
  415. m.put(sdate, mappingUrl + path.toString());
  416. /* |startTm| sdate |endTm| edate */
  417. } else if (startTm.compareTo(sdate) <= 0
  418. && endTm.compareTo(sdate) >= 0
  419. && endTm.compareTo(edate) <= 0) {
  420. m.put(sdate, mappingUrl + path.toString());
  421. /* sdate |startTm| |endTm| edate */
  422. } else if (startTm.compareTo(sdate) >= 0 && endTm.compareTo(edate) <= 0) {
  423. m.put(sdate, mappingUrl + path.toString());
  424. }
  425. }
  426. }
  427. }
  428. }
  429. if (!ObjectUtils.isEmpty(m) && m.size() > 0) {
  430. Set<Date> dates = m.keySet();
  431. // 排序
  432. dates.stream().parallel().collect(Collectors.toList()).stream().sorted().forEach(d -> {
  433. ls.add(m.get(d));
  434. });
  435. return ls;
  436. }
  437. return null;
  438. }
  439. /**
  440. * 合并视频(转化文件)
  441. *
  442. * @param fromVideoFileList 视频路径
  443. * @param newfilePath 生产新的视频文件路径
  444. * @throws IOException
  445. */
  446. public static Map<String, String> myConvetor(List<String> fromVideoFileList,
  447. String newfilePath,
  448. String uuid) throws IOException {
  449. /*
  450. * for f in *.flv; do echo "file '$f'" >> mylist.txt; done
  451. ffmpeg -f concat -i mylist.txt -c copy output.flv
  452. * */
  453. File file = new File(newfilePath);
  454. boolean flay = false;
  455. if (!file.getParentFile().exists()) {
  456. file.getParentFile().mkdirs();
  457. log.info("创建文件夹:{}", file.getParentFile().getPath());
  458. flay = true;
  459. }
  460. log.info("newfilePath:{}", newfilePath);
  461. StringBuffer sm = new StringBuffer("for f in ");
  462. String pathStr = null;
  463. for (int t = 0; t < fromVideoFileList.size(); t++) {
  464. File ft = new File(fromVideoFileList.get(t));
  465. if (ft.exists()) {
  466. if (t != fromVideoFileList.size() - 1) {
  467. // sm.append(fromVideoFileList.get(t) + " ");
  468. sm.append(fromVideoFileList.get(t).substring(fromVideoFileList.get(t).lastIndexOf("/") + 1, fromVideoFileList.get(t).length()) + " ");
  469. } else {
  470. // sm.append(fromVideoFileList.get(t));
  471. sm.append(fromVideoFileList.get(t).substring(fromVideoFileList.get(t).lastIndexOf("/") + 1, fromVideoFileList.get(t).length()));
  472. pathStr = fromVideoFileList.get(t).substring(0, fromVideoFileList.get(t).lastIndexOf("/"));
  473. }
  474. }
  475. }
  476. // String substring = newfilePath.substring(0, newfilePath.lastIndexOf("."));
  477. // substring = substring + ".txt";
  478. String substring = uuid + ".txt";
  479. log.info("临时转化的文件:{}", substring);
  480. sm.append("; do echo \"file '$f'\" >> " + substring + "; done");
  481. String commit = sm.toString();
  482. log.info("合并转化文件的命令:{}", commit);
  483. Process proc = Runtime.getRuntime().exec("/bin/bash", null, null);
  484. BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
  485. PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
  486. try {
  487. String commit1 = ffmpegPath + " -f concat -safe 0 -i " + pathStr + "/" + substring + " -c copy " + newfilePath;
  488. log.info("合并视频命令:{}", commit1);
  489. List<String> commands = new ArrayList<>();
  490. if (flay) {
  491. commands.add("chomd -R 777 " + file.getParentFile().getPath());
  492. }
  493. //
  494. commands.add("cd " + pathStr);
  495. // 合并成一个临时文件
  496. commands.add(commit);
  497. // 临时文件转化为 flv
  498. // commands.add(commit1);
  499. log.info("录像视频命令:{}", commands);
  500. for (String line : commands) {
  501. log.info("命令:{}", line);
  502. out.println(line);
  503. }
  504. out.println("exit");// 这个命令必须执行,否则in流不结束。
  505. log.info("命令:{}", "exit");
  506. String rspLine = "";
  507. while ((rspLine = in.readLine()) != null) {
  508. log.info("*****:{}", rspLine);
  509. }
  510. proc.waitFor();
  511. Map<String, String> map = new HashMap<>();
  512. map.put("cmd", commit1);
  513. map.put("path", pathStr + "/" + substring);
  514. return map;
  515. } catch (InterruptedException e) {
  516. log.error(e.getMessage());
  517. e.printStackTrace();
  518. } finally {
  519. in.close();
  520. out.close();
  521. proc.destroy();
  522. }
  523. return null;
  524. }
  525. @PostConstruct
  526. public void init() {
  527. historyUrl = caneraConfig.getHistoryUrl();
  528. ffmpegPath = caneraConfig.getFfmpegPath();
  529. filePath = caneraConfig.getFilePath();
  530. transcribeFilePath = caneraConfig.getTranscribeFilePath();
  531. webUrl = caneraConfig.getWebUrl();
  532. bakUrl = caneraConfig.getBakUrl();
  533. bakUrlRtsp = caneraConfig.getBakUrlRtsp();
  534. rc = redisCache;
  535. cUtil = cmdCameraUtil;
  536. sc = serverConfig;
  537. wsUrl = caneraConfig.getWsUrl();
  538. httpUrl = caneraConfig.getHttpUrl();
  539. recordUrl = caneraConfig.getRecordUrl();
  540. hkUrl = caneraConfig.getHkUrl();
  541. host = caneraConfig.getHost();
  542. appKey = caneraConfig.getAppKey();
  543. appSecret = caneraConfig.getAppSecret();
  544. rtmpUrl = caneraConfig.getRtmpUrl();
  545. }
  546. /**
  547. * 定时任务参数flv文件
  548. *
  549. * @throws IOException
  550. * @throws InterruptedException
  551. */
  552. public void deleteFlv() throws IOException, InterruptedException {
  553. SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
  554. Date date = new Date();
  555. Calendar calendar = new GregorianCalendar();
  556. calendar.setTime(date);
  557. calendar.add(Calendar.DATE, -1); //把日期往后增加一天,整数 往后推,负数往前移动
  558. date = calendar.getTime(); //这个时间就是日期往后推一天的结果
  559. String path = BaseConfig.getProfile() + "/flv/" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, date);
  560. File file = new File(path);
  561. if (file.exists()) {
  562. List<String> rspList = new ArrayList<String>();
  563. Process proc = Runtime.getRuntime().exec("/bin/bash", null, null);
  564. BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
  565. PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
  566. String commit = " rm -rf " + path;
  567. List<String> commands = new ArrayList<>();
  568. // 删除
  569. commands.add(commit);
  570. log.info("删除昨天的录像视频命令:{}", commands);
  571. for (String line : commands) {
  572. out.println(line);
  573. }
  574. out.println("exit");// 这个命令必须执行,否则in流不结束。
  575. String rspLine = "";
  576. while ((rspLine = in.readLine()) != null) {
  577. System.out.println(rspLine);
  578. rspList.add(rspLine);
  579. }
  580. int i = proc.waitFor();
  581. log.info("执行结果:{}", i);
  582. in.close();
  583. out.close();
  584. proc.destroy();
  585. }
  586. }
  587. /**
  588. * 定时任务:删除超过配置时长的录制视频
  589. *
  590. * @throws IOException
  591. * @throws InterruptedException
  592. */
  593. public void deleteFlvExceed() throws IOException, InterruptedException, ParseException {
  594. //字典中设置的值
  595. List<SysDictData> sysCameraRecordTime = dictDataMapper.selectDictDataByType("sys_camera_record_time");
  596. SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
  597. Date date = new Date();
  598. Calendar calendar = new GregorianCalendar();
  599. calendar.setTime(date);
  600. //正数,日期天数加
  601. //负数,日期天数减 提前45天
  602. if (!ObjectUtils.isEmpty(sysCameraRecordTime)) {
  603. String dictValue = sysCameraRecordTime.get(0).getDictValue();
  604. calendar.add(Calendar.DAY_OF_YEAR, Integer.parseInt("-" + dictValue));
  605. } else {
  606. calendar.add(Calendar.DAY_OF_YEAR, -45);
  607. }
  608. date = calendar.getTime();
  609. //遍历每个进行视频录制的摄像头
  610. File file = new File(transcribeFilePath);
  611. log.info("file.Name()======================================" + file.getName());
  612. log.info("file.exists()======================================" + file.exists());
  613. if (file.exists() && file.isDirectory()) {
  614. //获取文件夹中所有的子文件夹和文件
  615. File[] files = file.listFiles();
  616. if (!ObjectUtils.isEmpty(files) && files.length > 0) {
  617. for (File file1 : files) {
  618. // file1=/opt/streams/record/flv/34020000001320000167
  619. log.info("file1.Name()======================================" + file1.getName());
  620. if (file1.exists() && file1.isDirectory()) {
  621. //相机文件
  622. File[] fs = file1.listFiles();
  623. if (!ObjectUtils.isEmpty(fs) && fs.length > 0) {
  624. for (File f : fs) {
  625. // f=/opt/streams/record/flv/34020000001320000167/20230328_192033_192037-91509173-cd5a-11ed-8a42-fa163e4e1e9f.flv
  626. //fName=20230328_192033_192037-91509173-cd5a-11ed-8a42-fa163e4e1e9f.flv
  627. String fName = f.getName();
  628. log.info("fName======================================" + fName);
  629. String[] split = fName.split("_");
  630. if (split.length > 0) {
  631. //20230328
  632. String s = split[0];
  633. Date parse = sdf.parse(s);
  634. long fTime = parse.getTime();
  635. long dateTime = date.getTime();
  636. //删除过期文件
  637. if (fTime < dateTime) {
  638. f.delete();
  639. }
  640. }
  641. }
  642. }
  643. }
  644. }
  645. }
  646. }
  647. }
  648. public static File[] getCurFilesList(String filePath) {
  649. File path = new File(filePath);
  650. File[] listFiles = path.listFiles(new FileFilter() {
  651. @Override
  652. public boolean accept(File pathname) {
  653. if (pathname.isFile()) {
  654. return true;
  655. } else {
  656. return false;
  657. }
  658. }
  659. });
  660. return listFiles;
  661. }
  662. public static void execute(String command) {
  663. try {
  664. ProcessBuilder process = new ProcessBuilder(command);
  665. process.inheritIO().start().waitFor();
  666. } catch (Exception e) {
  667. e.printStackTrace();
  668. }
  669. }
  670. /**
  671. * web页面视频回放接口
  672. *
  673. * @param code
  674. * @param startTm
  675. * @param endTm
  676. * @return
  677. */
  678. public static String getRecordList(String code, Date startTm, Date endTm, String channel) {
  679. PlaybackVo playbackVo = new PlaybackVo();
  680. playbackVo.setCameraIndexCode(code);
  681. // 将 Date 转换为 Instant
  682. Instant startInstant = startTm.toInstant();
  683. Instant endInstant = endTm.toInstant();
  684. // 将 Instant 转换为 OffsetDateTime
  685. OffsetDateTime startOffsetDateTime = startInstant.atOffset(ZoneOffset.UTC);
  686. OffsetDateTime endOffsetDateTime = endInstant.atOffset(ZoneOffset.UTC);
  687. // 格式化为字符串
  688. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
  689. String formattedStartTime = startOffsetDateTime.format(formatter);
  690. String formattedEndTime = endOffsetDateTime.format(formatter);
  691. // 将格式化后的时间设置到 playbackVo 中
  692. playbackVo.setBeginTime(formattedStartTime);
  693. playbackVo.setEndTime(formattedEndTime);
  694. playbackVo.setProtocol("rtsp");
  695. playbackVo.setExpand("streamform=rtp");
  696. //对象转换json字符串
  697. String body = JSONObject.toJSONString(playbackVo);
  698. //调用天网接口
  699. String playbackURLs = getPreviewURLs("/api/video/v1/cameras/playbackURLs", body);
  700. JSONObject outJson = (JSONObject) JSONObject.parse(playbackURLs);
  701. log.info("outJson-------->" + outJson);
  702. if ("0".equals(outJson.getString("code"))) {
  703. JSONObject data = outJson.getJSONObject("data");
  704. String urls = data.getString("url");
  705. log.info("urls----------->" + urls);
  706. try {
  707. TimeUnit.SECONDS.sleep(3);
  708. String msg = HttpUtils.sendGet(httpUrl + "/rtsp/api/pull?target=" + urls + "&streamPath=" + code + "/" + channel + "&save=0");
  709. log.info("msg---------->" + msg);
  710. } catch (InterruptedException e) {
  711. e.printStackTrace();
  712. }
  713. return getPlayFlv(code, channel, true);
  714. } else {
  715. return "调用天网接口失败";
  716. }
  717. // return filterRecordList(channel, startTm, endTm, filePath, recordUrl + "profile/");
  718. }
  719. /**
  720. * HTTP流转RTSP流
  721. */
  722. public String streamConversion(String code) {
  723. ExecutorService executor = Executors.newSingleThreadExecutor();
  724. Callable<String> task = new Callable<String>() {
  725. @Override
  726. public String call() throws Exception {
  727. // 执行网络请求...
  728. log.info(ffmpegPath + " -re -i /opt/streams/compress/70b0bd685b0d4df1b4faf74ff5c1e7fd.mp4 -c:v copy -c:a copy -f flv rtmp://10.48.36.47:1935/live/70b0bd685b0d4df1b4faf74ff5c1e7fd");
  729. cmdCameraUtil.cmd(ffmpegPath + " -re -i /opt/streams/compress/" + code + ".mp4 -c:v copy -c:a copy -f flv " + rtmpUrl + "/live/" + code);
  730. return "Response";
  731. }
  732. };
  733. try {
  734. String result = executor.submit(task).get(1, TimeUnit.SECONDS); // 设置5秒超时时间
  735. System.out.println("Response: " + result);
  736. } catch (InterruptedException | ExecutionException | TimeoutException e) {
  737. // 请求超时处理逻辑
  738. System.out.println("Request timeout");
  739. }
  740. executor.shutdown();
  741. return bakUrlRtsp + "/live/" + code;
  742. }
  743. /**
  744. * RTSP流视频压缩
  745. */
  746. public void videoCompression(String code) {
  747. // 执行网络请求...
  748. /**
  749. * /usr/bin/ffmpeg -i /opt/streams/map/70b0bd685b0d4df1b4faf74ff5c1e7fd.mp4 -c:v libx264 -s 640x480 -c:a aac -ar 44100 /opt/streams/compress/70b0bd685b0d4df1b4faf74ff5c1e7fd.mp4
  750. */
  751. log.info(ffmpegPath + " -i /opt/streams/map/" + code + ".mp4 -c:v libx264 -s 640x480 -c:a aac -ar 44100 /opt/streams/compress/" + code + ".mp4");
  752. cmdCameraUtil.cmd(ffmpegPath + " -i /opt/streams/map/" + code + ".mp4 -c:v libx264 -s 640x480 -c:a aac -ar 44100 /opt/streams/compress/" + code + ".mp4");
  753. }
  754. public static List<Map<String, Object>> filterRecordList(String channel,
  755. Date startTm,
  756. Date endTm,
  757. String mappingUrl,
  758. String wUrl) {
  759. List<Map<String, Object>> rmaps = new ArrayList<>();
  760. if (StringUtils.isBlank(channel)
  761. || ObjectUtils.isEmpty(startTm)
  762. || ObjectUtils.isEmpty(endTm)) {
  763. return null;
  764. }
  765. Map<Date, Map<String, Object>> m = new HashMap<>();
  766. // 调用视频服务返回参数
  767. String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, startTm);
  768. String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, endTm);
  769. String param = "channel=" + channel + "&startTime=" + startTime + "&endTime=" + endTime;
  770. // /api/record/flv/list
  771. String s = HttpUtils.sendGet(webUrl + "/recordpro/api/list", param);
  772. // 视频拼接
  773. if (!StringUtils.isBlank(s) || "null".equals(s)) {
  774. List<Map<String, Object>> maps = JSON.parseArray(s, Map.class);
  775. if (ObjectUtils.isEmpty(maps)) {
  776. return null;
  777. }
  778. for (Map<String, Object> map : maps) {
  779. Object path = map.get("Path");
  780. Object size = map.get("Size");
  781. Object duration = map.get("Duration");
  782. if (!ObjectUtils.isEmpty(path)) {
  783. String s1 = path.toString();
  784. String substring = s1.substring(s1.lastIndexOf("/") + 1, s1.length());
  785. String substring1 = substring.substring(0, substring.indexOf("-"));
  786. String[] s2 = substring1.split("_");
  787. if (!ObjectUtils.isEmpty(s2)) {
  788. Map<String, Object> mo = new HashMap<>();
  789. String s3 = s2[0] + s2[1];
  790. String s4 = s2[0] + s2[2];
  791. Date sdate = DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, s3);
  792. if (s2[1].startsWith("23") && s2[2].startsWith("00")) {
  793. sdate = DateUtils.addDays(sdate, -1);
  794. }
  795. Date edate = DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, s4);
  796. mo.put("startTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, sdate));
  797. mo.put("entTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, edate));
  798. mo.put("url", wUrl + path.toString());
  799. mo.put("path", mappingUrl + path.toString());
  800. mo.put("fileName", substring);
  801. mo.put("size", size);
  802. mo.put("duration", duration);
  803. /* sdate |startTm| edate |endTm| */
  804. if (startTm.compareTo(sdate) >= 0
  805. && startTm.compareTo(edate) <= 0
  806. && endTm.compareTo(edate) >= 0) {
  807. m.put(sdate, mo);
  808. /* |startTm| sdate edate |endTm| */
  809. } else if (startTm.compareTo(sdate) <= 0 && endTm.compareTo(edate) >= 0) {
  810. m.put(sdate, mo);
  811. /* |startTm| sdate |endTm| edate */
  812. } else if (startTm.compareTo(sdate) <= 0
  813. && endTm.compareTo(sdate) >= 0
  814. && endTm.compareTo(edate) <= 0) {
  815. m.put(sdate, mo);
  816. /* sdate |startTm| |endTm| edate */
  817. } else if (startTm.compareTo(sdate) >= 0 && endTm.compareTo(edate) <= 0) {
  818. m.put(sdate, mo);
  819. }
  820. }
  821. }
  822. }
  823. }
  824. if (!ObjectUtils.isEmpty(m) && m.size() > 0) {
  825. Set<Date> dates = m.keySet();
  826. // 排序
  827. dates.stream().parallel().collect(Collectors.toList()).stream().sorted().forEach(d -> {
  828. rmaps.add(m.get(d));
  829. });
  830. log.info("rmaps:{}", rmaps);
  831. return rmaps;
  832. }
  833. return null;
  834. }
  835. /**
  836. * 机车状态修改
  837. */
  838. public void heartbeat() {
  839. List<BaseTerminal> list = baseTerminalService.list();
  840. for (BaseTerminal baseTerminal : list) {
  841. QueryWrapper<MsgHeartbeatAlarmMessage> wrapper = new QueryWrapper<>();
  842. wrapper.eq("terminal_code", wrapper);
  843. wrapper.orderByDesc("create_time");
  844. wrapper.last("limit 1");
  845. MsgHeartbeatAlarmMessage msgHeartbeatAlarmMessage = msgHeartbeatAlarmMessageService.getOne(wrapper);
  846. if (ObjectUtils.isEmpty(msgHeartbeatAlarmMessage)) {
  847. baseTerminal.setStatus(2);
  848. baseTerminalService.updateById(baseTerminal);
  849. } else {
  850. List<SysDictData> heartbeat = dictTypeService.selectDictDataByType("heartbeat");
  851. long timeNow = System.currentTimeMillis();
  852. long createTime = msgHeartbeatAlarmMessage.getCreateTime().getTime();
  853. int times = Integer.parseInt(heartbeat.get(0).getDictValue());
  854. long thereHourMillis = 60 * 1000 * 3 * times;
  855. long timeNew = timeNow - thereHourMillis;
  856. if (timeNew > createTime) {
  857. baseTerminal.setStatus(2);
  858. baseTerminalService.updateById(baseTerminal);
  859. } else {
  860. baseTerminal.setStatus(1);
  861. baseTerminalService.updateById(baseTerminal);
  862. }
  863. }
  864. }
  865. }
  866. /**
  867. * 天网接口
  868. *
  869. * @return
  870. */
  871. public static String getPreviewURLs(String url, String body) {
  872. /**
  873. * STEP1:设置平台参数,根据实际情况,设置host appkey appsecret 三个参数.
  874. */
  875. ArtemisConfig.host = host; // 平台的ip端口
  876. ArtemisConfig.appKey = appKey; // 密钥appkey
  877. ArtemisConfig.appSecret = appSecret;// 密钥appSecret
  878. /**
  879. * STEP2:设置OpenAPI接口的上下文
  880. */
  881. final String ARTEMIS_PATH = "/artemis";
  882. /**
  883. * STEP3:设置接口的URI地址
  884. */
  885. final String previewURLsApi = ARTEMIS_PATH + url;
  886. Map<String, String> path = new HashMap<String, String>(2) {
  887. {
  888. put("https://", previewURLsApi);//根据现场环境部署确认是http还是https
  889. }
  890. };
  891. /**
  892. * STEP4:设置参数提交方式
  893. */
  894. String contentType = "application/json";
  895. /**
  896. * STEP6:调用接口
  897. */
  898. String result = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, contentType, null);// post请求application/json类型参数
  899. log.info("GetCameraPreviewURL----->" + result);
  900. return result;
  901. }
  902. /**
  903. * 车载终端实时流调用的远程天网接口
  904. *
  905. * @param camerasVo
  906. * @param channel
  907. */
  908. public String apiPreviewURLs(CamerasVo camerasVo) {
  909. /**
  910. * jsonBody.put("cameraIndexCode", "01ea43e6676f4e47bd6c5cd9e02aa006");
  911. * jsonBody.put("streamType", 0);
  912. * jsonBody.put("protocol","rtsp");
  913. * jsonBody.put("transmode", 1);
  914. * jsonBody.put("expand","streamform=rtp");
  915. */
  916. camerasVo.setProtocol("rtsp");
  917. camerasVo.setTransmode(1);
  918. camerasVo.setExpand("streamform=rtp");
  919. String body = JSONObject.toJSONString(camerasVo);
  920. String previewURLs = getPreviewURLs("/api/video/v1/cameras/previewURLs", body);
  921. log.info("-------------------------------->>>>>previewURLs" + previewURLs);
  922. JSONObject outJson = JSONObject.parse(previewURLs);
  923. if ("0".equals(outJson.getString("code"))) {
  924. log.info("outJson----->" + outJson);
  925. JSONObject data = outJson.getJSONObject("data");
  926. String urls = data.getString("url");
  927. return urls;
  928. } else {
  929. return "1";
  930. }
  931. }
  932. /**
  933. * web页面实时流调用的远程天网接口
  934. *
  935. * @param camerasVo
  936. * @param channel
  937. */
  938. public static void previewURLs(CamerasVo camerasVo, String channel) {
  939. /**
  940. * jsonBody.put("cameraIndexCode", "01ea43e6676f4e47bd6c5cd9e02aa006");
  941. * jsonBody.put("streamType", 0);
  942. * jsonBody.put("protocol","rtsp");
  943. * jsonBody.put("transmode", 1);
  944. * jsonBody.put("expand","streamform=rtp");
  945. */
  946. camerasVo.setStreamType(0);
  947. camerasVo.setProtocol("rtsp");
  948. camerasVo.setTransmode(1);
  949. camerasVo.setExpand("streamform=rtp");
  950. String body = JSONObject.toJSONString(camerasVo);
  951. String previewURLs = getPreviewURLs("/api/video/v1/cameras/previewURLs", body);
  952. log.info("-------------------------------->>>>>previewURLs" + previewURLs);
  953. JSONObject outJson = JSONObject.parse(previewURLs);
  954. if ("0".equals(outJson.getString("code"))) {
  955. log.info("outJson----->" + outJson);
  956. JSONObject data = outJson.getJSONObject("data");
  957. String urls = data.getString("url");
  958. log.info("urls----->" + urls);
  959. try {
  960. TimeUnit.SECONDS.sleep(3);
  961. String msg = HttpUtils.sendGet(httpUrl + "/rtsp/api/pull?target=" + urls + "&streamPath=" + camerasVo.getCameraIndexCode() + "/" + channel + "&save=0");
  962. log.info("msg---------->" + msg);
  963. } catch (InterruptedException e) {
  964. e.printStackTrace();
  965. }
  966. } else {
  967. log.info("流媒体获取流失败----->");
  968. }
  969. }
  970. /**
  971. * 报警回放本地测试
  972. * 从天网拉回放流,然后根据url把流下载下来变成文件,然后进行视频压缩
  973. *
  974. * @param list
  975. * @param alarmPlayTimeValue
  976. */
  977. public void playbackURLs(List<String> list, String alarmPlayTimeValue) {
  978. log.info("--------------->playbackURLs");
  979. log.info("alarmPlayTimeValue------------->"+alarmPlayTimeValue);
  980. for (String code : list) {
  981. PlaybackVo playbackVo = new PlaybackVo();
  982. playbackVo.setCameraIndexCode(code);
  983. // 获取当前时间
  984. OffsetDateTime currentTime = OffsetDateTime.now();
  985. log.info("currentTime------------->"+currentTime);
  986. // 获取当前时间的前10分钟时间
  987. OffsetDateTime beforeTenMinutes = currentTime.minusMinutes(Long.parseLong(alarmPlayTimeValue));
  988. log.info("beforeTenMinutes------------->"+beforeTenMinutes);
  989. // 获取当前时间的后10分钟时间
  990. OffsetDateTime afterTenMinutes = currentTime.plusMinutes(Long.parseLong(alarmPlayTimeValue));
  991. log.info("afterTenMinutes------------->"+afterTenMinutes);
  992. // 格式化时间
  993. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
  994. playbackVo.setBeginTime(beforeTenMinutes.format(formatter));
  995. log.info("playbackVo.getBeginTime()------------->"+playbackVo.getBeginTime());
  996. //现在当前时间:后续需要修改成报警时间的后几分钟
  997. playbackVo.setEndTime(currentTime.format(formatter));
  998. log.info("playbackVo.getEndTime()------------->"+playbackVo.getEndTime());
  999. // jsonBody.put("protocol","rtsp");
  1000. // jsonBody.put("expand","streamform=rtp");
  1001. playbackVo.setProtocol("rtsp");
  1002. playbackVo.setExpand("streamform=rtp");
  1003. //对象转换json字符串
  1004. String body = JSONObject.toJSONString(playbackVo);
  1005. //调用天网接口
  1006. log.info("body----->" + body);
  1007. String playbackURLs = getPreviewURLs("/api/video/v1/cameras/playbackURLs", body);
  1008. log.info("playbackURLs----->" + playbackURLs);
  1009. JSONObject outJson = (JSONObject) JSONObject.parse(playbackURLs);
  1010. if ("0".equals(outJson.getString("code"))) {
  1011. log.info("outJson----->" + outJson);
  1012. JSONObject data = outJson.getJSONObject("data");
  1013. String urls = data.getString("url");
  1014. log.info("--------------->urls::" + urls);
  1015. String FilePath = "/opt/streams/map/" + code + ".mp4";
  1016. // String FilePath = "/opt/streams/map/01ea43e6676f4e47bd6c5cd9e02aa006.mp4";
  1017. // try {
  1018. // TimeUnit.SECONDS.sleep(62*Integer.parseInt(alarmPlayTimeValue));
  1019. // } catch (InterruptedException e) {
  1020. // e.printStackTrace();
  1021. // }
  1022. Process process = rtspToMP4.StartRecord(ffmpegPath, urls, FilePath);
  1023. log.info("------playbackURLs----->>>>:" + process);
  1024. if (null != process) {
  1025. map.put(code, process);
  1026. }
  1027. try {
  1028. TimeUnit.SECONDS.sleep(204 * Integer.parseInt(alarmPlayTimeValue));
  1029. } catch (InterruptedException e) {
  1030. e.printStackTrace();
  1031. }
  1032. log.info("------videoCompression----->>>>:");
  1033. videoCompression(code);
  1034. }
  1035. }
  1036. }
  1037. public AjaxResult stop(String id) {
  1038. if (map.containsKey(id)) {
  1039. Process process = map.get(id);
  1040. log.info("-----stop------>>>" + process);
  1041. if (null != process) {
  1042. rtspToMP4.stopRecord(process);
  1043. return AjaxResult.success();
  1044. }
  1045. }
  1046. return AjaxResult.error();
  1047. }
  1048. public static void main(String[] args) throws InterruptedException, ParseException, IOException {
  1049. // CameraUtil cameraUtil = new CameraUtil();
  1050. // cameraUtil.closeRecording();
  1051. // String s = "/opt/streams/record/flv/42010001541320001116/20230403_235506_000506-22e1523b-d170-11ed-8a42-fa163e4e1e9f.flv";
  1052. // String fileStr = s.substring(s.lastIndexOf("/") + 1, s.length());
  1053. // String pathStr = s.substring(0, s.lastIndexOf("/"));
  1054. // System.out.println(fileStr);
  1055. // System.out.println(pathStr);
  1056. String s = "20230403235512";
  1057. Date sdate = DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, s);
  1058. sdate = DateUtils.addDays(sdate, -1);
  1059. System.out.println(DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, sdate));
  1060. }
  1061. }