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,6 +44,49 @@ | ||
| 44 | </dependency> | 44 | </dependency> |
| 45 | 45 | ||
| 46 | <dependency> | 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 | <groupId>net.bramp.ffmpeg</groupId> | 90 | <groupId>net.bramp.ffmpeg</groupId> |
| 48 | <artifactId>ffmpeg</artifactId> | 91 | <artifactId>ffmpeg</artifactId> |
| 49 | <version>0.6.2</version> | 92 | <version>0.6.2</version> |
| @@ -56,18 +99,6 @@ | @@ -56,18 +99,6 @@ | ||
| 56 | <version>1.2.73</version> | 99 | <version>1.2.73</version> |
| 57 | </dependency> | 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 | <dependency> | 102 | <dependency> |
| 72 | <groupId>org.mp4parser</groupId> | 103 | <groupId>org.mp4parser</groupId> |
| 73 | <artifactId>muxer</artifactId> | 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 | package top.panll.assist.config; | 1 | package top.panll.assist.config; |
| 2 | 2 | ||
| 3 | -import net.bramp.ffmpeg.FFmpeg; | ||
| 4 | -import net.bramp.ffmpeg.FFprobe; | ||
| 5 | import org.slf4j.Logger; | 3 | import org.slf4j.Logger; |
| 6 | import org.slf4j.LoggerFactory; | 4 | import org.slf4j.LoggerFactory; |
| 7 | import org.springframework.beans.factory.annotation.Autowired; | 5 | import org.springframework.beans.factory.annotation.Autowired; |
| 8 | import org.springframework.beans.factory.annotation.Value; | 6 | import org.springframework.beans.factory.annotation.Value; |
| 9 | import org.springframework.boot.CommandLineRunner; | 7 | import org.springframework.boot.CommandLineRunner; |
| 10 | import org.springframework.core.annotation.Order; | 8 | import org.springframework.core.annotation.Order; |
| 9 | +import org.springframework.jdbc.datasource.DataSourceTransactionManager; | ||
| 11 | import org.springframework.stereotype.Component; | 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 | import java.io.*; | 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 | @Component | 26 | @Component |
| 23 | -@Order(value=1) | 27 | +@Order(value=10) |
| 24 | public class StartConfig implements CommandLineRunner { | 28 | public class StartConfig implements CommandLineRunner { |
| 25 | 29 | ||
| 26 | private final static Logger logger = LoggerFactory.getLogger(StartConfig.class); | 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 | @Autowired | 41 | @Autowired |
| 32 | - private UserSettings userSettings; | 42 | + TransactionDefinition transactionDefinition; |
| 33 | 43 | ||
| 34 | @Autowired | 44 | @Autowired |
| 35 | - private VideoFileService videoFileService; | 45 | + private CloudRecordServiceMapper cloudRecordServiceMapper; |
| 36 | 46 | ||
| 37 | 47 | ||
| 38 | @Override | 48 | @Override |
| 39 | public void run(String... args) { | 49 | public void run(String... args) { |
| 40 | - String record = userSettings.getRecord(); | ||
| 41 | if (!record.endsWith(File.separator)) { | 50 | if (!record.endsWith(File.separator)) { |
| 42 | - userSettings.setRecord(userSettings.getRecord() + File.separator); | 51 | + record = record + File.separator; |
| 43 | } | 52 | } |
| 44 | 53 | ||
| 45 | File recordFile = new File(record); | 54 | File recordFile = new File(record); |
| 46 | if (!recordFile.exists()){ | 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,25 +9,28 @@ import org.springframework.stereotype.Component; | ||
| 9 | @Component | 9 | @Component |
| 10 | public class UserSettings { | 10 | public class UserSettings { |
| 11 | 11 | ||
| 12 | - @Value("${userSettings.id}") | 12 | + @Value("${user-settings.id}") |
| 13 | private String id; | 13 | private String id; |
| 14 | 14 | ||
| 15 | - @Value("${userSettings.record}") | 15 | + @Value("${user-settings.record}") |
| 16 | private String record; | 16 | private String record; |
| 17 | 17 | ||
| 18 | - @Value("${userSettings.recordDay:7}") | 18 | + @Value("${user-settings.recordDay:7}") |
| 19 | private int recordDay; | 19 | private int recordDay; |
| 20 | 20 | ||
| 21 | - @Value("${userSettings.recordTempDay:-1}") | 21 | + @Value("${user-settings.recordTempDay:-1}") |
| 22 | private int recordTempDay; | 22 | private int recordTempDay; |
| 23 | 23 | ||
| 24 | - @Value("${userSettings.ffmpeg}") | 24 | + @Value("${user-settings.ffmpeg}") |
| 25 | private String ffmpeg; | 25 | private String ffmpeg; |
| 26 | 26 | ||
| 27 | - @Value("${userSettings.ffprobe}") | 27 | + @Value("${user-settings.ffprobe}") |
| 28 | private String ffprobe; | 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 | private int threads; | 34 | private int threads; |
| 32 | 35 | ||
| 33 | public String getId() { | 36 | public String getId() { |
| @@ -89,4 +92,12 @@ public class UserSettings { | @@ -89,4 +92,12 @@ public class UserSettings { | ||
| 89 | public void setThreads(int threads) { | 92 | public void setThreads(int threads) { |
| 90 | this.threads = threads; | 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,7 +18,6 @@ import org.springframework.stereotype.Component; | ||
| 18 | import org.springframework.util.DigestUtils; | 18 | import org.springframework.util.DigestUtils; |
| 19 | import top.panll.assist.dto.UserSettings; | 19 | import top.panll.assist.dto.UserSettings; |
| 20 | import top.panll.assist.dto.VideoFile; | 20 | import top.panll.assist.dto.VideoFile; |
| 21 | -import top.panll.assist.utils.RedisUtil; | ||
| 22 | 21 | ||
| 23 | import java.io.BufferedWriter; | 22 | import java.io.BufferedWriter; |
| 24 | import java.io.File; | 23 | import java.io.File; |
| @@ -32,21 +31,7 @@ import java.util.concurrent.TimeUnit; | @@ -32,21 +31,7 @@ import java.util.concurrent.TimeUnit; | ||
| 32 | public class FFmpegExecUtils implements InitializingBean{ | 31 | public class FFmpegExecUtils implements InitializingBean{ |
| 33 | 32 | ||
| 34 | private final static Logger logger = LoggerFactory.getLogger(FFmpegExecUtils.class); | 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 | @Autowired | 35 | @Autowired |
| 51 | private UserSettings userSettings; | 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 | package top.panll.assist.utils; | 1 | package top.panll.assist.utils; |
| 2 | 2 | ||
| 3 | +import java.text.ParseException; | ||
| 3 | import java.text.SimpleDateFormat; | 4 | import java.text.SimpleDateFormat; |
| 4 | import java.time.Instant; | 5 | import java.time.Instant; |
| 5 | import java.time.LocalDateTime; | 6 | import java.time.LocalDateTime; |
| 6 | import java.time.LocalTime; | 7 | import java.time.LocalTime; |
| 7 | import java.time.ZoneId; | 8 | import java.time.ZoneId; |
| 8 | import java.time.format.DateTimeFormatter; | 9 | import java.time.format.DateTimeFormatter; |
| 10 | +import java.time.temporal.TemporalAccessor; | ||
| 9 | import java.util.Date; | 11 | import java.util.Date; |
| 10 | import java.util.Locale; | 12 | import java.util.Locale; |
| 11 | 13 | ||
| @@ -13,10 +15,14 @@ public class DateUtils { | @@ -13,10 +15,14 @@ public class DateUtils { | ||
| 13 | 15 | ||
| 14 | public static final String PATTERNForDateTime = "yyyy-MM-dd HH:mm:ss"; | 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 | public static final String PATTERNForDate = "yyyy-MM-dd"; | 20 | public static final String PATTERNForDate = "yyyy-MM-dd"; |
| 17 | 21 | ||
| 18 | public static final String zoneStr = "Asia/Shanghai"; | 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 | // 获得某天最大时间 2020-02-19 23:59:59 | 28 | // 获得某天最大时间 2020-02-19 23:59:59 |
| @@ -39,8 +45,38 @@ public class DateUtils { | @@ -39,8 +45,38 @@ public class DateUtils { | ||
| 39 | } | 45 | } |
| 40 | 46 | ||
| 41 | public static String getDateTimeStr(Date date) { | 47 | public static String getDateTimeStr(Date date) { |
| 42 | - SimpleDateFormat formatter = new SimpleDateFormat(PATTERNForDateTime); | 48 | + SimpleDateFormat formatter = new SimpleDateFormat(PATTERNForDateTime); |
| 43 | return formatter.format(date); | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 0 | \ No newline at end of file |
src/main/resources/application.yml
| 1 | spring: | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 0 | \ No newline at end of file |