Commit cfc4df108e2652c1c1975e204d57fe290b5e1bc0

Authored by 64850858
1 parent f3e2bf1e

修改接口bug

.gitignore
  1 +/target/
1 2 /.idea/
  3 +/logs/
... ...
... ... @@ -81,6 +81,14 @@
81 81 <groupId>org.springframework.boot</groupId>
82 82 <artifactId>spring-boot-maven-plugin</artifactId>
83 83 </plugin>
  84 + <plugin>
  85 + <groupId>org.apache.maven.plugins</groupId>
  86 + <artifactId>maven-compiler-plugin</artifactId>
  87 + <configuration>
  88 + <source>1.8</source>
  89 + <target>1.8</target>
  90 + </configuration>
  91 + </plugin>
84 92 </plugins>
85 93 </build>
86 94  
... ...
src/main/java/top/panll/assist/config/FastJsonRedisSerializer.java 0 → 100644
  1 +package top.panll.assist.config;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.parser.ParserConfig;
  5 +import com.alibaba.fastjson.serializer.SerializerFeature;
  6 +import org.springframework.data.redis.serializer.RedisSerializer;
  7 +import org.springframework.data.redis.serializer.SerializationException;
  8 +
  9 +import java.nio.charset.Charset;
  10 +
  11 +public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
  12 + private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
  13 + private Class<T> clazz;
  14 +
  15 + /**
  16 + * 添加autotype白名单
  17 + * 解决redis反序列化对象时报错 :com.alibaba.fastjson.JSONException: autoType is not support
  18 + */
  19 + static {
  20 + ParserConfig.getGlobalInstance().addAccept("top.panll.assist");
  21 + }
  22 +
  23 + public FastJsonRedisSerializer(Class<T> clazz) {
  24 + super();
  25 + this.clazz = clazz;
  26 + }
  27 +
  28 + @Override
  29 + public byte[] serialize(T t) throws SerializationException {
  30 + if (null == t) {
  31 + return new byte[0];
  32 + }
  33 + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
  34 + }
  35 +
  36 + @Override
  37 + public T deserialize(byte[] bytes) throws SerializationException {
  38 + if (null == bytes || bytes.length <= 0) {
  39 + return null;
  40 + }
  41 + String str = new String(bytes, DEFAULT_CHARSET);
  42 + return JSON.parseObject(str, clazz);
  43 + }
  44 +}
... ...
src/main/java/top/panll/assist/config/RedisConfig.java
1 1 package top.panll.assist.config;
2 2  
3 3 import com.alibaba.fastjson.parser.ParserConfig;
4   -import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
5   -import org.springframework.cache.annotation.CachingConfigurerSupport;
  4 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  5 +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  6 +import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
  7 +import org.springframework.boot.context.properties.EnableConfigurationProperties;
6 8 import org.springframework.context.annotation.Bean;
7 9 import org.springframework.context.annotation.Configuration;
8 10 import org.springframework.data.redis.connection.RedisConnectionFactory;
  11 +import org.springframework.data.redis.core.RedisOperations;
