Commit 23b676e48384b66fdd88c77d3b894e0924d0a65d
1 parent
1cce3324
添加对旧录像文件的处理
Showing
29 changed files
with
580 additions
and
2785 deletions
libs/jdbc-aarch/kingbase8-8.6.0.jar
0 → 100644
No preview for this file type
libs/jdbc-aarch/kingbase8-8.6.0.jre7.jar
0 → 100644
No preview for this file type
libs/jdbc-aarch/postgresql-42.2.9.jar
0 → 100644
No preview for this file type
libs/jdbc-aarch/postgresql-42.2.9.jre7.jar
0 → 100644
No preview for this file type
pom.xml
| ... | ... | @@ -44,6 +44,49 @@ |
| 44 | 44 | </dependency> |
| 45 | 45 | |
| 46 | 46 | <dependency> |
| 47 | + <groupId>org.springframework.boot</groupId> | |
| 48 | + <artifactId>spring-boot-starter-jdbc</artifactId> | |
| 49 | + </dependency> | |
| 50 | + | |
| 51 | + <!-- mysql数据库 --> | |
| 52 | + <dependency> | |
| 53 | + <groupId>mysql</groupId> | |
| 54 | + <artifactId>mysql-connector-java</artifactId> | |
| 55 | + <version>8.0.30</version> | |
| 56 | + </dependency> | |
| 57 | + | |
| 58 | + <!--postgresql--> | |
| 59 | + <dependency> | |
| 60 | + <groupId>org.postgresql</groupId> | |
| 61 | + <artifactId>postgresql</artifactId> | |
| 62 | + <version>42.5.1</version> | |
| 63 | + </dependency> | |
| 64 | + | |
| 65 | + <!-- kingbase人大金仓 --> | |
| 66 | + <!-- 手动下载驱动后安装 --> | |
| 67 | + <!-- mvn install:install-file -Dfile=/home/lin/soft/kingbase/jdbc-aarch/kingbase8-8.6.0.jar -DgroupId=com.kingbase -DartifactId=kingbase8 -Dversion=8.6.0 -Dpackaging=jar | |
| 68 | + --> | |
| 69 | + <dependency> | |
| 70 | + <groupId>com.kingbase</groupId> | |
| 71 | + <artifactId>kingbase8</artifactId> | |
| 72 | + <version>8.6.0</version> | |
| 73 | + <scope>system</scope> | |
| 74 | + <systemPath>${basedir}/libs/jdbc-aarch/kingbase8-8.6.0.jar</systemPath> | |
| 75 | + </dependency> | |
| 76 | + | |
| 77 | + <dependency> | |
| 78 | + <groupId>org.mybatis.spring.boot</groupId> | |
| 79 | + <artifactId>mybatis-spring-boot-starter</artifactId> | |
| 80 | + <version>2.2.2</version> | |
| 81 | + <exclusions> | |
| 82 | + <exclusion> | |
| 83 | + <groupId>com.zaxxer</groupId> | |
| 84 | + <artifactId>HikariCP</artifactId> | |
| 85 | + </exclusion> | |
| 86 | + </exclusions> | |
| 87 | + </dependency> | |
| 88 | + | |
| 89 | + <dependency> | |
| 47 | 90 | <groupId>net.bramp.ffmpeg</groupId> |
| 48 | 91 | <artifactId>ffmpeg</artifactId> |
| 49 | 92 | <version>0.6.2</version> |
| ... | ... | @@ -56,18 +99,6 @@ |
| 56 | 99 | <version>1.2.73</version> |
| 57 | 100 | </dependency> |
| 58 | 101 | |
| 59 | - <!--在线文档 --> | |
| 60 | - <dependency> | |
| 61 | - <groupId>org.springdoc</groupId> | |
| 62 | - <artifactId>springdoc-openapi-ui</artifactId> | |
| 63 | - <version>1.6.10</version> | |
| 64 | - </dependency> | |
| 65 | - <dependency> | |
| 66 | - <groupId>com.github.xiaoymin</groupId> | |
| 67 | - <artifactId>knife4j-springdoc-ui</artifactId> | |
| 68 | - <version>3.0.3</version> | |
| 69 | - </dependency> | |
| 70 | - | |
| 71 | 102 | <dependency> |
| 72 | 103 | <groupId>org.mp4parser</groupId> |
| 73 | 104 | <artifactId>muxer</artifactId> | ... | ... |
src/main/java/top/panll/assist/config/FastJsonRedisSerializer.java deleted
100755 → 0
| 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/GlobalExceptionHandler.java deleted
100755 → 0
| 1 | -package top.panll.assist.config; | |
| 2 | - | |
| 3 | -import org.slf4j.Logger; | |
| 4 | -import org.slf4j.LoggerFactory; | |
| 5 | -import org.springframework.http.HttpStatus; | |
| 6 | -import org.springframework.web.bind.annotation.ExceptionHandler; | |
| 7 | -import org.springframework.web.bind.annotation.ResponseStatus; | |
| 8 | -import org.springframework.web.bind.annotation.RestControllerAdvice; | |
| 9 | -import top.panll.assist.controller.bean.ControllerException; | |
| 10 | -import top.panll.assist.controller.bean.ErrorCode; | |
| 11 | -import top.panll.assist.controller.bean.WVPResult; | |
| 12 | - | |
| 13 | -/** | |
| 14 | - * 全局异常处理 | |
| 15 | - */ | |
| 16 | -@RestControllerAdvice | |
| 17 | -public class GlobalExceptionHandler { | |
| 18 | - | |
| 19 | - private final static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); | |
| 20 | - | |
| 21 | - /** | |
| 22 | - * 默认异常处理 | |
| 23 | - * @param e 异常 | |
| 24 | - * @return 统一返回结果 | |
| 25 | - */ | |
| 26 | - @ExceptionHandler(Exception.class) | |
| 27 | - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) | |
| 28 | - public WVPResult<String> exceptionHandler(Exception e) { | |
| 29 | - logger.error("[全局异常]: ", e); | |
| 30 | - return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage()); | |
| 31 | - } | |
| 32 | - | |
| 33 | - /** | |
| 34 | - * 自定义异常处理, 处理controller中返回的错误 | |
| 35 | - * @param e 异常 | |
| 36 | - * @return 统一返回结果 | |
| 37 | - */ | |
| 38 | - @ExceptionHandler(ControllerException.class) | |
| 39 | - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) | |
| 40 | - public WVPResult<String> exceptionHandler(ControllerException e) { | |
| 41 | - return WVPResult.fail(e.getCode(), e.getMsg()); | |
| 42 | - } | |
| 43 | - | |
| 44 | -} |
src/main/java/top/panll/assist/config/GlobalResponseAdvice.java deleted
100755 → 0
| 1 | -package top.panll.assist.config; | |
| 2 | - | |
| 3 | -import com.alibaba.fastjson.JSON; | |
| 4 | -import org.springframework.core.MethodParameter; | |
| 5 | -import org.springframework.http.MediaType; | |
| 6 | -import org.springframework.http.converter.HttpMessageConverter; | |
| 7 | -import org.springframework.http.server.ServerHttpRequest; | |
| 8 | -import org.springframework.http.server.ServerHttpResponse; | |
| 9 | -import org.springframework.web.bind.annotation.RestControllerAdvice; | |
| 10 | -import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; | |
| 11 | -import top.panll.assist.controller.bean.ErrorCode; | |
| 12 | -import top.panll.assist.controller.bean.WVPResult; | |
| 13 | - | |
| 14 | -import javax.validation.constraints.NotNull; | |
| 15 | - | |
| 16 | -/** | |
| 17 | - * 全局统一返回结果 | |
| 18 | - * @author lin | |
| 19 | - */ | |
| 20 | -@RestControllerAdvice | |
| 21 | -public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> { | |
| 22 | - | |
| 23 | - | |
| 24 | - @Override | |
| 25 | - public boolean supports(@NotNull MethodParameter returnType, @NotNull Class<? extends HttpMessageConverter<?>> converterType) { | |
| 26 | - return true; | |
| 27 | - } | |
| 28 | - | |
| 29 | - @Override | |
| 30 | - public Object beforeBodyWrite(Object body, @NotNull MethodParameter returnType, @NotNull MediaType selectedContentType, @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType, @NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response) { | |
| 31 | - // 排除api文档的接口,这个接口不需要统一 | |
| 32 | - String[] excludePath = {"/v3/api-docs","/api/v1","/index/hook"}; | |
| 33 | - for (String path : excludePath) { | |
| 34 | - if (request.getURI().getPath().startsWith(path)) { | |
| 35 | - return body; | |
| 36 | - } | |
| 37 | - } | |
| 38 | - | |
| 39 | - if (body instanceof WVPResult) { | |
| 40 | - return body; | |
| 41 | - } | |
| 42 | - | |
| 43 | - if (body instanceof ErrorCode) { | |
| 44 | - ErrorCode errorCode = (ErrorCode) body; | |
| 45 | - return new WVPResult<>(errorCode.getCode(), errorCode.getMsg(), null); | |
| 46 | - } | |
| 47 | - | |
| 48 | - if (body instanceof String) { | |
| 49 | - return JSON.toJSONString(WVPResult.success(body)); | |
| 50 | - } | |
| 51 | - | |
| 52 | - return WVPResult.success(body); | |
| 53 | - } | |
| 54 | -} |
src/main/java/top/panll/assist/config/RedisConfig.java deleted
100755 → 0
| 1 | -package top.panll.assist.config; | |
| 2 | - | |
| 3 | -import com.alibaba.fastjson.parser.ParserConfig; | |
| 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; | |
| 8 | -import org.springframework.context.annotation.Bean; | |
| 9 | -import org.springframework.context.annotation.Configuration; | |
| 10 | -import org.springframework.data.redis.connection.RedisConnectionFactory; | |
| 11 | -import org.springframework.data.redis.core.RedisOperations; | |
| 12 | -import org.springframework.data.redis.core.RedisTemplate; | |
| 13 | -import org.springframework.data.redis.listener.RedisMessageListenerContainer; | |
| 14 | -import org.springframework.data.redis.serializer.StringRedisSerializer; | |
| 15 | - | |
| 16 | -/** | |
| 17 | - * @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置 | |
| 18 | - * @author: swwheihei | |
| 19 | - * @date: 2019年5月30日 上午10:58:25 | |
| 20 | - * | |
| 21 | - */ | |
| 22 | -@Configuration | |
| 23 | -@ConditionalOnClass(RedisOperations.class) | |
| 24 | -@EnableConfigurationProperties(RedisProperties.class) | |
| 25 | -public class RedisConfig { | |
| 26 | - | |
| 27 | - static { | |
| 28 | - ParserConfig.getGlobalInstance().addAccept("top.panll.assist"); | |
| 29 | - } | |
| 30 | - | |
| 31 | - @Bean | |
| 32 | - @ConditionalOnMissingBean(name = "redisTemplate") | |
| 33 | - public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { | |
| 34 | - RedisTemplate<Object, Object> template = new RedisTemplate<>(); | |
| 35 | - template.setConnectionFactory(redisConnectionFactory); | |
| 36 | - // 使用fastjson进行序列化处理,提高解析效率 | |
| 37 | - FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class); | |
| 38 | - // value值的序列化采用fastJsonRedisSerializer | |
| 39 | - template.setValueSerializer(serializer); | |
| 40 | - template.setHashValueSerializer(serializer); | |
| 41 | - // key的序列化采用StringRedisSerializer | |
| 42 | - template.setKeySerializer(new StringRedisSerializer()); | |
| 43 | - template.setHashKeySerializer(new StringRedisSerializer()); | |
| 44 | - template.setConnectionFactory(redisConnectionFactory); | |
| 45 | - // 使用fastjson时需设置此项,否则会报异常not support type | |
| 46 | -// ParserConfig.getGlobalInstance().setAutoTypeSupport(true); | |
| 47 | - return template; | |
| 48 | - | |
| 49 | - } | |
| 50 | - | |
| 51 | - /** | |
| 52 | - * redis消息监听器容器 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器 | |
| 53 | - * 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理 | |
| 54 | - * | |
| 55 | - * @param connectionFactory | |
| 56 | - * @return | |
| 57 | - */ | |
| 58 | - @Bean | |
| 59 | - RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { | |
| 60 | - | |
| 61 | - RedisMessageListenerContainer container = new RedisMessageListenerContainer(); | |
| 62 | - container.setConnectionFactory(connectionFactory); | |
| 63 | - return container; | |
| 64 | - } | |
| 65 | - | |
| 66 | -} |
src/main/java/top/panll/assist/config/SpringDocConfig.java deleted
100755 → 0
| 1 | -package top.panll.assist.config; | |
| 2 | - | |
| 3 | -import io.swagger.v3.oas.models.OpenAPI; | |
| 4 | -import io.swagger.v3.oas.models.info.Contact; | |
| 5 | -import io.swagger.v3.oas.models.info.Info; | |
| 6 | -import io.swagger.v3.oas.models.info.License; | |
| 7 | -import org.springdoc.core.GroupedOpenApi; | |
| 8 | -import org.springframework.beans.factory.annotation.Value; | |
| 9 | -import org.springframework.context.annotation.Bean; | |
| 10 | -import org.springframework.context.annotation.Configuration; | |
| 11 | - | |
| 12 | -/** | |
| 13 | - * @author lin | |
| 14 | - */ | |
| 15 | -@Configuration | |
| 16 | -public class SpringDocConfig { | |
| 17 | - | |
| 18 | - @Value("${doc.enabled: true}") | |
| 19 | - private boolean enable; | |
| 20 | - | |
| 21 | - @Bean | |
| 22 | - public OpenAPI springShopOpenApi() { | |
| 23 | - Contact contact = new Contact(); | |
| 24 | - contact.setName("pan"); | |
| 25 | - contact.setEmail("648540858@qq.com"); | |
| 26 | - return new OpenAPI() | |
| 27 | - .info(new Info().title("WVP-PRO-ASSIST 接口文档") | |
| 28 | - .contact(contact) | |
| 29 | - .description("WVP-PRO助手,补充ZLM功能") | |
| 30 | - .version("v2.0") | |
| 31 | - .license(new License().name("Apache 2.0").url("http://springdoc.org"))); | |
| 32 | - } | |
| 33 | - | |
| 34 | - /** | |
| 35 | - * 添加分组 | |
| 36 | - * @return | |
| 37 | - */ | |
| 38 | - @Bean | |
| 39 | - public GroupedOpenApi publicApi() { | |
| 40 | - return GroupedOpenApi.builder() | |
| 41 | - .group("1. 全部") | |
| 42 | - .packagesToScan("top.panll.assist") | |
| 43 | - .build(); | |
| 44 | - } | |
| 45 | -} |
src/main/java/top/panll/assist/config/StartConfig.java
| 1 | 1 | package top.panll.assist.config; |
| 2 | 2 | |
| 3 | -import net.bramp.ffmpeg.FFmpeg; | |
| 4 | -import net.bramp.ffmpeg.FFprobe; | |
| 5 | 3 | import org.slf4j.Logger; |
| 6 | 4 | import org.slf4j.LoggerFactory; |
| 7 | 5 | import org.springframework.beans.factory.annotation.Autowired; |
| 8 | 6 | import org.springframework.beans.factory.annotation.Value; |
| 9 | 7 | import org.springframework.boot.CommandLineRunner; |
| 10 | 8 | import org.springframework.core.annotation.Order; |
| 9 | +import org.springframework.jdbc.datasource.DataSourceTransactionManager; | |
| 11 | 10 | 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; | |
| 11 | +import org.springframework.transaction.TransactionDefinition; | |
| 12 | +import org.springframework.transaction.TransactionStatus; | |
| 13 | +import top.panll.assist.dto.CloudRecordItem; | |
| 14 | +import top.panll.assist.mapper.CloudRecordServiceMapper; | |
| 15 | +import top.panll.assist.utils.DateUtils; | |
| 15 | 16 | |
| 16 | 17 | import java.io.*; |
| 17 | -import java.nio.charset.StandardCharsets; | |
| 18 | +import java.util.ArrayList; | |
| 19 | +import java.util.HashMap; | |
| 20 | +import java.util.List; | |
| 21 | +import java.util.Map; | |
| 18 | 22 | |
| 19 | 23 | /** |
| 20 | 24 | * 用于启动检查环境 |
| 21 | 25 | */ |
| 22 | 26 | @Component |
| 23 | -@Order(value=1) | |
| 27 | +@Order(value=10) | |
| 24 | 28 | public class StartConfig implements CommandLineRunner { |
| 25 | 29 | |
| 26 | 30 | private final static Logger logger = LoggerFactory.getLogger(StartConfig.class); |
| 27 | 31 | |
| 28 | - @Value("${server.port}") | |
| 29 | - private String port; | |
| 32 | + @Value("${user-settings.record}") | |
| 33 | + private String record; | |
| 34 | + | |
| 35 | + @Value("${user-settings.media-server-id}") | |
| 36 | + private String mediaServerId; | |
| 37 | + | |
| 38 | + @Autowired | |
| 39 | + DataSourceTransactionManager dataSourceTransactionManager; | |
| 30 | 40 | |
| 31 | 41 | @Autowired |
| 32 | - private UserSettings userSettings; | |
| 42 | + TransactionDefinition transactionDefinition; | |
| 33 | 43 | |
| 34 | 44 | @Autowired |
| 35 | - private VideoFileService videoFileService; | |
| 45 | + private CloudRecordServiceMapper cloudRecordServiceMapper; | |
| 36 | 46 | |
| 37 | 47 | |
| 38 | 48 | @Override |
| 39 | 49 | public void run(String... args) { |
| 40 | - String record = userSettings.getRecord(); | |
| 41 | 50 | if (!record.endsWith(File.separator)) { |
| 42 | - userSettings.setRecord(userSettings.getRecord() + File.separator); | |
| 51 | + record = record + File.separator; | |
| 43 | 52 | } |
| 44 | 53 | |
| 45 | 54 | File recordFile = new File(record); |
| 46 | 55 | 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); | |
| 56 | + logger.warn("{}路径不存在", record); | |
| 57 | + System.exit(1); | |
| 58 | + } | |
| 59 | + logger.info("开始搜集数据"); | |
| 60 | + File[] appFiles = recordFile.listFiles(); | |
| 61 | + if (appFiles == null) { | |
| 62 | + logger.warn("{}路径下没有录像", record); | |
| 63 | + System.exit(1); | |
| 64 | + } | |
| 65 | + if (appFiles.length == 0) { | |
| 66 | + logger.warn("{}路径下没有录像", record); | |
| 67 | + System.exit(1); | |
| 68 | + } | |
| 69 | + List<CloudRecordItem> cloudRecordItemList = new ArrayList<>(); | |
| 70 | + Map<String, String> renameMap = new HashMap<>(); | |
| 71 | + // 搜集数据 | |
| 72 | + for (File file : appFiles) { | |
| 73 | + if (!file.isDirectory()) { | |
| 74 | + continue; | |
| 61 | 75 | } |
| 62 | - if (!recordFile.canWrite()) { | |
| 63 | - logger.error("[userSettings.record]路径无法写入"); | |
| 64 | - System.exit(1); | |
| 76 | + String app = file.getName(); | |
| 77 | + File[] streamFiles = file.listFiles(); | |
| 78 | + if (streamFiles == null || streamFiles.length == 0) { | |
| 79 | + continue; | |
| 65 | 80 | } |
| 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 | - } | |
| 81 | + for (File streamFile : streamFiles) { | |
| 82 | + String stream = streamFile.getName(); | |
| 83 | + if ("rtp".equals(app)) { | |
| 84 | + | |
| 85 | + }else { | |
| 86 | + if (stream.indexOf("_") > 0) { | |
| 87 | + String[] streamInfoArray = stream.split("_"); | |
| 88 | + if (streamInfoArray.length != 2) { | |
| 89 | + logger.warn("无法识别 {}/{}", app, stream); | |
| 90 | + continue; | |
| 91 | + } | |
| 92 | + stream = streamInfoArray[0]; | |
| 93 | + String callId = streamInfoArray[1]; | |
| 94 | + File[] dateFiles = streamFile.listFiles(); | |
| 95 | + if (dateFiles == null || dateFiles.length == 0) { | |
| 96 | + continue; | |
| 97 | + } | |
| 98 | + // TODC 确定关联和归档分别使用了什么类型名称 | |
| 99 | + boolean collect = false; | |
| 100 | + boolean reserve = false; | |
| 101 | + for (File dateFile : dateFiles) { | |
| 102 | + if (dateFile.isFile()) { | |
| 103 | + if (dateFile.getName().endsWith(".sign")) { | |
| 104 | + if (dateFile.getName().startsWith("a")) { | |
| 105 | + collect = true; | |
| 106 | + }else if (dateFile.getName().startsWith("b")) { | |
| 107 | + reserve = true; | |
| 88 | 108 | } |
| 89 | 109 | } |
| 110 | + }else { | |
| 111 | + // 检验是否是日期格式 | |
| 112 | + if (!DateUtils.checkDateFormat(dateFile.getName())) { | |
| 113 | + continue; | |
| 114 | + } | |
| 115 | + String date = dateFile.getName(); | |
| 116 | + File[] videoFiles = dateFile.listFiles(); | |
| 117 | + if (videoFiles == null || videoFiles.length == 0) { | |
| 118 | + continue; | |
| 119 | + } | |
| 120 | + for (int i = 0; i < videoFiles.length; i++) { | |
| 121 | + File videoFile = videoFiles[i]; | |
| 122 | + if (!videoFile.getName().endsWith(".mp4") && !videoFile.getName().contains("-")) { | |
| 123 | + continue; | |
| 124 | + } | |
| 125 | + String[] videoInfoArray = videoFile.getName().split("-"); | |
| 126 | + if (videoInfoArray.length != 3) { | |
| 127 | + logger.info("非目标视频文件格式,忽略此文件: {}", videoFile.getAbsolutePath() ); | |
| 128 | + continue; | |
| 129 | + } | |
| 130 | + if (!DateUtils.checkDateTimeFormat(date + " " + videoInfoArray[0]) | |
| 131 | + || !DateUtils.checkDateTimeFormat(date + " " + videoInfoArray[1]) ) { | |
| 132 | + logger.info("目标视频文件明明异常,忽略此文件: {}", videoFile.getName() ); | |
| 133 | + continue; | |
| 134 | + } | |
| 135 | + String startTime = date + " " + videoInfoArray[0]; | |
| 136 | + String endTime = date + " " + videoInfoArray[1]; | |
| 137 | + Long startTimeStamp = DateUtils.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime); | |
| 138 | + Long endTimeStamp = DateUtils.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime); | |
| 139 | + | |
| 140 | + long timeLength = Long.parseLong(videoInfoArray[2].substring(0, videoInfoArray[2].length() - 4)); | |
| 141 | + CloudRecordItem cloudRecordItem = new CloudRecordItem(); | |
| 142 | + cloudRecordItem.setApp(app); | |
| 143 | + cloudRecordItem.setStream(stream); | |
| 144 | + cloudRecordItem.setCallId(callId); | |
| 145 | + cloudRecordItem.setStartTime(startTimeStamp); | |
| 146 | + cloudRecordItem.setEndTime(endTimeStamp); | |
| 147 | + cloudRecordItem.setCollect(collect); | |
| 148 | + cloudRecordItem.setReserve(reserve); | |
| 149 | + cloudRecordItem.setMediaServerId(mediaServerId); | |
| 150 | + cloudRecordItem.setFileName(DateUtils.getTimeStr(startTimeStamp) + "-" + i + ".mp4"); | |
| 151 | + cloudRecordItem.setFolder(streamFile.getAbsolutePath()); | |
| 152 | + cloudRecordItem.setFileSize(videoFile.length()); | |
| 153 | + cloudRecordItem.setTimeLen(timeLength); | |
| 154 | + cloudRecordItem.setFilePath(videoFile.getParentFile().getAbsolutePath() + File.separator + cloudRecordItem.getFileName()); | |
| 155 | + cloudRecordItemList.add(cloudRecordItem); | |
| 156 | + renameMap.put(videoFile.getAbsolutePath(), cloudRecordItem.getFilePath()); | |
| 157 | + System.out.println(cloudRecordItem.getFilePath()); | |
| 158 | + } | |
| 90 | 159 | } |
| 91 | - | |
| 92 | 160 | } |
| 93 | 161 | } |
| 94 | - | |
| 95 | 162 | } |
| 96 | 163 | } |
| 97 | - | |
| 98 | - } catch (Exception exception){ | |
| 99 | - exception.printStackTrace(); | |
| 100 | - logger.error("环境错误: " + exception.getMessage()); | |
| 164 | + logger.info("数据收集完成, 待处理数据为: {}条", cloudRecordItemList.size()); | |
| 165 | + logger.info("开始将数据写入数据库"); | |
| 166 | + TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); | |
| 167 | + int limitCount = 50; | |
| 168 | + if (cloudRecordItemList.size() > 0) { | |
| 169 | + if (cloudRecordItemList.size() > limitCount) { | |
| 170 | + for (int i = 0; i < cloudRecordItemList.size(); i += limitCount) { | |
| 171 | + int toIndex = i + limitCount; | |
| 172 | + if (i + limitCount > cloudRecordItemList.size()) { | |
| 173 | + toIndex = cloudRecordItemList.size(); | |
| 174 | + } | |
| 175 | + int length = cloudRecordServiceMapper.batchAdd(cloudRecordItemList.subList(i, toIndex)); | |
| 176 | + if (length == 0) { | |
| 177 | + dataSourceTransactionManager.rollback(transactionStatus); | |
| 178 | + } | |
| 179 | + } | |
| 180 | + } else { | |
| 181 | + cloudRecordServiceMapper.batchAdd(cloudRecordItemList); | |
| 182 | + } | |
| 183 | + dataSourceTransactionManager.commit(transactionStatus); | |
| 184 | + } | |
| 185 | + logger.info("数据写入数据库完成"); | |
| 101 | 186 | } |
| 187 | + | |
| 188 | + | |
| 102 | 189 | } |
| 103 | 190 | |
| 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 | -// } | |
| 191 | + | |
| 148 | 192 | } | ... | ... |
src/main/java/top/panll/assist/config/WebMvcConfig.java deleted
100755 → 0
| 1 | -package top.panll.assist.config; | |
| 2 | - | |
| 3 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 4 | -import org.springframework.context.annotation.Configuration; | |
| 5 | -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; | |
| 6 | -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; | |
| 7 | -import top.panll.assist.dto.UserSettings; | |
| 8 | - | |
| 9 | -import java.io.File; | |
| 10 | - | |
| 11 | - | |
| 12 | -@Configuration | |
| 13 | -public class WebMvcConfig extends WebMvcConfigurerAdapter { | |
| 14 | - | |
| 15 | - @Autowired | |
| 16 | - private UserSettings userSettings; | |
| 17 | - | |
| 18 | - @Override | |
| 19 | - public void addResourceHandlers(ResourceHandlerRegistry registry) { | |
| 20 | - File file = new File(userSettings.getRecord()); | |
| 21 | - registry.addResourceHandler("/download/**").addResourceLocations("file://" + file.getAbsolutePath() + "/"); | |
| 22 | - super.addResourceHandlers(registry); | |
| 23 | - } | |
| 24 | -} |
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 deleted
100755 → 0
| 1 | -package top.panll.assist.controller; | |
| 2 | - | |
| 3 | -import com.alibaba.fastjson.JSON; | |
| 4 | -import com.alibaba.fastjson.JSONObject; | |
| 5 | -import io.swagger.v3.oas.annotations.Operation; | |
| 6 | -import io.swagger.v3.oas.annotations.Parameter; | |
| 7 | -import io.swagger.v3.oas.annotations.tags.Tag; | |
| 8 | -import org.apache.commons.io.FileUtils; | |
| 9 | -import org.slf4j.Logger; | |
| 10 | -import org.slf4j.LoggerFactory; | |
| 11 | -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.*; | |
| 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; | |
| 19 | -import top.panll.assist.dto.*; | |
| 20 | -import top.panll.assist.service.VideoFileService; | |
| 21 | -import top.panll.assist.utils.PageInfo; | |
| 22 | -import top.panll.assist.utils.RedisUtil; | |
| 23 | - | |
| 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; | |
| 29 | -import java.util.*; | |
| 30 | - | |
| 31 | -@Tag(name = "录像管理", description = "录像管理") | |
| 32 | -@CrossOrigin | |
| 33 | -@RestController | |
| 34 | -@RequestMapping("/api/record") | |
| 35 | -public class RecordController { | |
| 36 | - | |
| 37 | - private final static Logger logger = LoggerFactory.getLogger(RecordController.class); | |
| 38 | - | |
| 39 | - @Autowired | |
| 40 | - private VideoFileService videoFileService; | |
| 41 | - | |
| 42 | - @Autowired | |
| 43 | - private RedisUtil redisUtil; | |
| 44 | - | |
| 45 | - @Autowired | |
| 46 | - private UserSettings userSettings; | |
| 47 | - | |
| 48 | - private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
| 49 | - | |
| 50 | - | |
| 51 | - /** | |
| 52 | - * 获取Assist服务配置信息 | |
| 53 | - */ | |
| 54 | - @Operation(summary ="获取Assist服务配置信息") | |
| 55 | - @GetMapping(value = "/info") | |
| 56 | - @ResponseBody | |
| 57 | - public UserSettings getInfo(){ | |
| 58 | - return userSettings; | |
| 59 | - } | |
| 60 | - | |
| 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 | - | |
| 258 | - /** | |
| 259 | - * 添加视频裁剪合并任务 | |
| 260 | - */ | |
| 261 | - @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") | |
| 268 | - @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(); | |
| 286 | - } | |
| 287 | - String id = videoFileService.mergeOrCut(app, stream, startTimeDate, endTimeDate, remoteHost); | |
| 288 | - if (id== null) { | |
| 289 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "可能未找到视频文件"); | |
| 290 | - } | |
| 291 | - return id; | |
| 292 | - } | |
| 293 | - | |
| 294 | - /** | |
| 295 | - * 查询视频裁剪合并任务列表 | |
| 296 | - */ | |
| 297 | - @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) | |
| 301 | - @Parameter(name = "isEnd", description = "是否结束", required = true) | |
| 302 | - @GetMapping(value = "/file/download/task/list") | |
| 303 | - @ResponseBody | |
| 304 | - public List<MergeOrCutTaskInfo> getTaskListForDownload( | |
| 305 | - @RequestParam(required = false) String app, | |
| 306 | - @RequestParam(required = false) String stream, | |
| 307 | - @RequestParam(required = false) String taskId, | |
| 308 | - @RequestParam(required = false) Boolean isEnd){ | |
| 309 | - List<MergeOrCutTaskInfo> taskList = videoFileService.getTaskListForDownload(isEnd, app, stream, taskId); | |
| 310 | - if (taskList == null) { | |
| 311 | - throw new ControllerException(ErrorCode.ERROR100); | |
| 312 | - } | |
| 313 | - return taskList; | |
| 314 | - } | |
| 315 | - | |
| 316 | - /** | |
| 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 | - * 中止视频裁剪合并任务列表 | |
| 376 | - */ | |
| 377 | - @Operation(summary ="中止视频裁剪合并任务列表(暂不支持)") | |
| 378 | - @GetMapping(value = "/file/download/task/stop") | |
| 379 | - @ResponseBody | |
| 380 | - public WVPResult<String> stopTaskForDownload(@RequestParam String taskId){ | |
| 381 | -// WVPResult<String> result = new WVPResult<>(); | |
| 382 | -// if (taskId == null) { | |
| 383 | -// result.setCode(400); | |
| 384 | -// result.setMsg("taskId 不能为空"); | |
| 385 | -// return result; | |
| 386 | -// } | |
| 387 | -// boolean stopResult = videoFileService.stopTask(taskId); | |
| 388 | -// result.setCode(0); | |
| 389 | -// result.setMsg(stopResult ? "success": "fail"); | |
| 390 | - return null; | |
| 391 | - } | |
| 392 | - | |
| 393 | - /** | |
| 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 | - * 磁盘空间查询 | |
| 424 | - */ | |
| 425 | - @Operation(summary ="磁盘空间查询") | |
| 426 | - @ResponseBody | |
| 427 | - @GetMapping(value = "/space", produces = "application/json;charset=UTF-8") | |
| 428 | - public SpaceInfo getSpace() { | |
| 429 | - return videoFileService.getSpaceInfo(); | |
| 430 | - } | |
| 431 | - | |
| 432 | - /** | |
| 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 | - * 录像文件的时长 | |
| 449 | - */ | |
| 450 | - @Operation(summary ="录像文件的时长") | |
| 451 | - @Parameter(name = "app", description = "应用名", required = true) | |
| 452 | - @Parameter(name = "stream", description = "流ID", required = true) | |
| 453 | - @Parameter(name = "recordIng", description = "是否录制中", required = true) | |
| 454 | - @ResponseBody | |
| 455 | - @GetMapping(value = "/file/duration", produces = "application/json;charset=UTF-8") | |
| 456 | - @PostMapping(value = "/file/duration", produces = "application/json;charset=UTF-8") | |
| 457 | - public long fileDuration( @RequestParam String app, @RequestParam String stream) { | |
| 458 | - return videoFileService.fileDuration(app, stream); | |
| 459 | - } | |
| 460 | -} |
src/main/java/top/panll/assist/controller/bean/WVPResult.java deleted
100755 → 0
| 1 | -package top.panll.assist.controller.bean; | |
| 2 | - | |
| 3 | - | |
| 4 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | - | |
| 6 | -@Schema(description = "统一返回结果") | |
| 7 | -public class WVPResult<T> { | |
| 8 | - | |
| 9 | - public WVPResult() { | |
| 10 | - } | |
| 11 | - | |
| 12 | - public WVPResult(int code, String msg, T data) { | |
| 13 | - this.code = code; | |
| 14 | - this.msg = msg; | |
| 15 | - this.data = data; | |
| 16 | - } | |
| 17 | - | |
| 18 | - | |
| 19 | - @Schema(description = "错误码,0为成功") | |
| 20 | - private int code; | |
| 21 | - @Schema(description = "描述,错误时描述错误原因") | |
| 22 | - private String msg; | |
| 23 | - @Schema(description = "数据") | |
| 24 | - private T data; | |
| 25 | - | |
| 26 | - | |
| 27 | - public static <T> WVPResult<T> success(T t, String msg) { | |
| 28 | - return new WVPResult<>(ErrorCode.SUCCESS.getCode(), msg, t); | |
| 29 | - } | |
| 30 | - | |
| 31 | - public static <T> WVPResult<T> success(T t) { | |
| 32 | - return success(t, ErrorCode.SUCCESS.getMsg()); | |
| 33 | - } | |
| 34 | - | |
| 35 | - public static <T> WVPResult<T> fail(int code, String msg) { | |
| 36 | - return new WVPResult<>(code, msg, null); | |
| 37 | - } | |
| 38 | - | |
| 39 | - public static <T> WVPResult<T> fail(ErrorCode errorCode) { | |
| 40 | - return fail(errorCode.getCode(), errorCode.getMsg()); | |
| 41 | - } | |
| 42 | - | |
| 43 | - public int getCode() { | |
| 44 | - return code; | |
| 45 | - } | |
| 46 | - | |
| 47 | - public void setCode(int code) { | |
| 48 | - this.code = code; | |
| 49 | - } | |
| 50 | - | |
| 51 | - public String getMsg() { | |
| 52 | - return msg; | |
| 53 | - } | |
| 54 | - | |
| 55 | - public void setMsg(String msg) { | |
| 56 | - this.msg = msg; | |
| 57 | - } | |
| 58 | - | |
| 59 | - public T getData() { | |
| 60 | - return data; | |
| 61 | - } | |
| 62 | - | |
| 63 | - public void setData(T data) { | |
| 64 | - this.data = data; | |
| 65 | - } | |
| 66 | -} |
src/main/java/top/panll/assist/dto/CloudRecordItem.java
0 → 100644
| 1 | +package top.panll.assist.dto; | |
| 2 | + | |
| 3 | + | |
| 4 | +/** | |
| 5 | + * 云端录像数据 | |
| 6 | + */ | |
| 7 | +public class CloudRecordItem { | |
| 8 | + /** | |
| 9 | + * 主键 | |
| 10 | + */ | |
| 11 | + private int id; | |
| 12 | + | |
| 13 | + /** | |
| 14 | + * 应用名 | |
| 15 | + */ | |
| 16 | + private String app; | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * 流 | |
| 20 | + */ | |
| 21 | + private String stream; | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 健全ID | |
| 25 | + */ | |
| 26 | + private String callId; | |
| 27 | + | |
| 28 | + /** | |
| 29 | + * 开始时间 | |
| 30 | + */ | |
| 31 | + private long startTime; | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 结束时间 | |
| 35 | + */ | |
| 36 | + private long endTime; | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * ZLM Id | |
| 40 | + */ | |
| 41 | + private String mediaServerId; | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 文件名称 | |
| 45 | + */ | |
| 46 | + private String fileName; | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * 文件路径 | |
| 50 | + */ | |
| 51 | + private String filePath; | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 文件夹 | |
| 55 | + */ | |
| 56 | + private String folder; | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * 收藏,收藏的文件不移除 | |
| 60 | + */ | |
| 61 | + private Boolean collect; | |
| 62 | + | |
| 63 | + /** | |
| 64 | + * 保留,收藏的文件不移除 | |
| 65 | + */ | |
| 66 | + private Boolean reserve; | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * 文件大小 | |
| 70 | + */ | |
| 71 | + private long fileSize; | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * 文件时长 | |
| 75 | + */ | |
| 76 | + private long timeLen; | |
| 77 | + | |
| 78 | + public int getId() { | |
| 79 | + return id; | |
| 80 | + } | |
| 81 | + | |
| 82 | + public void setId(int id) { | |
| 83 | + this.id = id; | |
| 84 | + } | |
| 85 | + | |
| 86 | + public String getApp() { | |
| 87 | + return app; | |
| 88 | + } | |
| 89 | + | |
| 90 | + public void setApp(String app) { | |
| 91 | + this.app = app; | |
| 92 | + } | |
| 93 | + | |
| 94 | + public String getStream() { | |
| 95 | + return stream; | |
| 96 | + } | |
| 97 | + | |
| 98 | + public void setStream(String stream) { | |
| 99 | + this.stream = stream; | |
| 100 | + } | |
| 101 | + | |
| 102 | + public String getCallId() { | |
| 103 | + return callId; | |
| 104 | + } | |
| 105 | + | |
| 106 | + public void setCallId(String callId) { | |
| 107 | + this.callId = callId; | |
| 108 | + } | |
| 109 | + | |
| 110 | + public long getStartTime() { | |
| 111 | + return startTime; | |
| 112 | + } | |
| 113 | + | |
| 114 | + public void setStartTime(long startTime) { | |
| 115 | + this.startTime = startTime; | |
| 116 | + } | |
| 117 | + | |
| 118 | + public long getEndTime() { | |
| 119 | + return endTime; | |
| 120 | + } | |
| 121 | + | |
| 122 | + public void setEndTime(long endTime) { | |
| 123 | + this.endTime = endTime; | |
| 124 | + } | |
| 125 | + | |
| 126 | + public String getMediaServerId() { | |
| 127 | + return mediaServerId; | |
| 128 | + } | |
| 129 | + | |
| 130 | + public void setMediaServerId(String mediaServerId) { | |
| 131 | + this.mediaServerId = mediaServerId; | |
| 132 | + } | |
| 133 | + | |
| 134 | + public String getFileName() { | |
| 135 | + return fileName; | |
| 136 | + } | |
| 137 | + | |
| 138 | + public void setFileName(String fileName) { | |
| 139 | + this.fileName = fileName; | |
| 140 | + } | |
| 141 | + | |
| 142 | + public String getFilePath() { | |
| 143 | + return filePath; | |
| 144 | + } | |
| 145 | + | |
| 146 | + public void setFilePath(String filePath) { | |
| 147 | + this.filePath = filePath; | |
| 148 | + } | |
| 149 | + | |
| 150 | + public String getFolder() { | |
| 151 | + return folder; | |
| 152 | + } | |
| 153 | + | |
| 154 | + public void setFolder(String folder) { | |
| 155 | + this.folder = folder; | |
| 156 | + } | |
| 157 | + | |
| 158 | + public long getFileSize() { | |
| 159 | + return fileSize; | |
| 160 | + } | |
| 161 | + | |
| 162 | + public void setFileSize(long fileSize) { | |
| 163 | + this.fileSize = fileSize; | |
| 164 | + } | |
| 165 | + | |
| 166 | + public long getTimeLen() { | |
| 167 | + return timeLen; | |
| 168 | + } | |
| 169 | + | |
| 170 | + public void setTimeLen(long timeLen) { | |
| 171 | + this.timeLen = timeLen; | |
| 172 | + } | |
| 173 | + | |
| 174 | + public Boolean getCollect() { | |
| 175 | + return collect; | |
| 176 | + } | |
| 177 | + | |
| 178 | + public void setCollect(Boolean collect) { | |
| 179 | + this.collect = collect; | |
| 180 | + } | |
| 181 | + | |
| 182 | + public Boolean getReserve() { | |
| 183 | + return reserve; | |
| 184 | + } | |
| 185 | + | |
| 186 | + public void setReserve(Boolean reserve) { | |
| 187 | + this.reserve = reserve; | |
| 188 | + } | |
| 189 | +} | ... | ... |
src/main/java/top/panll/assist/dto/UserSettings.java
| ... | ... | @@ -9,25 +9,28 @@ import org.springframework.stereotype.Component; |
| 9 | 9 | @Component |
| 10 | 10 | public class UserSettings { |
| 11 | 11 | |
| 12 | - @Value("${userSettings.id}") | |
| 12 | + @Value("${user-settings.id}") | |
| 13 | 13 | private String id; |
| 14 | 14 | |
| 15 | - @Value("${userSettings.record}") | |
| 15 | + @Value("${user-settings.record}") | |
| 16 | 16 | private String record; |
| 17 | 17 | |
| 18 | - @Value("${userSettings.recordDay:7}") | |
| 18 | + @Value("${user-settings.recordDay:7}") | |
| 19 | 19 | private int recordDay; |
| 20 | 20 | |
| 21 | - @Value("${userSettings.recordTempDay:-1}") | |
| 21 | + @Value("${user-settings.recordTempDay:-1}") | |
| 22 | 22 | private int recordTempDay; |
| 23 | 23 | |
| 24 | - @Value("${userSettings.ffmpeg}") | |
| 24 | + @Value("${user-settings.ffmpeg}") | |
| 25 | 25 | private String ffmpeg; |
| 26 | 26 | |
| 27 | - @Value("${userSettings.ffprobe}") | |
| 27 | + @Value("${user-settings.ffprobe}") | |
| 28 | 28 | private String ffprobe; |
| 29 | 29 | |
| 30 | - @Value("${userSettings.threads:2}") | |
| 30 | + @Value("${user-settings.media-server-id}") | |
| 31 | + private String mediaServerId; | |
| 32 | + | |
| 33 | + @Value("${user-settings.threads:2}") | |
| 31 | 34 | private int threads; |
| 32 | 35 | |
| 33 | 36 | public String getId() { |
| ... | ... | @@ -89,4 +92,12 @@ public class UserSettings { |
| 89 | 92 | public void setThreads(int threads) { |
| 90 | 93 | this.threads = threads; |
| 91 | 94 | } |
| 95 | + | |
| 96 | + public String getMediaServerId() { | |
| 97 | + return mediaServerId; | |
| 98 | + } | |
| 99 | + | |
| 100 | + public void setMediaServerId(String mediaServerId) { | |
| 101 | + this.mediaServerId = mediaServerId; | |
| 102 | + } | |
| 92 | 103 | } | ... | ... |
src/main/java/top/panll/assist/mapper/CloudRecordServiceMapper.java
0 → 100644
| 1 | +package top.panll.assist.mapper; | |
| 2 | + | |
| 3 | +import org.apache.ibatis.annotations.*; | |
| 4 | +import top.panll.assist.dto.CloudRecordItem; | |
| 5 | + | |
| 6 | +import java.util.List; | |
| 7 | + | |
| 8 | +@Mapper | |
| 9 | +public interface CloudRecordServiceMapper { | |
| 10 | + | |
| 11 | + @Insert(" <script>" + | |
| 12 | + "INSERT INTO wvp_cloud_record (" + | |
| 13 | + " app," + | |
| 14 | + " stream," + | |
| 15 | + "<if test=\"callId != null\"> call_id,</if>" + | |
| 16 | + " start_time," + | |
| 17 | + " end_time," + | |
| 18 | + " media_server_id," + | |
| 19 | + " file_name," + | |
| 20 | + " folder," + | |
| 21 | + " file_path," + | |
| 22 | + " file_size," + | |
| 23 | + " time_len ) " + | |
| 24 | + "VALUES (" + | |
| 25 | + " #{app}," + | |
| 26 | + " #{stream}," + | |
| 27 | + " <if test=\"callId != null\"> #{callId},</if>" + | |
| 28 | + " #{startTime}," + | |
| 29 | + " #{endTime}," + | |
| 30 | + " #{mediaServerId}," + | |
| 31 | + " #{fileName}," + | |
| 32 | + " #{folder}," + | |
| 33 | + " #{filePath}," + | |
| 34 | + " #{fileSize}," + | |
| 35 | + " #{timeLen})" + | |
| 36 | + " </script>") | |
| 37 | + int add(CloudRecordItem cloudRecordItem); | |
| 38 | + | |
| 39 | + | |
| 40 | + @Update(" <script>" + | |
| 41 | + "update wvp_cloud_record set collect = #{collect} where file_path in " + | |
| 42 | + " <foreach collection='cloudRecordItemList' item='item' open='(' separator=',' close=')' > #{item.filePath}</foreach>" + | |
| 43 | + " </script>") | |
| 44 | + void updateCollectList(@Param("collect") boolean collect, List<CloudRecordItem> cloudRecordItemList); | |
| 45 | + | |
| 46 | + @Delete(" <script>" + | |
| 47 | + "delete from wvp_cloud_record where media_server_id=#{mediaServerId} file_path in " + | |
| 48 | + " <foreach collection='filePathList' item='item' open='(' separator=',' close=')' > #{item}</foreach>" + | |
| 49 | + " </script>") | |
| 50 | + void deleteByFileList(List<String> filePathList, @Param("mediaServerId") String mediaServerId); | |
| 51 | + | |
| 52 | + | |
| 53 | + @Select(" <script>" + | |
| 54 | + "select file_path" + | |
| 55 | + " from wvp_cloud_record " + | |
| 56 | + " where collect = false and reserve = false " + | |
| 57 | + " <if test= 'endTimeStamp != null '> and start_time <= #{endTimeStamp}</if>" + | |
| 58 | + " <if test= 'callId != null '> and call_id = #{callId}</if>" + | |
| 59 | + " <if test= 'mediaServerId != null ' > and media_server_id = #{mediaServerId} </if>" + | |
| 60 | + " </script>") | |
| 61 | + List<String> queryRecordFilePathListForDelete(@Param("endTimeStamp")Long endTimeStamp, String mediaServerId); | |
| 62 | + | |
| 63 | + @Update(" <script>" + | |
| 64 | + "update wvp_cloud_record set reserve = #{reserve} where file_path in " + | |
| 65 | + " <foreach collection='cloudRecordItems' item='item' open='(' separator=',' close=')' > #{item.filePath}</foreach>" + | |
| 66 | + " </script>") | |
| 67 | + void updateReserveList(@Param("reserve") boolean reserve,List<CloudRecordItem> cloudRecordItems); | |
| 68 | + | |
| 69 | + @Update(" <script>" + | |
| 70 | + "update wvp_cloud_record set collect = #{collect} where id = #{recordId} " + | |
| 71 | + " </script>") | |
| 72 | + void changeCollectById(@Param("collect") boolean collect, @Param("recordId") Integer recordId); | |
| 73 | + | |
| 74 | + @Update(" <script>" + | |
| 75 | + "update wvp_cloud_record set reserve = #{reserve} where id = #{recordId} " + | |
| 76 | + " </script>") | |
| 77 | + void changeReserveById(@Param("reserve") boolean reserve, Integer recordId); | |
| 78 | + | |
| 79 | + | |
| 80 | + @Insert("<script> " + | |
| 81 | + "insert into wvp_cloud_record " + | |
| 82 | + "(" + | |
| 83 | + " app," + | |
| 84 | + " stream," + | |
| 85 | + " call_id," + | |
| 86 | + " start_time," + | |
| 87 | + " end_time," + | |
| 88 | + " media_server_id," + | |
| 89 | + " file_name," + | |
| 90 | + " folder," + | |
| 91 | + " file_path," + | |
| 92 | + " file_size," + | |
| 93 | + " time_len " + | |
| 94 | + ") " + | |
| 95 | + "values " + | |
| 96 | + "<foreach collection='cloudRecordItems' index='index' item='item' separator=','> " + | |
| 97 | + "(#{item.app}, #{item.stream}, #{item.callId}, #{item.startTime}, " + | |
| 98 | + "#{item.endTime}, #{item.mediaServerId}, #{item.fileName},#{item.folder}," + | |
| 99 | + "#{item.filePath}, #{item.fileSize}, #{item.timeLen}) " + | |
| 100 | + "</foreach> " + | |
| 101 | + "</script>") | |
| 102 | + int batchAdd(@Param("cloudRecordItems") List<CloudRecordItem> cloudRecordItems); | |
| 103 | +} | ... | ... |
src/main/java/top/panll/assist/service/FFmpegExecUtils.java
| ... | ... | @@ -18,7 +18,6 @@ import org.springframework.stereotype.Component; |
| 18 | 18 | import org.springframework.util.DigestUtils; |
| 19 | 19 | import top.panll.assist.dto.UserSettings; |
| 20 | 20 | import top.panll.assist.dto.VideoFile; |
| 21 | -import top.panll.assist.utils.RedisUtil; | |
| 22 | 21 | |
| 23 | 22 | import java.io.BufferedWriter; |
| 24 | 23 | import java.io.File; |
| ... | ... | @@ -32,21 +31,7 @@ import java.util.concurrent.TimeUnit; |
| 32 | 31 | public class FFmpegExecUtils implements InitializingBean{ |
| 33 | 32 | |
| 34 | 33 | private final static Logger logger = LoggerFactory.getLogger(FFmpegExecUtils.class); |
| 35 | -// private static FFmpegExecUtils instance; | |
| 36 | -// | |
| 37 | -// public FFmpegExecUtils() { | |
| 38 | -// } | |
| 39 | -// | |
| 40 | -// public static FFmpegExecUtils getInstance(){ | |
| 41 | -// if(instance==null){ | |
| 42 | -// synchronized (FFmpegExecUtils.class){ | |
| 43 | -// if(instance==null){ | |
| 44 | -// instance=new FFmpegExecUtils(); | |
| 45 | -// } | |
| 46 | -// } | |
| 47 | -// } | |
| 48 | -// return instance; | |
| 49 | -// } | |
| 34 | + | |
| 50 | 35 | @Autowired |
| 51 | 36 | private UserSettings userSettings; |
| 52 | 37 | ... | ... |
src/main/java/top/panll/assist/service/FileManagerTimer.java deleted
100755 → 0
| 1 | -package top.panll.assist.service; | |
| 2 | - | |
| 3 | -import org.apache.commons.io.FileUtils; | |
| 4 | -import org.slf4j.Logger; | |
| 5 | -import org.slf4j.LoggerFactory; | |
| 6 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 7 | -import org.springframework.scheduling.annotation.Scheduled; | |
| 8 | -import org.springframework.stereotype.Component; | |
| 9 | -import org.springframework.util.StringUtils; | |
| 10 | -import top.panll.assist.dto.AssistConstants; | |
| 11 | -import top.panll.assist.dto.MergeOrCutTaskInfo; | |
| 12 | -import top.panll.assist.dto.UserSettings; | |
| 13 | -import top.panll.assist.utils.RedisUtil; | |
| 14 | - | |
| 15 | -import java.io.File; | |
| 16 | -import java.text.ParseException; | |
| 17 | -import java.text.SimpleDateFormat; | |
| 18 | -import java.util.Calendar; | |
| 19 | -import java.util.Date; | |
| 20 | -import java.util.List; | |
| 21 | - | |
| 22 | -@Component | |
| 23 | -public class FileManagerTimer { | |
| 24 | - | |
| 25 | - private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); | |
| 26 | - private final SimpleDateFormat simpleDateFormatForTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
| 27 | - | |
| 28 | - private final static Logger logger = LoggerFactory.getLogger(FileManagerTimer.class); | |
| 29 | - | |
| 30 | - @Autowired | |
| 31 | - private UserSettings userSettings; | |
| 32 | - | |
| 33 | - @Autowired | |
| 34 | - private VideoFileService videoFileService; | |
| 35 | - | |
| 36 | - @Autowired | |
| 37 | - private RedisUtil redisUtil; | |
| 38 | - | |
| 39 | -// @Scheduled(fixedDelay = 2000) //测试 20秒执行一次 | |
| 40 | - @Scheduled(cron = "0 0 0 * * ?") //每天的0点执行 | |
| 41 | - public void execute(){ | |
| 42 | - if (userSettings.getRecord() == null) { | |
| 43 | - return; | |
| 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 | - | |
| 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 | - // 清理任务临时文件 | |
| 114 | - int recordTempDay = userSettings.getRecordTempDay(); | |
| 115 | - Date lastTempDate = new Date(); | |
| 116 | - Calendar lastTempCalendar = Calendar.getInstance(); | |
| 117 | - lastTempCalendar.setTime(lastTempDate); | |
| 118 | - lastTempCalendar.add(Calendar.DAY_OF_MONTH, 0 - recordTempDay); | |
| 119 | - lastTempDate = lastTempCalendar.getTime(); | |
| 120 | - logger.info("[录像巡查]移除合并任务临时文件 {} 之前的文件", formatter.format(lastTempDate)); | |
| 121 | - File recordTempFile = new File(userSettings.getRecord() + "recordTemp"); | |
| 122 | - if (recordTempFile.exists() && recordTempFile.isDirectory() && recordTempFile.canWrite()) { | |
| 123 | - 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()); | |
| 131 | - } | |
| 132 | - } | |
| 133 | - } | |
| 134 | - } | |
| 135 | - // 清理redis记录 | |
| 136 | - String key = String.format("%S_%S_*_*_*", AssistConstants.MERGEORCUT, userSettings.getId()); | |
| 137 | - List<Object> taskKeys = redisUtil.scan(key); | |
| 138 | - for (Object taskKeyObj : taskKeys) { | |
| 139 | - String taskKey = (String) taskKeyObj; | |
| 140 | - MergeOrCutTaskInfo mergeOrCutTaskInfo = (MergeOrCutTaskInfo)redisUtil.get(taskKey); | |
| 141 | - try { | |
| 142 | - if (StringUtils.isEmpty(mergeOrCutTaskInfo.getCreateTime()) | |
| 143 | - || simpleDateFormatForTime.parse(mergeOrCutTaskInfo.getCreateTime()).before(lastTempDate)) { | |
| 144 | - redisUtil.del(taskKey); | |
| 145 | - } | |
| 146 | - } catch (ParseException e) { | |
| 147 | - e.printStackTrace(); | |
| 148 | - } | |
| 149 | - } | |
| 150 | - } | |
| 151 | -} |
src/main/java/top/panll/assist/service/VideoFileService.java deleted
100755 → 0
| 1 | -package top.panll.assist.service; | |
| 2 | - | |
| 3 | -import net.bramp.ffmpeg.FFprobe; | |
| 4 | -import net.bramp.ffmpeg.probe.FFmpegProbeResult; | |
| 5 | -import net.bramp.ffmpeg.progress.Progress; | |
| 6 | -import org.apache.commons.io.FileUtils; | |
| 7 | -import org.slf4j.Logger; | |
| 8 | -import org.slf4j.LoggerFactory; | |
| 9 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 10 | -import org.springframework.data.redis.core.RedisTemplate; | |
| 11 | -import org.springframework.stereotype.Service; | |
| 12 | -import org.springframework.util.DigestUtils; | |
| 13 | -import top.panll.assist.dto.*; | |
| 14 | -import top.panll.assist.utils.RedisUtil; | |
| 15 | -import top.panll.assist.utils.DateUtils; | |
| 16 | - | |
| 17 | -import java.io.File; | |
| 18 | -import java.io.IOException; | |
| 19 | -import java.nio.file.Files; | |
| 20 | -import java.nio.file.Path; | |
| 21 | -import java.nio.file.Paths; | |
| 22 | -import java.nio.file.attribute.BasicFileAttributes; | |
| 23 | -import java.text.ParseException; | |
| 24 | -import java.text.SimpleDateFormat; | |
| 25 | -import java.util.*; | |
| 26 | - | |
| 27 | -@Service | |
| 28 | -public class VideoFileService { | |
| 29 | - | |
| 30 | - private final static Logger logger = LoggerFactory.getLogger(VideoFileService.class); | |
| 31 | - | |
| 32 | - @Autowired | |
| 33 | - private UserSettings userSettings; | |
| 34 | - | |
| 35 | - @Autowired | |
| 36 | - private RedisUtil redisUtil; | |
| 37 | - | |
| 38 | - @Autowired | |
| 39 | - private FFmpegExecUtils ffmpegExecUtils; | |
| 40 | - | |
| 41 | - | |
| 42 | - | |
| 43 | - private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); | |
| 44 | - private final SimpleDateFormat simpleDateFormatForTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
| 45 | - | |
| 46 | - public List<File> getAppList(Boolean sort) { | |
| 47 | - File recordFile = new File(userSettings.getRecord()); | |
| 48 | - if (recordFile.isDirectory()) { | |
| 49 | - File[] files = recordFile.listFiles((File dir, String name) -> { | |
| 50 | - File currentFile = new File(dir.getAbsolutePath() + File.separator + name); | |
| 51 | - return currentFile.isDirectory() && !name.equals("recordTemp"); | |
| 52 | - }); | |
| 53 | - List<File> result = Arrays.asList(files); | |
| 54 | - if (sort != null && sort) { | |
| 55 | - Collections.sort(result); | |
| 56 | - } | |
| 57 | - return result; | |
| 58 | - }else { | |
| 59 | - return null; | |
| 60 | - } | |
| 61 | - } | |
| 62 | - | |
| 63 | - public SpaceInfo getSpaceInfo(){ | |
| 64 | - File recordFile = new File(userSettings.getRecord()); | |
| 65 | - SpaceInfo spaceInfo = new SpaceInfo(); | |
| 66 | - spaceInfo.setFree(recordFile.getFreeSpace()); | |
| 67 | - spaceInfo.setTotal(recordFile.getTotalSpace()); | |
| 68 | - return spaceInfo; | |
| 69 | - } | |
| 70 | - | |
| 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 | - | |
| 76 | - public List<File> getStreamList(File appFile, Boolean sort) { | |
| 77 | - if (appFile != null && appFile.isDirectory()) { | |
| 78 | - File[] files = appFile.listFiles((File dir, String name) -> { | |
| 79 | - File currentFile = new File(dir.getAbsolutePath() + File.separator + name); | |
| 80 | - return currentFile.isDirectory(); | |
| 81 | - }); | |
| 82 | - List<File> result = Arrays.asList(files); | |
| 83 | - if (sort != null && sort) { | |
| 84 | - Collections.sort(result); | |
| 85 | - } | |
| 86 | - return result; | |
| 87 | - }else { | |
| 88 | - return null; | |
| 89 | - } | |
| 90 | - } | |
| 91 | - | |
| 92 | - /** | |
| 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 | - * 获取制定推流的指定时间段内的推流 | |
| 167 | - * @param app | |
| 168 | - * @param stream | |
| 169 | - * @param startTime | |
| 170 | - * @param endTime | |
| 171 | - * @return | |
| 172 | - */ | |
| 173 | - public List<File> getFilesInTime(String app, String stream, Date startTime, Date endTime){ | |
| 174 | - | |
| 175 | - List<File> result = new ArrayList<>(); | |
| 176 | - if (app == null || stream == null) { | |
| 177 | - return result; | |
| 178 | - } | |
| 179 | - | |
| 180 | - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HHmmss"); | |
| 181 | - SimpleDateFormat formatterForDate = new SimpleDateFormat("yyyy-MM-dd"); | |
| 182 | - String startTimeStr = null; | |
| 183 | - String endTimeStr = null; | |
| 184 | - if (startTime != null) { | |
| 185 | - startTimeStr = formatter.format(startTime); | |
| 186 | - } | |
| 187 | - if (endTime != null) { | |
| 188 | - endTimeStr = formatter.format(endTime); | |
| 189 | - } | |
| 190 | - | |
| 191 | - logger.debug("获取[app: {}, stream: {}, statime: {}, endTime: {}]的视频", app, stream, | |
| 192 | - startTimeStr, endTimeStr); | |
| 193 | - | |
| 194 | - File recordFile = new File(userSettings.getRecord()); | |
| 195 | - File streamFile = new File(recordFile.getAbsolutePath() + File.separator + app + File.separator + stream + File.separator); | |
| 196 | - if (!streamFile.exists()) { | |
| 197 | - logger.warn("获取[app: {}, stream: {}, statime: {}, endTime: {}]的视频时未找到目录: {}", app, stream, | |
| 198 | - startTimeStr, endTimeStr, stream); | |
| 199 | - return null; | |
| 200 | - } | |
| 201 | - | |
| 202 | - File[] dateFiles = streamFile.listFiles((File dir, String name) -> { | |
| 203 | - Date fileDate = null; | |
| 204 | - Date startDate = null; | |
| 205 | - Date endDate = null; | |
| 206 | - if (new File(dir + File.separator + name).isFile()) { | |
| 207 | - return false; | |
| 208 | - } | |
| 209 | - if (startTime != null) { | |
| 210 | - startDate = new Date(startTime.getTime() - ((startTime.getTime() + 28800000) % (86400000))); | |
| 211 | - } | |
| 212 | - if (endTime != null) { | |
| 213 | - endDate = new Date(endTime.getTime() - ((endTime.getTime() + 28800000) % (86400000))); | |
| 214 | - } | |
| 215 | - try { | |
| 216 | - fileDate = formatterForDate.parse(name); | |
| 217 | - } catch (ParseException e) { | |
| 218 | - logger.error("过滤日期文件时异常: {}-{}", name, e.getMessage()); | |
| 219 | - return false; | |
| 220 | - } | |
| 221 | - boolean filterResult = true; | |
| 222 | - | |
| 223 | - if (startDate != null) { | |
| 224 | - filterResult = filterResult && DateUtils.getStartOfDay(startDate).compareTo(fileDate) <= 0; | |
| 225 | - } | |
| 226 | - | |
| 227 | - if (endDate != null) { | |
| 228 | - filterResult = filterResult && DateUtils.getEndOfDay(endDate).compareTo(fileDate) >= 0; | |
| 229 | - } | |
| 230 | - | |
| 231 | - return filterResult ; | |
| 232 | - }); | |
| 233 | - | |
| 234 | - if (dateFiles != null && dateFiles.length > 0) { | |
| 235 | - for (File dateFile : dateFiles) { | |
| 236 | - File[] files = dateFile.listFiles((File dir, String name) ->{ | |
| 237 | - File currentFile = new File(dir + File.separator + name); | |
| 238 | - VideoFile videoFile = VideoFileFactory.createFile(ffmpegExecUtils, currentFile); | |
| 239 | - if (videoFile == null ) { | |
| 240 | - return false; | |
| 241 | - }else { | |
| 242 | - if (!videoFile.isTargetFormat()) { | |
| 243 | - return false; | |
| 244 | - } | |
| 245 | - if (startTime == null && endTime == null) { | |
| 246 | - return true; | |
| 247 | - }else if (startTime == null && endTime != null) { | |
| 248 | - return videoFile.getEndTime().before(endTime) | |
| 249 | - || videoFile.getEndTime().equals(endTime) | |
| 250 | - || (videoFile.getEndTime().after(endTime) && videoFile.getStartTime().before(endTime)); | |
| 251 | - }else if (startTime != null && endTime == null) { | |
| 252 | - return videoFile.getStartTime().after(startTime) | |
| 253 | - || videoFile.getStartTime().equals(startTime) | |
| 254 | - || (videoFile.getStartTime().before(startTime) && videoFile.getEndTime().after(startTime)); | |
| 255 | - }else { | |
| 256 | - return videoFile.getStartTime().after(startTime) | |
| 257 | - || videoFile.getStartTime().equals(startTime) | |
| 258 | - || (videoFile.getStartTime().before(startTime) && videoFile.getEndTime().after(startTime)) | |
| 259 | - || videoFile.getEndTime().before(endTime) | |
| 260 | - || videoFile.getEndTime().equals(endTime) | |
| 261 | - || (videoFile.getEndTime().after(endTime) && videoFile.getStartTime().before(endTime)); | |
| 262 | - } | |
| 263 | - } | |
| 264 | - }); | |
| 265 | - if (files != null && files.length > 0) { | |
| 266 | - result.addAll(Arrays.asList(files)); | |
| 267 | - } | |
| 268 | - } | |
| 269 | - } | |
| 270 | - if (!result.isEmpty()) { | |
| 271 | - result.sort((File f1, File f2) -> { | |
| 272 | - VideoFile videoFile1 = VideoFileFactory.createFile(ffmpegExecUtils, f1); | |
| 273 | - VideoFile videoFile2 = VideoFileFactory.createFile(ffmpegExecUtils, f2); | |
| 274 | - if (videoFile1 == null || !videoFile1.isTargetFormat() || videoFile2 == null || !videoFile2.isTargetFormat()) { | |
| 275 | - logger.warn("[根据时间获取视频文件] 排序错误,文件错误: {}/{}", f1.getName(), f2.getName()); | |
| 276 | - return 0; | |
| 277 | - } | |
| 278 | - return videoFile1.getStartTime().compareTo(videoFile2.getStartTime()); | |
| 279 | - }); | |
| 280 | - } | |
| 281 | - return result; | |
| 282 | - } | |
| 283 | - | |
| 284 | - | |
| 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 | - } | |
| 293 | - 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 ); | |
| 297 | - if (!recordFile.exists()) { | |
| 298 | - recordFile.mkdirs(); | |
| 299 | - } | |
| 300 | - MergeOrCutTaskInfo mergeOrCutTaskInfo = new MergeOrCutTaskInfo(); | |
| 301 | - mergeOrCutTaskInfo.setId(taskId); | |
| 302 | - mergeOrCutTaskInfo.setApp(app); | |
| 303 | - mergeOrCutTaskInfo.setStream(stream); | |
| 304 | - 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) { | |
| 320 | - | |
| 321 | - // 文件只有一个则不合并,直接复制过去 | |
| 322 | - mergeOrCutTaskInfo.setPercentage("1"); | |
| 323 | - // 处理文件路径 | |
| 324 | - String recordFileResultPath = recordFile.getAbsolutePath() + File.separator + stream + ".mp4"; | |
| 325 | - Path relativize = Paths.get(userSettings.getRecord()).relativize(Paths.get(recordFileResultPath)); | |
| 326 | - try { | |
| 327 | - Files.copy(filesInTime.get(0).toPath(), Paths.get(recordFileResultPath)); | |
| 328 | - } catch (IOException e) { | |
| 329 | - e.printStackTrace(); | |
| 330 | - logger.info("[录像合并] 失败,APP:{}, STREAM: {}, 任务ID:{}", app, stream, taskId); | |
| 331 | - return taskId; | |
| 332 | - } | |
| 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); | |
| 337 | - } | |
| 338 | - String key = String.format("%S_%S_%S_%S_%S", AssistConstants.MERGEORCUT , userSettings.getId(), mergeOrCutTaskInfo.getApp(), mergeOrCutTaskInfo.getStream(), mergeOrCutTaskInfo.getId()); | |
| 339 | - redisUtil.set(key, mergeOrCutTaskInfo); | |
| 340 | - logger.info("[录像合并] 合并完成,APP:{}, STREAM: {}, 任务ID:{}", app, stream, taskId); | |
| 341 | - }else { | |
| 342 | - ffmpegExecUtils.mergeOrCutFile(filesInTime, recordFile, stream, (status, percentage, result)->{ | |
| 343 | - // 发出redis通知 | |
| 344 | - if (status.equals(Progress.Status.END.name())) { | |
| 345 | - mergeOrCutTaskInfo.setPercentage("1"); | |
| 346 | - | |
| 347 | - // 处理文件路径 | |
| 348 | - Path relativize = Paths.get(userSettings.getRecord()).relativize(Paths.get(result)); | |
| 349 | - mergeOrCutTaskInfo.setRecordFile(relativize.toString()); | |
| 350 | - if (remoteHost != null) { | |
| 351 | - mergeOrCutTaskInfo.setDownloadFile(remoteHost + "/download.html?url=download/" + relativize); | |
| 352 | - mergeOrCutTaskInfo.setPlayFile(remoteHost + "/download/" + relativize); | |
| 353 | - } | |
| 354 | - logger.info("[录像合并] 合并完成,APP:{}, STREAM: {}, 任务ID:{}", app, stream, taskId); | |
| 355 | - }else { | |
| 356 | - mergeOrCutTaskInfo.setPercentage(percentage + ""); | |
| 357 | - } | |
| 358 | - String key = String.format("%S_%S_%S_%S_%S", AssistConstants.MERGEORCUT, userSettings.getId(), mergeOrCutTaskInfo.getApp(), mergeOrCutTaskInfo.getStream(), mergeOrCutTaskInfo.getId()); | |
| 359 | - redisUtil.set(key, mergeOrCutTaskInfo); | |
| 360 | - }); | |
| 361 | - } | |
| 362 | - | |
| 363 | - return taskId; | |
| 364 | - } | |
| 365 | - | |
| 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) { | |
| 380 | - if (!streamFile.exists() && streamFile.isDirectory()) { | |
| 381 | - logger.warn("获取[]的视频时未找到目录: {}",streamFile.getName()); | |
| 382 | - return null; | |
| 383 | - } | |
| 384 | - File[] dateFiles = streamFile.listFiles((File dir, String name)->{ | |
| 385 | - File currentFile = new File(dir.getAbsolutePath() + File.separator + name); | |
| 386 | - if (!currentFile.isDirectory()){ | |
| 387 | - return false; | |
| 388 | - } | |
| 389 | - Date date = null; | |
| 390 | - try { | |
| 391 | - date = simpleDateFormat.parse(name); | |
| 392 | - } catch (ParseException e) { | |
| 393 | - logger.error("格式化时间{}错误", name); | |
| 394 | - return false; | |
| 395 | - } | |
| 396 | - Calendar c = Calendar.getInstance(); | |
| 397 | - c.setTime(date); | |
| 398 | - int y = c.get(Calendar.YEAR); | |
| 399 | - int m = c.get(Calendar.MONTH) + 1; | |
| 400 | - if (year != null) { | |
| 401 | - if (month != null) { | |
| 402 | - return y == year && m == month; | |
| 403 | - }else { | |
| 404 | - return y == year; | |
| 405 | - } | |
| 406 | - }else { | |
| 407 | - return true; | |
| 408 | - } | |
| 409 | - | |
| 410 | - }); | |
| 411 | - if (dateFiles == null) { | |
| 412 | - return new ArrayList<>(); | |
| 413 | - } | |
| 414 | - List<File> dateFileList = Arrays.asList(dateFiles); | |
| 415 | - if (sort != null && sort) { | |
| 416 | - dateFileList.sort((File f1, File f2)->{ | |
| 417 | - int sortResult = 0; | |
| 418 | - | |
| 419 | - try { | |
| 420 | - sortResult = simpleDateFormat.parse(f1.getName()).compareTo(simpleDateFormat.parse(f2.getName())); | |
| 421 | - } catch (ParseException e) { | |
| 422 | - logger.error("格式化时间{}/{}错误", f1.getName(), f2.getName()); | |
| 423 | - } | |
| 424 | - return sortResult; | |
| 425 | - }); | |
| 426 | - } | |
| 427 | - | |
| 428 | - return dateFileList; | |
| 429 | - } | |
| 430 | - | |
| 431 | - public List<MergeOrCutTaskInfo> getTaskListForDownload(Boolean idEnd, String app, String stream, String taskId) { | |
| 432 | - ArrayList<MergeOrCutTaskInfo> result = new ArrayList<>(); | |
| 433 | - if (app == null) { | |
| 434 | - app = "*"; | |
| 435 | - } | |
| 436 | - if (stream == null) { | |
| 437 | - stream = "*"; | |
| 438 | - } | |
| 439 | - if (taskId == null) { | |
| 440 | - taskId = "*"; | |
| 441 | - } | |
| 442 | - List<Object> taskCatch = redisUtil.scan(String.format("%S_%S_%S_%S_%S", AssistConstants.MERGEORCUT, | |
| 443 | - userSettings.getId(), app, stream, taskId)); | |
| 444 | - for (int i = 0; i < taskCatch.size(); i++) { | |
| 445 | - String keyItem = taskCatch.get(i).toString(); | |
| 446 | - 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); | |
| 452 | - } | |
| 453 | - }else { | |
| 454 | - if (Double.parseDouble(mergeOrCutTaskInfo.getPercentage()) < 1){ | |
| 455 | - result.add((MergeOrCutTaskInfo)redisUtil.get(keyItem)); | |
| 456 | - } | |
| 457 | - } | |
| 458 | - }else { | |
| 459 | - result.add((MergeOrCutTaskInfo)redisUtil.get(keyItem)); | |
| 460 | - } | |
| 461 | - } | |
| 462 | - } | |
| 463 | - result.sort((MergeOrCutTaskInfo m1, MergeOrCutTaskInfo m2)->{ | |
| 464 | - int sortResult = 0; | |
| 465 | - try { | |
| 466 | - sortResult = simpleDateFormatForTime.parse(m1.getCreateTime()).compareTo(simpleDateFormatForTime.parse(m2.getCreateTime())); | |
| 467 | - if (sortResult == 0) { | |
| 468 | - sortResult = simpleDateFormatForTime.parse(m1.getStartTime()).compareTo(simpleDateFormatForTime.parse(m2.getStartTime())); | |
| 469 | - } | |
| 470 | - if (sortResult == 0) { | |
| 471 | - sortResult = simpleDateFormatForTime.parse(m1.getEndTime()).compareTo(simpleDateFormatForTime.parse(m2.getEndTime())); | |
| 472 | - } | |
| 473 | - } catch (ParseException e) { | |
| 474 | - e.printStackTrace(); | |
| 475 | - } | |
| 476 | - return sortResult * -1; | |
| 477 | - }); | |
| 478 | - | |
| 479 | - return result; | |
| 480 | - } | |
| 481 | - | |
| 482 | - public boolean collection(String app, String stream, String type) { | |
| 483 | - File streamFile = new File(userSettings.getRecord() + File.separator + app + File.separator + stream); | |
| 484 | - boolean result = false; | |
| 485 | - if (streamFile.exists() && streamFile.isDirectory() && streamFile.canWrite()) { | |
| 486 | - File signFile = new File(streamFile.getAbsolutePath() + File.separator + type + ".sign"); | |
| 487 | - try { | |
| 488 | - result = signFile.createNewFile(); | |
| 489 | - } catch (IOException e) { | |
| 490 | - logger.error("[收藏文件]失败,{}/{}", app, stream); | |
| 491 | - } | |
| 492 | - } | |
| 493 | - return result; | |
| 494 | - } | |
| 495 | - | |
| 496 | - 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"); | |
| 498 | - boolean result = false; | |
| 499 | - if (signFile.exists() && signFile.isFile()) { | |
| 500 | - result = signFile.delete(); | |
| 501 | - } | |
| 502 | - return result; | |
| 503 | - } | |
| 504 | - | |
| 505 | - public List<SignInfo> getCollectionList(String app, String stream, String type) { | |
| 506 | - List<File> appList = this.getAppList(true); | |
| 507 | - List<SignInfo> result = new ArrayList<>(); | |
| 508 | - if (appList.size() > 0) { | |
| 509 | - for (File appFile : appList) { | |
| 510 | - if (app != null) { | |
| 511 | - if (!app.equals(appFile.getName())) { | |
| 512 | - continue; | |
| 513 | - } | |
| 514 | - } | |
| 515 | - List<File> streamList = getStreamList(appFile, true); | |
| 516 | - if (streamList.size() > 0) { | |
| 517 | - for (File streamFile : streamList) { | |
| 518 | - if (stream != null) { | |
| 519 | - if (!stream.equals(streamFile.getName())) { | |
| 520 | - continue; | |
| 521 | - } | |
| 522 | - } | |
| 523 | - | |
| 524 | - if (type != null) { | |
| 525 | - File signFile = new File(streamFile.getAbsolutePath() + File.separator + type + ".sign"); | |
| 526 | - if (signFile.exists()) { | |
| 527 | - SignInfo signInfo = new SignInfo(); | |
| 528 | - signInfo.setApp(appFile.getName()); | |
| 529 | - signInfo.setStream(streamFile.getName()); | |
| 530 | - signInfo.setType(type); | |
| 531 | - result.add(signInfo); | |
| 532 | - } | |
| 533 | - }else { | |
| 534 | - streamFile.listFiles((File dir, String name) -> { | |
| 535 | - File currentFile = new File(dir.getAbsolutePath() + File.separator + name); | |
| 536 | - if (currentFile.isFile() && name.endsWith(".sign")){ | |
| 537 | - String currentType = name.substring(0, name.length() - ".sign".length()); | |
| 538 | - SignInfo signInfo = new SignInfo(); | |
| 539 | - signInfo.setApp(appFile.getName()); | |
| 540 | - signInfo.setStream(streamFile.getName()); | |
| 541 | - signInfo.setType(currentType); | |
| 542 | - result.add(signInfo); | |
| 543 | - } | |
| 544 | - return false; | |
| 545 | - }); | |
| 546 | - } | |
| 547 | - } | |
| 548 | - } | |
| 549 | - } | |
| 550 | - } | |
| 551 | - return result; | |
| 552 | - } | |
| 553 | - | |
| 554 | - public long fileDuration(String app, String stream) { | |
| 555 | - List<File> allFiles = getFilesInTime(app, stream, null, null); | |
| 556 | - long durationResult = 0; | |
| 557 | - if (allFiles != null && allFiles.size() > 0) { | |
| 558 | - for (File file : allFiles) { | |
| 559 | - try { | |
| 560 | - durationResult += ffmpegExecUtils.duration(file); | |
| 561 | - } catch (IOException e) { | |
| 562 | - logger.error("获取{}视频时长错误:{}", file.getAbsolutePath(), e.getMessage()); | |
| 563 | - } | |
| 564 | - } | |
| 565 | - } | |
| 566 | - return durationResult; | |
| 567 | - } | |
| 568 | -} |
src/main/java/top/panll/assist/utils/DateUtils.java
| 1 | 1 | package top.panll.assist.utils; |
| 2 | 2 | |
| 3 | +import java.text.ParseException; | |
| 3 | 4 | import java.text.SimpleDateFormat; |
| 4 | 5 | import java.time.Instant; |
| 5 | 6 | import java.time.LocalDateTime; |
| 6 | 7 | import java.time.LocalTime; |
| 7 | 8 | import java.time.ZoneId; |
| 8 | 9 | import java.time.format.DateTimeFormatter; |
| 10 | +import java.time.temporal.TemporalAccessor; | |
| 9 | 11 | import java.util.Date; |
| 10 | 12 | import java.util.Locale; |
| 11 | 13 | |
| ... | ... | @@ -13,10 +15,14 @@ public class DateUtils { |
| 13 | 15 | |
| 14 | 16 | public static final String PATTERNForDateTime = "yyyy-MM-dd HH:mm:ss"; |
| 15 | 17 | |
| 18 | + public static final String PATTERNForTime = "HH:mm:ss"; | |
| 19 | + | |
| 16 | 20 | public static final String PATTERNForDate = "yyyy-MM-dd"; |
| 17 | 21 | |
| 18 | 22 | public static final String zoneStr = "Asia/Shanghai"; |
| 19 | 23 | |
| 24 | + public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERNForDateTime, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); | |
| 25 | + public static final DateTimeFormatter formatterForTime = DateTimeFormatter.ofPattern(PATTERNForTime, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); | |
| 20 | 26 | |
| 21 | 27 | |
| 22 | 28 | // 获得某天最大时间 2020-02-19 23:59:59 |
| ... | ... | @@ -39,8 +45,38 @@ public class DateUtils { |
| 39 | 45 | } |
| 40 | 46 | |
| 41 | 47 | public static String getDateTimeStr(Date date) { |
| 42 | - SimpleDateFormat formatter = new SimpleDateFormat(PATTERNForDateTime); | |
| 48 | + SimpleDateFormat formatter = new SimpleDateFormat(PATTERNForDateTime); | |
| 43 | 49 | return formatter.format(date); |
| 44 | 50 | } |
| 51 | + public static String getTimeStr(Long dateTime) { | |
| 52 | + SimpleDateFormat formatter = new SimpleDateFormat(PATTERNForTime); | |
| 53 | + return formatter.format(new Date(dateTime)); | |
| 54 | + } | |
| 55 | + | |
| 56 | + public static boolean checkDateFormat(String dateStr) { | |
| 57 | + SimpleDateFormat formatter = new SimpleDateFormat(PATTERNForDate); | |
| 58 | + try { | |
| 59 | + formatter.parse(dateStr); | |
| 60 | + return true; | |
| 61 | + } catch (ParseException e) { | |
| 62 | + return false; | |
| 63 | + } | |
| 64 | + } | |
| 65 | + | |
| 66 | + public static boolean checkDateTimeFormat(String dateStr) { | |
| 67 | + SimpleDateFormat formatter = new SimpleDateFormat(PATTERNForDateTime); | |
| 68 | + try { | |
| 69 | + formatter.parse(dateStr); | |
| 70 | + return true; | |
| 71 | + } catch (ParseException e) { | |
| 72 | + return false; | |
| 73 | + } | |
| 74 | + } | |
| 75 | + | |
| 76 | + public static long yyyy_MM_dd_HH_mm_ssToTimestamp(String formatTime) { | |
| 77 | + TemporalAccessor temporalAccessor = formatter.parse(formatTime); | |
| 78 | + Instant instant = Instant.from(temporalAccessor); | |
| 79 | + return instant.getEpochSecond(); | |
| 80 | + } | |
| 45 | 81 | |
| 46 | 82 | } | ... | ... |
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/java/top/panll/assist/utils/RedisUtil.java deleted
100755 → 0
| 1 | -package top.panll.assist.utils; | |
| 2 | - | |
| 3 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 4 | -import org.springframework.data.redis.core.*; | |
| 5 | -import org.springframework.stereotype.Component; | |
| 6 | -import org.springframework.util.CollectionUtils; | |
| 7 | - | |
| 8 | -import java.util.*; | |
| 9 | -import java.util.concurrent.TimeUnit; | |
| 10 | - | |
| 11 | -/** | |
| 12 | - * @Description:Redis工具类 | |
| 13 | - * @author: swwheihei | |
| 14 | - * @date: 2020年5月6日 下午8:27:29 | |
| 15 | - */ | |
| 16 | -@Component | |
| 17 | -@SuppressWarnings(value = {"rawtypes", "unchecked"}) | |
| 18 | -public class RedisUtil { | |
| 19 | - | |
| 20 | - @Autowired | |
| 21 | - private RedisTemplate<Object, Object> redisTemplate; | |
| 22 | - | |
| 23 | - /** | |
| 24 | - * 指定缓存失效时间 | |
| 25 | - * @param key 键 | |
| 26 | - * @param time 时间(秒) | |
| 27 | - * @return true / false | |
| 28 | - */ | |
| 29 | - public boolean expire(String key, long time) { | |
| 30 | - try { | |
| 31 | - if (time > 0) { | |
| 32 | - redisTemplate.expire(key, time, TimeUnit.SECONDS); | |
| 33 | - } | |
| 34 | - return true; | |
| 35 | - } catch (Exception e) { | |
| 36 | - e.printStackTrace(); | |
| 37 | - return false; | |
| 38 | - } | |
| 39 | - | |
| 40 | - } | |
| 41 | - | |
| 42 | - /** | |
| 43 | - * 根据 key 获取过期时间 | |
| 44 | - * @param key 键 | |
| 45 | - * @return | |
| 46 | - */ | |
| 47 | - public long getExpire(String key) { | |
| 48 | - return redisTemplate.getExpire(key, TimeUnit.SECONDS); | |
| 49 | - } | |
| 50 | - | |
| 51 | - /** | |
| 52 | - * 判断 key 是否存在 | |
| 53 | - * @param key 键 | |
| 54 | - * @return true / false | |
| 55 | - */ | |
| 56 | - public boolean hasKey(String key) { | |
| 57 | - try { | |
| 58 | - return redisTemplate.hasKey(key); | |
| 59 | - } catch (Exception e) { | |
| 60 | - e.printStackTrace(); | |
| 61 | - return false; | |
| 62 | - } | |
| 63 | - } | |
| 64 | - | |
| 65 | - /** | |
| 66 | - * 删除缓存 | |
| 67 | - * @SuppressWarnings("unchecked") 忽略类型转换警告 | |
| 68 | - * @param key 键(一个或者多个) | |
| 69 | - */ | |
| 70 | - public boolean del(String... key) { | |
| 71 | - try { | |
| 72 | - if (key != null && key.length > 0) { | |
| 73 | - if (key.length == 1) { | |
| 74 | - redisTemplate.delete(key[0]); | |
| 75 | - } else { | |
| 76 | -// 传入一个 Collection<String> 集合 | |
| 77 | - redisTemplate.delete(CollectionUtils.arrayToList(key)); | |
| 78 | - } | |
| 79 | - } | |
| 80 | - return true; | |
| 81 | - } catch (Exception e) { | |
| 82 | - e.printStackTrace(); | |
| 83 | - return false; | |
| 84 | - } | |
| 85 | - } | |
| 86 | - | |
| 87 | -// ============================== String ============================== | |
| 88 | - | |
| 89 | - /** | |
| 90 | - * 普通缓存获取 | |
| 91 | - * @param key 键 | |
| 92 | - * @return 值 | |
| 93 | - */ | |
| 94 | - public Object get(String key) { | |
| 95 | - return key == null ? null : redisTemplate.opsForValue().get(key); | |
| 96 | - } | |
| 97 | - | |
| 98 | - /** | |
| 99 | - * 普通缓存放入 | |
| 100 | - * @param key 键 | |
| 101 | - * @param value 值 | |
| 102 | - * @return true / false | |
| 103 | - */ | |
| 104 | - public boolean set(String key, Object value) { | |
| 105 | - try { | |
| 106 | - redisTemplate.opsForValue().set(key, value); | |
| 107 | - return true; | |
| 108 | - } catch (Exception e) { | |
| 109 | -// e.printStackTrace(); | |
| 110 | - return false; | |
| 111 | - } | |
| 112 | - } | |
| 113 | - | |
| 114 | - /** | |
| 115 | - * 普通缓存放入并设置时间 | |
| 116 | - * @param key 键 | |
| 117 | - * @param value 值 | |
| 118 | - * @param time 时间(秒),如果 time < 0 则设置无限时间 | |
| 119 | - * @return true / false | |
| 120 | - */ | |
| 121 | - public boolean set(String key, Object value, long time) { | |
| 122 | - try { | |
| 123 | - if (time > 0) { | |
| 124 | - redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); | |
| 125 | - } else { | |
| 126 | - set(key, value); | |
| 127 | - } | |
| 128 | - return true; | |
| 129 | - } catch (Exception e) { | |
| 130 | - e.printStackTrace(); | |
| 131 | - return false; | |
| 132 | - } | |
| 133 | - } | |
| 134 | - | |
| 135 | - /** | |
| 136 | - * 递增 | |
| 137 | - * @param key 键 | |
| 138 | - * @param delta 递增大小 | |
| 139 | - * @return | |
| 140 | - */ | |
| 141 | - public long incr(String key, long delta) { | |
| 142 | - if (delta < 0) { | |
| 143 | - throw new RuntimeException("递增因子必须大于 0"); | |
| 144 | - } | |
| 145 | - return redisTemplate.opsForValue().increment(key, delta); | |
| 146 | - } | |
| 147 | - | |
| 148 | - /** | |
| 149 | - * 递减 | |
| 150 | - * @param key 键 | |
| 151 | - * @param delta 递减大小 | |
| 152 | - * @return | |
| 153 | - */ | |
| 154 | - public long decr(String key, long delta) { | |
| 155 | - if (delta < 0) { | |
| 156 | - throw new RuntimeException("递减因子必须大于 0"); | |
| 157 | - } | |
| 158 | - return redisTemplate.opsForValue().increment(key, delta); | |
| 159 | - } | |
| 160 | - | |
| 161 | -// ============================== Map ============================== | |
| 162 | - | |
| 163 | - /** | |
| 164 | - * HashGet | |
| 165 | - * @param key 键(no null) | |
| 166 | - * @param item 项(no null) | |
| 167 | - * @return 值 | |
| 168 | - */ | |
| 169 | - public Object hget(String key, String item) { | |
| 170 | - return redisTemplate.opsForHash().get(key, item); | |
| 171 | - } | |
| 172 | - | |
| 173 | - /** | |
| 174 | - * 获取 key 对应的 map | |
| 175 | - * @param key 键(no null) | |
| 176 | - * @return 对应的多个键值 | |
| 177 | - */ | |
| 178 | - public Map<Object, Object> hmget(String key) { | |
| 179 | - return redisTemplate.opsForHash().entries(key); | |
| 180 | - } | |
| 181 | - | |
| 182 | - /** | |
| 183 | - * HashSet | |
| 184 | - * @param key 键 | |
| 185 | - * @param map 值 | |
| 186 | - * @return true / false | |
| 187 | - */ | |
| 188 | - public boolean hmset(String key, Map<Object, Object> map) { | |
| 189 | - try { | |
| 190 | - redisTemplate.opsForHash().putAll(key, map); | |
| 191 | - return true; | |
| 192 | - } catch (Exception e) { | |
| 193 | - e.printStackTrace(); | |
| 194 | - return false; | |
| 195 | - } | |
| 196 | - } | |
| 197 | - | |
| 198 | - /** | |
| 199 | - * HashSet 并设置时间 | |
| 200 | - * @param key 键 | |
| 201 | - * @param map 值 | |
| 202 | - * @param time 时间 | |
| 203 | - * @return true / false | |
| 204 | - */ | |
| 205 | - public boolean hmset(String key, Map<Object, Object> map, long time) { | |
| 206 | - try { | |
| 207 | - redisTemplate.opsForHash().putAll(key, map); | |
| 208 | - if (time > 0) { | |
| 209 | - expire(key, time); | |
| 210 | - } | |
| 211 | - return true; | |
| 212 | - } catch (Exception e) { | |
| 213 | - e.printStackTrace(); | |
| 214 | - return false; | |
| 215 | - } | |
| 216 | - } | |
| 217 | - | |
| 218 | - /** | |
| 219 | - * 向一张 Hash表 中放入数据,如不存在则创建 | |
| 220 | - * @param key 键 | |
| 221 | - * @param item 项 | |
| 222 | - * @param value 值 | |
| 223 | - * @return true / false | |
| 224 | - */ | |
| 225 | - public boolean hset(String key, String item, Object value) { | |
| 226 | - try { | |
| 227 | - redisTemplate.opsForHash().put(key, item, value); | |
| 228 | - return true; | |
| 229 | - } catch (Exception e) { | |
| 230 | - e.printStackTrace(); | |
| 231 | - return false; | |
| 232 | - } | |
| 233 | - } | |
| 234 | - | |
| 235 | - /** | |
| 236 | - * 向一张 Hash表 中放入数据,并设置时间,如不存在则创建 | |
| 237 | - * @param key 键 | |
| 238 | - * @param item 项 | |
| 239 | - * @param value 值 | |
| 240 | - * @param time 时间(如果原来的 Hash表 设置了时间,这里会覆盖) | |
| 241 | - * @return true / false | |
| 242 | - */ | |
| 243 | - public boolean hset(String key, String item, Object value, long time) { | |
| 244 | - try { | |
| 245 | - redisTemplate.opsForHash().put(key, item, value); | |
| 246 | - if (time > 0) { | |
| 247 | - expire(key, time); | |
| 248 | - } | |
| 249 | - return true; | |
| 250 | - } catch (Exception e) { | |
| 251 | - e.printStackTrace(); | |
| 252 | - return false; | |
| 253 | - } | |
| 254 | - } | |
| 255 | - | |
| 256 | - /** | |
| 257 | - * 删除 Hash表 中的值 | |
| 258 | - * @param key 键 | |
| 259 | - * @param item 项(可以多个,no null) | |
| 260 | - */ | |
| 261 | - public void hdel(String key, Object... item) { | |
| 262 | - redisTemplate.opsForHash().delete(key, item); | |
| 263 | - } | |
| 264 | - | |
| 265 | - /** | |
| 266 | - * 判断 Hash表 中是否有该键的值 | |
| 267 | - * @param key 键(no null) | |
| 268 | - * @param item 值(no null) | |
| 269 | - * @return true / false | |
| 270 | - */ | |
| 271 | - public boolean hHasKey(String key, String item) { | |
| 272 | - return redisTemplate.opsForHash().hasKey(key, item); | |
| 273 | - } | |
| 274 | - | |
| 275 | - /** | |
| 276 | - * Hash递增,如果不存在则创建一个,并把新增的值返回 | |
| 277 | - * @param key 键 | |
| 278 | - * @param item 项 | |
| 279 | - * @param by 递增大小 > 0 | |
| 280 | - * @return | |
| 281 | - */ | |
| 282 | - public Double hincr(String key, String item, Double by) { | |
| 283 | - return redisTemplate.opsForHash().increment(key, item, by); | |
| 284 | - } | |
| 285 | - | |
| 286 | - /** | |
| 287 | - * Hash递减 | |
| 288 | - * @param key 键 | |
| 289 | - * @param item 项 | |
| 290 | - * @param by 递减大小 | |
| 291 | - * @return | |
| 292 | - */ | |
| 293 | - public Double hdecr(String key, String item, Double by) { | |
| 294 | - return redisTemplate.opsForHash().increment(key, item, -by); | |
| 295 | - } | |
| 296 | - | |
| 297 | -// ============================== Set ============================== | |
| 298 | - | |
| 299 | - /** | |
| 300 | - * 根据 key 获取 set 中的所有值 | |
| 301 | - * @param key 键 | |
| 302 | - * @return 值 | |
| 303 | - */ | |
| 304 | - public Set<Object> sGet(String key) { | |
| 305 | - try { | |
| 306 | - return redisTemplate.opsForSet().members(key); | |
| 307 | - } catch (Exception e) { | |
| 308 | - e.printStackTrace(); | |
| 309 | - return null; | |
| 310 | - } | |
| 311 | - } | |
| 312 | - | |
| 313 | - /** | |
| 314 | - * 从键为 key 的 set 中,根据 value 查询是否存在 | |
| 315 | - * @param key 键 | |
| 316 | - * @param value 值 | |
| 317 | - * @return true / false | |
| 318 | - */ | |
| 319 | - public boolean sHasKey(String key, Object value) { | |
| 320 | - try { | |
| 321 | - return redisTemplate.opsForSet().isMember(key, value); | |
| 322 | - } catch (Exception e) { | |
| 323 | - e.printStackTrace(); | |
| 324 | - return false; | |
| 325 | - } | |
| 326 | - } | |
| 327 | - | |
| 328 | - /** | |
| 329 | - * 将数据放入 set缓存 | |
| 330 | - * @param key 键值 | |
| 331 | - * @param values 值(可以多个) | |
| 332 | - * @return 成功个数 | |
| 333 | - */ | |
| 334 | - public long sSet(String key, Object... values) { | |
| 335 | - try { | |
| 336 | - return redisTemplate.opsForSet().add(key, values); | |
| 337 | - } catch (Exception e) { | |
| 338 | - e.printStackTrace(); | |
| 339 | - return 0; | |
| 340 | - } | |
| 341 | - } | |
| 342 | - | |
| 343 | - /** | |
| 344 | - * 将数据放入 set缓存,并设置时间 | |
| 345 | - * @param key 键 | |
| 346 | - * @param time 时间 | |
| 347 | - * @param values 值(可以多个) | |
| 348 | - * @return 成功放入个数 | |
| 349 | - */ | |
| 350 | - public long sSet(String key, long time, Object... values) { | |
| 351 | - try { | |
| 352 | - long count = redisTemplate.opsForSet().add(key, values); | |
| 353 | - if (time > 0) { | |
| 354 | - expire(key, time); | |
| 355 | - } | |
| 356 | - return count; | |
| 357 | - } catch (Exception e) { | |
| 358 | - e.printStackTrace(); | |
| 359 | - return 0; | |
| 360 | - } | |
| 361 | - } | |
| 362 | - | |
| 363 | - /** | |
| 364 | - * 获取 set缓存的长度 | |
| 365 | - * @param key 键 | |
| 366 | - * @return 长度 | |
| 367 | - */ | |
| 368 | - public long sGetSetSize(String key) { | |
| 369 | - try { | |
| 370 | - return redisTemplate.opsForSet().size(key); | |
| 371 | - } catch (Exception e) { | |
| 372 | - e.printStackTrace(); | |
| 373 | - return 0; | |
| 374 | - } | |
| 375 | - } | |
| 376 | - | |
| 377 | - /** | |
| 378 | - * 移除 set缓存中,值为 value 的 | |
| 379 | - * @param key 键 | |
| 380 | - * @param values 值 | |
| 381 | - * @return 成功移除个数 | |
| 382 | - */ | |
| 383 | - public long setRemove(String key, Object... values) { | |
| 384 | - try { | |
| 385 | - return redisTemplate.opsForSet().remove(key, values); | |
| 386 | - } catch (Exception e) { | |
| 387 | - e.printStackTrace(); | |
| 388 | - return 0; | |
| 389 | - } | |
| 390 | - } | |
| 391 | -// ============================== ZSet ============================== | |
| 392 | - | |
| 393 | - /** | |
| 394 | - * 添加一个元素, zset与set最大的区别就是每个元素都有一个score,因此有个排序的辅助功能; zadd | |
| 395 | - * | |
| 396 | - * @param key | |
| 397 | - * @param value | |
| 398 | - * @param score | |
| 399 | - */ | |
| 400 | - public void zAdd(Object key, Object value, double score) { | |
| 401 | - redisTemplate.opsForZSet().add(key, value, score); | |
| 402 | - } | |
| 403 | - | |
| 404 | - /** | |
| 405 | - * 删除元素 zrem | |
| 406 | - * | |
| 407 | - * @param key | |
| 408 | - * @param value | |
| 409 | - */ | |
| 410 | - public void zRemove(Object key, Object value) { | |
| 411 | - redisTemplate.opsForZSet().remove(key, value); | |
| 412 | - } | |
| 413 | - | |
| 414 | - /** | |
| 415 | - * score的增加or减少 zincrby | |
| 416 | - * | |
| 417 | - * @param key | |
| 418 | - * @param value | |
| 419 | - * @param score | |
| 420 | - */ | |
| 421 | - public Double zIncrScore(Object key, Object value, double score) { | |
| 422 | - return redisTemplate.opsForZSet().incrementScore(key, value, score); | |
| 423 | - } | |
| 424 | - | |
| 425 | - /** | |
| 426 | - * 查询value对应的score zscore | |
| 427 | - * | |
| 428 | - * @param key | |
| 429 | - * @param value | |
| 430 | - * @return | |
| 431 | - */ | |
| 432 | - public Double zScore(Object key, Object value) { | |
| 433 | - return redisTemplate.opsForZSet().score(key, value); | |
| 434 | - } | |
| 435 | - | |
| 436 | - /** | |
| 437 | - * 判断value在zset中的排名 zrank | |
| 438 | - * | |
| 439 | - * @param key | |
| 440 | - * @param value | |
| 441 | - * @return | |
| 442 | - */ | |
| 443 | - public Long zRank(Object key, Object value) { | |
| 444 | - return redisTemplate.opsForZSet().rank(key, value); | |
| 445 | - } | |
| 446 | - | |
| 447 | - /** | |
| 448 | - * 返回集合的长度 | |
| 449 | - * | |
| 450 | - * @param key | |
| 451 | - * @return | |
| 452 | - */ | |
| 453 | - public Long zSize(Object key) { | |
| 454 | - return redisTemplate.opsForZSet().zCard(key); | |
| 455 | - } | |
| 456 | - | |
| 457 | - /** | |
| 458 | - * 查询集合中指定顺序的值, 0 -1 表示获取全部的集合内容 zrange | |
| 459 | - * | |
| 460 | - * 返回有序的集合,score小的在前面 | |
| 461 | - * | |
| 462 | - * @param key | |
| 463 | - * @param start | |
| 464 | - * @param end | |
| 465 | - * @return | |
| 466 | - */ | |
| 467 | - public Set<Object> ZRange(Object key, int start, int end) { | |
| 468 | - return redisTemplate.opsForZSet().range(key, start, end); | |
| 469 | - } | |
| 470 | - /** | |
| 471 | - * 查询集合中指定顺序的值和score,0, -1 表示获取全部的集合内容 | |
| 472 | - * | |
| 473 | - * @param key | |
| 474 | - * @param start | |
| 475 | - * @param end | |
| 476 | - * @return | |
| 477 | - */ | |
| 478 | - public Set<ZSetOperations.TypedTuple<Object>> zRangeWithScore(Object key, int start, int end) { | |
| 479 | - return redisTemplate.opsForZSet().rangeWithScores(key, start, end); | |
| 480 | - } | |
| 481 | - /** | |
| 482 | - * 查询集合中指定顺序的值 zrevrange | |
| 483 | - * | |
| 484 | - * 返回有序的集合中,score大的在前面 | |
| 485 | - * | |
| 486 | - * @param key | |
| 487 | - * @param start | |
| 488 | - * @param end | |
| 489 | - * @return | |
| 490 | - */ | |
| 491 | - public Set<Object> zRevRange(Object key, int start, int end) { | |
| 492 | - return redisTemplate.opsForZSet().reverseRange(key, start, end); | |
| 493 | - } | |
| 494 | - /** | |
| 495 | - * 根据score的值,来获取满足条件的集合 zrangebyscore | |
| 496 | - * | |
| 497 | - * @param key | |
| 498 | - * @param min | |
| 499 | - * @param max | |
| 500 | - * @return | |
| 501 | - */ | |
| 502 | - public Set<Object> zSortRange(Object key, int min, int max) { | |
| 503 | - return redisTemplate.opsForZSet().rangeByScore(key, min, max); | |
| 504 | - } | |
| 505 | - | |
| 506 | - | |
| 507 | -// ============================== List ============================== | |
| 508 | - | |
| 509 | - /** | |
| 510 | - * 获取 list缓存的内容 | |
| 511 | - * @param key 键 | |
| 512 | - * @param start 开始 | |
| 513 | - * @param end 结束(0 到 -1 代表所有值) | |
| 514 | - * @return | |
| 515 | - */ | |
| 516 | - public List<Object> lGet(String key, long start, long end) { | |
| 517 | - try { | |
| 518 | - return redisTemplate.opsForList().range(key, start, end); | |
| 519 | - } catch (Exception e) { | |
| 520 | - e.printStackTrace(); | |
| 521 | - return null; | |
| 522 | - } | |
| 523 | - } | |
| 524 | - | |
| 525 | - /** | |
| 526 | - * 获取 list缓存的长度 | |
| 527 | - * @param key 键 | |
| 528 | - * @return 长度 | |
| 529 | - */ | |
| 530 | - public long lGetListSize(String key) { | |
| 531 | - try { | |
| 532 | - return redisTemplate.opsForList().size(key); | |
| 533 | - } catch (Exception e) { | |
| 534 | - e.printStackTrace(); | |
| 535 | - return 0; | |
| 536 | - } | |
| 537 | - } | |
| 538 | - | |
| 539 | - /** | |
| 540 | - * 根据索引 index 获取键为 key 的 list 中的元素 | |
| 541 | - * @param key 键 | |
| 542 | - * @param index 索引 | |
| 543 | - * 当 index >= 0 时 {0:表头, 1:第二个元素} | |
| 544 | - * 当 index < 0 时 {-1:表尾, -2:倒数第二个元素} | |
| 545 | - * @return 值 | |
| 546 | - */ | |
| 547 | - public Object lGetIndex(String key, long index) { | |
| 548 | - try { | |
| 549 | - return redisTemplate.opsForList().index(key, index); | |
| 550 | - } catch (Exception e) { | |
| 551 | - e.printStackTrace(); | |
| 552 | - return null; | |
| 553 | - } | |
| 554 | - } | |
| 555 | - | |
| 556 | - /** | |
| 557 | - * 将值 value 插入键为 key 的 list 中,如果 list 不存在则创建空 list | |
| 558 | - * @param key 键 | |
| 559 | - * @param value 值 | |
| 560 | - * @return true / false | |
| 561 | - */ | |
| 562 | - public boolean lSet(String key, Object value) { | |
| 563 | - try { | |
| 564 | - redisTemplate.opsForList().rightPush(key, value); | |
| 565 | - return true; | |
| 566 | - } catch (Exception e) { | |
| 567 | - e.printStackTrace(); | |
| 568 | - return false; | |
| 569 | - } | |
| 570 | - } | |
| 571 | - | |
| 572 | - /** | |
| 573 | - * 将值 value 插入键为 key 的 list 中,并设置时间 | |
| 574 | - * @param key 键 | |
| 575 | - * @param value 值 | |
| 576 | - * @param time 时间 | |
| 577 | - * @return true / false | |
| 578 | - */ | |
| 579 | - public boolean lSet(String key, Object value, long time) { | |
| 580 | - try { | |
| 581 | - redisTemplate.opsForList().rightPush(key, value); | |
| 582 | - if (time > 0) { | |
| 583 | - expire(key, time); | |
| 584 | - } | |
| 585 | - return true; | |
| 586 | - } catch (Exception e) { | |
| 587 | - e.printStackTrace(); | |
| 588 | - return false; | |
| 589 | - } | |
| 590 | - } | |
| 591 | - | |
| 592 | - /** | |
| 593 | - * 将 values 插入键为 key 的 list 中 | |
| 594 | - * @param key 键 | |
| 595 | - * @param values 值 | |
| 596 | - * @return true / false | |
| 597 | - */ | |
| 598 | - public boolean lSetList(String key, List<Object> values) { | |
| 599 | - try { | |
| 600 | - redisTemplate.opsForList().rightPushAll(key, values); | |
| 601 | - return true; | |
| 602 | - } catch (Exception e) { | |
| 603 | - e.printStackTrace(); | |
| 604 | - return false; | |
| 605 | - } | |
| 606 | - } | |
| 607 | - | |
| 608 | - /** | |
| 609 | - * 将 values 插入键为 key 的 list 中,并设置时间 | |
| 610 | - * @param key 键 | |
| 611 | - * @param values 值 | |
| 612 | - * @param time 时间 | |
| 613 | - * @return true / false | |
| 614 | - */ | |
| 615 | - public boolean lSetList(String key, List<Object> values, long time) { | |
| 616 | - try { | |
| 617 | - redisTemplate.opsForList().rightPushAll(key, values); | |
| 618 | - if (time > 0) { | |
| 619 | - expire(key, time); | |
| 620 | - } | |
| 621 | - return true; | |
| 622 | - } catch (Exception e) { | |
| 623 | - e.printStackTrace(); | |
| 624 | - return false; | |
| 625 | - } | |
| 626 | - } | |
| 627 | - | |
| 628 | - /** | |
| 629 | - * 根据索引 index 修改键为 key 的值 | |
| 630 | - * @param key 键 | |
| 631 | - * @param index 索引 | |
| 632 | - * @param value 值 | |
| 633 | - * @return true / false | |
| 634 | - */ | |
| 635 | - public boolean lUpdateIndex(String key, long index, Object value) { | |
| 636 | - try { | |
| 637 | - redisTemplate.opsForList().set(key, index, value); | |
| 638 | - return true; | |
| 639 | - } catch (Exception e) { | |
| 640 | - e.printStackTrace(); | |
| 641 | - return false; | |
| 642 | - } | |
| 643 | - } | |
| 644 | - | |
| 645 | - /** | |
| 646 | - * 在键为 key 的 list 中删除值为 value 的元素 | |
| 647 | - * @param key 键 | |
| 648 | - * @param count 如果 count == 0 则删除 list 中所有值为 value 的元素 | |
| 649 | - * 如果 count > 0 则删除 list 中最左边那个值为 value 的元素 | |
| 650 | - * 如果 count < 0 则删除 list 中最右边那个值为 value 的元素 | |
| 651 | - * @param value | |
| 652 | - * @return | |
| 653 | - */ | |
| 654 | - public long lRemove(String key, long count, Object value) { | |
| 655 | - try { | |
| 656 | - return redisTemplate.opsForList().remove(key, count, value); | |
| 657 | - } catch (Exception e) { | |
| 658 | - e.printStackTrace(); | |
| 659 | - return 0; | |
| 660 | - } | |
| 661 | - } | |
| 662 | - | |
| 663 | - /** | |
| 664 | - * 模糊查询 | |
| 665 | - * @param key 键 | |
| 666 | - * @return true / false | |
| 667 | - */ | |
| 668 | - public List<Object> keys(String key) { | |
| 669 | - try { | |
| 670 | - Set<Object> set = redisTemplate.keys(key); | |
| 671 | - return new ArrayList<>(set); | |
| 672 | - } catch (Exception e) { | |
| 673 | - e.printStackTrace(); | |
| 674 | - return null; | |
| 675 | - } | |
| 676 | - } | |
| 677 | - | |
| 678 | - | |
| 679 | - /** | |
| 680 | - * 模糊查询 | |
| 681 | - * @param query 查询参数 | |
| 682 | - * @return | |
| 683 | - */ | |
| 684 | -// public List<Object> scan(String query) { | |
| 685 | -// List<Object> result = new ArrayList<>(); | |
| 686 | -// try { | |
| 687 | -// Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan("field", | |
| 688 | -// ScanOptions.scanOptions().match(query).count(1000).build()); | |
| 689 | -// while (cursor.hasNext()) { | |
| 690 | -// Map.Entry<Object,Object> entry = cursor.next(); | |
| 691 | -// result.add(entry.getKey()); | |
| 692 | -// Object key = entry.getKey(); | |
| 693 | -// Object valueSet = entry.getValue(); | |
| 694 | -// } | |
| 695 | -// //关闭cursor | |
| 696 | -// cursor.close(); | |
| 697 | -// } catch (Exception e) { | |
| 698 | -// e.printStackTrace(); | |
| 699 | -// } | |
| 700 | -// return result; | |
| 701 | -// } | |
| 702 | - | |
| 703 | - /** | |
| 704 | - * 模糊查询 | |
| 705 | - * @param query 查询参数 | |
| 706 | - * @return | |
| 707 | - */ | |
| 708 | - public List<Object> scan(String query) { | |
| 709 | - Set<String> resultKeys = redisTemplate.execute((RedisCallback<Set<String>>) connection -> { | |
| 710 | - ScanOptions scanOptions = ScanOptions.scanOptions().match("*" + query + "*").count(1000).build(); | |
| 711 | - Cursor<byte[]> scan = connection.scan(scanOptions); | |
| 712 | - Set<String> keys = new HashSet<>(); | |
| 713 | - while (scan.hasNext()) { | |
| 714 | - byte[] next = scan.next(); | |
| 715 | - keys.add(new String(next)); | |
| 716 | - } | |
| 717 | - return keys; | |
| 718 | - }); | |
| 719 | - | |
| 720 | - return new ArrayList<>(resultKeys); | |
| 721 | - } | |
| 722 | - | |
| 723 | -} |
src/main/resources/all-application.yml deleted
100755 → 0
| 1 | -spring: | |
| 2 | - # REDIS数据库配置 | |
| 3 | - redis: | |
| 4 | - # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1 | |
| 5 | - host: 127.0.0.1 | |
| 6 | - # [必须修改] 端口号 | |
| 7 | - port: 6379 | |
| 8 | - # [可选] 数据库 DB | |
| 9 | - database: 8 | |
| 10 | - # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 | |
| 11 | - password: | |
| 12 | - # [可选] 超时时间 | |
| 13 | - timeout: 10000 | |
| 14 | - | |
| 15 | -# [必选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 | |
| 16 | -server: | |
| 17 | - port: 18081 | |
| 18 | - # [可选] HTTPS配置, 默认不开启 | |
| 19 | - ssl: | |
| 20 | - # [可选] 是否开启HTTPS访问 | |
| 21 | - enabled: false | |
| 22 | - # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名 | |
| 23 | - key-store: classpath:xxx.jks | |
| 24 | - # [可选] 证书密码 | |
| 25 | - key-password: password | |
| 26 | - # [可选] 证书类型, 默认为jks,根据实际修改 | |
| 27 | - key-store-type: JKS | |
| 28 | - | |
| 29 | -# [根据业务需求配置] | |
| 30 | -user-settings: | |
| 31 | - # [可选 ] zlm配置的录像路径,不配置则使用当前目录下的record目录 即: ./record | |
| 32 | - record: /media/lin/Server/ZLMediaKit/dev/ZLMediaKit/release/linux/Debug/www/record | |
| 33 | - # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理, 不配置则不删除 | |
| 34 | - recordDay: 7 | |
| 35 | - # [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理 | |
| 36 | - # recordTempDay: 7 | |
| 37 | - # [必选 ] ffmpeg路径 | |
| 38 | - ffmpeg: /usr/bin/ffmpeg | |
| 39 | - # [必选 ] ffprobe路径, 一般安装ffmpeg就会自带, 一般跟ffmpeg在同一目录,用于查询文件的信息 | |
| 40 | - ffprobe: /usr/bin/ffprobe | |
| 41 | - # [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50% | |
| 42 | - threads: 2 | |
| 43 | - | |
| 44 | -swagger-ui: | |
| 45 | - | |
| 46 | -# [可选] 日志配置, 一般不需要改 | |
| 47 | -logging: | |
| 48 | - file: | |
| 49 | - name: logs/wvp.log | |
| 50 | - max-history: 30 | |
| 51 | - max-size: 10MB | |
| 52 | - total-size-cap: 300MB | |
| 53 | - level: | |
| 54 | - root: WARN | |
| 55 | - top: | |
| 56 | - panll: | |
| 57 | - assist: info | |
| 58 | 0 | \ No newline at end of file |
src/main/resources/application-dev.yml deleted
100755 → 0
| 1 | -spring: | |
| 2 | - # REDIS数据库配置 | |
| 3 | - redis: | |
| 4 | - # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1 | |
| 5 | - host: 127.0.0.1 | |
| 6 | - # [必须修改] 端口号 | |
| 7 | - port: 6379 | |
| 8 | - # [可选] 数据库 DB | |
| 9 | - database: 8 | |
| 10 | - # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 | |
| 11 | - password: | |
| 12 | - # [可选] 超时时间 | |
| 13 | - timeout: 10000 | |
| 14 | - | |
| 15 | -# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 | |
| 16 | -server: | |
| 17 | - port: 18081 | |
| 18 | - # [可选] HTTPS配置, 默认不开启 | |
| 19 | - ssl: | |
| 20 | - # [可选] 是否开启HTTPS访问 | |
| 21 | - enabled: false | |
| 22 | - # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名 | |
| 23 | - key-store: classpath:xxx.jks | |
| 24 | - # [可选] 证书密码 | |
| 25 | - key-password: password | |
| 26 | - # [可选] 证书类型, 默认为jks,根据实际修改 | |
| 27 | - key-store-type: JKS | |
| 28 | - | |
| 29 | -# [根据业务需求配置] | |
| 30 | -userSettings: | |
| 31 | - # [可选 ] zlm配置的录像路径, | |
| 32 | - record: /media/lin/Server/ZLMediaKit/dev/ZLMediaKit/release/linux/Debug/www/record | |
| 33 | - # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理 | |
| 34 | - recordDay: 7 | |
| 35 | - # [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理 | |
| 36 | - # recordTempDay: 7 | |
| 37 | - # [必选 ] ffmpeg路径 | |
| 38 | - ffmpeg: /usr/bin/ffmpeg | |
| 39 | - # [必选 ] ffprobe路径, 一般安装ffmpeg就会自带, 一般跟ffmpeg在同一目录,用于查询文件的信息 | |
| 40 | - ffprobe: /usr/bin/ffprobe | |
| 41 | - # [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50% | |
| 42 | - threads: 2 | |
| 43 | - | |
| 44 | -swagger-ui: | |
| 45 | - | |
| 46 | -# [可选] 日志配置, 一般不需要改 | |
| 47 | -logging: | |
| 48 | - file: | |
| 49 | - name: logs/wvp.log | |
| 50 | - max-history: 30 | |
| 51 | - max-size: 10MB | |
| 52 | - total-size-cap: 300MB | |
| 53 | - level: | |
| 54 | - root: WARN | |
| 55 | - top: | |
| 56 | - panll: | |
| 57 | - assist: info | |
| 58 | 0 | \ No newline at end of file |
src/main/resources/application-local.yml deleted
100755 → 0
| 1 | -spring: | |
| 2 | - # REDIS数据库配置 | |
| 3 | - redis: | |
| 4 | - # [可选] 超时时间 | |
| 5 | - timeout: 10000 | |
| 6 | - # 以下为单机配置 | |
| 7 | - # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1 | |
| 8 | - host: 127.0.0.1 | |
| 9 | - # [必须修改] 端口号 | |
| 10 | - port: 6379 | |
| 11 | - # [可选] 数据库 DB | |
| 12 | - database: 1 | |
| 13 | - # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 | |
| 14 | - password: adminadmin123. | |
| 15 | - # 以下为集群配置 | |
| 16 | -# cluster: | |
| 17 | -# nodes: 192.168.1.242:7001 | |
| 18 | -# password: 4767cb971b40a1300fa09b7f87b09d1c | |
| 19 | - | |
| 20 | -# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 | |
| 21 | -server: | |
| 22 | - port: 18089 | |
| 23 | - # [可选] HTTPS配置, 默认不开启 | |
| 24 | - ssl: | |
| 25 | - # [可选] 是否开启HTTPS访问 | |
| 26 | - enabled: false | |
| 27 | - # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名 | |
| 28 | - key-store: classpath:xxx.jks | |
| 29 | - # [可选] 证书密码 | |
| 30 | - key-password: password | |
| 31 | - # [可选] 证书类型, 默认为jks,根据实际修改 | |
| 32 | - key-store-type: JKS | |
| 33 | - | |
| 34 | -# [根据业务需求配置] | |
| 35 | -userSettings: | |
| 36 | - # [必选 ] 服务ID | |
| 37 | - id: 334533 | |
| 38 | - # [必选 ] 录像路径 | |
| 39 | - record: /home/lin/record/ | |
| 40 | - # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理 | |
| 41 | - recordDay: 10 | |
| 42 | - # [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理 | |
| 43 | - # recordTempDay: 7 | |
| 44 | - # [必选 ] ffmpeg路径 | |
| 45 | - ffmpeg: /home/lin/IdeaProjects/wvp-pro-assist/lib/ffmpeg | |
| 46 | - # [必选 ] ffprobe路径, 一般安装ffmpeg就会自带, 一般跟ffmpeg在同一目录,用于查询文件的信息, | |
| 47 | - ffprobe: /home/lin/IdeaProjects/wvp-pro-assist/lib/ffprobe | |
| 48 | - # [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50% | |
| 49 | - threads: 2 | |
| 50 | - | |
| 51 | -# [可选] 日志配置, 一般不需要改 | |
| 52 | -logging: | |
| 53 | - file: | |
| 54 | - name: logs/wvp.log | |
| 55 | - max-history: 30 | |
| 56 | - max-size: 10MB | |
| 57 | - total-size-cap: 300MB | |
| 58 | - level: | |
| 59 | - root: WARN | |
| 60 | - top: | |
| 61 | - panll: | |
| 62 | - assist: info | |
| 63 | 0 | \ No newline at end of file |
src/main/resources/application.yml
| 1 | 1 | spring: |
| 2 | - profiles: | |
| 3 | - active: local | |
| 2 | + application: | |
| 3 | + name: wvp-assist | |
| 4 | + datasource: | |
| 5 | + type: com.zaxxer.hikari.HikariDataSource | |
| 6 | + driver-class-name: com.mysql.cj.jdbc.Driver | |
| 7 | + url: jdbc:mysql://127.0.0.1:3306/wvp_test?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true&allowPublicKeyRetrieval=true | |
| 8 | + username: root | |
| 9 | + password: 12345678 | |
| 10 | + | |
| 11 | +# [必选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 | |
| 12 | +server: | |
| 13 | + port: 18081 | |
| 14 | + | |
| 15 | +# [根据业务需求配置] | |
| 16 | +user-settings: | |
| 17 | + id: 1111 | |
| 18 | + media-server-id: 11212 | |
| 19 | + # [可选 ] zlm配置的录像路径,不配置则使用当前目录下的record目录 即: ./record | |
| 20 | + record: /home/lin/record/ | |
| 21 | + # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理, 不配置则不删除 | |
| 22 | + recordDay: 7 | |
| 23 | + # [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理 | |
| 24 | + # recordTempDay: 7 | |
| 25 | + # [必选 ] ffmpeg路径 | |
| 26 | + ffmpeg: /usr/bin/ffmpeg | |
| 27 | + # [必选 ] ffprobe路径, 一般安装ffmpeg就会自带, 一般跟ffmpeg在同一目录,用于查询文件的信息 | |
| 28 | + ffprobe: /usr/bin/ffprobe | |
| 29 | + # [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50% | |
| 30 | + threads: 2 | |
| 31 | + | |
| 32 | + | |
| 33 | +# [可选] 日志配置, 一般不需要改 | |
| 34 | +logging: | |
| 35 | + file: | |
| 36 | + name: logs/wvp.log | |
| 37 | + max-history: 30 | |
| 38 | + max-size: 10MB | |
| 39 | + total-size-cap: 300MB | |
| 40 | + level: | |
| 41 | + root: WARN | |
| 42 | + top: | |
| 43 | + panll: | |
| 44 | + assist: info | |
| 4 | 45 | \ No newline at end of file | ... | ... |
src/main/resources/static/download.html deleted
100755 → 0
| 1 | -<!DOCTYPE html> | |
| 2 | -<html lang="en"> | |
| 3 | -<head> | |
| 4 | - <meta charset="UTF-8"> | |
| 5 | - <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
| 6 | - <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 7 | - <title>下载</title> | |
| 8 | -</head> | |
| 9 | -<body> | |
| 10 | -<a id="download" download></a> | |
| 11 | -<script> | |
| 12 | - (function () { | |
| 13 | - let searchParams = new URLSearchParams(location.search); | |
| 14 | - var download = document.getElementById("download"); | |
| 15 | - download.setAttribute("href", searchParams.get("url")) | |
| 16 | - download.click() | |
| 17 | - setTimeout(() => { | |
| 18 | - window.location.href = "about:blank"; | |
| 19 | - window.close(); | |
| 20 | - }, 200) | |
| 21 | - })(); | |
| 22 | - | |
| 23 | -</script> | |
| 24 | -</body> | |
| 25 | -</html> | |
| 26 | 0 | \ No newline at end of file |