Commit fb7063c400704cf4a379c7701625a2fe9fd2edb0

Authored by 648540858
2 parents 80cafd65 ede562fc

Merge branch '优化'

@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 </parent> 9 </parent>
10 <groupId>top.panll.assist</groupId> 10 <groupId>top.panll.assist</groupId>
11 <artifactId>wvp-pro-assist</artifactId> 11 <artifactId>wvp-pro-assist</artifactId>
12 - <version>2.6.8</version> 12 + <version>2.6.9</version>
13 <name>wvp-pro-assist</name> 13 <name>wvp-pro-assist</name>
14 <description></description> 14 <description></description>
15 <properties> 15 <properties>
src/main/java/top/panll/assist/config/StartConfig.java deleted 100755 → 0
1 -package top.panll.assist.config;  
2 -  
3 -import net.bramp.ffmpeg.FFmpeg;  
4 -import net.bramp.ffmpeg.FFprobe;  
5 -import org.slf4j.Logger;  
6 -import org.slf4j.LoggerFactory;  
7 -import org.springframework.beans.factory.annotation.Autowired;  
8 -import org.springframework.beans.factory.annotation.Value;  
9 -import org.springframework.boot.CommandLineRunner;  
10 -import org.springframework.core.annotation.Order;  
11 -import org.springframework.stereotype.Component;  
12 -import top.panll.assist.dto.UserSettings;  
13 -import top.panll.assist.service.FFmpegExecUtils;  
14 -import top.panll.assist.service.VideoFileService;  
15 -  
16 -import java.io.*;  
17 -import java.nio.charset.StandardCharsets;  
18 -  
19 -/**  
20 - * 用于启动检查环境  
21 - */  
22 -@Component  
23 -@Order(value=1)  
24 -public class StartConfig implements CommandLineRunner {  
25 -  
26 - private final static Logger logger = LoggerFactory.getLogger(StartConfig.class);  
27 -  
28 - @Value("${server.port}")  
29 - private String port;  
30 -  
31 - @Autowired  
32 - private UserSettings userSettings;  
33 -  
34 - @Autowired  
35 - private VideoFileService videoFileService;  
36 -  
37 -  
38 - @Override  
39 - public void run(String... args) {  
40 - String record = userSettings.getRecord();  
41 - if (!record.endsWith(File.separator)) {  
42 - userSettings.setRecord(userSettings.getRecord() + File.separator);  
43 - }  
44 -  
45 - File recordFile = new File(record);  
46 - if (!recordFile.exists()){  
47 - logger.warn("[userSettings.record]路径不存在,开始创建");  
48 - boolean mkResult = recordFile.mkdirs();  
49 - if (!mkResult) {  
50 - logger.info("[userSettings.record]目录创建失败");  
51 - System.exit(1);  
52 - }  
53 - }else {  
54 - if ( !recordFile.isDirectory()) {  
55 - logger.warn("[userSettings.record]路径是文件,请修改为目录");  
56 - System.exit(1);  
57 - }  
58 - if (!recordFile.canRead()) {  
59 - logger.error("[userSettings.record]路径无法读取");  
60 - System.exit(1);  
61 - }  
62 - if (!recordFile.canWrite()) {  
63 - logger.error("[userSettings.record]路径无法写入");  
64 - System.exit(1);  
65 - }  
66 - }  
67 -  
68 - try {  
69 -  
70 - // 对目录进行预整理  
71 - File[] appFiles = recordFile.listFiles();  
72 - if (appFiles != null && appFiles.length > 0) {  
73 - for (File appFile : appFiles) {  
74 - if (appFile.getName().equals("recordTemp")) {  
75 - continue;  
76 - }  
77 - File[] streamFiles = appFile.listFiles();  
78 - if (streamFiles != null && streamFiles.length > 0) {  
79 - for (File streamFile : streamFiles) {  
80 - File[] dateFiles = streamFile.listFiles();  
81 - if (dateFiles != null && dateFiles.length > 0) {  
82 - for (File dateFile : dateFiles) {  
83 - File[] files = dateFile.listFiles();  
84 - if (files != null && files.length > 0) {  
85 - for (File file : files) {  
86 - videoFileService.handFile(file, appFile.getName(), streamFile.getName());  
87 - }  
88 - }  
89 - }  
90 - }  
91 -  
92 - }  
93 - }  
94 -  
95 - }  
96 - }  
97 -  
98 - } catch (Exception exception){  
99 - exception.printStackTrace();  
100 - logger.error("环境错误: " + exception.getMessage());  
101 - }  
102 - }  
103 -  
104 -// private void writeAssistDownPage(File recordFile) {  
105 -// try {  
106 -// File file = new File(recordFile.getParentFile().getAbsolutePath(), "download.html");  
107 -// if (file.exists()) {  
108 -// file.delete();  
109 -// }  
110 -// file.createNewFile();  
111 -// FileOutputStream fs = new FileOutputStream(file);  
112 -// StringBuffer stringBuffer = new StringBuffer();  
113 -// String content = "<!DOCTYPE html>\n" +  
114 -// "<html lang=\"en\">\n" +  
115 -// "<head>\n" +  
116 -// " <meta charset=\"UTF-8\">\n" +  
117 -// " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n" +  
118 -// " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +  
119 -// " <title>下载</title>\n" +  
120 -// "</head>\n" +  
121 -// "<body>\n" +  
122 -// " <a id=\"download\" download />\n" +  
123 -// " <script>\n" +  
124 -// " (function(){\n" +  
125 -// " let searchParams = new URLSearchParams(location.search);\n" +  
126 -// " var download = document.getElementById(\"download\");\n" +  
127 -// " download.setAttribute(\"href\", searchParams.get(\"url\"))\n" +  
128 -// " download.click()\n" +  
129 -// " setTimeout(()=>{\n" +  
130 -// " window.location.href=\"about:blank\";\n" +  
131 -// "\t\t\t window.close();\n" +  
132 -// " },200)\n" +  
133 -// " })();\n" +  
134 -// " \n" +  
135 -// " </script>\n" +  
136 -// "</body>\n" +  
137 -// "</html>";  
138 -// fs.write(content.getBytes(StandardCharsets.UTF_8));  
139 -// logger.info("已写入html配置页面: " + file.getAbsolutePath());  
140 -// } catch (FileNotFoundException e) {  
141 -// logger.error("写入html页面错误", e);  
142 -// } catch (IOException e) {  
143 -// logger.error("写入html页面错误", e);  
144 -// }  
145 -//  
146 -//  
147 -// }  
148 -}  
src/main/java/top/panll/assist/config/WebMvcConfig.java
@@ -17,7 +17,7 @@ public class WebMvcConfig extends WebMvcConfigurerAdapter { @@ -17,7 +17,7 @@ public class WebMvcConfig extends WebMvcConfigurerAdapter {
17 17
18 @Override 18 @Override
19 public void addResourceHandlers(ResourceHandlerRegistry registry) { 19 public void addResourceHandlers(ResourceHandlerRegistry registry) {
20 - File file = new File(userSettings.getRecord()); 20 + File file = new File(userSettings.getRecordTempPath());
21 registry.addResourceHandler("/download/**").addResourceLocations("file://" + file.getAbsolutePath() + "/"); 21 registry.addResourceHandler("/download/**").addResourceLocations("file://" + file.getAbsolutePath() + "/");
22 super.addResourceHandlers(registry); 22 super.addResourceHandlers(registry);
23 } 23 }
src/main/java/top/panll/assist/controller/DownController.java deleted 100755 → 0
1 -package top.panll.assist.controller;  
2 -  
3 -  
4 -import org.apache.catalina.connector.ClientAbortException;  
5 -import org.mp4parser.BasicContainer;  
6 -import org.mp4parser.Container;  
7 -import org.mp4parser.muxer.Movie;  
8 -import org.mp4parser.muxer.Track;  
9 -import org.mp4parser.muxer.builder.DefaultMp4Builder;  
10 -import org.mp4parser.muxer.builder.Mp4Builder;  
11 -import org.mp4parser.muxer.container.mp4.MovieCreator;  
12 -import org.mp4parser.muxer.tracks.AppendTrack;  
13 -import org.slf4j.Logger;  
14 -import org.slf4j.LoggerFactory;  
15 -import org.springframework.beans.factory.annotation.Autowired;  
16 -import org.springframework.stereotype.Controller;  
17 -import org.springframework.web.bind.annotation.GetMapping;  
18 -import org.springframework.web.bind.annotation.RequestMapping;  
19 -import org.springframework.web.bind.annotation.ResponseBody;  
20 -import top.panll.assist.dto.UserSettings;  
21 -  
22 -import javax.servlet.http.HttpServletRequest;  
23 -import javax.servlet.http.HttpServletResponse;  
24 -import java.io.*;  
25 -import java.nio.channels.Channels;  
26 -import java.nio.channels.WritableByteChannel;  
27 -import java.nio.charset.StandardCharsets;  
28 -import java.util.ArrayList;  
29 -import java.util.LinkedList;  
30 -import java.util.List;  
31 -  
32 -@Controller  
33 -@RequestMapping("/down")  
34 -public class DownController {  
35 -  
36 - private final static Logger logger = LoggerFactory.getLogger(DownController.class);  
37 -  
38 - @Autowired  
39 - private UserSettings userSettings;  
40 -  
41 - /**  
42 - * 获取app+stream列表  
43 - *  
44 - * @return  
45 - */  
46 - @GetMapping(value = "/**")  
47 - @ResponseBody  
48 - public void download(HttpServletRequest request, HttpServletResponse response) throws IOException {  
49 -  
50 - List<String> videoList = new ArrayList<>();  
51 - videoList.add("/home/lin/server/test/zlm/Debug/www/record/rtp/34020000002000000003_34020000001310000001/2023-03-20/16-09-07.mp4");  
52 - videoList.add("/home/lin/server/test/zlm/Debug/www/record/rtp/34020000002000000003_34020000001310000001/2023-03-20/17-12-10.mp4");  
53 - videoList.add("/home/lin/server/test/zlm/Debug/www/record/rtp/34020000002000000003_34020000001310000001/2023-03-20/17-38-36.mp4");  
54 - List<Movie> sourceMovies = new ArrayList<>();  
55 - for (String video : videoList) {  
56 - sourceMovies.add(MovieCreator.build(video));  
57 - }  
58 -  
59 - List<Track> videoTracks = new LinkedList<>();  
60 - List<Track> audioTracks = new LinkedList<>();  
61 - for (Movie movie : sourceMovies) {  
62 - for (Track track : movie.getTracks()) {  
63 - if ("soun".equals(track.getHandler())) {  
64 - audioTracks.add(track);  
65 - }  
66 -  
67 - if ("vide".equals(track.getHandler())) {  
68 - videoTracks.add(track);  
69 - }  
70 - }  
71 - }  
72 - Movie mergeMovie = new Movie();  
73 - if (audioTracks.size() > 0) {  
74 - mergeMovie.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));  
75 - }  
76 -  
77 - if (videoTracks.size() > 0) {  
78 - mergeMovie.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()])));  
79 - }  
80 -  
81 - BasicContainer out = (BasicContainer)new DefaultMp4Builder().build(mergeMovie);  
82 -  
83 - // 文件名  
84 - String fileName = "测试.mp4";  
85 - // 文件类型  
86 - String contentType = request.getServletContext().getMimeType(fileName);  
87 -  
88 - // 解决下载文件时文件名乱码问题  
89 - byte[] fileNameBytes = fileName.getBytes(StandardCharsets.UTF_8);  
90 - fileName = new String(fileNameBytes, 0, fileNameBytes.length, StandardCharsets.ISO_8859_1);  
91 -  
92 - response.setHeader("Content-Type", contentType);  
93 - response.setHeader("Content-Length", String.valueOf(out));  
94 - //inline表示浏览器直接使用,attachment表示下载,fileName表示下载的文件名  
95 - response.setHeader("Content-Disposition", "inline;filename=" + fileName);  
96 - response.setContentType(contentType);  
97 -  
98 - WritableByteChannel writableByteChannel = Channels.newChannel(response.getOutputStream());  
99 - out.writeContainer(writableByteChannel);  
100 - writableByteChannel.close();  
101 -  
102 - }  
103 -}  
src/main/java/top/panll/assist/controller/RecordController.java
1 package top.panll.assist.controller; 1 package top.panll.assist.controller;
2 2
3 -import com.alibaba.fastjson.JSON;  
4 -import com.alibaba.fastjson.JSONObject;  
5 import io.swagger.v3.oas.annotations.Operation; 3 import io.swagger.v3.oas.annotations.Operation;
6 import io.swagger.v3.oas.annotations.Parameter; 4 import io.swagger.v3.oas.annotations.Parameter;
7 import io.swagger.v3.oas.annotations.tags.Tag; 5 import io.swagger.v3.oas.annotations.tags.Tag;
8 -import org.apache.commons.io.FileUtils;  
9 import org.slf4j.Logger; 6 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory; 7 import org.slf4j.LoggerFactory;
11 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.annotation.Autowired;
12 -import org.springframework.http.HttpStatus;  
13 -import org.springframework.http.ResponseEntity;  
14 import org.springframework.web.bind.annotation.*; 9 import org.springframework.web.bind.annotation.*;
15 -import top.panll.assist.controller.bean.ControllerException;  
16 -import top.panll.assist.controller.bean.ErrorCode;  
17 -import top.panll.assist.controller.bean.RecordFile;  
18 -import top.panll.assist.controller.bean.WVPResult; 10 +import top.panll.assist.controller.bean.*;
19 import top.panll.assist.dto.*; 11 import top.panll.assist.dto.*;
20 import top.panll.assist.service.VideoFileService; 12 import top.panll.assist.service.VideoFileService;
21 -import top.panll.assist.utils.PageInfo;  
22 import top.panll.assist.utils.RedisUtil; 13 import top.panll.assist.utils.RedisUtil;
23 14
24 -import javax.servlet.http.HttpServletRequest;  
25 -import java.io.File;  
26 -import java.text.DateFormat;  
27 -import java.text.ParseException;  
28 import java.text.SimpleDateFormat; 15 import java.text.SimpleDateFormat;
29 import java.util.*; 16 import java.util.*;
30 17
@@ -58,233 +45,19 @@ public class RecordController { @@ -58,233 +45,19 @@ public class RecordController {
58 return userSettings; 45 return userSettings;
59 } 46 }
60 47
61 - /**  
62 - * 获取app+stream列表  
63 - * @return  
64 - */  
65 - @Operation(summary ="分页获取app+stream的列表")  
66 - @Parameter(name = "page", description = "当前页", required = true)  
67 - @Parameter(name = "count", description = "每页查询数量", required = true)  
68 - @GetMapping(value = "/list")  
69 - @ResponseBody  
70 - public PageInfo<Map<String, String>> getList(@RequestParam int page,  
71 - @RequestParam int count){  
72 - List<Map<String, String>> appList = videoFileService.getList();  
73 -  
74 - PageInfo<Map<String, String>> stringPageInfo = new PageInfo<>(appList);  
75 - stringPageInfo.startPage(page, count);  
76 - return stringPageInfo;  
77 - }  
78 -  
79 - /**  
80 - * 分页获取app列表  
81 - * @return  
82 - */  
83 - @Operation(summary ="分页获取app列表")  
84 - @Parameter(name = "page", description = "当前页", required = true)  
85 - @Parameter(name = "count", description = "每页查询数量", required = true)  
86 - @GetMapping(value = "/app/list")  
87 - @ResponseBody  
88 - public PageInfo<String> getAppList(@RequestParam int page,  
89 - @RequestParam int count){  
90 - List<String> resultData = new ArrayList<>();  
91 - List<File> appList = videoFileService.getAppList(true);  
92 - if (appList.size() > 0) {  
93 - for (File file : appList) {  
94 - resultData.add(file.getName());  
95 - }  
96 - }  
97 - Collections.sort(resultData);  
98 -  
99 - PageInfo<String> stringPageInfo = new PageInfo<>(resultData);  
100 - stringPageInfo.startPage(page, count);  
101 - return stringPageInfo;  
102 - }  
103 -  
104 - /**  
105 - * 分页stream列表  
106 - * @return  
107 - */  
108 - @Operation(summary ="分页stream列表")  
109 - @Parameter(name = "page", description = "当前页", required = true)  
110 - @Parameter(name = "count", description = "每页查询数量", required = true)  
111 - @Parameter(name = "app", description = "应用名", required = true)  
112 - @GetMapping(value = "/stream/list")  
113 - @ResponseBody  
114 - public PageInfo<String> getStreamList(@RequestParam int page,  
115 - @RequestParam int count,  
116 - @RequestParam String app ){  
117 - List<String> resultData = new ArrayList<>();  
118 - if (app == null) {  
119 - throw new ControllerException(ErrorCode.ERROR400.getCode(), "app不能为空");  
120 - }  
121 - List<File> streamList = videoFileService.getStreamList(app, true);  
122 - if (streamList != null) {  
123 - for (File file : streamList) {  
124 - resultData.add(file.getName());  
125 - }  
126 - }  
127 - PageInfo<String> stringPageInfo = new PageInfo<>(resultData);  
128 - stringPageInfo.startPage(page, count);  
129 - return stringPageInfo;  
130 - }  
131 -  
132 - /**  
133 - * 获取日期文件夹列表  
134 - * @return  
135 - */  
136 - @Operation(summary ="获取日期文件夹列表")  
137 - @Parameter(name = "year", description = "月", required = true)  
138 - @Parameter(name = "month", description = "年", required = true)  
139 - @Parameter(name = "app", description = "应用名", required = true)  
140 - @Parameter(name = "stream", description = "流ID", required = true)  
141 - @GetMapping(value = "/date/list")  
142 - @ResponseBody  
143 - public List<String> getDateList( @RequestParam(required = false) Integer year,  
144 - @RequestParam(required = false) Integer month,  
145 - @RequestParam String app,  
146 - @RequestParam String stream ){  
147 - List<String> resultData = new ArrayList<>();  
148 - if (app == null) {  
149 - throw new ControllerException(ErrorCode.ERROR400.getCode(), "app不能为空");  
150 - };  
151 - if (stream == null) {  
152 - throw new ControllerException(ErrorCode.ERROR400.getCode(), "stream不能为空");  
153 - }  
154 - List<File> dateList = videoFileService.getDateList(app, stream, year, month, true);  
155 - for (File file : dateList) {  
156 - resultData.add(file.getName());  
157 - }  
158 - return resultData;  
159 - }  
160 -  
161 - /**  
162 - * 获取视频文件列表  
163 - * @return  
164 - */  
165 - @Operation(summary ="获取视频文件列表")  
166 - @Parameter(name = "page", description = "当前页", required = true)  
167 - @Parameter(name = "count", description = "每页查询数量", required = true)  
168 - @Parameter(name = "app", description = "应用名", required = true)  
169 - @Parameter(name = "stream", description = "流ID", required = true)  
170 - @Parameter(name = "startTime", description = "开始时间(yyyy-MM-dd HH:mm:ss)", required = true)  
171 - @Parameter(name = "endTime", description = "结束时间(yyyy-MM-dd HH:mm:ss)", required = true)  
172 - @GetMapping(value = "/file/list")  
173 - @ResponseBody  
174 - public PageInfo<String> getRecordList(@RequestParam int page,  
175 - @RequestParam int count,  
176 - @RequestParam String app,  
177 - @RequestParam String stream,  
178 - @RequestParam(required = false) String startTime,  
179 - @RequestParam(required = false) String endTime  
180 - ){  
181 -  
182 - // 开始时间与结束时间可不传或只传其一  
183 - List<String> recordList = new ArrayList<>();  
184 - try {  
185 - Date startTimeDate = null;  
186 - Date endTimeDate = null;  
187 - if (startTime != null ) {  
188 - startTimeDate = formatter.parse(startTime);  
189 - }  
190 - if (endTime != null ) {  
191 - endTimeDate = formatter.parse(endTime);  
192 - }  
193 -  
194 - List<File> filesInTime = videoFileService.getFilesInTime(app, stream, startTimeDate, endTimeDate);  
195 - if (filesInTime != null && filesInTime.size() > 0) {  
196 - for (File file : filesInTime) {  
197 - recordList.add(file.getName());  
198 - }  
199 - }  
200 - PageInfo<String> stringPageInfo = new PageInfo<>(recordList);  
201 - stringPageInfo.startPage(page, count);  
202 - return stringPageInfo;  
203 - } catch (ParseException e) {  
204 - logger.error("错误的开始时间[{}]或结束时间[{}]", startTime, endTime);  
205 - throw new ControllerException(ErrorCode.ERROR400.getCode(), "错误的开始时间或结束时间, e=" + e.getMessage());  
206 - }  
207 - }  
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 -  
257 48
258 /** 49 /**
259 * 添加视频裁剪合并任务 50 * 添加视频裁剪合并任务
260 */ 51 */
261 @Operation(summary ="添加视频裁剪合并任务") 52 @Operation(summary ="添加视频裁剪合并任务")
262 - @Parameter(name = "app", description = "应用名", required = true)  
263 - @Parameter(name = "stream", description = "流ID", required = true)  
264 - @Parameter(name = "startTime", description = "开始时间(yyyy-MM-dd HH:mm:ss)", required = true)  
265 - @Parameter(name = "endTime", description = "结束时间(yyyy-MM-dd HH:mm:ss)", required = true)  
266 - @Parameter(name = "remoteHost", description = "服务的IP:端口(用于直接返回完整播放地址以及下载地址)", required = true)  
267 - @GetMapping(value = "/file/download/task/add") 53 + @Parameter(name = "videoTaskInfo", description = "视频合并任务的信息", required = true)
  54 + @PostMapping(value = "/file/download/task/add")
268 @ResponseBody 55 @ResponseBody
269 - public String addTaskForDownload(@RequestParam String app,  
270 - @RequestParam String stream,  
271 - @RequestParam(required = false) String startTime,  
272 - @RequestParam(required = false) String endTime,  
273 - @RequestParam(required = false) String remoteHost  
274 - ){  
275 - Date startTimeDate = null;  
276 - Date endTimeDate = null;  
277 - try {  
278 - if (startTime != null ) {  
279 - startTimeDate = formatter.parse(startTime);  
280 - }  
281 - if (endTime != null ) {  
282 - endTimeDate = formatter.parse(endTime);  
283 - }  
284 - } catch (ParseException e) {  
285 - e.printStackTrace(); 56 + public String addTaskForDownload(@RequestBody VideoTaskInfo videoTaskInfo ){
  57 + if (videoTaskInfo.getFilePathList() == null || videoTaskInfo.getFilePathList().isEmpty()) {
  58 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "视频文件列表不可为空");
286 } 59 }
287 - String id = videoFileService.mergeOrCut(app, stream, startTimeDate, endTimeDate, remoteHost); 60 + String id = videoFileService.mergeOrCut(videoTaskInfo);
288 if (id== null) { 61 if (id== null) {
289 throw new ControllerException(ErrorCode.ERROR100.getCode(), "可能未找到视频文件"); 62 throw new ControllerException(ErrorCode.ERROR100.getCode(), "可能未找到视频文件");
290 } 63 }
@@ -295,8 +68,6 @@ public class RecordController { @@ -295,8 +68,6 @@ public class RecordController {
295 * 查询视频裁剪合并任务列表 68 * 查询视频裁剪合并任务列表
296 */ 69 */
297 @Operation(summary ="查询视频裁剪合并任务列表") 70 @Operation(summary ="查询视频裁剪合并任务列表")
298 - @Parameter(name = "app", description = "应用名", required = true)  
299 - @Parameter(name = "stream", description = "流ID", required = true)  
300 @Parameter(name = "taskId", description = "任务ID", required = true) 71 @Parameter(name = "taskId", description = "任务ID", required = true)
301 @Parameter(name = "isEnd", description = "是否结束", required = true) 72 @Parameter(name = "isEnd", description = "是否结束", required = true)
302 @GetMapping(value = "/file/download/task/list") 73 @GetMapping(value = "/file/download/task/list")
@@ -304,9 +75,10 @@ public class RecordController { @@ -304,9 +75,10 @@ public class RecordController {
304 public List<MergeOrCutTaskInfo> getTaskListForDownload( 75 public List<MergeOrCutTaskInfo> getTaskListForDownload(
305 @RequestParam(required = false) String app, 76 @RequestParam(required = false) String app,
306 @RequestParam(required = false) String stream, 77 @RequestParam(required = false) String stream,
  78 + @RequestParam(required = false) String callId,
307 @RequestParam(required = false) String taskId, 79 @RequestParam(required = false) String taskId,
308 @RequestParam(required = false) Boolean isEnd){ 80 @RequestParam(required = false) Boolean isEnd){
309 - List<MergeOrCutTaskInfo> taskList = videoFileService.getTaskListForDownload(isEnd, app, stream, taskId); 81 + List<MergeOrCutTaskInfo> taskList = videoFileService.getTaskListForDownload(app, stream, callId, isEnd, taskId);
310 if (taskList == null) { 82 if (taskList == null) {
311 throw new ControllerException(ErrorCode.ERROR100); 83 throw new ControllerException(ErrorCode.ERROR100);
312 } 84 }
@@ -314,64 +86,6 @@ public class RecordController { @@ -314,64 +86,6 @@ public class RecordController {
314 } 86 }
315 87
316 /** 88 /**
317 - * 收藏录像(被收藏的录像不会被清理任务清理)  
318 - */  
319 - @Operation(summary ="收藏录像(被收藏的录像不会被清理任务清理)")  
320 - @Parameter(name = "type", description = "类型", required = true)  
321 - @Parameter(name = "app", description = "应用名", required = true)  
322 - @Parameter(name = "stream", description = "流ID", required = true)  
323 - @GetMapping(value = "/file/collection/add")  
324 - @ResponseBody  
325 - public void collection(  
326 - @RequestParam(required = true) String type,  
327 - @RequestParam(required = true) String app,  
328 - @RequestParam(required = true) String stream){  
329 -  
330 - boolean collectionResult = videoFileService.collection(app, stream, type);  
331 - if (!collectionResult) {  
332 - throw new ControllerException(ErrorCode.ERROR100);  
333 - }  
334 - }  
335 -  
336 - /**  
337 - * 移除收藏录像  
338 - */  
339 - @Operation(summary ="移除收藏录像")  
340 - @Parameter(name = "type", description = "类型", required = true)  
341 - @Parameter(name = "app", description = "应用名", required = true)  
342 - @Parameter(name = "stream", description = "流ID", required = true)  
343 - @GetMapping(value = "/file/collection/remove")  
344 - @ResponseBody  
345 - public void removeCollection(  
346 - @RequestParam(required = true) String type,  
347 - @RequestParam(required = true) String app,  
348 - @RequestParam(required = true) String stream){  
349 -  
350 - boolean collectionResult = videoFileService.removeCollection(app, stream, type);  
351 - if (!collectionResult) {  
352 - throw new ControllerException(ErrorCode.ERROR100);  
353 - }  
354 - }  
355 -  
356 - /**  
357 - * 收藏录像列表  
358 - */  
359 - @Operation(summary ="收藏录像列表")  
360 - @Parameter(name = "type", description = "类型", required = false)  
361 - @Parameter(name = "app", description = "应用名", required = false)  
362 - @Parameter(name = "stream", description = "流ID", required = false)  
363 - @GetMapping(value = "/file/collection/list")  
364 - @ResponseBody  
365 - public List<SignInfo> collectionList(  
366 - @RequestParam(required = false) String type,  
367 - @RequestParam(required = false) String app,  
368 - @RequestParam(required = false) String stream){  
369 -  
370 - List<SignInfo> signInfos = videoFileService.getCollectionList(app, stream, type);  
371 - return signInfos;  
372 - }  
373 -  
374 - /**  
375 * 中止视频裁剪合并任务列表 89 * 中止视频裁剪合并任务列表
376 */ 90 */
377 @Operation(summary ="中止视频裁剪合并任务列表(暂不支持)") 91 @Operation(summary ="中止视频裁剪合并任务列表(暂不支持)")
@@ -391,35 +105,6 @@ public class RecordController { @@ -391,35 +105,6 @@ public class RecordController {
391 } 105 }
392 106
393 /** 107 /**
394 - * 录制完成的通知, 对用zlm的hook  
395 - * @return  
396 - */  
397 - @ResponseBody  
398 - @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8")  
399 - public ResponseEntity<String> onRecordMp4(@RequestBody JSONObject json) {  
400 - JSONObject ret = new JSONObject();  
401 - ret.put("code", 0);  
402 - ret.put("msg", "success");  
403 - String file_path = json.getString("file_path");  
404 -  
405 - String app = json.getString("app");  
406 - String stream = json.getString("stream");  
407 - logger.debug("ZLM 录制完成,文件路径:" + file_path);  
408 -  
409 - if (file_path == null) {  
410 - return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);  
411 - }  
412 - if (userSettings.getRecordDay() <= 0) {  
413 - logger.info("录像保存事件为{}天,直接删除: {}", userSettings.getRecordDay(), file_path);  
414 - FileUtils.deleteQuietly(new File(file_path));  
415 - }else {  
416 - videoFileService.handFile(new File(file_path), app, stream);  
417 - }  
418 -  
419 - return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);  
420 - }  
421 -  
422 - /**  
423 * 磁盘空间查询 108 * 磁盘空间查询
424 */ 109 */
425 @Operation(summary ="磁盘空间查询") 110 @Operation(summary ="磁盘空间查询")
@@ -430,21 +115,6 @@ public class RecordController { @@ -430,21 +115,6 @@ public class RecordController {
430 } 115 }
431 116
432 /** 117 /**
433 - * 增加推流的鉴权信息,用于录像存储使用  
434 - */  
435 - @Operation(summary ="增加推流的鉴权信息")  
436 - @Parameter(name = "app", description = "应用名", required = true)  
437 - @Parameter(name = "stream", description = "流ID", required = true)  
438 - @Parameter(name = "callId", description = "录像自鉴权ID", required = true)  
439 - @ResponseBody  
440 - @GetMapping(value = "/addStreamCallInfo", produces = "application/json;charset=UTF-8")  
441 - @PostMapping(value = "/addStreamCallInfo", produces = "application/json;charset=UTF-8")  
442 - public void addStreamCallInfo(String app, String stream, String callId) {  
443 - String key = AssistConstants.STREAM_CALL_INFO + userSettings.getId() + "_" + app + "_" + stream;  
444 - redisUtil.set(key, callId, -1);  
445 - }  
446 -  
447 - /**  
448 * 录像文件的时长 118 * 录像文件的时长
449 */ 119 */
450 @Operation(summary ="录像文件的时长") 120 @Operation(summary ="录像文件的时长")
src/main/java/top/panll/assist/controller/bean/FileLIstInfo.java 0 → 100644
  1 +package top.panll.assist.controller.bean;
  2 +
  3 +import java.util.List;
  4 +
  5 +public class FileLIstInfo {
  6 +
  7 + private List<String> filePathList;
  8 +
  9 + public List<String> getFilePathList() {
  10 + return filePathList;
  11 + }
  12 +
  13 + public void setFilePathList(List<String> filePathList) {
  14 + this.filePathList = filePathList;
  15 + }
  16 +}
src/main/java/top/panll/assist/dto/MergeOrCutTaskInfo.java
@@ -3,12 +3,7 @@ package top.panll.assist.dto; @@ -3,12 +3,7 @@ package top.panll.assist.dto;
3 3
4 public class MergeOrCutTaskInfo { 4 public class MergeOrCutTaskInfo {
5 private String id; 5 private String id;
6 - private String app;  
7 - private String stream;  
8 - private String startTime;  
9 - private String endTime;  
10 private String createTime; 6 private String createTime;
11 -  
12 private String percentage; 7 private String percentage;
13 8
14 private String recordFile; 9 private String recordFile;
@@ -17,6 +12,12 @@ public class MergeOrCutTaskInfo { @@ -17,6 +12,12 @@ public class MergeOrCutTaskInfo {
17 12
18 private String playFile; 13 private String playFile;
19 14
  15 + private String app;
  16 + private String stream;
  17 + private String startTime;
  18 + private String endTime;
  19 + private String callId;
  20 +
20 public String getId() { 21 public String getId() {
21 return id; 22 return id;
22 } 23 }
@@ -25,38 +26,6 @@ public class MergeOrCutTaskInfo { @@ -25,38 +26,6 @@ public class MergeOrCutTaskInfo {
25 this.id = id; 26 this.id = id;
26 } 27 }
27 28
28 - public String getStartTime() {  
29 - return startTime;  
30 - }  
31 -  
32 - public void setStartTime(String startTime) {  
33 - this.startTime = startTime;  
34 - }  
35 -  
36 - public String getEndTime() {  
37 - return endTime;  
38 - }  
39 -  
40 - public void setEndTime(String endTime) {  
41 - this.endTime = endTime;  
42 - }  
43 -  
44 - public String getApp() {  
45 - return app;  
46 - }  
47 -  
48 - public void setApp(String app) {  
49 - this.app = app;  
50 - }  
51 -  
52 - public String getStream() {  
53 - return stream;  
54 - }  
55 -  
56 - public void setStream(String stream) {  
57 - this.stream = stream;  
58 - }  
59 -  
60 public String getPercentage() { 29 public String getPercentage() {
61 return percentage; 30 return percentage;
62 } 31 }
@@ -96,4 +65,44 @@ public class MergeOrCutTaskInfo { @@ -96,4 +65,44 @@ public class MergeOrCutTaskInfo {
96 public void setCreateTime(String createTime) { 65 public void setCreateTime(String createTime) {
97 this.createTime = createTime; 66 this.createTime = createTime;
98 } 67 }
  68 +
  69 + public String getApp() {
  70 + return app;
  71 + }
  72 +
  73 + public void setApp(String app) {
  74 + this.app = app;
  75 + }
  76 +
  77 + public String getStream() {
  78 + return stream;
  79 + }
  80 +
  81 + public void setStream(String stream) {
  82 + this.stream = stream;
  83 + }
  84 +
  85 + public String getStartTime() {
  86 + return startTime;
  87 + }
  88 +
  89 + public void setStartTime(String startTime) {
  90 + this.startTime = startTime;
  91 + }
  92 +
  93 + public String getEndTime() {
  94 + return endTime;
  95 + }
  96 +
  97 + public void setEndTime(String endTime) {
  98 + this.endTime = endTime;
  99 + }
  100 +
  101 + public String getCallId() {
  102 + return callId;
  103 + }
  104 +
  105 + public void setCallId(String callId) {
  106 + this.callId = callId;
  107 + }
99 } 108 }
src/main/java/top/panll/assist/dto/UserSettings.java
@@ -12,13 +12,10 @@ public class UserSettings { @@ -12,13 +12,10 @@ public class UserSettings {
12 @Value("${userSettings.id}") 12 @Value("${userSettings.id}")
13 private String id; 13 private String id;
14 14
15 - @Value("${userSettings.record}")  
16 - private String record; 15 + @Value("${userSettings.record-temp:./recordTemp}")
  16 + private String recordTempPath;
17 17
18 - @Value("${userSettings.recordDay:7}")  
19 - private int recordDay;  
20 -  
21 - @Value("${userSettings.recordTempDay:-1}") 18 + @Value("${userSettings.record-temp-day:7}")
22 private int recordTempDay; 19 private int recordTempDay;
23 20
24 @Value("${userSettings.ffmpeg}") 21 @Value("${userSettings.ffmpeg}")
@@ -38,14 +35,6 @@ public class UserSettings { @@ -38,14 +35,6 @@ public class UserSettings {
38 this.id = id; 35 this.id = id;
39 } 36 }
40 37
41 - public String getRecord() {  
42 - return record;  
43 - }  
44 -  
45 - public void setRecord(String record) {  
46 - this.record = record;  
47 - }  
48 -  
49 public String getFfmpeg() { 38 public String getFfmpeg() {
50 return ffmpeg; 39 return ffmpeg;
51 } 40 }
@@ -62,20 +51,9 @@ public class UserSettings { @@ -62,20 +51,9 @@ public class UserSettings {
62 this.ffprobe = ffprobe; 51 this.ffprobe = ffprobe;
63 } 52 }
64 53
65 - public int getRecordDay() {  
66 - return recordDay;  
67 - }  
68 -  
69 - public void setRecordDay(int recordDay) {  
70 - this.recordDay = recordDay;  
71 - }  
72 54
73 public int getRecordTempDay() { 55 public int getRecordTempDay() {
74 - if (recordTempDay == -1) {  
75 - return recordDay;  
76 - }else {  
77 - return recordTempDay;  
78 - } 56 + return recordTempDay;
79 } 57 }
80 58
81 public void setRecordTempDay(int recordTempDay) { 59 public void setRecordTempDay(int recordTempDay) {
@@ -89,4 +67,12 @@ public class UserSettings { @@ -89,4 +67,12 @@ public class UserSettings {
89 public void setThreads(int threads) { 67 public void setThreads(int threads) {
90 this.threads = threads; 68 this.threads = threads;
91 } 69 }
  70 +
  71 + public String getRecordTempPath() {
  72 + return recordTempPath;
  73 + }
  74 +
  75 + public void setRecordTempPath(String recordTempPath) {
  76 + this.recordTempPath = recordTempPath;
  77 + }
92 } 78 }
src/main/java/top/panll/assist/dto/VideoTaskInfo.java 0 → 100644
  1 +package top.panll.assist.dto;
  2 +
  3 +import io.swagger.v3.oas.annotations.Parameter;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +
  6 +import java.util.List;
  7 +
  8 +@Schema(description = "视频合并任务的信息")
  9 +public class VideoTaskInfo {
  10 +
  11 + private String app;
  12 + private String stream;
  13 + private String startTime;
  14 + private String endTime;
  15 + private String callId;
  16 +
  17 +
  18 + @Schema(description = "视频文件路径列表")
  19 + private List<String> filePathList;
  20 +
  21 + @Schema(description = "返回地址时的远程地址")
  22 + private String remoteHost;
  23 +
  24 + public List<String> getFilePathList() {
  25 + return filePathList;
  26 + }
  27 +
  28 + public void setFilePathList(List<String> filePathList) {
  29 + this.filePathList = filePathList;
  30 + }
  31 +
  32 + public String getRemoteHost() {
  33 + return remoteHost;
  34 + }
  35 +
  36 + public void setRemoteHost(String remoteHost) {
  37 + this.remoteHost = remoteHost;
  38 + }
  39 +
  40 + public String getApp() {
  41 + return app;
  42 + }
  43 +
  44 + public void setApp(String app) {
  45 + this.app = app;
  46 + }
  47 +
  48 + public String getStream() {
  49 + return stream;
  50 + }
  51 +
  52 + public void setStream(String stream) {
  53 + this.stream = stream;
  54 + }
  55 +
  56 + public String getStartTime() {
  57 + return startTime;
  58 + }
  59 +
  60 + public void setStartTime(String startTime) {
  61 + this.startTime = startTime;
  62 + }
  63 +
  64 + public String getEndTime() {
  65 + return endTime;
  66 + }
  67 +
  68 + public void setEndTime(String endTime) {
  69 + this.endTime = endTime;
  70 + }
  71 +
  72 + public String getCallId() {
  73 + return callId;
  74 + }
  75 +
  76 + public void setCallId(String callId) {
  77 + this.callId = callId;
  78 + }
  79 +}
src/main/java/top/panll/assist/service/FFmpegExecUtils.java
@@ -77,7 +77,7 @@ public class FFmpegExecUtils implements InitializingBean{ @@ -77,7 +77,7 @@ public class FFmpegExecUtils implements InitializingBean{
77 } 77 }
78 78
79 @Async 79 @Async
80 - public void mergeOrCutFile(List<File> fils, File dest, String destFileName, VideoHandEndCallBack callBack){ 80 + public void mergeOrCutFile(List<File> fils, File dest, String destFileName, VideoHandEndCallBack callBack){
81 81
82 if (fils == null || fils.size() == 0 || ffmpeg == null || ffprobe == null || dest== null || !dest.exists()){ 82 if (fils == null || fils.size() == 0 || ffmpeg == null || ffprobe == null || dest== null || !dest.exists()){
83 callBack.run("error", 0.0, null); 83 callBack.run("error", 0.0, null);
@@ -95,7 +95,7 @@ public class FFmpegExecUtils implements InitializingBean{ @@ -95,7 +95,7 @@ public class FFmpegExecUtils implements InitializingBean{
95 BufferedWriter bw =new BufferedWriter(new FileWriter(fileListName)); 95 BufferedWriter bw =new BufferedWriter(new FileWriter(fileListName));
96 for (File file : fils) { 96 for (File file : fils) {
97 VideoFile videoFile = VideoFileFactory.createFile(this, file); 97 VideoFile videoFile = VideoFileFactory.createFile(this, file);
98 - if (videoFile == null || !videoFile.isTargetFormat()) { 98 + if (videoFile == null) {
99 return; 99 return;
100 } 100 }
101 bw.write("file " + file.getAbsolutePath()); 101 bw.write("file " + file.getAbsolutePath());
@@ -129,15 +129,15 @@ public class FFmpegExecUtils implements InitializingBean{ @@ -129,15 +129,15 @@ public class FFmpegExecUtils implements InitializingBean{
129 double percentage = progress.out_time_ns / duration_ns; 129 double percentage = progress.out_time_ns / duration_ns;
130 130
131 // Print out interesting information about the progress 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 - )); 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 +// ));
141 141
142 if (progress.status.equals(Progress.Status.END)){ 142 if (progress.status.equals(Progress.Status.END)){
143 callBack.run(progress.status.name(), percentage, recordFileResultPath); 143 callBack.run(progress.status.name(), percentage, recordFileResultPath);
src/main/java/top/panll/assist/service/FileManagerTimer.java
@@ -39,112 +39,47 @@ public class FileManagerTimer { @@ -39,112 +39,47 @@ public class FileManagerTimer {
39 // @Scheduled(fixedDelay = 2000) //测试 20秒执行一次 39 // @Scheduled(fixedDelay = 2000) //测试 20秒执行一次
40 @Scheduled(cron = "0 0 0 * * ?") //每天的0点执行 40 @Scheduled(cron = "0 0 0 * * ?") //每天的0点执行
41 public void execute(){ 41 public void execute(){
42 - if (userSettings.getRecord() == null) { 42 + if (userSettings.getRecordTempPath() == null) {
43 return; 43 return;
44 } 44 }
45 - int recordDay = userSettings.getRecordDay();  
46 - Date lastDate=new Date();  
47 - Calendar lastCalendar = Calendar.getInstance();  
48 - if (recordDay > 0) {  
49 - lastCalendar.setTime(lastDate);  
50 - lastCalendar.add(Calendar.DAY_OF_MONTH, 0 - recordDay);  
51 - lastDate = lastCalendar.getTime();  
52 - }  
53 45
54 - logger.info("[录像巡查]移除 {} 之前的文件", formatter.format(lastDate));  
55 - File recordFileDir = new File(userSettings.getRecord());  
56 - if (recordFileDir.canWrite()) {  
57 - List<File> appList = videoFileService.getAppList(false);  
58 - if (appList != null && appList.size() > 0) {  
59 - for (File appFile : appList) {  
60 - if ("download.html".equals(appFile.getName())) {  
61 - continue;  
62 - }  
63 - List<File> streamList = videoFileService.getStreamList(appFile, false);  
64 - if (streamList != null && streamList.size() > 0) {  
65 - for (File streamFile : streamList) {  
66 - // 带有sig标记文件的为收藏文件,不被自动清理任务移除  
67 - File[] signFiles = streamFile.listFiles((File dir, String name) -> {  
68 - File currentFile = new File(dir.getAbsolutePath() + File.separator + name);  
69 - return currentFile.isFile() && name.endsWith(".sign");  
70 - });  
71 - if (signFiles != null && signFiles.length > 0) {  
72 - continue;  
73 - }  
74 - List<File> dateList = videoFileService.getDateList(streamFile, null, null, false);  
75 - if (dateList != null && dateList.size() > 0) {  
76 - for (File dateFile : dateList) {  
77 - try {  
78 - Date parse = formatter.parse(dateFile.getName());  
79 - if (parse.before(lastDate)) {  
80 - boolean result = FileUtils.deleteQuietly(dateFile);  
81 - if (result) {  
82 - logger.info("[录像巡查]成功移除 {} ", dateFile.getAbsolutePath());  
83 - }else {  
84 - logger.info("[录像巡查]移除失败 {} ", dateFile.getAbsolutePath());  
85 - }  
86 - }  
87 - } catch (ParseException e) {  
88 - e.printStackTrace();  
89 - }  
90 - }  
91 - }  
92 - if (streamFile.listFiles() == null || streamFile.listFiles().length == 0) {  
93 - boolean result = FileUtils.deleteQuietly(streamFile);  
94 - if (result) {  
95 - logger.info("[录像巡查]成功移除 {} ", streamFile.getAbsolutePath());  
96 - }else {  
97 - logger.info("[录像巡查]移除失败 {} ", streamFile.getAbsolutePath());  
98 - }  
99 - }  
100 - }  
101 - }  
102 - if (appFile.listFiles() == null || appFile.listFiles().length == 0) {  
103 - boolean result = FileUtils.deleteQuietly(appFile);  
104 - if (result) {  
105 - logger.info("[录像巡查]成功移除 {} ", appFile.getAbsolutePath());  
106 - }else {  
107 - logger.info("[录像巡查]移除失败 {} ", appFile.getAbsolutePath());  
108 - }  
109 - }  
110 - }  
111 - }  
112 - }  
113 // 清理任务临时文件 46 // 清理任务临时文件
114 int recordTempDay = userSettings.getRecordTempDay(); 47 int recordTempDay = userSettings.getRecordTempDay();
115 Date lastTempDate = new Date(); 48 Date lastTempDate = new Date();
116 Calendar lastTempCalendar = Calendar.getInstance(); 49 Calendar lastTempCalendar = Calendar.getInstance();
117 lastTempCalendar.setTime(lastTempDate); 50 lastTempCalendar.setTime(lastTempDate);
118 - lastTempCalendar.add(Calendar.DAY_OF_MONTH, 0 - recordTempDay); 51 + lastTempCalendar.add(Calendar.DAY_OF_MONTH, -recordTempDay);
119 lastTempDate = lastTempCalendar.getTime(); 52 lastTempDate = lastTempCalendar.getTime();
120 logger.info("[录像巡查]移除合并任务临时文件 {} 之前的文件", formatter.format(lastTempDate)); 53 logger.info("[录像巡查]移除合并任务临时文件 {} 之前的文件", formatter.format(lastTempDate));
121 - File recordTempFile = new File(userSettings.getRecord() + "recordTemp"); 54 + File recordTempFile = new File(userSettings.getRecordTempPath());
122 if (recordTempFile.exists() && recordTempFile.isDirectory() && recordTempFile.canWrite()) { 55 if (recordTempFile.exists() && recordTempFile.isDirectory() && recordTempFile.canWrite()) {
123 File[] tempFiles = recordTempFile.listFiles(); 56 File[] tempFiles = recordTempFile.listFiles();
124 - for (File tempFile : tempFiles) {  
125 - if (tempFile.isDirectory() && new Date(tempFile.lastModified()).before(lastTempDate)) {  
126 - boolean result = FileUtils.deleteQuietly(tempFile);  
127 - if (result) {  
128 - logger.info("[录像巡查]成功移除合并任务临时文件 {} ", tempFile.getAbsolutePath());  
129 - }else {  
130 - logger.info("[录像巡查]合并任务临时文件移除失败 {} ", tempFile.getAbsolutePath()); 57 + if (tempFiles != null) {
  58 + for (File tempFile : tempFiles) {
  59 + if (tempFile.isFile() && tempFile.lastModified() < lastTempDate.getTime()) {
  60 + boolean result = FileUtils.deleteQuietly(tempFile);
  61 + if (result) {
  62 + logger.info("[录像巡查]成功移除合并任务临时文件 {} ", tempFile.getAbsolutePath());
  63 + }else {
  64 + logger.info("[录像巡查]合并任务临时文件移除失败 {} ", tempFile.getAbsolutePath());
  65 + }
131 } 66 }
132 } 67 }
133 } 68 }
134 } 69 }
135 // 清理redis记录 70 // 清理redis记录
136 - String key = String.format("%S_%S_*_*_*", AssistConstants.MERGEORCUT, userSettings.getId()); 71 + String key = String.format("%S_%S_*", AssistConstants.MERGEORCUT, userSettings.getId());
137 List<Object> taskKeys = redisUtil.scan(key); 72 List<Object> taskKeys = redisUtil.scan(key);
138 for (Object taskKeyObj : taskKeys) { 73 for (Object taskKeyObj : taskKeys) {
139 String taskKey = (String) taskKeyObj; 74 String taskKey = (String) taskKeyObj;
140 MergeOrCutTaskInfo mergeOrCutTaskInfo = (MergeOrCutTaskInfo)redisUtil.get(taskKey); 75 MergeOrCutTaskInfo mergeOrCutTaskInfo = (MergeOrCutTaskInfo)redisUtil.get(taskKey);
141 try { 76 try {
142 - if (StringUtils.isEmpty(mergeOrCutTaskInfo.getCreateTime()) 77 + if (StringUtils.hasLength(mergeOrCutTaskInfo.getCreateTime())
143 || simpleDateFormatForTime.parse(mergeOrCutTaskInfo.getCreateTime()).before(lastTempDate)) { 78 || simpleDateFormatForTime.parse(mergeOrCutTaskInfo.getCreateTime()).before(lastTempDate)) {
144 redisUtil.del(taskKey); 79 redisUtil.del(taskKey);
145 } 80 }
146 } catch (ParseException e) { 81 } catch (ParseException e) {
147 - e.printStackTrace(); 82 + logger.error("[清理过期的redis合并任务信息] 失败", e);
148 } 83 }
149 } 84 }
150 } 85 }
src/main/java/top/panll/assist/service/VideoFileService.java
@@ -10,6 +10,9 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -10,6 +10,9 @@ import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.data.redis.core.RedisTemplate; 10 import org.springframework.data.redis.core.RedisTemplate;
11 import org.springframework.stereotype.Service; 11 import org.springframework.stereotype.Service;
12 import org.springframework.util.DigestUtils; 12 import org.springframework.util.DigestUtils;
  13 +import org.springframework.util.ObjectUtils;
  14 +import top.panll.assist.controller.bean.ControllerException;
  15 +import top.panll.assist.controller.bean.ErrorCode;
13 import top.panll.assist.dto.*; 16 import top.panll.assist.dto.*;
14 import top.panll.assist.utils.RedisUtil; 17 import top.panll.assist.utils.RedisUtil;
15 import top.panll.assist.utils.DateUtils; 18 import top.panll.assist.utils.DateUtils;
@@ -44,7 +47,7 @@ public class VideoFileService { @@ -44,7 +47,7 @@ public class VideoFileService {
44 private final SimpleDateFormat simpleDateFormatForTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 47 private final SimpleDateFormat simpleDateFormatForTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
45 48
46 public List<File> getAppList(Boolean sort) { 49 public List<File> getAppList(Boolean sort) {
47 - File recordFile = new File(userSettings.getRecord()); 50 + File recordFile = new File(userSettings.getRecordTempPath());
48 if (recordFile.isDirectory()) { 51 if (recordFile.isDirectory()) {
49 File[] files = recordFile.listFiles((File dir, String name) -> { 52 File[] files = recordFile.listFiles((File dir, String name) -> {
50 File currentFile = new File(dir.getAbsolutePath() + File.separator + name); 53 File currentFile = new File(dir.getAbsolutePath() + File.separator + name);
@@ -61,17 +64,13 @@ public class VideoFileService { @@ -61,17 +64,13 @@ public class VideoFileService {
61 } 64 }
62 65
63 public SpaceInfo getSpaceInfo(){ 66 public SpaceInfo getSpaceInfo(){
64 - File recordFile = new File(userSettings.getRecord()); 67 + File recordFile = new File(userSettings.getRecordTempPath());
65 SpaceInfo spaceInfo = new SpaceInfo(); 68 SpaceInfo spaceInfo = new SpaceInfo();
66 spaceInfo.setFree(recordFile.getFreeSpace()); 69 spaceInfo.setFree(recordFile.getFreeSpace());
67 spaceInfo.setTotal(recordFile.getTotalSpace()); 70 spaceInfo.setTotal(recordFile.getTotalSpace());
68 return spaceInfo; 71 return spaceInfo;
69 } 72 }
70 73
71 - public List<File> getStreamList(String app, Boolean sort) {  
72 - File appFile = new File(userSettings.getRecord() + File.separator + app);  
73 - return getStreamList(appFile, sort);  
74 - }  
75 74
76 public List<File> getStreamList(File appFile, Boolean sort) { 75 public List<File> getStreamList(File appFile, Boolean sort) {
77 if (appFile != null && appFile.isDirectory()) { 76 if (appFile != null && appFile.isDirectory()) {
@@ -90,79 +89,6 @@ public class VideoFileService { @@ -90,79 +89,6 @@ public class VideoFileService {
90 } 89 }
91 90
92 /** 91 /**
93 - * 对视频文件重命名  
94 - */  
95 - public void handFile(File file,String app, String stream) {  
96 - VideoFile videoFile = VideoFileFactory.createFile(ffmpegExecUtils, file);  
97 - if (videoFile == null || videoFile.isTargetFormat()) {  
98 - return;  
99 - }  
100 -  
101 - SimpleDateFormat dateFormat = new SimpleDateFormat("HHmmss");  
102 -  
103 - String key = AssistConstants.STREAM_CALL_INFO + userSettings.getId() + "_" + app + "_" + stream;  
104 - String callId = (String) redisUtil.get(key);  
105 -  
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 - }  
112 -  
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);  
119 - }  
120 - }  
121 -  
122 - public List<Map<String, String>> getList() {  
123 -  
124 - List<Map<String, String>> result = new ArrayList<>();  
125 -  
126 - List<File> appList = getAppList(true);  
127 - if (appList != null && appList.size() > 0) {  
128 - for (File appFile : appList) {  
129 - if (appFile.isDirectory()) {  
130 - List<File> streamList = getStreamList(appFile.getName(), true);  
131 - if (streamList != null && streamList.size() > 0) {  
132 - for (File streamFile : streamList) {  
133 - Map<String, String> data = new HashMap<>();  
134 - data.put("app", appFile.getName());  
135 - data.put("stream", streamFile.getName());  
136 -  
137 - BasicFileAttributes bAttributes = null;  
138 - try {  
139 - bAttributes = Files.readAttributes(streamFile.toPath(),  
140 - BasicFileAttributes.class);  
141 - } catch (IOException e) {  
142 - e.printStackTrace();  
143 - }  
144 - data.put("time", simpleDateFormatForTime.format(new Date(bAttributes.lastModifiedTime().toMillis())));  
145 - result.add(data);  
146 - }  
147 - }  
148 - }  
149 - }  
150 - }  
151 - result.sort((Map f1, Map f2)->{  
152 - Date time1 = null;  
153 - Date time2 = null;  
154 - try {  
155 - time1 = simpleDateFormatForTime.parse(f1.get("time").toString());  
156 - time2 = simpleDateFormatForTime.parse(f2.get("time").toString());  
157 - } catch (ParseException e) {  
158 - logger.error("时间格式化失败", e);  
159 - }  
160 - return time1.compareTo(time2) * -1;  
161 - });  
162 - return result;  
163 - }  
164 -  
165 - /**  
166 * 获取制定推流的指定时间段内的推流 92 * 获取制定推流的指定时间段内的推流
167 * @param app 93 * @param app
168 * @param stream 94 * @param stream
@@ -191,7 +117,7 @@ public class VideoFileService { @@ -191,7 +117,7 @@ public class VideoFileService {
191 logger.debug("获取[app: {}, stream: {}, statime: {}, endTime: {}]的视频", app, stream, 117 logger.debug("获取[app: {}, stream: {}, statime: {}, endTime: {}]的视频", app, stream,
192 startTimeStr, endTimeStr); 118 startTimeStr, endTimeStr);
193 119
194 - File recordFile = new File(userSettings.getRecord()); 120 + File recordFile = new File(userSettings.getRecordTempPath());
195 File streamFile = new File(recordFile.getAbsolutePath() + File.separator + app + File.separator + stream + File.separator); 121 File streamFile = new File(recordFile.getAbsolutePath() + File.separator + app + File.separator + stream + File.separator);
196 if (!streamFile.exists()) { 122 if (!streamFile.exists()) {
197 logger.warn("获取[app: {}, stream: {}, statime: {}, endTime: {}]的视频时未找到目录: {}", app, stream, 123 logger.warn("获取[app: {}, stream: {}, statime: {}, endTime: {}]的视频时未找到目录: {}", app, stream,
@@ -282,80 +208,79 @@ public class VideoFileService { @@ -282,80 +208,79 @@ public class VideoFileService {
282 } 208 }
283 209
284 210
285 - public String mergeOrCut(String app, String stream, Date startTime, Date endTime, String remoteHost) {  
286 - List<File> filesInTime = this.getFilesInTime(app, stream, startTime, endTime);  
287 - if (filesInTime== null || filesInTime.isEmpty()){  
288 - logger.info("此时间段未未找到视频文件, {}/{} {}->{}", app, stream,  
289 - startTime == null? null:DateUtils.getDateTimeStr(startTime),  
290 - endTime == null? null:DateUtils.getDateTimeStr(endTime));  
291 - return null;  
292 - } 211 + public String mergeOrCut(VideoTaskInfo videoTaskInfo) {
  212 + assert videoTaskInfo.getFilePathList() != null;
  213 + assert !videoTaskInfo.getFilePathList().isEmpty();
293 String taskId = DigestUtils.md5DigestAsHex(String.valueOf(System.currentTimeMillis()).getBytes()); 214 String taskId = DigestUtils.md5DigestAsHex(String.valueOf(System.currentTimeMillis()).getBytes());
294 - logger.info("[录像合并] 开始合并,APP:{}, STREAM: {}, 任务ID:{}", app, stream, taskId);  
295 - String destDir = "recordTemp" + File.separator + taskId + File.separator + app;  
296 - File recordFile = new File(userSettings.getRecord() + destDir ); 215 + String logInfo = String.format("app: %S, stream: %S, callId: %S, 任务ID:%S",
  216 + videoTaskInfo.getApp(), videoTaskInfo.getStream(), videoTaskInfo.getCallId(), taskId);
  217 + logger.info("[录像合并] 开始合并,{} ", logInfo);
  218 + List<File> fileList = new ArrayList<>();
  219 + for (String filePath : videoTaskInfo.getFilePathList()) {
  220 + File file = new File(filePath);
  221 + if (!file.exists()) {
  222 + logger.info("[录像合并] 失败,{} ", logInfo);
  223 + throw new ControllerException(ErrorCode.ERROR100.getCode(), filePath + "文件不存在");
  224 + }
  225 + logger.info("[录像合并] 添加文件,{}, 文件: {}", logInfo, filePath);
  226 + fileList.add(file);
  227 + }
  228 +
  229 + File recordFile = new File(userSettings.getRecordTempPath() );
297 if (!recordFile.exists()) { 230 if (!recordFile.exists()) {
298 - recordFile.mkdirs(); 231 + if (!recordFile.mkdirs()) {
  232 + logger.info("[录像合并] 失败,{}, 创建临时目录失败", logInfo);
  233 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "创建临时目录失败");
  234 + }
299 } 235 }
300 MergeOrCutTaskInfo mergeOrCutTaskInfo = new MergeOrCutTaskInfo(); 236 MergeOrCutTaskInfo mergeOrCutTaskInfo = new MergeOrCutTaskInfo();
301 mergeOrCutTaskInfo.setId(taskId); 237 mergeOrCutTaskInfo.setId(taskId);
302 - mergeOrCutTaskInfo.setApp(app);  
303 - mergeOrCutTaskInfo.setStream(stream); 238 + mergeOrCutTaskInfo.setApp(videoTaskInfo.getApp());
  239 + mergeOrCutTaskInfo.setStream(videoTaskInfo.getStream());
  240 + mergeOrCutTaskInfo.setCallId(videoTaskInfo.getCallId());
  241 + mergeOrCutTaskInfo.setStartTime(videoTaskInfo.getStartTime());
  242 + mergeOrCutTaskInfo.setEndTime(videoTaskInfo.getEndTime());
304 mergeOrCutTaskInfo.setCreateTime(simpleDateFormatForTime.format(System.currentTimeMillis())); 243 mergeOrCutTaskInfo.setCreateTime(simpleDateFormatForTime.format(System.currentTimeMillis()));
305 - if(startTime != null) {  
306 - mergeOrCutTaskInfo.setStartTime(simpleDateFormatForTime.format(startTime));  
307 - }else {  
308 - String startTimeInFile = filesInTime.get(0).getParentFile().getName() + " "  
309 - + filesInTime.get(0).getName().split("-")[0];  
310 - mergeOrCutTaskInfo.setStartTime(startTimeInFile);  
311 - }  
312 - if(endTime != null) {  
313 - mergeOrCutTaskInfo.setEndTime(simpleDateFormatForTime.format(endTime));  
314 - }else {  
315 - String endTimeInFile = filesInTime.get(filesInTime.size()- 1).getParentFile().getName() + " "  
316 - + filesInTime.get(filesInTime.size()- 1).getName().split("-")[1];  
317 - mergeOrCutTaskInfo.setEndTime(endTimeInFile);  
318 - }  
319 - if (filesInTime.size() == 1) { 244 + String destFileName = videoTaskInfo.getStream() + "_" + videoTaskInfo.getCallId();
  245 + if (fileList.size() == 1) {
320 246
321 // 文件只有一个则不合并,直接复制过去 247 // 文件只有一个则不合并,直接复制过去
322 mergeOrCutTaskInfo.setPercentage("1"); 248 mergeOrCutTaskInfo.setPercentage("1");
323 // 处理文件路径 249 // 处理文件路径
324 - String recordFileResultPath = recordFile.getAbsolutePath() + File.separator + stream + ".mp4";  
325 - Path relativize = Paths.get(userSettings.getRecord()).relativize(Paths.get(recordFileResultPath)); 250 +
  251 + String recordFileResultPath = recordFile.getAbsolutePath() + File.separator + destFileName + ".mp4";
326 try { 252 try {
327 - Files.copy(filesInTime.get(0).toPath(), Paths.get(recordFileResultPath)); 253 + Files.copy(fileList.get(0).toPath(), Paths.get(recordFileResultPath));
328 } catch (IOException e) { 254 } catch (IOException e) {
329 - e.printStackTrace();  
330 - logger.info("[录像合并] 失败,APP:{}, STREAM: {}, 任务ID:{}", app, stream, taskId);  
331 - return taskId; 255 + logger.info("[录像合并] 失败, {}", logInfo, e);
  256 + throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
332 } 257 }
333 - mergeOrCutTaskInfo.setRecordFile("/download/" + relativize.toString());  
334 - if (remoteHost != null) {  
335 - mergeOrCutTaskInfo.setDownloadFile(remoteHost + "/download.html?url=download/" + relativize);  
336 - mergeOrCutTaskInfo.setPlayFile(remoteHost + "/download/" + relativize); 258 + mergeOrCutTaskInfo.setRecordFile("/download/" + destFileName + ".mp4");
  259 + if (videoTaskInfo.getRemoteHost() != null) {
  260 + mergeOrCutTaskInfo.setDownloadFile(videoTaskInfo.getRemoteHost() + "/download.html?url=download/" + destFileName + ".mp4");
  261 + mergeOrCutTaskInfo.setPlayFile(videoTaskInfo.getRemoteHost() + "/download/" + destFileName + ".mp4");
337 } 262 }
338 - String key = String.format("%S_%S_%S_%S_%S", AssistConstants.MERGEORCUT , userSettings.getId(), mergeOrCutTaskInfo.getApp(), mergeOrCutTaskInfo.getStream(), mergeOrCutTaskInfo.getId()); 263 + String key = String.format("%S_%S_%S", AssistConstants.MERGEORCUT , userSettings.getId(), mergeOrCutTaskInfo.getId());
339 redisUtil.set(key, mergeOrCutTaskInfo); 264 redisUtil.set(key, mergeOrCutTaskInfo);
340 - logger.info("[录像合并] 合并完成,APP:{}, STREAM: {}, 任务ID:{}", app, stream, taskId); 265 + logger.info("[录像合并] 成功, 任务ID:{}", taskId);
341 }else { 266 }else {
342 - ffmpegExecUtils.mergeOrCutFile(filesInTime, recordFile, stream, (status, percentage, result)->{ 267 + ffmpegExecUtils.mergeOrCutFile(fileList, recordFile, destFileName, (status, percentage, result)->{
343 // 发出redis通知 268 // 发出redis通知
344 if (status.equals(Progress.Status.END.name())) { 269 if (status.equals(Progress.Status.END.name())) {
345 mergeOrCutTaskInfo.setPercentage("1"); 270 mergeOrCutTaskInfo.setPercentage("1");
346 271
347 // 处理文件路径 272 // 处理文件路径
348 - Path relativize = Paths.get(userSettings.getRecord()).relativize(Paths.get(result)); 273 + String relativize = new File(result).getName();
349 mergeOrCutTaskInfo.setRecordFile(relativize.toString()); 274 mergeOrCutTaskInfo.setRecordFile(relativize.toString());
350 - if (remoteHost != null) {  
351 - mergeOrCutTaskInfo.setDownloadFile(remoteHost + "/download.html?url=download/" + relativize);  
352 - mergeOrCutTaskInfo.setPlayFile(remoteHost + "/download/" + relativize); 275 + if (videoTaskInfo.getRemoteHost() != null) {
  276 + mergeOrCutTaskInfo.setDownloadFile(videoTaskInfo.getRemoteHost() + "/download.html?url=download/" + relativize);
  277 + mergeOrCutTaskInfo.setPlayFile(videoTaskInfo.getRemoteHost() + "/download/" + relativize);
353 } 278 }
354 - logger.info("[录像合并] 合并完成,APP:{}, STREAM: {}, 任务ID:{}", app, stream, taskId); 279 + logger.info("[录像合并] 成功, {}", logInfo);
355 }else { 280 }else {
356 mergeOrCutTaskInfo.setPercentage(percentage + ""); 281 mergeOrCutTaskInfo.setPercentage(percentage + "");
357 } 282 }
358 - String key = String.format("%S_%S_%S_%S_%S", AssistConstants.MERGEORCUT, userSettings.getId(), mergeOrCutTaskInfo.getApp(), mergeOrCutTaskInfo.getStream(), mergeOrCutTaskInfo.getId()); 283 + String key = String.format("%S_%S_%S", AssistConstants.MERGEORCUT, userSettings.getId(), mergeOrCutTaskInfo.getId());
359 redisUtil.set(key, mergeOrCutTaskInfo); 284 redisUtil.set(key, mergeOrCutTaskInfo);
360 }); 285 });
361 } 286 }
@@ -363,19 +288,6 @@ public class VideoFileService { @@ -363,19 +288,6 @@ public class VideoFileService {
363 return taskId; 288 return taskId;
364 } 289 }
365 290
366 - /**  
367 - * 获取指定时间的日期文件夹  
368 - * @param app  
369 - * @param stream  
370 - * @param year  
371 - * @param month  
372 - * @return  
373 - */  
374 - public List<File> getDateList(String app, String stream, Integer year, Integer month, Boolean sort) {  
375 - File recordFile = new File(userSettings.getRecord());  
376 - File streamFile = new File(recordFile.getAbsolutePath() + File.separator + app + File.separator + stream);  
377 - return getDateList(streamFile, year, month, sort);  
378 - }  
379 public List<File> getDateList(File streamFile, Integer year, Integer month, Boolean sort) { 291 public List<File> getDateList(File streamFile, Integer year, Integer month, Boolean sort) {
380 if (!streamFile.exists() && streamFile.isDirectory()) { 292 if (!streamFile.exists() && streamFile.isDirectory()) {
381 logger.warn("获取[]的视频时未找到目录: {}",streamFile.getName()); 293 logger.warn("获取[]的视频时未找到目录: {}",streamFile.getName());
@@ -428,35 +340,39 @@ public class VideoFileService { @@ -428,35 +340,39 @@ public class VideoFileService {
428 return dateFileList; 340 return dateFileList;
429 } 341 }
430 342
431 - public List<MergeOrCutTaskInfo> getTaskListForDownload(Boolean idEnd, String app, String stream, String taskId) { 343 + public List<MergeOrCutTaskInfo> getTaskListForDownload(String app, String stream, String callId, Boolean isEnd, String taskId) {
  344 + logger.info("[查询录像合成列表] app: {}, stream: {}, callId: {}, isEnd: {}, taskId: {}",
  345 + app, stream, callId, isEnd, taskId);
432 ArrayList<MergeOrCutTaskInfo> result = new ArrayList<>(); 346 ArrayList<MergeOrCutTaskInfo> result = new ArrayList<>();
433 - if (app == null) {  
434 - app = "*";  
435 - }  
436 - if (stream == null) {  
437 - stream = "*";  
438 - }  
439 if (taskId == null) { 347 if (taskId == null) {
440 taskId = "*"; 348 taskId = "*";
441 } 349 }
442 - List<Object> taskCatch = redisUtil.scan(String.format("%S_%S_%S_%S_%S", AssistConstants.MERGEORCUT,  
443 - userSettings.getId(), app, stream, taskId)); 350 + List<Object> taskCatch = redisUtil.scan(String.format("%S_%S_%S", AssistConstants.MERGEORCUT,
  351 + userSettings.getId(), taskId));
444 for (int i = 0; i < taskCatch.size(); i++) { 352 for (int i = 0; i < taskCatch.size(); i++) {
445 String keyItem = taskCatch.get(i).toString(); 353 String keyItem = taskCatch.get(i).toString();
446 MergeOrCutTaskInfo mergeOrCutTaskInfo = (MergeOrCutTaskInfo)redisUtil.get(keyItem); 354 MergeOrCutTaskInfo mergeOrCutTaskInfo = (MergeOrCutTaskInfo)redisUtil.get(keyItem);
447 - if (mergeOrCutTaskInfo != null && mergeOrCutTaskInfo.getPercentage() != null){  
448 - if (idEnd != null ) {  
449 - if (idEnd) {  
450 - if (Double.parseDouble(mergeOrCutTaskInfo.getPercentage()) == 1){  
451 - result.add(mergeOrCutTaskInfo); 355 + if (mergeOrCutTaskInfo != null){
  356 + if ((!ObjectUtils.isEmpty(app) && !mergeOrCutTaskInfo.getApp().equals(app))
  357 + || (!ObjectUtils.isEmpty(stream) && !mergeOrCutTaskInfo.getStream().equals(stream))
  358 + || (!ObjectUtils.isEmpty(callId) && !mergeOrCutTaskInfo.getCallId().equals(callId))
  359 + ) {
  360 + continue;
  361 + }
  362 + if (mergeOrCutTaskInfo.getPercentage() != null){
  363 + if (isEnd != null ) {
  364 + if (isEnd) {
  365 + if (Double.parseDouble(mergeOrCutTaskInfo.getPercentage()) == 1){
  366 + result.add(mergeOrCutTaskInfo);
  367 + }
  368 + }else {
  369 + if (Double.parseDouble(mergeOrCutTaskInfo.getPercentage()) < 1){
  370 + result.add((MergeOrCutTaskInfo)redisUtil.get(keyItem));
  371 + }
452 } 372 }
453 }else { 373 }else {
454 - if (Double.parseDouble(mergeOrCutTaskInfo.getPercentage()) < 1){  
455 - result.add((MergeOrCutTaskInfo)redisUtil.get(keyItem));  
456 - } 374 + result.add((MergeOrCutTaskInfo)redisUtil.get(keyItem));
457 } 375 }
458 - }else {  
459 - result.add((MergeOrCutTaskInfo)redisUtil.get(keyItem));  
460 } 376 }
461 } 377 }
462 } 378 }
@@ -465,10 +381,10 @@ public class VideoFileService { @@ -465,10 +381,10 @@ public class VideoFileService {
465 try { 381 try {
466 sortResult = simpleDateFormatForTime.parse(m1.getCreateTime()).compareTo(simpleDateFormatForTime.parse(m2.getCreateTime())); 382 sortResult = simpleDateFormatForTime.parse(m1.getCreateTime()).compareTo(simpleDateFormatForTime.parse(m2.getCreateTime()));
467 if (sortResult == 0) { 383 if (sortResult == 0) {
468 - sortResult = simpleDateFormatForTime.parse(m1.getStartTime()).compareTo(simpleDateFormatForTime.parse(m2.getStartTime())); 384 + sortResult = simpleDateFormatForTime.parse(m1.getCreateTime()).compareTo(simpleDateFormatForTime.parse(m2.getCreateTime()));
469 } 385 }
470 if (sortResult == 0) { 386 if (sortResult == 0) {
471 - sortResult = simpleDateFormatForTime.parse(m1.getEndTime()).compareTo(simpleDateFormatForTime.parse(m2.getEndTime())); 387 + sortResult = simpleDateFormatForTime.parse(m1.getCreateTime()).compareTo(simpleDateFormatForTime.parse(m2.getCreateTime()));
472 } 388 }
473 } catch (ParseException e) { 389 } catch (ParseException e) {
474 e.printStackTrace(); 390 e.printStackTrace();
@@ -480,7 +396,7 @@ public class VideoFileService { @@ -480,7 +396,7 @@ public class VideoFileService {
480 } 396 }
481 397
482 public boolean collection(String app, String stream, String type) { 398 public boolean collection(String app, String stream, String type) {
483 - File streamFile = new File(userSettings.getRecord() + File.separator + app + File.separator + stream); 399 + File streamFile = new File(userSettings.getRecordTempPath() + File.separator + app + File.separator + stream);
484 boolean result = false; 400 boolean result = false;
485 if (streamFile.exists() && streamFile.isDirectory() && streamFile.canWrite()) { 401 if (streamFile.exists() && streamFile.isDirectory() && streamFile.canWrite()) {
486 File signFile = new File(streamFile.getAbsolutePath() + File.separator + type + ".sign"); 402 File signFile = new File(streamFile.getAbsolutePath() + File.separator + type + ".sign");
@@ -494,7 +410,7 @@ public class VideoFileService { @@ -494,7 +410,7 @@ public class VideoFileService {
494 } 410 }
495 411
496 public boolean removeCollection(String app, String stream, String type) { 412 public boolean removeCollection(String app, String stream, String type) {
497 - File signFile = new File(userSettings.getRecord() + File.separator + app + File.separator + stream + File.separator + type + ".sign"); 413 + File signFile = new File(userSettings.getRecordTempPath() + File.separator + app + File.separator + stream + File.separator + type + ".sign");
498 boolean result = false; 414 boolean result = false;
499 if (signFile.exists() && signFile.isFile()) { 415 if (signFile.exists() && signFile.isFile()) {
500 result = signFile.delete(); 416 result = signFile.delete();
@@ -565,4 +481,24 @@ public class VideoFileService { @@ -565,4 +481,24 @@ public class VideoFileService {
565 } 481 }
566 return durationResult; 482 return durationResult;
567 } 483 }
  484 +
  485 + public int deleteFile(List<String> filePathList) {
  486 + assert filePathList != null;
  487 + assert filePathList.isEmpty();
  488 + int deleteResult = 0;
  489 + for (String filePath : filePathList) {
  490 + File file = new File(filePath);
  491 + if (file.exists()) {
  492 + if (file.delete()) {
  493 + deleteResult ++;
  494 + }
  495 + }else {
  496 + logger.warn("[删除文件] 文件不存在,{}", filePath);
  497 + }
  498 + }
  499 + if (deleteResult == 0) {
  500 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "未删除任何文件");
  501 + }
  502 + return deleteResult;
  503 + }
568 } 504 }
src/main/java/top/panll/assist/utils/PageInfo.java deleted 100755 → 0
1 -package top.panll.assist.utils;  
2 -  
3 -import java.util.ArrayList;  
4 -import java.util.List;  
5 -  
6 -public class PageInfo<T> {  
7 - //当前页  
8 - private int pageNum;  
9 - //每页的数量  
10 - private int pageSize;  
11 - //当前页的数量  
12 - private int size;  
13 - //总页数  
14 - private int pages;  
15 - //总数  
16 - private int total;  
17 -  
18 - private List<T> resultData;  
19 -  
20 - private List<T> list;  
21 -  
22 - public PageInfo(List<T> resultData) {  
23 - this.resultData = resultData;  
24 - }  
25 -  
26 - public void startPage(int page, int count) {  
27 - if (count <= 0) count = 10;  
28 - if (page <= 0) page = 1;  
29 - this.pageNum = page;  
30 - this.pageSize = count;  
31 - this.total = resultData.size();  
32 -  
33 - this.pages = total%count == 0 ? total/count : total/count + 1;  
34 - int fromIndx = (page - 1) * count;  
35 - if ( fromIndx > this.total - 1) {  
36 - this.list = new ArrayList<>();  
37 - this.size = 0;  
38 - return;  
39 - }  
40 -  
41 - int toIndx = page * count;  
42 - if (toIndx > this.total) {  
43 - toIndx = this.total;  
44 - }  
45 - this.list = this.resultData.subList(fromIndx, toIndx);  
46 - this.size = this.list.size();  
47 - }  
48 -  
49 - public int getPageNum() {  
50 - return pageNum;  
51 - }  
52 -  
53 - public void setPageNum(int pageNum) {  
54 - this.pageNum = pageNum;  
55 - }  
56 -  
57 - public int getPageSize() {  
58 - return pageSize;  
59 - }  
60 -  
61 - public void setPageSize(int pageSize) {  
62 - this.pageSize = pageSize;  
63 - }  
64 -  
65 - public int getSize() {  
66 - return size;  
67 - }  
68 -  
69 - public void setSize(int size) {  
70 - this.size = size;  
71 - }  
72 -  
73 - public int getPages() {  
74 - return pages;  
75 - }  
76 -  
77 - public void setPages(int pages) {  
78 - this.pages = pages;  
79 - }  
80 -  
81 - public int getTotal() {  
82 - return total;  
83 - }  
84 -  
85 - public void setTotal(int total) {  
86 - this.total = total;  
87 - }  
88 -  
89 - public List<T> getList() {  
90 - return list;  
91 - }  
92 -  
93 - public void setList(List<T> list) {  
94 - this.list = list;  
95 - }  
96 -}  
src/main/resources/all-application.yml
@@ -28,10 +28,10 @@ server: @@ -28,10 +28,10 @@ server:
28 28
29 # [根据业务需求配置] 29 # [根据业务需求配置]
30 user-settings: 30 user-settings:
31 - # [可选 ] zlm配置的录像路径,不配置则使用当前目录下的record目录 即: ./record  
32 - record: /media/lin/Server/ZLMediaKit/dev/ZLMediaKit/release/linux/Debug/www/record 31 + # [可选 ] 临时录像路径
  32 + record-temp-path: ./recordTemp
33 # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理, 不配置则不删除 33 # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理, 不配置则不删除
34 - recordDay: 7 34 + record-temp-day: 7
35 # [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理 35 # [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理
36 # recordTempDay: 7 36 # recordTempDay: 7
37 # [必选 ] ffmpeg路径 37 # [必选 ] ffmpeg路径
src/main/resources/application-local.yml
@@ -11,7 +11,7 @@ spring: @@ -11,7 +11,7 @@ spring:
11 # [可选] 数据库 DB 11 # [可选] 数据库 DB
12 database: 1 12 database: 1
13 # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 13 # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
14 - password: adminadmin123. 14 + password:
15 # 以下为集群配置 15 # 以下为集群配置
16 # cluster: 16 # cluster:
17 # nodes: 192.168.1.242:7001 17 # nodes: 192.168.1.242:7001
@@ -33,18 +33,13 @@ server: @@ -33,18 +33,13 @@ server:
33 33
34 # [根据业务需求配置] 34 # [根据业务需求配置]
35 userSettings: 35 userSettings:
36 - # [必选 ] 服务ID  
37 - id: 334533  
38 - # [必选 ] 录像路径  
39 - record: /home/lin/record/  
40 - # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理  
41 - recordDay: 10  
42 - # [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理  
43 - # recordTempDay: 7 36 + id: 111
  37 + # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理, 不配置则不删除
  38 + record-temp-day: 7
44 # [必选 ] ffmpeg路径 39 # [必选 ] ffmpeg路径
45 - ffmpeg: /home/lin/IdeaProjects/wvp-pro-assist/lib/ffmpeg 40 + ffmpeg: ./lib/ffmpeg
46 # [必选 ] ffprobe路径, 一般安装ffmpeg就会自带, 一般跟ffmpeg在同一目录,用于查询文件的信息, 41 # [必选 ] ffprobe路径, 一般安装ffmpeg就会自带, 一般跟ffmpeg在同一目录,用于查询文件的信息,
47 - ffprobe: /home/lin/IdeaProjects/wvp-pro-assist/lib/ffprobe 42 + ffprobe: ./lib/ffprobe
48 # [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50% 43 # [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50%
49 threads: 2 44 threads: 2
50 45