| 
					
				 | 
			
			
				@@ -5,6 +5,7 @@ import com.alibaba.fastjson2.JSONObject; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ozs.common.config.BaseConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ozs.common.constant.Constants; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ozs.common.core.domain.entity.SysDictData; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ozs.common.core.redis.RedisCache; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ozs.common.exception.base.BaseException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ozs.common.utils.DateUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ozs.common.utils.HttpClientUtil; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -14,6 +15,7 @@ import com.ozs.entity.MsgAlarm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ozs.service.BaseCameraManagementService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ozs.system.mapper.SysDictDataMapper; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ozs.web.core.config.CaneraConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import lombok.SneakyThrows; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import lombok.extern.slf4j.Slf4j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.apache.commons.lang3.StringUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.beans.factory.annotation.Autowired; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -37,6 +39,7 @@ import java.util.stream.Collectors; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @Configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @Slf4j 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 public class CameraUtil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private static final ExecutorService executor = Executors.newFixedThreadPool(20); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private static String historyUrl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private static String ffmpegPath; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -56,6 +59,11 @@ public class CameraUtil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private SysDictDataMapper dictDataMapper; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     BaseCameraManagementService baseCameraManagementService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private static RedisCache rc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private RedisCache redisCache; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public final static String tsFilekey = "mergeVideoTsFile"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -66,7 +74,7 @@ public class CameraUtil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @throws IOException 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static String historyPlay(List<String> fromVideoFileList, String ph, String uuid) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static String historyPlay(List<String> fromVideoFileList, String ph, boolean flay) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // 视频服务映射路径 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String NewfilePath = BaseConfig.getProfile() + "/" + ph; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log.info("NewfilePath:{}", NewfilePath); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -74,32 +82,89 @@ public class CameraUtil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (ObjectUtils.isEmpty(fromVideoFileList) || fromVideoFileList.size() <= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             throw new BaseException("当前相机无视频录像"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ExecutorService executor = Executors.newFixedThreadPool(10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         executor.submit(new Runnable() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             public void run() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Map<String, String> map = myConvetor(fromVideoFileList, NewfilePath, uuid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (!ObjectUtils.isEmpty(map)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        cUtil.cmd(map.get("cmd")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        //删除生成的ts文件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        File file1 = new File(map.get("path")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if (file1.exists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            file1.delete(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    txConvetor(fromVideoFileList, NewfilePath, flay); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } catch (IOException e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     log.error(e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     e.printStackTrace(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        executor.shutdown(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        executor.shutdown(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return Constants.RESOURCE_PREFIX + "/" + ph; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @SneakyThrows 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static void txConvetor(List<String> fromVideoFileList, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  String newfilePath, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  boolean fly) throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        * ffmpeg -i 20230411_155847_155947-d4c2265d-d83e-11ed-8e7f-fa163e4e1e9f.flv -c:v copy 1.ts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ffmpeg -i 20230411_155948_160048-f91fea03-d83e-11ed-8e7f-fa163e4e1e9f.flv -c:v copy 2.ts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ffmpeg -i "concat:1.ts|2.ts" -c copy output.mp4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        * */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        File file = new File(newfilePath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        boolean flay = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!file.getParentFile().exists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            boolean mkdirs = file.getParentFile().mkdirs(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.info("创建文件夹:{}", file.getParentFile().getPath()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.info("创建文件夹结果:{}", mkdirs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            flay = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cUtil.cmd("chomd -R 777 " + file.getParentFile().getPath()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("newfilePath:{}", newfilePath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        StringBuffer sm = new StringBuffer(ffmpegPath + " -i \"concat:"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<String> fileTs = new ArrayList<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int t = 0; t < fromVideoFileList.size(); t++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            File ft = new File(fromVideoFileList.get(t)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (ft.exists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.info("file:{}", fromVideoFileList.get(t)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                String substring = fromVideoFileList.get(t).substring(0, fromVideoFileList.get(t).lastIndexOf(".")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                int x;//定义两变量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Random ne = new Random();//实例化一个random的对象ne 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                x = ne.nextInt(9999 - 1000 + 1) + 1000;//为变量赋随机值1000-9999 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                substring = substring + x;//定义两变量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                String cmdstr = ffmpegPath + " -i " + fromVideoFileList.get(t) + " -c:v copy " + substring + ".ts"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.info("转换命令:{}", cmdstr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                cUtil.cmd(cmdstr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                fileTs.add(substring + ".ts"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (t != fromVideoFileList.size() - 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    sm.append(substring + ".ts|"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    sm.append(substring + ".ts\" "); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (fileTs.size() > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Map<String, Object> mergeVideoTsFile = rc.getCacheMap(tsFilekey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (ObjectUtils.isEmpty(mergeVideoTsFile)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                mergeVideoTsFile = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!flay) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 如果没有解除,把生成的文件放入要删除的定时任务 redis key 中 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                fileTs.add(newfilePath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            mergeVideoTsFile.put(new Date().getTime() + "", fileTs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            rc.deleteObject(tsFilekey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (mergeVideoTsFile.size() > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                rc.setCacheMap(tsFilekey, mergeVideoTsFile); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sm.append("-c copy " + newfilePath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log.info("合并命令:{}", sm.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            cUtil.cmd(sm.toString()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 实时播放的拼接流 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -169,15 +234,15 @@ public class CameraUtil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @param endTm   结束时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static String historyPlayListStr(String channel, Date startTm, Date endTm) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static String historyPlayListStr(String channel, Date startTm, Date endTm, boolean flay) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         List<String> list = filterPlayList(channel, startTm, endTm, filePath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String uuid = UUID.randomUUID().toString(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String ph = "flv/" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, new Date()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String ph = "record/flv/" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, new Date()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 + "/" + channel + "/" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                + uuid + ".flv"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                + uuid + ".mp4"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!ObjectUtils.isEmpty(list)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return historyPlay(list, ph, uuid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return historyPlay(list, ph, flay); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 log.error(e.getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 e.printStackTrace(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -376,6 +441,7 @@ public class CameraUtil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         transcribeFilePath = caneraConfig.getTranscribeFilePath(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         webUrl = caneraConfig.getWebUrl(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         bakUrl = caneraConfig.getBakUrl(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        rc = redisCache; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         cUtil = cmdCameraUtil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |