Commit e8ac6bf8af09213d36df2fde8cc1bf4bc405f1a3
1 parent
6f091112
添加获取视频时长接口
Showing
4 changed files
with
93 additions
and
8 deletions
pom.xml
| @@ -44,12 +44,6 @@ | @@ -44,12 +44,6 @@ | ||
| 44 | </dependency> | 44 | </dependency> |
| 45 | 45 | ||
| 46 | <dependency> | 46 | <dependency> |
| 47 | - <groupId>log4j</groupId> | ||
| 48 | - <artifactId>log4j</artifactId> | ||
| 49 | - <version>1.2.17</version> | ||
| 50 | - </dependency> | ||
| 51 | - | ||
| 52 | - <dependency> | ||
| 53 | <groupId>net.bramp.ffmpeg</groupId> | 47 | <groupId>net.bramp.ffmpeg</groupId> |
| 54 | <artifactId>ffmpeg</artifactId> | 48 | <artifactId>ffmpeg</artifactId> |
| 55 | <version>0.6.2</version> | 49 | <version>0.6.2</version> |
src/main/java/top/panll/assist/controller/RecordController.java
| @@ -411,4 +411,25 @@ public class RecordController { | @@ -411,4 +411,25 @@ public class RecordController { | ||
| 411 | ret.put("data", JSON.toJSON(spaceInfo)); | 411 | ret.put("data", JSON.toJSON(spaceInfo)); |
| 412 | return new ResponseEntity<>(ret.toString(), HttpStatus.OK); | 412 | return new ResponseEntity<>(ret.toString(), HttpStatus.OK); |
| 413 | } | 413 | } |
| 414 | + | ||
| 415 | + /** | ||
| 416 | + * 录像文件的时长 | ||
| 417 | + */ | ||
| 418 | + @ApiOperation("录像文件的时长") | ||
| 419 | + @ApiImplicitParams({ | ||
| 420 | + @ApiImplicitParam(name="app", value = "应用名", required = true, dataTypeClass = String.class), | ||
| 421 | + @ApiImplicitParam(name="stream", value = "流ID", required = true, dataTypeClass = String.class), | ||
| 422 | + @ApiImplicitParam(name="recordIng", value = "是否录制中", required = false, dataTypeClass = String.class), | ||
| 423 | + }) | ||
| 424 | + @ResponseBody | ||
| 425 | + @GetMapping(value = "/file/duration", produces = "application/json;charset=UTF-8") | ||
| 426 | + public ResponseEntity<String> fileDuration( @RequestParam String app, @RequestParam String stream, Boolean recordIng) { | ||
| 427 | + if (recordIng == null) recordIng = true; | ||
| 428 | + JSONObject ret = new JSONObject(); | ||
| 429 | + ret.put("code", 0); | ||
| 430 | + ret.put("msg", "success"); | ||
| 431 | + Double duration = videoFileService.fileDuration(app, stream, recordIng); | ||
| 432 | + ret.put("data", duration); | ||
| 433 | + return new ResponseEntity<>(ret.toString(), HttpStatus.OK); | ||
| 434 | + } | ||
| 414 | } | 435 | } |
src/main/java/top/panll/assist/service/FFmpegExecUtils.java
| @@ -72,6 +72,8 @@ public class FFmpegExecUtils implements InitializingBean{ | @@ -72,6 +72,8 @@ public class FFmpegExecUtils implements InitializingBean{ | ||
| 72 | logger.info("wvp-pro辅助程序启动成功。 \n{}\n{} ", this.ffmpeg.version(), this.ffprobe.version()); | 72 | logger.info("wvp-pro辅助程序启动成功。 \n{}\n{} ", this.ffmpeg.version(), this.ffprobe.version()); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | + | ||
| 76 | + | ||
| 75 | public interface VideoHandEndCallBack { | 77 | public interface VideoHandEndCallBack { |
| 76 | void run(String status, double percentage, String result); | 78 | void run(String status, double percentage, String result); |
| 77 | } | 79 | } |
| @@ -149,4 +151,9 @@ public class FFmpegExecUtils implements InitializingBean{ | @@ -149,4 +151,9 @@ public class FFmpegExecUtils implements InitializingBean{ | ||
| 149 | job.run(); | 151 | job.run(); |
| 150 | } | 152 | } |
| 151 | 153 | ||
| 154 | + public double duration(File file) throws IOException { | ||
| 155 | + FFmpegProbeResult in = ffprobe.probe(file.getAbsolutePath()); | ||
| 156 | + return in.getFormat().duration * 1000; | ||
| 157 | + } | ||
| 158 | + | ||
| 152 | } | 159 | } |
src/main/java/top/panll/assist/service/VideoFileService.java
| @@ -135,8 +135,7 @@ public class VideoFileService { | @@ -135,8 +135,7 @@ public class VideoFileService { | ||
| 135 | FFprobe ffprobe = ffmpegExecUtils.getFfprobe(); | 135 | FFprobe ffprobe = ffmpegExecUtils.getFfprobe(); |
| 136 | if(file.exists() && file.isFile() && !file.getName().startsWith(".")&& file.getName().endsWith(".mp4") && file.getName().indexOf(":") < 0) { | 136 | if(file.exists() && file.isFile() && !file.getName().startsWith(".")&& file.getName().endsWith(".mp4") && file.getName().indexOf(":") < 0) { |
| 137 | try { | 137 | try { |
| 138 | - FFmpegProbeResult in = null; | ||
| 139 | - in = ffprobe.probe(file.getAbsolutePath()); | 138 | + FFmpegProbeResult in = ffprobe.probe(file.getAbsolutePath()); |
| 140 | double duration = in.getFormat().duration * 1000; | 139 | double duration = in.getFormat().duration * 1000; |
| 141 | String endTimeStr = file.getName().replace(".mp4", ""); | 140 | String endTimeStr = file.getName().replace(".mp4", ""); |
| 142 | 141 | ||
| @@ -206,6 +205,55 @@ public class VideoFileService { | @@ -206,6 +205,55 @@ public class VideoFileService { | ||
| 206 | return result; | 205 | return result; |
| 207 | } | 206 | } |
| 208 | 207 | ||
| 208 | + public List<File> getAllFiles(String app, String stream, Boolean recording){ | ||
| 209 | + | ||
| 210 | + List<File> result = new ArrayList<>(); | ||
| 211 | + if (app == null || stream == null) { | ||
| 212 | + return result; | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | ||
| 216 | + SimpleDateFormat formatterForDate = new SimpleDateFormat("yyyy-MM-dd"); | ||
| 217 | + | ||
| 218 | + File recordFile = new File(userSettings.getRecord()); | ||
| 219 | + File streamFile = new File(recordFile.getAbsolutePath() + File.separator + app + File.separator + stream + File.separator); | ||
| 220 | + if (!streamFile.exists()) { | ||
| 221 | + logger.warn("获取[app: {}, stream: {}]的视频时未找到目录: {}", app, stream, stream); | ||
| 222 | + return null; | ||
| 223 | + } | ||
| 224 | + | ||
| 225 | + File[] dateFiles = streamFile.listFiles((File dir, String name) -> { | ||
| 226 | + if (new File(dir + File.separator + name).isFile()) { | ||
| 227 | + return false; | ||
| 228 | + } | ||
| 229 | + try { | ||
| 230 | + formatterForDate.parse(name); | ||
| 231 | + } catch (ParseException e) { | ||
| 232 | + logger.error("过滤日期文件时异常: {}-{}", name, e.getMessage()); | ||
| 233 | + return false; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + return true ; | ||
| 237 | + }); | ||
| 238 | + | ||
| 239 | + if (dateFiles != null && dateFiles.length > 0) { | ||
| 240 | + for (File dateFile : dateFiles) { | ||
| 241 | + File[] files = dateFile.listFiles((File dir, String name) ->{ | ||
| 242 | + File currentFile = new File(dir + File.separator + name); | ||
| 243 | + if (recording) { | ||
| 244 | + return currentFile.isFile() && name.contains(":") && name.endsWith(".mp4") && currentFile.length() > 0; | ||
| 245 | + }else { | ||
| 246 | + return currentFile.isFile() && name.contains(":") && name.endsWith(".mp4") && currentFile.length() > 0 && !name.startsWith("."); | ||
| 247 | + } | ||
| 248 | + }); | ||
| 249 | + List<File> fileList = Arrays.asList(files); | ||
| 250 | + result.addAll(fileList); | ||
| 251 | + } | ||
| 252 | + } | ||
| 253 | + return result; | ||
| 254 | + } | ||
| 255 | + | ||
| 256 | + | ||
| 209 | /** | 257 | /** |
| 210 | * 获取制定推流的指定时间段内的推流 | 258 | * 获取制定推流的指定时间段内的推流 |
| 211 | * @param app | 259 | * @param app |
| @@ -604,4 +652,19 @@ public class VideoFileService { | @@ -604,4 +652,19 @@ public class VideoFileService { | ||
| 604 | } | 652 | } |
| 605 | return result; | 653 | return result; |
| 606 | } | 654 | } |
| 655 | + | ||
| 656 | + public Double fileDuration(String app, String stream, Boolean recordIng) { | ||
| 657 | + List<File> allFiles = getAllFiles(app, stream, recordIng); | ||
| 658 | + Double durationResult = 0.0; | ||
| 659 | + if (allFiles.size() > 0) { | ||
| 660 | + for (File file : allFiles) { | ||
| 661 | + try { | ||
| 662 | + durationResult += ffmpegExecUtils.duration(file); | ||
| 663 | + } catch (IOException e) { | ||
| 664 | + logger.error("获取{}视频时长错误:{}", file.getAbsolutePath(), e.getMessage()); | ||
| 665 | + } | ||
| 666 | + } | ||
| 667 | + } | ||
| 668 | + return durationResult; | ||
| 669 | + } | ||
| 607 | } | 670 | } |