Commit 42993a5635367bd057088748c2b8f27695ff3f98
1 parent
add6d0eb
优化多平台的命名规则
Showing
11 changed files
with
410 additions
and
137 deletions
src/main/java/top/panll/assist/config/WebMvcConfig.java
100644 → 100755
src/main/java/top/panll/assist/controller/DownController.java
100644 → 100755
src/main/java/top/panll/assist/controller/RecordController.java
| ... | ... | @@ -14,6 +14,7 @@ import org.springframework.http.ResponseEntity; |
| 14 | 14 | import org.springframework.web.bind.annotation.*; |
| 15 | 15 | import top.panll.assist.controller.bean.ControllerException; |
| 16 | 16 | import top.panll.assist.controller.bean.ErrorCode; |
| 17 | +import top.panll.assist.controller.bean.RecordFile; | |
| 17 | 18 | import top.panll.assist.controller.bean.WVPResult; |
| 18 | 19 | import top.panll.assist.dto.*; |
| 19 | 20 | import top.panll.assist.service.VideoFileService; |
| ... | ... | @@ -22,6 +23,7 @@ import top.panll.assist.utils.RedisUtil; |
| 22 | 23 | |
| 23 | 24 | import javax.servlet.http.HttpServletRequest; |
| 24 | 25 | import java.io.File; |
| 26 | +import java.text.DateFormat; | |
| 25 | 27 | import java.text.ParseException; |
| 26 | 28 | import java.text.SimpleDateFormat; |
| 27 | 29 | import java.util.*; |
| ... | ... | @@ -160,7 +162,7 @@ public class RecordController { |
| 160 | 162 | * 获取视频文件列表 |
| 161 | 163 | * @return |
| 162 | 164 | */ |
| 163 | - @Operation(summary ="获取日期文件夹列表") | |
| 165 | + @Operation(summary ="获取视频文件列表") | |
| 164 | 166 | @Parameter(name = "page", description = "当前页", required = true) |
| 165 | 167 | @Parameter(name = "count", description = "每页查询数量", required = true) |
| 166 | 168 | @Parameter(name = "app", description = "应用名", required = true) |
| ... | ... | @@ -204,6 +206,54 @@ public class RecordController { |
| 204 | 206 | } |
| 205 | 207 | } |
| 206 | 208 | |
| 209 | + /** | |
| 210 | + * 获取视频文件列表 | |
| 211 | + * @return | |
| 212 | + */ | |
| 213 | + @Operation(summary ="获取视频文件列表") | |
| 214 | + @Parameter(name = "page", description = "当前页", required = true) | |
| 215 | + @Parameter(name = "count", description = "每页查询数量", required = true) | |
| 216 | + @Parameter(name = "app", description = "应用名", required = true) | |
| 217 | + @Parameter(name = "stream", description = "流ID", required = true) | |
| 218 | + @Parameter(name = "startTime", description = "开始时间(yyyy-MM-dd HH:mm:ss)", required = true) | |
| 219 | + @Parameter(name = "endTime", description = "结束时间(yyyy-MM-dd HH:mm:ss)", required = true) | |
| 220 | + @GetMapping(value = "/file/listWithDate") | |
| 221 | + @ResponseBody | |
| 222 | + public PageInfo<RecordFile> getRecordListWithDate(@RequestParam int page, | |
| 223 | + @RequestParam int count, | |
| 224 | + @RequestParam String app, | |
| 225 | + @RequestParam String stream, | |
| 226 | + @RequestParam(required = false) String startTime, | |
| 227 | + @RequestParam(required = false) String endTime | |
| 228 | + ){ | |
| 229 | + | |
| 230 | + // 开始时间与结束时间可不传或只传其一 | |
| 231 | + List<RecordFile> recordList = new ArrayList<>(); | |
| 232 | + try { | |
| 233 | + Date startTimeDate = null; | |
| 234 | + Date endTimeDate = null; | |
| 235 | + if (startTime != null ) { | |
| 236 | + startTimeDate = formatter.parse(startTime); | |
| 237 | + } | |
| 238 | + if (endTime != null ) { | |
| 239 | + endTimeDate = formatter.parse(endTime); | |
| 240 | + } | |
| 241 | + | |
| 242 | + List<File> filesInTime = videoFileService.getFilesInTime(app, stream, startTimeDate, endTimeDate); | |
| 243 | + if (filesInTime != null && filesInTime.size() > 0) { | |
| 244 | + for (File file : filesInTime) { | |
| 245 | + recordList.add(RecordFile.instance(app, stream, file.getName(), file.getParentFile().getName())); | |
| 246 | + } | |
| 247 | + } | |
| 248 | + PageInfo<RecordFile> stringPageInfo = new PageInfo<>(recordList); | |
| 249 | + stringPageInfo.startPage(page, count); | |
| 250 | + return stringPageInfo; | |
| 251 | + } catch (ParseException e) { | |
| 252 | + logger.error("错误的开始时间[{}]或结束时间[{}]", startTime, endTime); | |
| 253 | + throw new ControllerException(ErrorCode.ERROR400.getCode(), "错误的开始时间或结束时间, e=" + e.getMessage()); | |
| 254 | + } | |
| 255 | + } | |
| 256 | + | |
| 207 | 257 | |
| 208 | 258 | /** |
| 209 | 259 | * 添加视频裁剪合并任务 | ... | ... |
src/main/java/top/panll/assist/controller/bean/ControllerException.java
100644 → 100755
src/main/java/top/panll/assist/controller/bean/RecordFile.java
0 → 100755
| 1 | +package top.panll.assist.controller.bean; | |
| 2 | + | |
| 3 | +public class RecordFile { | |
| 4 | + private String app; | |
| 5 | + private String stream; | |
| 6 | + | |
| 7 | + private String fileName; | |
| 8 | + | |
| 9 | + private String date; | |
| 10 | + | |
| 11 | + | |
| 12 | + public static RecordFile instance(String app, String stream, String fileName, String date) { | |
| 13 | + RecordFile recordFile = new RecordFile(); | |
| 14 | + recordFile.setApp(app); | |
| 15 | + recordFile.setStream(stream); | |
| 16 | + recordFile.setFileName(fileName); | |
| 17 | + recordFile.setDate(date); | |
| 18 | + return recordFile; | |
| 19 | + } | |
| 20 | + | |
| 21 | + | |
| 22 | + public String getApp() { | |
| 23 | + return app; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public void setApp(String app) { | |
| 27 | + this.app = app; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public String getStream() { | |
| 31 | + return stream; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public void setStream(String stream) { | |
| 35 | + this.stream = stream; | |
| 36 | + } | |
| 37 | + | |
| 38 | + public String getFileName() { | |
| 39 | + return fileName; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public void setFileName(String fileName) { | |
| 43 | + this.fileName = fileName; | |
| 44 | + } | |
| 45 | + | |
| 46 | + public String getDate() { | |
| 47 | + return date; | |
| 48 | + } | |
| 49 | + | |
| 50 | + public void setDate(String date) { | |
| 51 | + this.date = date; | |
| 52 | + } | |
| 53 | +} | ... | ... |
src/main/java/top/panll/assist/dto/AssistConstants.java
100644 → 100755
src/main/java/top/panll/assist/dto/VideoFile.java
0 → 100644
| 1 | +package top.panll.assist.dto; | |
| 2 | + | |
| 3 | +import java.io.File; | |
| 4 | +import java.util.Date; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * 视频文件 | |
| 8 | + */ | |
| 9 | +public class VideoFile { | |
| 10 | + | |
| 11 | + /** | |
| 12 | + * 文件对象 | |
| 13 | + */ | |
| 14 | + private File file; | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 文件开始时间 | |
| 18 | + */ | |
| 19 | + private Date startTime; | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 文件结束时间 | |
| 23 | + */ | |
| 24 | + private Date endTime; | |
| 25 | + | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * 时长, 单位:秒 | |
| 29 | + */ | |
| 30 | + private long duration; | |
| 31 | + | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 是否是目标格式 | |
| 35 | + */ | |
| 36 | + private boolean targetFormat; | |
| 37 | + | |
| 38 | + public File getFile() { | |
| 39 | + return file; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public void setFile(File file) { | |
| 43 | + this.file = file; | |
| 44 | + } | |
| 45 | + | |
| 46 | + public Date getStartTime() { | |
| 47 | + return startTime; | |
| 48 | + } | |
| 49 | + | |
| 50 | + public void setStartTime(Date startTime) { | |
| 51 | + this.startTime = startTime; | |
| 52 | + } | |
| 53 | + | |
| 54 | + public Date getEndTime() { | |
| 55 | + return endTime; | |
| 56 | + } | |
| 57 | + | |
| 58 | + public void setEndTime(Date endTime) { | |
| 59 | + this.endTime = endTime; | |
| 60 | + } | |
| 61 | + | |
| 62 | + public long getDuration() { | |
| 63 | + return duration; | |
| 64 | + } | |
| 65 | + | |
| 66 | + public void setDuration(long duration) { | |
| 67 | + this.duration = duration; | |
| 68 | + } | |
| 69 | + | |
| 70 | + public boolean isTargetFormat() { | |
| 71 | + return targetFormat; | |
| 72 | + } | |
| 73 | + | |
| 74 | + public void setTargetFormat(boolean targetFormat) { | |
| 75 | + this.targetFormat = targetFormat; | |
| 76 | + } | |
| 77 | +} | ... | ... |
src/main/java/top/panll/assist/service/FFmpegExecUtils.java
| ... | ... | @@ -17,6 +17,7 @@ import org.springframework.scheduling.annotation.Async; |
| 17 | 17 | import org.springframework.stereotype.Component; |
| 18 | 18 | import org.springframework.util.DigestUtils; |
| 19 | 19 | import top.panll.assist.dto.UserSettings; |
| 20 | +import top.panll.assist.dto.VideoFile; | |
| 20 | 21 | import top.panll.assist.utils.RedisUtil; |
| 21 | 22 | |
| 22 | 23 | import java.io.BufferedWriter; |
| ... | ... | @@ -93,13 +94,13 @@ public class FFmpegExecUtils implements InitializingBean{ |
| 93 | 94 | try { |
| 94 | 95 | BufferedWriter bw =new BufferedWriter(new FileWriter(fileListName)); |
| 95 | 96 | for (File file : fils) { |
| 96 | - String[] split = file.getName().split("-"); | |
| 97 | - if (split.length != 3) continue; | |
| 98 | - String durationStr = split[2].replace(".mp4", ""); | |
| 99 | - Double duration = Double.parseDouble(durationStr)/1000; | |
| 97 | + VideoFile videoFile = VideoFileFactory.createFile(this, file); | |
| 98 | + if (videoFile == null || !videoFile.isTargetFormat()) { | |
| 99 | + return; | |
| 100 | + } | |
| 100 | 101 | bw.write("file " + file.getAbsolutePath()); |
| 101 | 102 | bw.newLine(); |
| 102 | - durationAll += duration; | |
| 103 | + durationAll += videoFile.getDuration(); | |
| 103 | 104 | } |
| 104 | 105 | bw.flush(); |
| 105 | 106 | bw.close(); |
| ... | ... | @@ -127,16 +128,16 @@ public class FFmpegExecUtils implements InitializingBean{ |
| 127 | 128 | final double duration_ns = finalDurationAll * TimeUnit.SECONDS.toNanos(1); |
| 128 | 129 | double percentage = progress.out_time_ns / duration_ns; |
| 129 | 130 | |
| 130 | - // Print out interesting information about the progress | |
| 131 | -// System.out.println(String.format( | |
| 132 | -// "[%.0f%%] status:%s frame:%d time:%s ms fps:%.0f speed:%.2fx", | |
| 133 | -// percentage * 100, | |
| 134 | -// progress.status, | |
| 135 | -// progress.frame, | |
| 136 | -// FFmpegUtils.toTimecode(progress.out_time_ns, TimeUnit.NANOSECONDS), | |
| 137 | -// progress.fps.doubleValue(), | |
| 138 | -// progress.speed | |
| 139 | -// )); | |
| 131 | +// Print out interesting information about the progress | |
| 132 | + System.out.println(String.format( | |
| 133 | + "[%.0f%%] status:%s frame:%d time:%s ms fps:%.0f speed:%.2fx", | |
| 134 | + percentage * 100, | |
| 135 | + progress.status, | |
| 136 | + progress.frame, | |
| 137 | + FFmpegUtils.toTimecode(progress.out_time_ns, TimeUnit.NANOSECONDS), | |
| 138 | + progress.fps.doubleValue(), | |
| 139 | + progress.speed | |
| 140 | + )); | |
| 140 | 141 | |
| 141 | 142 | if (progress.status.equals(Progress.Status.END)){ |
| 142 | 143 | callBack.run(progress.status.name(), percentage, recordFileResultPath); | ... | ... |
src/main/java/top/panll/assist/service/VideoFileFactory.java
0 → 100644
| 1 | +package top.panll.assist.service; | |
| 2 | + | |
| 3 | +import net.bramp.ffmpeg.probe.FFmpegProbeResult; | |
| 4 | +import org.slf4j.Logger; | |
| 5 | +import org.slf4j.LoggerFactory; | |
| 6 | +import top.panll.assist.dto.VideoFile; | |
| 7 | + | |
| 8 | +import java.io.File; | |
| 9 | +import java.io.IOException; | |
| 10 | +import java.text.ParseException; | |
| 11 | +import java.text.SimpleDateFormat; | |
| 12 | +import java.util.Date; | |
| 13 | + | |
| 14 | +public class VideoFileFactory { | |
| 15 | + | |
| 16 | + private final static Logger logger = LoggerFactory.getLogger(VideoFileFactory.class); | |
| 17 | + | |
| 18 | + public static VideoFile createFile(FFmpegExecUtils ffmpegExecUtils, File file){ | |
| 19 | + if (!file.exists()) { | |
| 20 | + return null; | |
| 21 | + } | |
| 22 | + if (!file.isFile()){ | |
| 23 | + return null; | |
| 24 | + } | |
| 25 | + if (file.getName().startsWith(".")){ | |
| 26 | + return null; | |
| 27 | + } | |
| 28 | + if (!file.getName().endsWith(".mp4")){ | |
| 29 | + return null; | |
| 30 | + } | |
| 31 | + String date = file.getParentFile().getName(); | |
| 32 | + if (file.getName().indexOf(":") > 0) { | |
| 33 | + // 格式为 HH:mm:ss-HH:mm:ss-时长 | |
| 34 | + | |
| 35 | + String[] split = file.getName().split("-"); | |
| 36 | + if (split.length != 3) { | |
| 37 | + return null; | |
| 38 | + } | |
| 39 | + String startTimeStr = date + " " + split[0]; | |
| 40 | + String endTimeStr = date + " " + split[1]; | |
| 41 | + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
| 42 | + VideoFile videoFile = new VideoFile(); | |
| 43 | + videoFile.setFile(file); | |
| 44 | + videoFile.setTargetFormat(false); | |
| 45 | + try { | |
| 46 | + Date startTimeDate = simpleDateFormat.parse(startTimeStr); | |
| 47 | + videoFile.setStartTime(startTimeDate); | |
| 48 | + Date endTimeDate = simpleDateFormat.parse(endTimeStr); | |
| 49 | + videoFile.setEndTime(endTimeDate); | |
| 50 | + videoFile.setDuration((endTimeDate.getTime() - startTimeDate.getTime())); | |
| 51 | + } catch (ParseException e) { | |
| 52 | + logger.error("[构建视频文件对象] 格式化时间失败, file:{}", file.getAbsolutePath(), e); | |
| 53 | + return null; | |
| 54 | + } | |
| 55 | + return videoFile; | |
| 56 | + | |
| 57 | + }else if (getStrCountInStr(file.getName(), "-") == 3){ | |
| 58 | + | |
| 59 | + // 格式为zlm的录制格式 HH-mm-ss-序号 | |
| 60 | + String startStr = file.getName().substring(0, file.getName().lastIndexOf("-")); | |
| 61 | + String startTimeStr = date + " " + startStr; | |
| 62 | + VideoFile videoFile = null; | |
| 63 | + try { | |
| 64 | + FFmpegProbeResult fFmpegProbeResult = ffmpegExecUtils.getFfprobe().probe(file.getAbsolutePath()); | |
| 65 | + double duration = fFmpegProbeResult.getFormat().duration * 1000; | |
| 66 | + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"); | |
| 67 | + Date startTimeDate = simpleDateFormat.parse(startTimeStr); | |
| 68 | + Date endTimeDate = new Date(startTimeDate.getTime() + new Double(duration).longValue()); | |
| 69 | + videoFile = new VideoFile(); | |
| 70 | + videoFile.setTargetFormat(false); | |
| 71 | + videoFile.setFile(file); | |
| 72 | + videoFile.setStartTime(startTimeDate); | |
| 73 | + videoFile.setEndTime(endTimeDate); | |
| 74 | + videoFile.setDuration((endTimeDate.getTime() - startTimeDate.getTime())/1000); | |
| 75 | + } catch (IOException e) { | |
| 76 | + logger.error("[构建视频文件对象] 获取视频时长失败, file:{}", file.getAbsolutePath(), e); | |
| 77 | + return null; | |
| 78 | + } catch (ParseException e) { | |
| 79 | + logger.error("[构建视频文件对象] 格式化时间失败, file:{}", file.getAbsolutePath(), e); | |
| 80 | + return null; | |
| 81 | + } | |
| 82 | + return videoFile; | |
| 83 | + }else if (getStrCountInStr(file.getName(), "-") == 2 && file.getName().length() == 10 ){ | |
| 84 | + // 格式为zlm的录制格式 HH-mm-ss | |
| 85 | + String startTimeStr = date + " " + file.getName(); | |
| 86 | + VideoFile videoFile = null; | |
| 87 | + try { | |
| 88 | + FFmpegProbeResult fFmpegProbeResult = ffmpegExecUtils.getFfprobe().probe(file.getAbsolutePath()); | |
| 89 | + double duration = fFmpegProbeResult.getFormat().duration * 1000; | |
| 90 | + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"); | |
| 91 | + Date startTimeDate = simpleDateFormat.parse(startTimeStr); | |
| 92 | + Date endTimeDate = new Date(startTimeDate.getTime() + new Double(duration).longValue()); | |
| 93 | + videoFile = new VideoFile(); | |
| 94 | + videoFile.setTargetFormat(false); | |
| 95 | + videoFile.setFile(file); | |
| 96 | + videoFile.setStartTime(startTimeDate); | |
| 97 | + videoFile.setEndTime(endTimeDate); | |
| 98 | + videoFile.setDuration((endTimeDate.getTime() - startTimeDate.getTime())/1000); | |
| 99 | + } catch (IOException e) { | |
| 100 | + logger.error("[构建视频文件对象] 获取视频时长失败, file:{}", file.getAbsolutePath(), e); | |
| 101 | + return null; | |
| 102 | + } catch (ParseException e) { | |
| 103 | + logger.warn("[构建视频文件对象] 格式化时间失败, file:{}", file.getAbsolutePath(), e); | |
| 104 | + return null; | |
| 105 | + } | |
| 106 | + return videoFile; | |
| 107 | + }else if (getStrCountInStr(file.getName(), "-") == 1 ){ | |
| 108 | + // 格式为zlm的录制格式 HH-mm-ss | |
| 109 | + // 格式为 HH:mm:ss-HH:mm:ss-时长 | |
| 110 | + | |
| 111 | + String[] split = file.getName().split("-"); | |
| 112 | + if (split.length != 2) { | |
| 113 | + return null; | |
| 114 | + } | |
| 115 | + String startTimeStr = date + " " + split[0]; | |
| 116 | + String endTimeStr = date + " " + split[1]; | |
| 117 | + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HHmmss"); | |
| 118 | + VideoFile videoFile = new VideoFile(); | |
| 119 | + videoFile.setTargetFormat(true); | |
| 120 | + videoFile.setFile(file); | |
| 121 | + try { | |
| 122 | + Date startTimeDate = simpleDateFormat.parse(startTimeStr); | |
| 123 | + videoFile.setStartTime(startTimeDate); | |
| 124 | + Date endTimeDate = simpleDateFormat.parse(endTimeStr); | |
| 125 | + videoFile.setEndTime(endTimeDate); | |
| 126 | + videoFile.setDuration((endTimeDate.getTime() - startTimeDate.getTime())); | |
| 127 | + } catch (ParseException e) { | |
| 128 | + logger.error("[构建视频文件对象] 格式化时间失败, file:{}", file.getAbsolutePath(), e); | |
| 129 | + return null; | |
| 130 | + } | |
| 131 | + return videoFile; | |
| 132 | + }else { | |
| 133 | + return null; | |
| 134 | + } | |
| 135 | + } | |
| 136 | + | |
| 137 | + | |
| 138 | + public static int getStrCountInStr(String sourceStr, String content) { | |
| 139 | + int index = sourceStr.indexOf(content); | |
| 140 | + if (index < 0) { | |
| 141 | + return 0; | |
| 142 | + } | |
| 143 | + int count = 1; | |
| 144 | + int lastIndex = sourceStr.lastIndexOf(content); | |
| 145 | + while (index != lastIndex) { | |
| 146 | + index = sourceStr.indexOf(content, index + 1); | |
| 147 | + count++; | |
| 148 | + } | |
| 149 | + return count; | |
| 150 | + } | |
| 151 | + | |
| 152 | +} | ... | ... |
src/main/java/top/panll/assist/service/VideoFileService.java
| ... | ... | @@ -68,35 +68,6 @@ public class VideoFileService { |
| 68 | 68 | return spaceInfo; |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | -// public String getPrintSize(long size) { | |
| 72 | -// // 如果字节数少于1024,则直接以B为单位,否则先除于1024,后3位因太少无意义 | |
| 73 | -// if (size < 1024) { | |
| 74 | -// return String.valueOf(size) + "B"; | |
| 75 | -// } else { | |
| 76 | -// size = size / 1024; | |
| 77 | -// } | |
| 78 | -// // 如果原字节数除于1024之后,少于1024,则可以直接以KB作为单位 | |
| 79 | -// // 因为还没有到达要使用另一个单位的时候 | |
| 80 | -// // 接下去以此类推 | |
| 81 | -// if (size < 1024) { | |
| 82 | -// return String.valueOf(size) + "KB"; | |
| 83 | -// } else { | |
| 84 | -// size = size / 1024; | |
| 85 | -// } | |
| 86 | -// if (size < 1024) { | |
| 87 | -// // 因为如果以MB为单位的话,要保留最后1位小数, | |
| 88 | -// // 因此,把此数乘以100之后再取余 | |
| 89 | -// size = size * 100; | |
| 90 | -// return String.valueOf((size / 100)) + "." | |
| 91 | -// + String.valueOf((size % 100)) + "MB"; | |
| 92 | -// } else { | |
| 93 | -// // 否则如果要以GB为单位的,先除于1024再作同样的处理 | |
| 94 | -// size = size * 100 / 1024; | |
| 95 | -// return String.valueOf((size / 100)) + "." | |
| 96 | -// + String.valueOf((size % 100)) + "GB"; | |
| 97 | -// } | |
| 98 | -// } | |
| 99 | - | |
| 100 | 71 | public List<File> getStreamList(String app, Boolean sort) { |
| 101 | 72 | File appFile = new File(userSettings.getRecord() + File.separator + app); |
| 102 | 73 | return getStreamList(appFile, sort); |
| ... | ... | @@ -119,47 +90,32 @@ public class VideoFileService { |
| 119 | 90 | } |
| 120 | 91 | |
| 121 | 92 | /** |
| 122 | - * 对视频文件重命名, 00:00:00-00:00:00 | |
| 123 | - * @param file | |
| 124 | - * @throws ParseException | |
| 93 | + * 对视频文件重命名 | |
| 125 | 94 | */ |
| 126 | 95 | public void handFile(File file,String app, String stream) { |
| 127 | - FFprobe ffprobe = ffmpegExecUtils.getFfprobe(); | |
| 128 | - if(file.exists() && file.isFile() && !file.getName().startsWith(".")&& file.getName().endsWith(".mp4") && file.getName().indexOf(":") < 0) { | |
| 129 | - try { | |
| 130 | - | |
| 131 | - FFmpegProbeResult in = ffprobe.probe(file.getAbsolutePath()); | |
| 132 | - double duration = in.getFormat().duration * 1000; | |
| 133 | - String endTimeStr = file.getName().replace(".mp4", ""); | |
| 134 | - | |
| 135 | - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"); | |
| 136 | - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss"); | |
| 137 | - | |
| 138 | - File dateFile = new File(file.getParent()); | |
| 96 | + VideoFile videoFile = VideoFileFactory.createFile(ffmpegExecUtils, file); | |
| 97 | + if (videoFile == null || videoFile.isTargetFormat()) { | |
| 98 | + return; | |
| 99 | + } | |
| 139 | 100 | |
| 140 | - long startTime = formatter.parse(dateFile.getName() + " " + endTimeStr).getTime(); | |
| 141 | - long durationLong = new Double(duration).longValue(); | |
| 142 | - long endTime = startTime + durationLong; | |
| 143 | - endTime = endTime - endTime%1000; | |
| 101 | + SimpleDateFormat dateFormat = new SimpleDateFormat("HHmmss"); | |
| 144 | 102 | |
| 145 | - String key = AssistConstants.STREAM_CALL_INFO + userSettings.getId() + "_" + app + "_" + stream; | |
| 146 | - String callId = (String) redisUtil.get(key); | |
| 103 | + String key = AssistConstants.STREAM_CALL_INFO + userSettings.getId() + "_" + app + "_" + stream; | |
| 104 | + String callId = (String) redisUtil.get(key); | |
| 147 | 105 | |
| 148 | - String streamNew = (callId == null? stream : stream + "_" + callId); | |
| 149 | - File newPath = new File(userSettings.getRecord() + File.separator + app + File.separator + streamNew + File.separator + DateUtils.getDateStr(new Date(startTime))); | |
| 150 | - if (!newPath.exists()) { | |
| 151 | - newPath.mkdirs(); | |
| 152 | - } | |
| 106 | + String streamNew = (callId == null? stream : stream + "_" + callId); | |
| 107 | + File newPath = new File(userSettings.getRecord() + File.separator + app + File.separator + streamNew | |
| 108 | + + File.separator + DateUtils.getDateStr(videoFile.getStartTime())); | |
| 109 | + if (!newPath.exists()) { | |
| 110 | + newPath.mkdirs(); | |
| 111 | + } | |
| 153 | 112 | |
| 154 | - String newName = newPath.getAbsolutePath() + File.separator+ simpleDateFormat.format(startTime) + "-" + simpleDateFormat.format(endTime) + "-" + durationLong + ".mp4"; | |
| 155 | - file.renameTo(new File(newName)); | |
| 156 | - System.out.println(file.getAbsolutePath()); | |
| 157 | - logger.info("[处理文件] {}", file.getName()); | |
| 158 | - } catch (IOException e) { | |
| 159 | - logger.warn("文件可能以损坏[{}]", file.getAbsolutePath()); | |
| 160 | - } catch (ParseException e) { | |
| 161 | - logger.error("时间格式化失败", e.getMessage()); | |
| 162 | - } | |
| 113 | + String newName = newPath.getAbsolutePath() + File.separator+ dateFormat.format(videoFile.getStartTime()) | |
| 114 | + + "-" + dateFormat.format(videoFile.getEndTime()) + ".mp4"; | |
| 115 | + logger.info("[处理文件] {}->{}", file.getAbsolutePath(), newName); | |
| 116 | + boolean renameTo = file.renameTo(new File(newName)); | |
| 117 | + if (!renameTo) { | |
| 118 | + logger.info("[处理文件]文件重命名失败 {}->{}", file.getAbsolutePath(), newName); | |
| 163 | 119 | } |
| 164 | 120 | } |
| 165 | 121 | |
| ... | ... | @@ -199,7 +155,7 @@ public class VideoFileService { |
| 199 | 155 | time1 = simpleDateFormatForTime.parse(f1.get("time").toString()); |
| 200 | 156 | time2 = simpleDateFormatForTime.parse(f2.get("time").toString()); |
| 201 | 157 | } catch (ParseException e) { |
| 202 | - logger.error("时间格式化失败", e.getMessage()); | |
| 158 | + logger.error("时间格式化失败", e); | |
| 203 | 159 | } |
| 204 | 160 | return time1.compareTo(time2) * -1; |
| 205 | 161 | }); |
| ... | ... | @@ -221,7 +177,7 @@ public class VideoFileService { |
| 221 | 177 | return result; |
| 222 | 178 | } |
| 223 | 179 | |
| 224 | - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
| 180 | + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HHmmss"); | |
| 225 | 181 | SimpleDateFormat formatterForDate = new SimpleDateFormat("yyyy-MM-dd"); |
| 226 | 182 | String startTimeStr = null; |
| 227 | 183 | String endTimeStr = null; |
| ... | ... | @@ -277,54 +233,50 @@ public class VideoFileService { |
| 277 | 233 | |
| 278 | 234 | if (dateFiles != null && dateFiles.length > 0) { |
| 279 | 235 | for (File dateFile : dateFiles) { |
| 280 | - // TODO 按时间获取文件 | |
| 281 | 236 | File[] files = dateFile.listFiles((File dir, String name) ->{ |
| 282 | - boolean filterResult = true; | |
| 283 | 237 | File currentFile = new File(dir + File.separator + name); |
| 284 | - if (currentFile.isFile() && name.contains(":") && name.endsWith(".mp4") && !name.startsWith(".") && currentFile.length() > 0){ | |
| 285 | - String[] timeArray = name.split("-"); | |
| 286 | - if (timeArray.length == 3){ | |
| 287 | - String fileStartTimeStr = dateFile.getName() + " " + timeArray[0]; | |
| 288 | - String fileEndTimeStr = dateFile.getName() + " " + timeArray[1]; | |
| 289 | - try { | |
| 290 | - if (startTime != null) { | |
| 291 | - filterResult = filterResult && (formatter.parse(fileStartTimeStr).after(startTime) || (formatter.parse(fileStartTimeStr).before(startTime) && formatter.parse(fileEndTimeStr).after(startTime))); | |
| 292 | - } | |
| 293 | - if (endTime != null) { | |
| 294 | - filterResult = filterResult && (formatter.parse(fileEndTimeStr).before(endTime) || (formatter.parse(fileEndTimeStr).after(endTime) && formatter.parse(fileStartTimeStr).before(endTime))); | |
| 295 | - } | |
| 296 | - } catch (ParseException e) { | |
| 297 | - logger.error("过滤视频文件时异常: {}-{}", name, e.getMessage()); | |
| 298 | - return false; | |
| 299 | - } | |
| 300 | - } | |
| 238 | + VideoFile videoFile = VideoFileFactory.createFile(ffmpegExecUtils, currentFile); | |
| 239 | + if (videoFile == null ) { | |
| 240 | + return false; | |
| 301 | 241 | }else { |
| 302 | - filterResult = false; | |
| 242 | + if (!videoFile.isTargetFormat()) { | |
| 243 | + return false; | |
| 244 | + } | |
| 245 | + if (startTime == null && endTime == null) { | |
| 246 | + return true; | |
| 247 | + }else if (startTime == null && endTime != null) { | |
| 248 | + return videoFile.getEndTime().before(endTime) | |
| 249 | + || videoFile.getEndTime().equals(endTime) | |
| 250 | + || (videoFile.getEndTime().after(endTime) && videoFile.getStartTime().before(endTime)); | |
| 251 | + }else if (startTime != null && endTime == null) { | |
| 252 | + return videoFile.getStartTime().after(startTime) | |
| 253 | + || videoFile.getStartTime().equals(startTime) | |
| 254 | + || (videoFile.getStartTime().before(startTime) && videoFile.getEndTime().after(startTime)); | |
| 255 | + }else { | |
| 256 | + return videoFile.getStartTime().after(startTime) | |
| 257 | + || videoFile.getStartTime().equals(startTime) | |
| 258 | + || (videoFile.getStartTime().before(startTime) && videoFile.getEndTime().after(startTime)) | |
| 259 | + || videoFile.getEndTime().before(endTime) | |
| 260 | + || videoFile.getEndTime().equals(endTime) | |
| 261 | + || (videoFile.getEndTime().after(endTime) && videoFile.getStartTime().before(endTime)); | |
| 262 | + } | |
| 263 | + | |
| 303 | 264 | } |
| 304 | - return filterResult; | |
| 305 | 265 | }); |
| 306 | - | |
| 307 | - List<File> fileList = Arrays.asList(files); | |
| 308 | - result.addAll(fileList); | |
| 266 | + if (files != null && files.length > 0) { | |
| 267 | + result.addAll(Arrays.asList(files)); | |
| 268 | + } | |
| 309 | 269 | } |
| 310 | 270 | } |
| 311 | - if (result.size() > 0) { | |
| 271 | + if (!result.isEmpty()) { | |
| 312 | 272 | result.sort((File f1, File f2) -> { |
| 313 | - int sortResult = 0; | |
| 314 | - String[] timeArray1 = f1.getName().split("-"); | |
| 315 | - String[] timeArray2 = f2.getName().split("-"); | |
| 316 | - if (timeArray1.length == 3 && timeArray2.length == 3){ | |
| 317 | - File dateFile1 = f1.getParentFile(); | |
| 318 | - File dateFile2 = f2.getParentFile(); | |
| 319 | - String fileStartTimeStr1 = dateFile1.getName() + " " + timeArray1[0]; | |
| 320 | - String fileStartTimeStr2 = dateFile2.getName() + " " + timeArray2[0]; | |
| 321 | - try { | |
| 322 | - sortResult = formatter.parse(fileStartTimeStr1).compareTo(formatter.parse(fileStartTimeStr2)); | |
| 323 | - } catch (ParseException e) { | |
| 324 | - e.printStackTrace(); | |
| 325 | - } | |
| 273 | + VideoFile videoFile1 = VideoFileFactory.createFile(ffmpegExecUtils, f1); | |
| 274 | + VideoFile videoFile2 = VideoFileFactory.createFile(ffmpegExecUtils, f2); | |
| 275 | + if (videoFile1 == null || !videoFile1.isTargetFormat() || videoFile2 == null || !videoFile2.isTargetFormat()) { | |
| 276 | + logger.warn("[根据时间获取视频文件] 排序错误,文件错误: {}/{}", f1.getName(), f2.getName()); | |
| 277 | + return 0; | |
| 326 | 278 | } |
| 327 | - return sortResult; | |
| 279 | + return videoFile1.getStartTime().compareTo(videoFile2.getStartTime()); | |
| 328 | 280 | }); |
| 329 | 281 | } |
| 330 | 282 | return result; |
| ... | ... | @@ -333,7 +285,7 @@ public class VideoFileService { |
| 333 | 285 | |
| 334 | 286 | public String mergeOrCut(String app, String stream, Date startTime, Date endTime, String remoteHost) { |
| 335 | 287 | List<File> filesInTime = this.getFilesInTime(app, stream, startTime, endTime); |
| 336 | - if (filesInTime== null || filesInTime.size() == 0){ | |
| 288 | + if (filesInTime== null || filesInTime.isEmpty()){ | |
| 337 | 289 | logger.info("此时间段未未找到视频文件, {}/{} {}->{}", app, stream, |
| 338 | 290 | startTime == null? null:DateUtils.getDateTimeStr(startTime), |
| 339 | 291 | endTime == null? null:DateUtils.getDateTimeStr(endTime)); |
| ... | ... | @@ -457,6 +409,9 @@ public class VideoFileService { |
| 457 | 409 | } |
| 458 | 410 | |
| 459 | 411 | }); |
| 412 | + if (dateFiles == null) { | |
| 413 | + return new ArrayList<>(); | |
| 414 | + } | |
| 460 | 415 | List<File> dateFileList = Arrays.asList(dateFiles); |
| 461 | 416 | if (sort != null && sort) { |
| 462 | 417 | dateFileList.sort((File f1, File f2)->{ |
| ... | ... | @@ -525,21 +480,6 @@ public class VideoFileService { |
| 525 | 480 | return result; |
| 526 | 481 | } |
| 527 | 482 | |
| 528 | - public boolean stopTask(String taskId) { | |
| 529 | -// Runnable task = taskList.get(taskId); | |
| 530 | -// boolean result = false; | |
| 531 | -// if (task != null) { | |
| 532 | -// processThreadPool.remove(task); | |
| 533 | -// taskList.remove(taskId); | |
| 534 | -// List<Object> taskCatch = redisUtil.scan(String.format("%S_*_*_%S", keyStr, taskId)); | |
| 535 | -// if (taskCatch.size() == 1) { | |
| 536 | -// redisUtil.del((String) taskCatch.get(0)); | |
| 537 | -// result = true; | |
| 538 | -// } | |
| 539 | -// } | |
| 540 | - return false; | |
| 541 | - } | |
| 542 | - | |
| 543 | 483 | public boolean collection(String app, String stream, String type) { |
| 544 | 484 | File streamFile = new File(userSettings.getRecord() + File.separator + app + File.separator + stream); |
| 545 | 485 | boolean result = false; | ... | ... |
src/main/resources/static/download.html
100644 → 100755