9 12 import org.springframework.data.redis.core.RedisTemplate;
10 13 import org.springframework.data.redis.listener.RedisMessageListenerContainer;
11 14 import org.springframework.data.redis.serializer.StringRedisSerializer;
... ... @@ -17,14 +20,21 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
17 20 *
18 21 */
19 22 @Configuration
20   -public class RedisConfig extends CachingConfigurerSupport {
  23 +@ConditionalOnClass(RedisOperations.class)
  24 +@EnableConfigurationProperties(RedisProperties.class)
  25 +public class RedisConfig {
21 26  
22   - @Bean("redisTemplate")
  27 + static {
  28 + ParserConfig.getGlobalInstance().addAccept("top.panll.assist");
  29 + }
  30 +
  31 + @Bean
  32 + @ConditionalOnMissingBean(name = "redisTemplate")
23 33 public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
24 34 RedisTemplate<Object, Object> template = new RedisTemplate<>();
25 35 template.setConnectionFactory(redisConnectionFactory);
26 36 // 使用fastjson进行序列化处理,提高解析效率
27   - FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<Object>(Object.class);
  37 + FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
28 38 // value值的序列化采用fastJsonRedisSerializer
29 39 template.setValueSerializer(serializer);
30 40 template.setHashValueSerializer(serializer);
... ... @@ -33,8 +43,9 @@ public class RedisConfig extends CachingConfigurerSupport {
33 43 template.setHashKeySerializer(new StringRedisSerializer());
34 44 template.setConnectionFactory(redisConnectionFactory);
35 45 // 使用fastjson时需设置此项,否则会报异常not support type
36   - ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
  46 +// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
37 47 return template;
  48 +
38 49 }
39 50  
40 51 /**
... ...
src/main/java/top/panll/assist/config/StartConfig.java
... ... @@ -53,7 +53,7 @@ public class StartConfig implements CommandLineRunner {
53 53 String ffprobePath = userSettings.getFfprobe();
54 54 FFmpeg ffmpeg = new FFmpeg(ffmpegPath);
55 55 FFprobe ffprobe = new FFprobe(ffprobePath);
56   - logger.info("wvp-pro辅助程序启动成功");
  56 + logger.info("wvp-pro辅助程序启动成功。 \n{}\n{} ", ffmpeg.version(), ffprobe.version());
57 57 FFmpegExecUtils.getInstance().ffmpeg = ffmpeg;
58 58 FFmpegExecUtils.getInstance().ffprobe = ffprobe;
59 59 // 对目录进行预整理
... ...
src/main/java/top/panll/assist/config/TaskConfig.java
... ... @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
6 6 import org.springframework.context.annotation.Configuration;
7 7 import org.springframework.scheduling.annotation.EnableScheduling;
8 8 import org.springframework.scheduling.annotation.Scheduled;
  9 +import org.springframework.stereotype.Component;
9 10 import top.panll.assist.service.VideoFileService;
10 11  
11 12 import java.io.File;
... ... @@ -16,7 +17,7 @@ import java.util.Calendar;
16 17 import java.util.Date;
17 18 import java.util.List;
18 19  
19   -@Configuration
  20 +@Component
20 21 @EnableScheduling
21 22 public class TaskConfig {
22 23  
... ...
src/main/java/top/panll/assist/controller/RecordController.java
1 1 package top.panll.assist.controller;
2 2  
  3 +import com.alibaba.fastjson.JSONObject;
3 4 import org.slf4j.Logger;
4 5 import org.slf4j.LoggerFactory;
5 6 import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.http.HttpStatus;
  8 +import org.springframework.http.ResponseEntity;
6 9 import org.springframework.web.bind.annotation.*;
7 10 import top.panll.assist.controller.bean.WVPResult;
  11 +import top.panll.assist.dto.MergeOrCutTaskInfo;
8 12 import top.panll.assist.service.VideoFileService;
9 13 import top.panll.assist.utils.PageInfo;
10 14  
... ... @@ -105,11 +109,11 @@ public class RecordController {
105 109 */
106 110 @GetMapping(value = "/date/list")
107 111 @ResponseBody
108   - public WVPResult<PageInfo<String>> getDateList(@RequestParam int page,
109   - @RequestParam int count,
110   - @RequestParam String app,
111   - @RequestParam String stream ){
112   - WVPResult<PageInfo<String>> result = new WVPResult<>();
  112 + public WVPResult<List<String>> getDateList( @RequestParam(required = false) Integer year,
  113 + @RequestParam(required = false) Integer month,
  114 + @RequestParam String app,
  115 + @RequestParam String stream ){
  116 + WVPResult<List<String>> result = new WVPResult<>();
113 117 List<String> resultData = new ArrayList<>();
114 118 if (app == null) {
115 119 result.setCode(400);
... ... @@ -121,15 +125,13 @@ public class RecordController {
121 125 result.setMsg("stream不能为空");
122 126 return result;
123 127 }
124   - List<File> dateList = videoFileService.getDateList(app, stream);
  128 + List<File> dateList = videoFileService.getDateList(app, stream, year, month);
125 129 for (File file : dateList) {
126 130 resultData.add(file.getName());
127 131 }
128 132 result.setCode(0);
129 133 result.setMsg("success");
130   - PageInfo<String> stringPageInfo = new PageInfo<>(resultData);
131   - stringPageInfo.startPage(page, count);
132   - result.setData(stringPageInfo);
  134 + result.setData(resultData);
133 135 return result;
134 136 }
135 137  
... ... @@ -188,7 +190,7 @@ public class RecordController {
188 190 * @param endTime
189 191 * @return
190 192 */
191   - @GetMapping(value = "/file/download/task")
  193 + @GetMapping(value = "/file/download/task/add")
192 194 @ResponseBody
193 195 public WVPResult<String> addTaskForDownload(@RequestParam String app,
194 196 @RequestParam String stream,
... ... @@ -210,35 +212,63 @@ public class RecordController {
210 212 }
211 213 String id = videoFileService.mergeOrCut(app, stream, startTimeDate, endTimeDate);
212 214 result.setCode(0);
213   - result.setMsg(id!= null?"success":"error");
  215 + result.setMsg(id!= null?"success":"error: 可能未找到视频文件");
214 216 result.setData(id);
215 217 return result;
216 218 }
217 219  
218 220 /**
219   - * 录制完成的通知
  221 + * 查询视频裁剪合并任务列表
220 222 * @return
221 223 */
222   - @GetMapping(value = "/end")
  224 + @GetMapping(value = "/file/download/task/list")
223 225 @ResponseBody
224   - public WVPResult<String> recordEnd(@RequestParam String path
225   - ){
226   - File file = new File(path);
227   - WVPResult<String> result = new WVPResult<>();
228   - if (file.exists()) {
229   - try {
230   - videoFileService.handFile(file);
231   - result.setCode(0);
232   - result.setMsg("success");
233   - } catch (ParseException e) {
234   - e.printStackTrace();
235   - result.setCode(500);
236   - result.setMsg("error");
237   - }
238   - }else {
239   - result.setCode(400);
240   - result.setMsg("路径不存在");
  226 + public WVPResult<List<MergeOrCutTaskInfo>> getTaskListForDownload(@RequestParam Boolean isEnd){
  227 + if (isEnd == null) {
  228 + isEnd = false;
241 229 }
  230 + List<MergeOrCutTaskInfo> taskList = videoFileService.getTaskListForDownload(isEnd);
  231 + WVPResult<List<MergeOrCutTaskInfo>> result = new WVPResult<>();
  232 + result.setCode(0);
  233 + result.setMsg(taskList != null?"success":"error");
  234 + result.setData(taskList);
242 235 return result;
243 236 }
  237 +
  238 + /**
  239 + * TODO 中止视频裁剪合并任务列表
  240 + * @return
  241 + */
  242 + @GetMapping(value = "/file/download/task/stop")
  243 + @ResponseBody
  244 + public WVPResult<String> stopTaskForDownload(@RequestParam String taskId){
  245 +// WVPResult<String> result = new WVPResult<>();
  246 +// if (taskId == null) {
  247 +// result.setCode(400);
  248 +// result.setMsg("taskId 不能为空");
  249 +// return result;
  250 +// }
  251 +// boolean stopResult = videoFileService.stopTask(taskId);
  252 +// result.setCode(0);
  253 +// result.setMsg(stopResult ? "success": "fail");
  254 + return null;
  255 + }
  256 +
  257 + /**
  258 + * 录制完成的通知, 对用zlm的hook
  259 + * @return
  260 + */
  261 + @ResponseBody
  262 + @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8")
  263 + public ResponseEntity<String> onRecordMp4(@RequestBody JSONObject json) {
  264 + JSONObject ret = new JSONObject();
  265 + ret.put("code", 0);
  266 + ret.put("msg", "success");
  267 + String file_path = json.getString("file_path");
  268 + logger.debug("ZLM 录制完成,参数:" + file_path);
  269 + if (file_path == null) return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
  270 + videoFileService.handFile(new File(file_path));
  271 +
  272 + return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
  273 + }
244 274 }
... ...
src/main/java/top/panll/assist/dto/MergeOrCutTaskInfo.java 0 → 100644
  1 +package top.panll.assist.dto;
  2 +
  3 +import java.util.Date;
  4 +
  5 +public class MergeOrCutTaskInfo {
  6 + private String id;
  7 + private String startTime;
  8 + private String endTime;
  9 + private String app;
  10 + private String stream;
  11 +
  12 + private String percentage;
  13 +
  14 + private String recordFile;
  15 +
  16 + public String getId() {
  17 + return id;
  18 + }
  19 +
  20 + public void setId(String id) {
  21 + this.id = id;
  22 + }
  23 +
  24 + public String getStartTime() {
  25 + return startTime;
  26 + }
  27 +
  28 + public void setStartTime(String startTime) {
  29 + this.startTime = startTime;
  30 + }
  31 +
  32 + public String getEndTime() {
  33 + return endTime;
  34 + }
  35 +
  36 + public void setEndTime(String endTime) {
  37 + this.endTime = endTime;
  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 getPercentage() {
  57 + return percentage;
  58 + }
  59 +
  60 + public void setPercentage(String percentage) {
  61 + this.percentage = percentage;
  62 + }
  63 +
  64 + public String getRecordFile() {
  65 + return recordFile;
  66 + }
  67 +
  68 + public void setRecordFile(String recordFile) {
  69 + this.recordFile = recordFile;
  70 + }
  71 +}
... ...
src/main/java/top/panll/assist/service/FFmpegExecUtils.java
... ... @@ -51,7 +51,6 @@ public class FFmpegExecUtils {
51 51 return null;
52 52 }
53 53  
54   -
55 54 File tempFile = new File(dest.getAbsolutePath() + File.separator + temp);
56 55 if (!tempFile.exists()) {
57 56 tempFile.mkdirs();
... ... @@ -66,14 +65,12 @@ public class FFmpegExecUtils {
66 65 if (split.length != 3) continue;
67 66 String durationStr = split[2].replace(".mp4", "");
68 67 Double duration = Double.parseDouble(durationStr)/1000;
69   - System.out.println(duration);
70 68 bw.write("file " + file.getAbsolutePath());
71 69 bw.newLine();
72 70 durationAll += duration;
73 71 }
74 72 bw.flush();
75 73 bw.close();
76   - System.out.println(durationAll);
77 74 } catch (IOException e) {
78 75 e.printStackTrace();
79 76 callBack.run("error", 0.0, null);
... ... @@ -91,7 +88,6 @@ public class FFmpegExecUtils {
91 88 .setFormat("mp4")
92 89 .done();
93 90  
94   -
95 91 double finalDurationAll = durationAll;
96 92 FFmpegJob job = executor.createJob(builder, (Progress progress) -> {
97 93 final double duration_ns = finalDurationAll * TimeUnit.SECONDS.toNanos(1);
... ... @@ -107,6 +103,7 @@ public class FFmpegExecUtils {
107 103 // progress.fps.doubleValue(),
108 104 // progress.speed
109 105 // ));
  106 +
110 107 if (progress.status.equals(Progress.Status.END)){
111 108 callBack.run(progress.status.name(), percentage,dest.getName() + File.separator + temp + File.separator + "record.mp4");
112 109 System.out.println(System.currentTimeMillis() - startTime);
... ... @@ -114,7 +111,6 @@ public class FFmpegExecUtils {
114 111 callBack.run(progress.status.name(), percentage, null);
115 112 }
116 113 });
117   -
118 114 job.run();
119 115 return temp;
120 116 }
... ...
src/main/java/top/panll/assist/service/VideoFileService.java
1 1 package top.panll.assist.service;
2 2  
3   -import com.alibaba.fastjson.JSON;
  3 +import com.alibaba.fastjson.JSONObject;
4 4 import net.bramp.ffmpeg.FFprobe;
5 5 import net.bramp.ffmpeg.probe.FFmpegProbeResult;
6 6 import net.bramp.ffmpeg.progress.Progress;
... ... @@ -11,12 +11,15 @@ import org.springframework.context.annotation.Bean;
11 11 import org.springframework.data.redis.core.StringRedisTemplate;
12 12 import org.springframework.stereotype.Service;
13 13 import org.springframework.util.DigestUtils;
14   -import top.panll.assist.config.RedisUtil;
  14 +import top.panll.assist.utils.RedisUtil;
  15 +import top.panll.assist.dto.MergeOrCutTaskInfo;
15 16 import top.panll.assist.dto.UserSettings;
16 17 import top.panll.assist.utils.DateUtils;
17 18  
18 19 import java.io.File;
19 20 import java.io.IOException;
  21 +import java.nio.file.Files;
  22 +import java.nio.file.attribute.BasicFileAttributes;
20 23 import java.text.ParseException;
21 24 import java.text.SimpleDateFormat;
22 25 import java.util.*;
... ... @@ -41,7 +44,9 @@ public class VideoFileService {
41 44 private ThreadPoolExecutor processThreadPool;
42 45  
43 46 private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  47 + private SimpleDateFormat simpleDateFormatForTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
44 48  
  49 + private String keyStr = "MERGEORCUT";
45 50  
46 51 @Bean("threadPoolExecutor")
47 52 private ThreadPoolExecutor iniThreadPool() {
... ... @@ -84,9 +89,9 @@ public class VideoFileService {
84 89 * @param file
85 90 * @throws ParseException
86 91 */
87   - public void handFile(File file) throws ParseException {
  92 + public void handFile(File file) {
88 93 FFprobe ffprobe = FFmpegExecUtils.getInstance().ffprobe;
89   - if(file.isFile() && !file.getName().startsWith(".")&& file.getName().endsWith(".mp4") && file.getName().indexOf(":") < 0) {
  94 + if(file.exists() && file.isFile() && !file.getName().startsWith(".")&& file.getName().endsWith(".mp4") && file.getName().indexOf(":") < 0) {
90 95 try {
91 96 FFmpegProbeResult in = null;
92 97 in = ffprobe.probe(file.getAbsolutePath());
... ... @@ -107,8 +112,11 @@ public class VideoFileService {
107 112 simpleDateFormat.format(startTime) + "-" + simpleDateFormat.format(endTime) + "-" + durationLong + ".mp4");
108 113 file.renameTo(new File(newName));
109 114 System.out.println(newName);
110   - } catch (IOException exception) {
111   - exception.printStackTrace();
  115 + } catch (IOException e) {
  116 + logger.warn("文件可能以损坏[{}]", file.getAbsolutePath());
  117 +// e.printStackTrace();
  118 + } catch (ParseException e) {
  119 + logger.error("时间格式化失败", e.getMessage());
112 120 }
113 121 }
114 122 }
... ... @@ -127,19 +135,30 @@ public class VideoFileService {
127 135 data.put("app", appFile.getName());
128 136 data.put("stream", streamFile.getName());
129 137  
130   -// BasicFileAttributes bAttributes = null;
131   -// try {
132   -// bAttributes = Files.readAttributes(streamFile.toPath(),
133   -// BasicFileAttributes.class);
134   -// } catch (IOException e) {
135   -// e.printStackTrace();
136   -// }
137   -// data.put("time", simpleDateFormat.format(new Date(bAttributes.lastModifiedTime().toMillis())));
  138 + BasicFileAttributes bAttributes = null;
  139 + try {
  140 + bAttributes = Files.readAttributes(streamFile.toPath(),
  141 + BasicFileAttributes.class);
  142 + } catch (IOException e) {
  143 + e.printStackTrace();
  144 + }
  145 + data.put("time", simpleDateFormatForTime.format(new Date(bAttributes.lastModifiedTime().toMillis())));
138 146 result.add(data);
139 147 }
140 148 }
141 149 }
142 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.getMessage());
  159 + }
  160 + return time1.compareTo(time2) * -1;
  161 + });
143 162 return result;
144 163 }
145 164  
... ... @@ -175,14 +194,16 @@ public class VideoFileService {
175 194 }
176 195 File[] dateFiles = streamFile.listFiles((File dir, String name) -> {
177 196 Date fileDate = null;
  197 + Date startDate = new Date(startTime.getTime() - ((startTime.getTime() + 28800000) % (86400000)));
  198 + Date endDate = new Date(endTime.getTime() - ((endTime.getTime() + 28800000) % (86400000)));
178 199 try {
179 200 fileDate = formatterForDate.parse(name);
180 201 } catch (ParseException e) {
181 202 logger.error("过滤日期文件时异常: {}-{}", name, e.getMessage());
182 203 return false;
183 204 }
184   - return (DateUtils.getStartOfDay(fileDate).compareTo(startTime) >= 0
185   - && DateUtils.getStartOfDay(fileDate).compareTo(endTime) <= 0) ;
  205 + return (DateUtils.getStartOfDay(fileDate).compareTo(startDate) <= 0
  206 + && DateUtils.getStartOfDay(fileDate).compareTo(endDate) >= 0) ;
186 207 });
187 208  
188 209 if (dateFiles != null && dateFiles.length > 0) {
... ... @@ -235,50 +256,131 @@ public class VideoFileService {
235 256  
236 257 public String mergeOrCut(String app, String stream, Date startTime, Date endTime) {
237 258 List<File> filesInTime = this.getFilesInTime(app, stream, startTime, endTime);
  259 + if (filesInTime== null || filesInTime.size() == 0){
  260 + logger.info("此时间段未未找到视频文件");
  261 + return null;
  262 + }
238 263 File recordFile = new File(new File(userSettings.getRecord()).getParentFile().getAbsolutePath() + File.separator + "recordTemp");
239 264 if (!recordFile.exists()) recordFile.mkdirs();
240 265  
241   - String temp = DigestUtils.md5DigestAsHex(String.valueOf(System.currentTimeMillis()).getBytes());
242   - processThreadPool.execute(() -> {
243   - FFmpegExecUtils.getInstance().mergeOrCutFile(filesInTime, recordFile, temp, (String status, double percentage, String result)->{
244   - Map<String, String> data = new HashMap<>();
245   - data.put("id", temp);
  266 + String taskId = DigestUtils.md5DigestAsHex(String.valueOf(System.currentTimeMillis()).getBytes());
  267 + MergeOrCutTaskInfo mergeOrCutTaskInfo = new MergeOrCutTaskInfo();
  268 + mergeOrCutTaskInfo.setId(taskId);
  269 + mergeOrCutTaskInfo.setApp(app);
  270 + mergeOrCutTaskInfo.setStream(stream);
  271 + mergeOrCutTaskInfo.setStartTime(simpleDateFormatForTime.format(startTime));
  272 + mergeOrCutTaskInfo.setEndTime(simpleDateFormatForTime.format(endTime));
  273 +
  274 + Runnable task = () -> {
  275 + FFmpegExecUtils.getInstance().mergeOrCutFile(filesInTime, recordFile, taskId, (String status, double percentage, String result)->{
  276 +
246 277 // 发出redis通知
247 278 if (status.equals(Progress.Status.END.name())) {
248   - data.put("percentage", "1");
249   - data.put("recordFile", result);
250   - redisUtil.set(app + "_" + stream + "_" + temp, data, 3*60*60);
251   - stringRedisTemplate.convertAndSend("topic_mergeorcut_end", JSON.toJSONString(data));
  279 + mergeOrCutTaskInfo.setPercentage("1");
  280 + mergeOrCutTaskInfo.setRecordFile(result);
  281 + stringRedisTemplate.convertAndSend("topic_mergeorcut_end", JSONObject.toJSONString(mergeOrCutTaskInfo));
252 282 }else {
253   - data.put("percentage", percentage + "");
254   - redisUtil.set(app + "_" + stream + "_" + temp, data, 3*60*60);
255   - stringRedisTemplate.convertAndSend("topic_mergeorcut_continue", JSON.toJSONString(data));
  283 + mergeOrCutTaskInfo.setPercentage(percentage + "");
  284 + stringRedisTemplate.convertAndSend("topic_mergeorcut_continue", JSONObject.toJSONString(mergeOrCutTaskInfo));
256 285 }
  286 + String key = String.format("%S_%S_%S_%S", keyStr, app, stream, taskId);
  287 + redisUtil.set(key, mergeOrCutTaskInfo);
257 288 });
258   - });
259   - return temp;
  289 + };
  290 + processThreadPool.execute(task);
  291 + return taskId;
260 292 }
261 293  
262 294  
263   - public List<File> getDateList(String app, String stream) {
  295 + public List<File> getDateList(String app, String stream, Integer year, Integer month) {
264 296 File recordFile = new File(userSettings.getRecord());
265 297 File streamFile = new File(recordFile.getAbsolutePath() + File.separator + app + File.separator + stream);
266 298 if (!streamFile.exists()) {
267 299 logger.warn("获取[app: {}, stream: {}]的视频时未找到目录: {}", app, stream, stream);
268 300 return null;
269 301 }
270   - File[] dateFiles = streamFile.listFiles();
  302 + File[] dateFiles = streamFile.listFiles((File dir, String name)->{
  303 + Date date = null;
  304 + try {
  305 + date = simpleDateFormat.parse(name);
  306 + } catch (ParseException e) {
  307 + logger.error("格式化时间{}错误", name);
  308 + }
  309 + Calendar c = Calendar.getInstance();
  310 + c.setTime(date);
  311 + int y = c.get(Calendar.YEAR);
  312 + int m = c.get(Calendar.MONTH);
  313 + if (year != null) {
  314 + if (month != null) {
  315 + return y == year && m == month;
  316 + }else {
  317 + return y == year;
  318 + }
  319 + }else {
  320 + return true;
  321 + }
  322 +
  323 + });
271 324 List<File> dateFileList = Arrays.asList(dateFiles);
  325 +
272 326 dateFileList.sort((File f1, File f2)->{
273 327 int sortResult = 0;
274   - SimpleDateFormat formatterForDate = new SimpleDateFormat("yyyy-MM-dd");
  328 +
275 329 try {
276   - sortResult = formatterForDate.parse(f1.getName()).compareTo(formatterForDate.parse(f2.getName()));
  330 + sortResult = simpleDateFormat.parse(f1.getName()).compareTo(simpleDateFormat.parse(f2.getName()));
277 331 } catch (ParseException e) {
278   - e.printStackTrace();
  332 + logger.error("格式化时间{}/{}错误", f1.getName(), f2.getName());
279 333 }
280 334 return sortResult;
281 335 });
282 336 return dateFileList;
283 337 }
  338 +
  339 + public List<MergeOrCutTaskInfo> getTaskListForDownload(boolean idEnd) {
  340 + ArrayList<MergeOrCutTaskInfo> result = new ArrayList<>();
  341 + List<Object> taskCatch = redisUtil.scan(String.format("%S_*_*_*", keyStr));
  342 + for (int i = 0; i < taskCatch.size(); i++) {
  343 + String keyItem = taskCatch.get(i).toString();
  344 + MergeOrCutTaskInfo mergeOrCutTaskInfo = (MergeOrCutTaskInfo)redisUtil.get(keyItem);
  345 + if (mergeOrCutTaskInfo != null){
  346 + if (idEnd) {
  347 + if (Double.parseDouble(mergeOrCutTaskInfo.getPercentage()) == 1){
  348 + result.add(mergeOrCutTaskInfo);
  349 + }
  350 + }else {
  351 + if (Double.parseDouble(mergeOrCutTaskInfo.getPercentage()) < 1){
  352 + result.add((MergeOrCutTaskInfo)redisUtil.get(keyItem));
  353 + }
  354 + }
  355 + }
  356 + }
  357 + result.sort((MergeOrCutTaskInfo m1, MergeOrCutTaskInfo m2)->{
  358 + int sortResult = 0;
  359 + try {
  360 + sortResult = simpleDateFormatForTime.parse(m1.getStartTime()).compareTo(simpleDateFormatForTime.parse(m2.getStartTime()));
  361 + if (sortResult == 0) {
  362 + sortResult = simpleDateFormatForTime.parse(m1.getEndTime()).compareTo(simpleDateFormatForTime.parse(m2.getEndTime()));
  363 + }
  364 + } catch (ParseException e) {
  365 + e.printStackTrace();
  366 + }
  367 + return sortResult * -1;
  368 + });
  369 + return result;
  370 + }
  371 +
  372 + public boolean stopTask(String taskId) {
  373 +// Runnable task = taskList.get(taskId);
  374 +// boolean result = false;
  375 +// if (task != null) {
  376 +// processThreadPool.remove(task);
  377 +// taskList.remove(taskId);
  378 +// List<Object> taskCatch = redisUtil.scan(String.format("%S_*_*_%S", keyStr, taskId));
  379 +// if (taskCatch.size() == 1) {
  380 +// redisUtil.del((String) taskCatch.get(0));
  381 +// result = true;
  382 +// }
  383 +// }
  384 + return false;
  385 + }
284 386 }
... ...
src/main/java/top/panll/assist/config/RedisUtil.java renamed to src/main/java/top/panll/assist/utils/RedisUtil.java
1   -package top.panll.assist.config;
  1 +package top.panll.assist.utils;
2 2  
3 3 import org.springframework.beans.factory.annotation.Autowired;
4 4 import org.springframework.data.redis.core.*;
... ... @@ -18,7 +18,7 @@ import java.util.concurrent.TimeUnit;
18 18 public class RedisUtil {
19 19  
20 20 @Autowired
21   - private RedisTemplate redisTemplate;
  21 + private RedisTemplate<Object, Object> redisTemplate;
22 22  
23 23 /**
24 24 * 指定缓存失效时间
... ... @@ -474,7 +474,7 @@ public class RedisUtil {
474 474 * @param end
475 475 * @return
476 476 */
477   - public Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(Object key, int start, int end) {
  477 + public Set<ZSetOperations.TypedTuple<Object>> zRangeWithScore(Object key, int start, int end) {
478 478 return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
479 479 }
480 480 /**
... ... @@ -487,7 +487,7 @@ public class RedisUtil {
487 487 * @param end
488 488 * @return
489 489 */
490   - public Set<String> zRevRange(Object key, int start, int end) {
  490 + public Set<Object> zRevRange(Object key, int start, int end) {
491 491 return redisTemplate.opsForZSet().reverseRange(key, start, end);
492 492 }
493 493 /**
... ... @@ -498,7 +498,7 @@ public class RedisUtil {
498 498 * @param max
499 499 * @return
500 500 */
501   - public Set<String> zSortRange(Object key, int min, int max) {
  501 + public Set<Object> zSortRange(Object key, int min, int max) {
502 502 return redisTemplate.opsForZSet().rangeByScore(key, min, max);
503 503 }
504 504  
... ... @@ -666,7 +666,7 @@ public class RedisUtil {
666 666 */
667 667 public List<Object> keys(String key) {
668 668 try {
669   - Set<String> set = redisTemplate.keys(key);
  669 + Set<Object> set = redisTemplate.keys(key);
670 670 return new ArrayList<>(set);
671 671 } catch (Exception e) {
672 672 e.printStackTrace();
... ...
src/main/resources/application-dev.yml
... ... @@ -46,8 +46,7 @@ logging:
46 46 max-size: 10MB
47 47 total-size-cap: 300MB
48 48 level:
49   - com:
50   - genersoft:
51   - iot: info
52   - net:
53   - bramp: warning
54 49 \ No newline at end of file
  50 + root: WARN
  51 + top:
  52 + panll:
  53 + assist: info
55 54 \ No newline at end of file
... ...
src/main/resources/application-local.yml
... ... @@ -6,7 +6,7 @@ spring:
6 6 # [必须修改] 端口号
7 7 port: 6379
8 8 # [可选] 数据库 DB
9   - database: 8
  9 + database: 10
10 10 # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
11 11 password:
12 12 # [可选] 超时时间
... ... @@ -29,7 +29,7 @@ server:
29 29 # [根据业务需求配置]
30 30 userSettings:
31 31 # [必选 ] zlm配置的录像路径
32   - record: /media/lin/Server/ZLMediaKit/dev/ZLMediaKit/release/linux/Debug/www/record
  32 + record: /home/lin/server/ZLMediaKit/release/linux/Debug/www/record/
33 33 # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理
34 34 recordDay: 7
35 35 # [必选 ] ffmpeg路径
... ... @@ -45,8 +45,7 @@ logging:
45 45 max-size: 10MB
46 46 total-size-cap: 300MB
47 47 level:
48   - com:
49   - genersoft:
50   - iot: info
51   - net:
52   - bramp: warning
53 48 \ No newline at end of file
  49 + root: WARN
  50 + top:
  51 + panll:
  52 + assist: debug
54 53 \ No newline at end of file
... ...