root

云媒资

Showing 137 changed files with 7642 additions and 0 deletions
  1 +/.externalToolBuilders
  2 +/.settings
  3 +.svn
  4 +/.project
  5 +/target
  6 +target/
  7 +/.classpath
  8 +/src/main/webapp/temp
  9 +/src/main/webapp/source
  10 +/src/main/webapp/store
  11 +/src/main/webapp/depository
  12 +.idea/
  13 +*.iml
  14 +*.iws
  15 +*.ipr
  16 +*.ids
  17 +*.orig
  18 +classes/
  19 +*.properties
  20 +*.log
  1 +/.externalToolBuilders
  2 +/.settings
  3 +.svn
  4 +/.project
  5 +/target
  6 +target/
  7 +/.classpath
  8 +/src/main/webapp/temp
  9 +/src/main/webapp/source
  10 +/src/main/webapp/store
  11 +/src/main/webapp/depository
  12 +.idea/
  13 +*.iml
  14 +*.iws
  15 +*.ipr
  16 +*.ids
  17 +*.orig
  18 +classes/
  19 +*.properties
  20 +*.log
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>cloud-media-resources</artifactId>
  7 + <groupId>com.wondertek.ivod.cmr</groupId>
  8 + <version>1.0.0</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <groupId>com.wondertek.ivod.cmr.commons</groupId>
  13 + <artifactId>cmr-commons</artifactId>
  14 + <packaging>jar</packaging>
  15 + <version>1.0.0</version>
  16 + <properties>
  17 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  18 + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  19 + <java.version>1.8</java.version>
  20 + <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
  21 + </properties>
  22 +
  23 + <dependencies>
  24 + <dependency>
  25 + <groupId>com.wondertek.ivod.cmr.core</groupId>
  26 + <artifactId>cmr-core</artifactId>
  27 + <version>1.0.0</version>
  28 + </dependency>
  29 + </dependencies>
  30 +
  31 +</project>
  1 +package com.wondertek.ivod.cmr.commons.constant;
  2 +
  3 +/**
  4 + * @Author yubin
  5 + * @Date 2021/8/20 10:20
  6 + */
  7 +public class FileConstant {
  8 + /**
  9 + * 视频类型
  10 + */
  11 + public static final String VIDEO_TYPE = "mp4";
  12 + /**
  13 + * 视频最大
  14 + */
  15 + public static final Long VIDEO_MAX_SIZE = 500L * 1024 * 1024;
  16 + /**
  17 + * 图片类型
  18 + */
  19 + public static final String IMAGE_TYPE = "png,jpg,jpeg";
  20 + /**
  21 + * 图片最大
  22 + */
  23 + public static final Long IMAGE_MAX_SIZE = 10L * 1024 * 1024;
  24 +}
  1 +package com.wondertek.ivod.cmr.commons.enums;
  2 +
  3 +import java.util.Arrays;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/8/11 13:46
  8 + *
  9 + * 通用状态
  10 + */
  11 +public enum CommonStatusEnum {
  12 + EXT(-1, "额外补充特殊状态"),
  13 + INIT(0, "初始化"),
  14 + SUCCESS(1, "成功"),
  15 + FAIL(2, "失败"),
  16 + WAIT(3, "进行中");
  17 +
  18 + private Integer code;
  19 + private String msg;
  20 +
  21 + CommonStatusEnum(Integer code, String msg) {
  22 + this.code = code;
  23 + this.msg = msg;
  24 + }
  25 +
  26 + public Integer getCode() {
  27 + return code;
  28 + }
  29 +
  30 + public String getMsg() {
  31 + return msg;
  32 + }
  33 +
  34 + /**
  35 + * 根据Key得到枚举的Value
  36 + * Lambda表达式,比较判断(JDK 1.8)
  37 + *
  38 + * @param key
  39 + * @return
  40 + */
  41 + public static String getMsg(String key) {
  42 + return Arrays.stream(CommonStatusEnum.values())
  43 + .filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
  44 + .findFirst().orElse(null).getMsg();
  45 + }
  46 +}
  1 +package com.wondertek.ivod.cmr.commons.enums;
  2 +
  3 +import java.util.Arrays;
  4 +
  5 +/**
  6 + * 全局枚举属性
  7 + * @date: 2021/4/6
  8 + */
  9 +public enum GlobalCodeEnum {
  10 + //错误枚举
  11 + UNKNOWN_ERROR("-1", "服务器异常"),
  12 + FAILURE("0", "failure"),
  13 + SUCCESS("1", "success"),
  14 + INVALID_PARAMS("2", "请求参数无效"),
  15 + UNSUPPORTED_URI("3", "未知URI"),
  16 + LACK_PARAMS("4", "请求参数缺失"),
  17 + PASS_URL_ERR("5", "组装pass层公共参数出现异常"),
  18 + DATE_ISNULL_ERR("6", "数据不存在!"),
  19 + REQUEST_PASS_ERROR("7", "请求pass层出现异常"),
  20 +
  21 + AI_CLOUD_ERR("3001","Ai云调度服务响应异常"),
  22 + ACCESS_CLOUD_ERR("3001","接入云调度服务响应异常"),
  23 + DATA_CLOUD_ERR("3001","数据云服务响应异常"),
  24 + ICLOUD_ERR("3001","存储云调度服务响应异常"),
  25 + MAINTENANCE_ERR("3001","营维中台服务响应异常"),
  26 + ;
  27 +
  28 + private String code;
  29 + private String msg;
  30 +
  31 + private GlobalCodeEnum(String code, String msg) {
  32 + this.code = code;
  33 + this.msg = msg;
  34 + }
  35 +
  36 + public String getCode() {
  37 + return code;
  38 + }
  39 +
  40 + public String getMsg() {
  41 + return msg;
  42 + }
  43 +
  44 + /**
  45 + * 根据Key得到枚举的Value
  46 + * Lambda表达式,比较判断(JDK 1.8)
  47 + *
  48 + * @param key
  49 + * @return
  50 + */
  51 + public static String getMsg(String key) {
  52 + return Arrays.stream(GlobalCodeEnum.values())
  53 + .filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
  54 + .findFirst().orElse(GlobalCodeEnum.UNKNOWN_ERROR).getMsg();
  55 + }
  56 +}
  1 +package com.wondertek.ivod.cmr.commons.enums;
  2 +
  3 +import java.util.Arrays;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/8/3 15:24
  8 + * <p>
  9 + * 媒资来源
  10 + */
  11 +public enum MaterialSourceEnum {
  12 + LOCAL_UPLOAD(1, "本地上传"),
  13 + VIDEO_REMOVAL(2, "视频搬迁"),
  14 + LIVE_RECORDING(3, "直播录制"),
  15 + CLOUD_EDITING(4, "云剪辑"),
  16 + VIDEO_MONITORING(5, "视频监控");
  17 +
  18 + private Integer code;
  19 + private String msg;
  20 +
  21 + MaterialSourceEnum(Integer code, String msg) {
  22 + this.code = code;
  23 + this.msg = msg;
  24 + }
  25 +
  26 + public Integer getCode() {
  27 + return code;
  28 + }
  29 +
  30 + public String getMsg() {
  31 + return msg;
  32 + }
  33 +
  34 + /**
  35 + * 根据Key得到枚举的Value
  36 + * Lambda表达式,比较判断(JDK 1.8)
  37 + *
  38 + * @param key
  39 + * @return
  40 + */
  41 + public static String getMsg(String key) {
  42 + return Arrays.stream(MaterialSourceEnum.values())
  43 + .filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
  44 + .findFirst().orElse(null).getMsg();
  45 + }
  46 +}
  1 +package com.wondertek.ivod.cmr.commons.enums;
  2 +
  3 +import java.util.Arrays;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/8/3 15:24
  8 + * <p>
  9 + * 媒资类型
  10 + */
  11 +public enum MaterialTypeEnum {
  12 + VIDEO(1, "视频"),
  13 + AUDIO(2, "音频"),
  14 + PICTURE(3, "图片");
  15 +
  16 + private Integer code;
  17 + private String msg;
  18 +
  19 + MaterialTypeEnum(Integer code, String msg) {
  20 + this.code = code;
  21 + this.msg = msg;
  22 + }
  23 +
  24 + public Integer getCode() {
  25 + return code;
  26 + }
  27 +
  28 + public String getMsg() {
  29 + return msg;
  30 + }
  31 +
  32 + /**
  33 + * 根据Key得到枚举的Value
  34 + * Lambda表达式,比较判断(JDK 1.8)
  35 + *
  36 + * @param key
  37 + * @return
  38 + */
  39 + public static String getMsg(String key) {
  40 + return Arrays.stream(MaterialTypeEnum.values())
  41 + .filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
  42 + .findFirst().orElse(null).getMsg();
  43 + }
  44 +}
  1 +package com.wondertek.ivod.cmr.commons.enums;
  2 +
  3 +/**
  4 + * @author xh
  5 + * @date 2023/9/18 11:18
  6 + */
  7 +public enum OperateTypeEnum {
  8 + /**
  9 + * 下载
  10 + */
  11 + DOWNLOAD("1", "下载"),
  12 + /**
  13 + * 浏览
  14 + */
  15 + VIEW("2", "浏览");
  16 + private String code;
  17 + private String msg;
  18 +
  19 + OperateTypeEnum(String code, String msg) {
  20 + this.code = code;
  21 + this.msg = msg;
  22 + }
  23 +
  24 + public String getCode() {
  25 + return code;
  26 + }
  27 +
  28 + public String getMsg() {
  29 + return msg;
  30 + }
  31 +}
  1 +package com.wondertek.ivod.cmr.commons.exception;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
  4 +
  5 +/**
  6 + * <p><b>BusinessException Description:</b> 业务类运行时异常, 所有业务类运行时异常继承于该异常</p>
  7 + * @author douzi
  8 + * <b>DATE</b> 2019年2月18日 上午10:27:00
  9 + */
  10 +public class DefaultException extends RuntimeException {
  11 +
  12 + private static final long serialVersionUID = 1L;
  13 +
  14 + protected int errorCode;
  15 +
  16 + public DefaultException(GlobalCodeEnum globalCodeEnum) {
  17 + super(globalCodeEnum.getMsg());
  18 + this.errorCode = Integer.parseInt(globalCodeEnum.getCode());
  19 + }
  20 + public DefaultException(GlobalCodeEnum globalCodeEnum,String message) {
  21 + super(message);
  22 + this.errorCode = Integer.parseInt(globalCodeEnum.getCode());
  23 + }
  24 +
  25 + public DefaultException(Throwable cause) {
  26 + super(cause);
  27 + }
  28 +
  29 + /**
  30 + * @param message
  31 + * @param cause
  32 + */
  33 + public DefaultException(int errorCode, String message, Throwable cause) {
  34 + super(message, cause);
  35 + this.errorCode = errorCode;
  36 + }
  37 +
  38 + /**
  39 + * @param message
  40 + */
  41 + public DefaultException(int errorCode, String message) {
  42 + super(message);
  43 + this.errorCode = errorCode;
  44 + }
  45 +
  46 + public DefaultException(String message) {
  47 + super(message);
  48 + this.errorCode = Integer.parseInt(GlobalCodeEnum.FAILURE.getCode());
  49 + }
  50 +
  51 + public DefaultException(String message,Throwable throwable) {
  52 + super(message + throwable.getMessage());
  53 + this.errorCode = Integer.parseInt(GlobalCodeEnum.FAILURE.getCode());
  54 + }
  55 + /**
  56 + * @param cause
  57 + */
  58 + public DefaultException(int errorCode, Throwable cause) {
  59 + super(cause);
  60 + this.errorCode = errorCode;
  61 + }
  62 +
  63 + public int getErrorCode() {
  64 + return this.errorCode;
  65 + }
  66 +}
  1 +package com.wondertek.ivod.cmr.commons.exception;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  4 +import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.http.converter.HttpMessageNotReadableException;
  7 +import org.springframework.validation.BindException;
  8 +import org.springframework.web.HttpRequestMethodNotSupportedException;
  9 +import org.springframework.web.bind.MissingServletRequestParameterException;
  10 +import org.springframework.web.bind.annotation.ExceptionHandler;
  11 +import org.springframework.web.bind.annotation.ResponseBody;
  12 +import org.springframework.web.bind.annotation.RestControllerAdvice;
  13 +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
  14 +
  15 +import javax.servlet.http.HttpServletRequest;
  16 +
  17 +/**
  18 + * @Title com.migu.editor.cloudeditor.advice
  19 + * @Author beckhamyht
  20 + * @Created 2019/5/23 19:01
  21 + */
  22 +
  23 +@RestControllerAdvice
  24 +@Slf4j
  25 +public class ExceptionHandlerAdvice {
  26 +
  27 +
  28 + @ExceptionHandler(Exception.class)
  29 + @ResponseBody
  30 + public ResultBean handlerException(HttpServletRequest req, Exception e) {
  31 + log.error(e.getMessage(), e);
  32 + return ResultBean.error(GlobalCodeEnum.UNKNOWN_ERROR.getCode(), GlobalCodeEnum.UNKNOWN_ERROR.getMsg());
  33 + }
  34 +
  35 +
  36 + @ExceptionHandler({BindException.class})
  37 + @ResponseBody
  38 + public ResultBean handlerBindException(BindException e) {
  39 + log.error(e.getMessage(), e);
  40 + return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
  41 + }
  42 +
  43 + @ExceptionHandler({HttpMessageNotReadableException.class})
  44 + @ResponseBody
  45 + public ResultBean handlerParseException(HttpMessageNotReadableException e) {
  46 + log.error(e.getMessage(), e);
  47 + return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
  48 + }
  49 +
  50 + @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
  51 + @ResponseBody
  52 + public ResultBean handlerParseException(HttpRequestMethodNotSupportedException e) {
  53 + log.error(e.getMessage(), e);
  54 + return ResultBean.error(GlobalCodeEnum.FAILURE.getCode(), e.getMessage());
  55 + }
  56 +
  57 + @ExceptionHandler(MethodArgumentTypeMismatchException.class)
  58 + @ResponseBody
  59 + public ResultBean handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
  60 + log.error(e.getMessage(), e);
  61 + return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
  62 + }
  63 +
  64 + @ExceptionHandler(MissingServletRequestParameterException.class)
  65 + @ResponseBody
  66 + public ResultBean missingServletRequestParameterException(MissingServletRequestParameterException e) {
  67 + log.error(e.getMessage(), e);
  68 + return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
  69 + }
  70 +
  71 + /**
  72 + * 自定义异常拦截
  73 + *
  74 + * @param ex
  75 + * @return
  76 + */
  77 + @ExceptionHandler({DefaultException.class})
  78 + public ResultBean DefaultException(DefaultException ex) {
  79 + log.error("{},{}",ex.getErrorCode(),ex.getMessage());
  80 + return ResultBean.error(ex.getErrorCode() + "", ex.getMessage());
  81 + }
  82 +
  83 +}
  1 +package com.wondertek.ivod.cmr.commons.utils;
  2 +
  3 +
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import com.wondertek.ivod.cmr.commons.constant.FileConstant;
  6 +import com.wondertek.ivod.cmr.commons.enums.MaterialTypeEnum;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.beans.factory.annotation.Value;
  9 +import org.springframework.stereotype.Component;
  10 +import org.springframework.web.multipart.MultipartFile;
  11 +
  12 +import java.io.*;
  13 +import java.net.HttpURLConnection;
  14 +import java.net.URL;
  15 +import java.util.Arrays;
  16 +import java.util.List;
  17 +
  18 +/**
  19 + * @Author yubin
  20 + * @Date 2021/8/4 14:48
  21 + */
  22 +@Slf4j
  23 +@Component
  24 +public class FileUtils {
  25 + private static String uploadPath;
  26 + private static String downloadPath;
  27 +
  28 + @Value("${file.uploadPath}")
  29 + public void setUploadPath(String uploadPath) {
  30 + FileUtils.uploadPath = uploadPath;
  31 + }
  32 +
  33 + @Value("${file.downloadPath}")
  34 + public void setDownloadPath(String downloadPath) {
  35 + FileUtils.downloadPath = downloadPath;
  36 + }
  37 +
  38 + /**
  39 + * MultipartFile 转 File
  40 + *
  41 + * @param file
  42 + * @throws Exception
  43 + */
  44 + public static File multipartFileToFile(MultipartFile file) {
  45 + File toFile = null;
  46 + String fileName = file.getOriginalFilename();
  47 + try {
  48 + InputStream ins = file.getInputStream();
  49 + //文件保存位置
  50 + String path = System.getProperty("user.dir");
  51 + File saveDir = new File(path + uploadPath);
  52 + if (!saveDir.exists()) {
  53 + saveDir.mkdir();
  54 + }
  55 + toFile = new File(saveDir + File.separator + fileName);
  56 + inputStreamToFile(ins, toFile);
  57 + ins.close();
  58 + } catch (Exception e) {
  59 + e.printStackTrace();
  60 + log.info("MultipartFile转File失败:{}", fileName);
  61 + }
  62 + return toFile;
  63 + }
  64 +
  65 + //获取流文件
  66 + private static void inputStreamToFile(InputStream ins, File file) throws Exception {
  67 + OutputStream os = new FileOutputStream(file);
  68 + int bytesRead = 0;
  69 + byte[] buffer = new byte[8192];
  70 + while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
  71 + os.write(buffer, 0, bytesRead);
  72 + }
  73 + os.close();
  74 + ins.close();
  75 + }
  76 +
  77 + /**
  78 + * 删除本地临时文件
  79 + *
  80 + * @param file
  81 + */
  82 + public static void delteTempFile(File file) {
  83 + if (file != null) {
  84 + File del = new File(file.toURI());
  85 + del.delete();
  86 + }
  87 + }
  88 +
  89 + /**
  90 + * 从网络Url中下载文件
  91 + *
  92 + * @param urlStr
  93 + * @throws IOException
  94 + */
  95 + public static File downLoadFromUrl(String urlStr, String fileName) {
  96 + File file = null;
  97 + try {
  98 + URL url = new URL(urlStr);
  99 + HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  100 + conn.setDoOutput(false);
  101 + conn.setDoInput(true);
  102 + //连接建立超时时间还有读取数据超时时间
  103 + conn.setConnectTimeout(600000);
  104 + conn.setReadTimeout(600000);
  105 + conn.setRequestMethod("GET");
  106 + conn.connect();
  107 + //获取状态码
  108 + int code = conn.getResponseCode();
  109 + log.info(">>>>>>>>>>网络连接情况:{}", code);
  110 +
  111 + //得到输入流
  112 + InputStream inputStream = conn.getInputStream();
  113 + //获取自己数组
  114 + byte[] getData = readInputStream(inputStream);
  115 +
  116 + //文件保存位置
  117 + String path = System.getProperty("user.dir");
  118 + File saveDir = new File(path + downloadPath);
  119 + if (!saveDir.exists()) {
  120 + saveDir.mkdir();
  121 + }
  122 + //得到最后一个分隔符后的名字
  123 + file = new File(saveDir + File.separator + fileName);
  124 + FileOutputStream fos = new FileOutputStream(file);
  125 + fos.write(getData);
  126 + if (fos != null) {
  127 + fos.close();
  128 + }
  129 + if (inputStream != null) {
  130 + inputStream.close();
  131 + }
  132 + log.info("info:" + url + " download success");
  133 + } catch (Exception e) {
  134 + e.printStackTrace();
  135 + }
  136 + return file;
  137 + }
  138 +
  139 + /**
  140 + * 从输入流中获取字节数组
  141 + *
  142 + * @param inputStream
  143 + * @return
  144 + * @throws IOException
  145 + */
  146 + public static byte[] readInputStream(InputStream inputStream) throws IOException {
  147 + byte[] buffer = new byte[1024];
  148 + int len = 0;
  149 + ByteArrayOutputStream bos = new ByteArrayOutputStream();
  150 + while ((len = inputStream.read(buffer)) != -1) {
  151 + bos.write(buffer, 0, len);
  152 + }
  153 + bos.close();
  154 + return bos.toByteArray();
  155 + }
  156 +
  157 + /**
  158 + * 文件校验
  159 + *
  160 + * @param materialFile
  161 + * @return
  162 + */
  163 + public static String checkFile(MultipartFile materialFile) {
  164 + List<String> videoType = Arrays.asList(FileConstant.VIDEO_TYPE.split(","));
  165 + List<String> imageType = Arrays.asList(FileConstant.IMAGE_TYPE.split(","));
  166 + String fileName = materialFile.getOriginalFilename();
  167 + if (ObjectUtil.isEmpty(fileName)) {
  168 + return "请选择要上传的文件";
  169 + }
  170 + String fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
  171 + long size = materialFile.getSize();
  172 + if (videoType.contains(fileType)) {
  173 + if (FileConstant.VIDEO_MAX_SIZE < size) {
  174 + return "不支持大于" + (FileConstant.VIDEO_MAX_SIZE / 1024 / 1024) + "M的视频文件上传";
  175 + }
  176 + } else if (imageType.contains(fileType)) {
  177 + if (FileConstant.IMAGE_MAX_SIZE < size) {
  178 + return "不支持大于" + (FileConstant.IMAGE_MAX_SIZE / 1024 / 1024) + "M的图片文件上传";
  179 + }
  180 + } else {
  181 + return "文件格式错误";
  182 + }
  183 + return null;
  184 + }
  185 +
  186 + /**
  187 + * 图片文件校验
  188 + *
  189 + * @param materialFile
  190 + * @return
  191 + */
  192 + public static String checkImageFile(MultipartFile materialFile) {
  193 + List<String> imageType = Arrays.asList(FileConstant.IMAGE_TYPE.split(","));
  194 + String fileName = materialFile.getOriginalFilename();
  195 + if (ObjectUtil.isEmpty(fileName)) {
  196 + return "请选择要上传的文件";
  197 + }
  198 + String fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
  199 + long size = materialFile.getSize();
  200 + if (imageType.contains(fileType)) {
  201 + if (FileConstant.IMAGE_MAX_SIZE < size) {
  202 + return "选择人脸照不能大于" + (FileConstant.IMAGE_MAX_SIZE / 1024 / 1024) + "M";
  203 + }
  204 + } else {
  205 + return "选择人脸照格式不符合要求";
  206 + }
  207 + return null;
  208 + }
  209 +
  210 + /**
  211 + * 获取文件类型
  212 + *
  213 + * @param fileName
  214 + * @return
  215 + */
  216 + public static Integer getFileType(String fileName) {
  217 + List<String> videoType = Arrays.asList(FileConstant.VIDEO_TYPE.split(","));
  218 + List<String> imageType = Arrays.asList(FileConstant.IMAGE_TYPE.split(","));
  219 + String fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
  220 + if (videoType.contains(fileType)) {
  221 + return MaterialTypeEnum.VIDEO.getCode();
  222 + } else if (imageType.contains(fileType)) {
  223 + return MaterialTypeEnum.PICTURE.getCode();
  224 + }
  225 + return null;
  226 + }
  227 +}
  1 +package com.wondertek.ivod.cmr.commons.utils;
  2 +
  3 +
  4 +
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.stereotype.Component;
  7 +
  8 +import java.net.URL;
  9 +
  10 +/**
  11 + * @author admin
  12 + */
  13 +@Slf4j
  14 +@Component
  15 +public class GetLocation {
  16 +
  17 +
  18 + /*public static void main(String[] args) {
  19 + // lat 39.97646
  20 + //log 116.3039
  21 + String add = getAdd("116.3039", "39.97646");
  22 + JSONObject jsonObject = JSONObject.parseObject(add);
  23 + JSONObject jsonArray = JSONArray.parseObject(jsonObject.getString("addrList"));
  24 + JSONObject j_2 = JSONObject.parseObject((String) jsonArray.get(0));
  25 + String allAdd = j_2.getString("admName");
  26 + String arr[] = allAdd.split(",");
  27 + System.out.println("省:"+arr[0]+"\n市:"+arr[1]+"\n区:"+arr[2]);
  28 + }*/
  29 +
  30 + public static String getAdd(String Longitude, String Latitude ){
  31 + //lat 小 log 大
  32 + //参数解释: 纬度,经度 type 001 (100代表道路,010代表POI,001代表门址,111可以同时显示前三项)
  33 + String urlString = "https://apis.map.qq.com/ws/geocoder/v1/?location="+Latitude+","+Longitude+"&key=UUMBZ-PJLCI-KWMGL-UCFWF-XXKKS-XGF67&get_poi=1";
  34 + String res = "";
  35 + try {
  36 + URL url = new URL(urlString);
  37 + java.net.HttpURLConnection conn = (java.net.HttpURLConnection)url.openConnection();
  38 + conn.setDoOutput(true);
  39 + conn.setRequestMethod("GET");
  40 + java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream(),"UTF-8"));
  41 + String line;
  42 + while ((line = in.readLine()) != null) {
  43 + res += line+"\n";
  44 + }
  45 + in.close();
  46 + } catch (Exception e) {
  47 + log.error("error in wapaction,and e is " + e.getMessage());
  48 + }
  49 + log.info(res);
  50 + return res;
  51 + }
  52 +
  53 +}
  1 +package com.wondertek.ivod.cmr.commons.utils;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonInclude;
  4 +import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +
  8 +import java.util.ArrayList;
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * 分页对象
  13 + *
  14 + * @author beckhamyht
  15 + * @param <T>
  16 + */
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@JsonInclude(JsonInclude.Include.NON_NULL)
  20 +public class PageBean<T> extends ResultBean<Object> {
  21 +
  22 + /**
  23 + * 总的页数
  24 + */
  25 + private Integer totalPage;
  26 + /**
  27 + * 总记录数
  28 + */
  29 + private Long totalCount;
  30 + /**
  31 + * 分页数据
  32 + */
  33 + private List<T> result;
  34 +
  35 + public PageBean(){}
  36 +
  37 + /**
  38 + *
  39 + * @param totalPage 总页数
  40 + * @param totalCount 总数
  41 + * @param result
  42 + */
  43 + public PageBean(Integer totalPage, Long totalCount, List<T> result) {
  44 + super(GlobalCodeEnum.SUCCESS.getCode(), GlobalCodeEnum.SUCCESS.getMsg());
  45 + this.totalPage = totalPage;
  46 + this.totalCount = totalCount;
  47 + this.result = result;
  48 + }
  49 +
  50 + public static <T> PageBean<T> ok(Integer totalPage, Long totalCount, List<T> result){
  51 + return new PageBean<>(totalPage, totalCount, result);
  52 + }
  53 +
  54 + public static <T> PageBean<T> empty() {
  55 + return new PageBean<>(0, 0L, new ArrayList<>());
  56 + }
  57 +
  58 +}
  1 +package com.wondertek.ivod.cmr.commons.utils;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
  4 +import lombok.Data;
  5 +
  6 +
  7 +@Data
  8 +public class ResultBean<T> {
  9 +
  10 + private String code;
  11 + private String msg;
  12 + private T result;
  13 +
  14 + protected ResultBean() {
  15 +
  16 + }
  17 +
  18 + public ResultBean(String code, String msg) {
  19 + this.code = code;
  20 + this.msg = msg;
  21 + }
  22 +
  23 + public ResultBean(String code, String msg, T result) {
  24 + super();
  25 + this.code = code;
  26 + this.msg = msg;
  27 + this.result = result;
  28 + }
  29 +
  30 + public static ResultBean ok() {
  31 + return new ResultBean(GlobalCodeEnum.SUCCESS.getCode(), GlobalCodeEnum.SUCCESS.getMsg(), null);
  32 + }
  33 +
  34 + public static ResultBean ok(Object data) {
  35 + return new ResultBean(GlobalCodeEnum.SUCCESS.getCode(), GlobalCodeEnum.SUCCESS.getMsg(), data);
  36 + }
  37 +
  38 + public static ResultBean error(String msg) {
  39 + return new ResultBean(GlobalCodeEnum.FAILURE.getCode(), msg, null);
  40 + }
  41 +
  42 + public static ResultBean error(String msg, Object data) {
  43 + return new ResultBean(GlobalCodeEnum.FAILURE.getCode(), msg, data);
  44 + }
  45 +
  46 + public static ResultBean error(String code, String msg) {
  47 + return new ResultBean(code, msg, null);
  48 + }
  49 +}
  1 +package com.wondertek.ivod.cmr.commons.utils;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import com.wondertek.ivod.cmr.commons.exception.DefaultException;
  5 +import com.wondertek.ivod.cmr.core.entity.bean.UserInfo;
  6 +
  7 +import javax.servlet.http.Cookie;
  8 +import javax.servlet.http.HttpServletRequest;
  9 +
  10 +/**
  11 + * @Author yubin
  12 + * @Date 2021/8/4 13:54
  13 + */
  14 +public class UserUtils {
  15 + private static ThreadLocal<UserInfo> loginUser = new ThreadLocal<>();
  16 +
  17 + public static void setUser(HttpServletRequest request) {
  18 + UserInfo userInfo = new UserInfo();
  19 + Cookie[] cookies = request.getCookies();
  20 + if (ObjectUtil.isNotEmpty(cookies)) {
  21 + for (Cookie cookie : cookies) {
  22 + if (cookie.getName().equals("userId")) {
  23 + userInfo.setId(cookie.getValue());
  24 + continue;
  25 + }
  26 + if (cookie.getName().equals("userName")) {
  27 + userInfo.setUserName(cookie.getValue());
  28 + continue;
  29 + }
  30 + if (cookie.getName().equals("tenantId")) {
  31 + userInfo.setTenantId(cookie.getValue());
  32 + continue;
  33 + }
  34 + }
  35 + }
  36 + loginUser.set(userInfo);
  37 + }
  38 +
  39 + public static void setUser(String userId, String userName, String tenantId) {
  40 + UserInfo userInfo = loginUser.get();
  41 + if (ObjectUtil.isEmpty(userInfo.getId())) {
  42 + userInfo = new UserInfo();
  43 + userInfo.setId(userId);
  44 + userInfo.setUserName(userName);
  45 + userInfo.setTenantId(tenantId);
  46 + loginUser.set(userInfo);
  47 + }
  48 + }
  49 +
  50 + public static UserInfo getUser() {
  51 + return loginUser.get();
  52 + }
  53 +}
  1 +/.externalToolBuilders
  2 +/.settings
  3 +.svn
  4 +/.project
  5 +/target
  6 +target/
  7 +/.classpath
  8 +/src/main/webapp/temp
  9 +/src/main/webapp/source
  10 +/src/main/webapp/store
  11 +/src/main/webapp/depository
  12 +.idea/
  13 +*.iml
  14 +*.iws
  15 +*.ipr
  16 +*.ids
  17 +*.orig
  18 +classes/
  19 +*.properties
  20 +*.log
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>cloud-media-resources</artifactId>
  7 + <groupId>com.wondertek.ivod.cmr</groupId>
  8 + <version>1.0.0</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>cmr-core</artifactId>
  13 + <groupId>com.wondertek.ivod.cmr.core</groupId>
  14 + <packaging>jar</packaging>
  15 + <version>1.0.0</version>
  16 + <properties>
  17 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  18 + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  19 + <java.version>1.8</java.version>
  20 + <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
  21 + </properties>
  22 +
  23 + <dependencies>
  24 +
  25 + </dependencies>
  26 +
  27 +</project>
  1 +package com.wondertek.ivod.cmr.core.entity.bean;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Polygon;
  4 +import lombok.Data;
  5 +
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * @Author lyf
  10 + * @Date 2023/9/18 11:13
  11 + */
  12 +@Data
  13 +public class ImageWordsData {
  14 + private String content;
  15 + private String confidence;
  16 + private List<Polygon> polygon;
  17 + private String start;
  18 + private String end;
  19 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.*;
  4 +import lombok.Data;
  5 +import org.springframework.data.annotation.Id;
  6 +import org.springframework.data.elasticsearch.annotations.Document;
  7 +import org.springframework.data.elasticsearch.annotations.Field;
  8 +import org.springframework.data.elasticsearch.annotations.FieldType;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * @Author yubin
  14 + * @Date 2021/8/5 17:00
  15 + * <p>
  16 + * 介质es存储对象
  17 + */
  18 +@Data
  19 +@Document(indexName = "cloud_media_resource", type = "material_info")
  20 +public class MaterialInfo {
  21 + /**
  22 + * 媒资ID
  23 + */
  24 + @Id
  25 + @Field(type = FieldType.Long)
  26 + private Long materialId;
  27 + /**
  28 + * 基本信息
  29 + */
  30 + @Field(type = FieldType.Object)
  31 + private BasicInfo basicInfo;
  32 + /**
  33 + * 介质信息
  34 + */
  35 + @Field(type = FieldType.Object)
  36 + private MediaInfo mediaInfo;
  37 + /**
  38 + * 人脸识别信息
  39 + */
  40 + @Field(type = FieldType.Nested)
  41 + private List<FaceInfo> faceInfo;
  42 + /**
  43 + * 文字识别信息
  44 + */
  45 + @Field(type = FieldType.Nested)
  46 + private List<WordInfo> wordInfo;
  47 + /**
  48 + * 状态信息
  49 + */
  50 + @Field(type = FieldType.Object)
  51 + private MaterialStatus materialStatus;
  52 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.data.elasticsearch.annotations.Field;
  5 +import org.springframework.data.elasticsearch.annotations.FieldType;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/4 13:57
  10 + */
  11 +@Data
  12 +public class UserInfo {
  13 + /**
  14 + * 用户ID
  15 + */
  16 + @Field(type = FieldType.Keyword)
  17 + private String id;
  18 + /**
  19 + * 操作人
  20 + */
  21 + @Field(type = FieldType.Keyword)
  22 + private String userName;
  23 + /**
  24 + * 租户ID
  25 + */
  26 + @Field(type = FieldType.Keyword)
  27 + private String tenantId;
  28 + /**
  29 + * 所属类型
  30 + */
  31 + @Field(type = FieldType.Keyword)
  32 + private String type;
  33 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Box;
  4 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Slce;
  5 +import lombok.Data;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * @Author yubin
  11 + * @Date 2021/8/9 11:13
  12 + */
  13 +@Data
  14 +public class VideoFigureData {
  15 + private String strangerId;
  16 + private String image;
  17 + private String featureStr;
  18 + private List<Slce> slces;
  19 + private String figureName;
  20 + private Box box;
  21 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Polygon;
  4 +import lombok.Data;
  5 +
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * @Author lyf
  10 + * @Date 2023/9/18 11:13
  11 + */
  12 +@Data
  13 +public class VideoWordsData {
  14 + private String[] content;
  15 + private String confidence;
  16 + private List<Polygon> polygon;
  17 + private String start;
  18 + private String end;
  19 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.analyser;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/8/17 10:31
  8 + *
  9 + * 分析器上传接口返回结果
  10 + */
  11 +@Data
  12 +public class AnalysisUploadResult {
  13 + /**
  14 + * 预览路径
  15 + */
  16 + private String previewUrl;
  17 + /**
  18 + * 文件ID
  19 + */
  20 + private String fileId;
  21 + /**
  22 + * 文件原名
  23 + */
  24 + private String originalName;
  25 + /**
  26 + * 文件相对路径
  27 + */
  28 + private String relativePath;
  29 + /**
  30 + * 封面图
  31 + */
  32 + private String coverMap;
  33 + /**
  34 + * md5
  35 + */
  36 + private String md5;
  37 + /**
  38 + * 宽
  39 + */
  40 + private Integer height;
  41 + /**
  42 + * 长
  43 + */
  44 + private Integer width;
  45 + /**
  46 + * 文件大小
  47 + */
  48 + private Long size;
  49 + /**
  50 + * 时长
  51 + */
  52 + private Long duration;
  53 + /**
  54 + * 码率
  55 + */
  56 + private Long bitRate;
  57 + /**
  58 + * 文件类型
  59 + */
  60 + private String fileType;
  61 + /**
  62 + * 文件格式
  63 + */
  64 + private String format;
  65 + /**
  66 + * 云剪Id
  67 + */
  68 + private String clipId;
  69 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.analyser;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/10/19 14:33
  8 + */
  9 +@Data
  10 +public class Feature2FigureResult {
  11 + private String familiarFigureId;
  12 + private String name;
  13 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.analyser;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.io.Serializable;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/6 17:23
  10 + *
  11 + * 人物分析mq消息
  12 + */
  13 +@Data
  14 +public class FigureAnalyseResult implements Serializable {
  15 + /**
  16 + * 媒资ID
  17 + */
  18 + private String tag;
  19 + /**
  20 + * 分析结果存储路径
  21 + */
  22 + private String path;
  23 + /**
  24 + * 状态 success:成功 file_decode_error:文件解析错误 file_notfund:文件找不到 error:未知错误 read_auth_error:文件读取权限 write_auth_error:结果无法写入
  25 + */
  26 + private String status;
  27 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.analyser;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/9/16 14:43
  10 + * <p>
  11 + * 熟人与人脸一起添加结果
  12 + */
  13 +@Data
  14 +public class FigureFaceResult {
  15 + /**
  16 + * 熟人ID
  17 + */
  18 + private String familiarFigureId;
  19 + private String namespace;
  20 + private List<Face> faces;
  21 +
  22 + @Data
  23 + public class Face {
  24 + /**
  25 + * 人脸ID
  26 + */
  27 + private String faceId;
  28 + /**
  29 + * 图片预览路径
  30 + */
  31 + private String previewPath;
  32 + }
  33 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.analyser;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/8/19 16:01
  8 + */
  9 +@Data
  10 +public class FileInfoToMq {
  11 + private String tag;
  12 + private String fileId;
  13 + private String relativePath;
  14 + private String namespace;
  15 + private String userId;
  16 + private String path;
  17 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.analyser;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.io.Serializable;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/6 17:23
  10 + *
  11 + * 人物分析mq消息
  12 + */
  13 +@Data
  14 +public class OcrAnalyseResult implements Serializable {
  15 + /**
  16 + * 媒资ID
  17 + */
  18 + private String tag;
  19 + /**
  20 + * 分析结果存储路径
  21 + */
  22 + private String path;
  23 + /**
  24 + * 状态 success:成功 file_decode_error:文件解析错误 file_notfund:文件找不到 error:未知错误 read_auth_error:文件读取权限 write_auth_error:结果无法写入
  25 + */
  26 + private String status;
  27 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.analyser;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author Hcg
  7 + * @Date 2021/8/23
  8 + * @desc
  9 + */
  10 +@Data
  11 +public class PictureAnalysisResult {
  12 + private Long faceId;
  13 + private String feature;
  14 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.UserInfo;
  4 +import lombok.Data;
  5 +import org.springframework.data.elasticsearch.annotations.Field;
  6 +import org.springframework.data.elasticsearch.annotations.FieldType;
  7 +
  8 +import java.util.Set;
  9 +
  10 +
  11 +/**
  12 + * @Author yubin
  13 + * @Date 2021/8/5 16:26
  14 + * <p>
  15 + * 基本信息
  16 + */
  17 +@Data
  18 +public class BasicInfo {
  19 + /**
  20 + * 媒资ID
  21 + */
  22 + @Field(type = FieldType.Long)
  23 + private Long materialId;
  24 + /**
  25 + * 媒资类型 1-视频 2-音频 3-图片
  26 + */
  27 + @Field(type = FieldType.Integer)
  28 + private Integer materialType;
  29 + /**
  30 + * 名称
  31 + */
  32 + @Field(type = FieldType.Keyword)
  33 + private String name;
  34 + /**
  35 + * 创建时间
  36 + */
  37 + @Field(type = FieldType.Keyword)
  38 + private String createTime;
  39 + /**
  40 + * 更新时间
  41 + */
  42 + @Field(type = FieldType.Keyword)
  43 + private String updateTime;
  44 + /**
  45 + * 来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控
  46 + */
  47 + @Field(type = FieldType.Integer)
  48 + private Integer source;
  49 + /**
  50 + * 标签
  51 + */
  52 + @Field(type = FieldType.Keyword)
  53 + private Set<String> tagInfoSet;
  54 + /**
  55 + * 封面图路径
  56 + */
  57 + @Field(type = FieldType.Keyword, index = false)
  58 + private String previewUrl;
  59 + /**
  60 + * 视频路径
  61 + */
  62 + @Field(type = FieldType.Keyword, index = false)
  63 + private String mediaUrl;
  64 + /**
  65 + * 用户
  66 + */
  67 + @Field(type = FieldType.Object)
  68 + private UserInfo owner;
  69 + /**
  70 + * 文件ID
  71 + */
  72 + @Field(type = FieldType.Keyword, index = false)
  73 + private String fileId;
  74 + /**
  75 + * 云剪ID
  76 + */
  77 + @Field(type = FieldType.Keyword, index = false)
  78 + private String clipId;
  79 + /**
  80 + * 文件相对路径
  81 + */
  82 + @Field(type = FieldType.Keyword, index = false)
  83 + private String relativePath;
  84 + /**
  85 + * 标签
  86 + */
  87 + @Field(type = FieldType.Keyword)
  88 + private Set<String> customLabelSet;
  89 + /**
  90 + * 标签
  91 + */
  92 + @Field(type = FieldType.Keyword)
  93 + private ImageAttr imageAttr;
  94 +
  95 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author lyf
  7 + * @Date 2023/9/18 11:14
  8 + */
  9 +@Data
  10 +public class Box {
  11 +
  12 + private Long w;
  13 + private Long h;
  14 + private Long x;
  15 + private Long y;
  16 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.data.elasticsearch.annotations.Field;
  5 +import org.springframework.data.elasticsearch.annotations.FieldType;
  6 +
  7 +import javax.persistence.Column;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * @Author yubin
  12 + * @Date 2021/8/5 16:47
  13 + * <p>
  14 + * 人脸识别信息
  15 + */
  16 +@Data
  17 +public class FaceInfo {
  18 + /**
  19 + * 人物ID
  20 + */
  21 + @Field(type = FieldType.Keyword)
  22 + private String figureId;
  23 + /**
  24 + * 人物名称
  25 + */
  26 + @Field(type = FieldType.Keyword)
  27 + private String figureName;
  28 + /**
  29 + * 人物图片路径
  30 + */
  31 + @Field(type = FieldType.Keyword, index = false)
  32 + private String face;
  33 + /**
  34 + * 出现率
  35 + */
  36 + @Field(type = FieldType.Keyword, index = false)
  37 + private String appearRate;
  38 + /**
  39 + * 出现总时长
  40 + */
  41 + @Field(type = FieldType.Long, index = false)
  42 + private Long totalDuration;
  43 + /**
  44 + * 出现时间列表
  45 + */
  46 + @Field(type = FieldType.Nested)
  47 + private List<Fragment> fragments;
  48 + /** 宽 */
  49 + @Field(type = FieldType.Keyword, index = false)
  50 + private String wight;
  51 + /** 高 */
  52 + @Field(type = FieldType.Keyword, index = false)
  53 + private String high;
  54 + /** 横坐标 */
  55 + @Field(type = FieldType.Keyword, index = false)
  56 + private String x;
  57 + /** 竖坐标 */
  58 + @Field(type = FieldType.Keyword, index = false)
  59 + private String y;
  60 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.data.elasticsearch.annotations.Field;
  5 +import org.springframework.data.elasticsearch.annotations.FieldType;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/5 16:54
  10 + *
  11 + * 人物出现时间
  12 + */
  13 +@Data
  14 +public class Fragment {
  15 + @Field(type = FieldType.Keyword, index = false)
  16 + private String start;
  17 + @Field(type = FieldType.Keyword, index = false)
  18 + private String end;
  19 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.data.elasticsearch.annotations.Field;
  5 +import org.springframework.data.elasticsearch.annotations.FieldType;
  6 +
  7 +import javax.persistence.Column;
  8 +
  9 +/**
  10 + * @author admin
  11 + */
  12 +@Data
  13 +public class ImageAttr {
  14 +
  15 + /**
  16 + * 拍摄时间
  17 + */
  18 + @Field(type = FieldType.Keyword, index = false)
  19 + private String shootingTime;
  20 + /**
  21 + * 作者
  22 + */
  23 + @Field(type = FieldType.Keyword, index = false)
  24 + private String artist;
  25 + /**
  26 + * 地点
  27 + */
  28 + @Field(type = FieldType.Keyword, index = false)
  29 + private String location;
  30 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.data.elasticsearch.annotations.Field;
  5 +import org.springframework.data.elasticsearch.annotations.FieldType;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/5 16:58
  10 + * <p>
  11 + * 状态信息
  12 + */
  13 +@Data
  14 +public class MaterialStatus {
  15 + /**
  16 + * AI分析状态 0-未开启 1-成功 2-失败 3-进行中
  17 + */
  18 + @Field(type = FieldType.Integer)
  19 + private Integer aiAnalysisStatus;
  20 + /**
  21 + * ocr分析状态 0-未开启 1-成功 2-失败 3-进行中
  22 + */
  23 + @Field(type = FieldType.Integer)
  24 + private Integer ocrAnalysisStatus;
  25 + /**
  26 + * 上传状态 1-成功 2-失败 3-进行中
  27 + */
  28 + @Field(type = FieldType.Integer)
  29 + private Integer uploadStatus;
  30 + /**
  31 + * 收录状态 1-成功 2-失败 3-进行中
  32 + */
  33 + @Field(type = FieldType.Integer)
  34 + private Integer embodyStatus;
  35 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.data.elasticsearch.annotations.Field;
  5 +import org.springframework.data.elasticsearch.annotations.FieldType;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/4 15:35
  10 + * <p>
  11 + * 介质信息
  12 + */
  13 +@Data
  14 +public class MediaInfo {
  15 + /**
  16 + * 宽
  17 + */
  18 + @Field(type = FieldType.Integer, index = false)
  19 + private Integer width;
  20 + /**
  21 + * 高
  22 + */
  23 + @Field(type = FieldType.Integer, index = false)
  24 + private Integer height;
  25 + /**
  26 + * 时长
  27 + */
  28 + @Field(type = FieldType.Long, index = false)
  29 + private Long duration;
  30 + /**
  31 + * 大小
  32 + */
  33 + @Field(type = FieldType.Long, index = false)
  34 + private Long size;
  35 + /**
  36 + * md5
  37 + */
  38 + @Field(type = FieldType.Keyword, index = false)
  39 + private String md5;
  40 + /**
  41 + * 码率
  42 + */
  43 + @Field(type = FieldType.Long, index = false)
  44 + private Long bitRate;
  45 + /**
  46 + * 介质类型
  47 + */
  48 + @Field(type = FieldType.Integer)
  49 + private Integer mediaType;
  50 +
  51 + /**
  52 + * 图片属性
  53 + */
  54 + @Field(type = FieldType.Keyword)
  55 + private ImageAttr imageAttr;
  56 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.data.elasticsearch.annotations.Field;
  5 +import org.springframework.data.elasticsearch.annotations.FieldType;
  6 +
  7 +/**
  8 + * @Author lyf
  9 + * @Date 2023/9/18 11:14
  10 + */
  11 +@Data
  12 +public class Polygon {
  13 +
  14 + @Field(type = FieldType.Keyword, index = false)
  15 + private Long x;
  16 + @Field(type = FieldType.Keyword, index = false)
  17 + private Long y;
  18 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/8/9 11:14
  8 + */
  9 +@Data
  10 +public class Slce {
  11 + private Long startTime;
  12 + private Long endTime;
  13 +}
  1 +package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.data.elasticsearch.annotations.Field;
  5 +import org.springframework.data.elasticsearch.annotations.FieldType;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * @Author yubin
  11 + * @Date 2021/10/14 10:12
  12 + * <p>
  13 + * 文字识别
  14 + */
  15 +@Data
  16 +public class WordInfo {
  17 +
  18 + @Field(type = FieldType.Keyword)
  19 + private String word;
  20 +
  21 + /**
  22 + * 出现时间列表
  23 + *//*
  24 + @Field(type = FieldType.Nested)
  25 + private List<Fragment> fragments;*/
  26 + @Field(type = FieldType.Keyword, index = false)
  27 + private String start;
  28 + @Field(type = FieldType.Keyword, index = false)
  29 + private String end;
  30 + /**
  31 + * 坐标列表
  32 + */
  33 + @Field(type = FieldType.Nested)
  34 + private List<Polygon> polygons;
  35 +}
  1 +package com.wondertek.ivod.cmr.core.entity.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/11 16:43
  10 + */
  11 +@Data
  12 +public class AiAnalysisDto {
  13 + private List<Long> materialIds;
  14 +}
  1 +package com.wondertek.ivod.cmr.core.entity.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/10/18 10:26
  8 + */
  9 +@Data
  10 +public class AnalysisPictureDto {
  11 + private String imageBase64;
  12 +}
  1 +package com.wondertek.ivod.cmr.core.entity.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/9/16 16:35
  10 + */
  11 +@Data
  12 +public class FigureDeleteDto {
  13 + private List<Long> figureIds;
  14 +}
  1 +package com.wondertek.ivod.cmr.core.entity.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/9/18 14:25
  8 + */
  9 +@Data
  10 +public class FigureUpdateDto {
  11 + private Long id;
  12 + private String name;
  13 + private String figureDefineId;
  14 + private Integer gender;
  15 + private String familiarFigureId;
  16 + private String remark;
  17 +}
  1 +package com.wondertek.ivod.cmr.core.entity.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author yubin
  7 + * @Date 2021/10/13 16:31
  8 + */
  9 +@Data
  10 +public class MaterialAddDto {
  11 + /**
  12 + * 媒资名称
  13 + */
  14 + private String name;
  15 + /**
  16 + * 是否开启AI智能识别 false-否 true-是
  17 + */
  18 + private Boolean isOpenAi;
  19 + /**
  20 + * 媒资id,重新上传需要
  21 + */
  22 + private Long materialId;
  23 +}
  1 +package com.wondertek.ivod.cmr.core.entity.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/10/13 16:31
  10 + */
  11 +@Data
  12 +public class MaterialCustomLabelDto {
  13 + /**
  14 + * 自定义标签
  15 + */
  16 + private String customLabel;
  17 + /**
  18 + * 媒资id
  19 + */
  20 + private List<Long> materialIds;
  21 +}
  1 +package com.wondertek.ivod.cmr.core.entity.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/11 16:43
  10 + */
  11 +@Data
  12 +public class MaterialDeleteDto {
  13 + private List<Long> materialIds;
  14 +}
  1 +package com.wondertek.ivod.cmr.core.entity.dto;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.MediaInfo;
  4 +import lombok.Data;
  5 +
  6 +/**
  7 + * @Author yubin
  8 + * @Date 2021/8/17 10:59
  9 + */
  10 +@Data
  11 +public class MaterialInfoDto extends MediaInfo {
  12 + private Long materialId;
  13 + /**
  14 + * 名称
  15 + */
  16 + private String name;
  17 + /**
  18 + * 视频路径
  19 + */
  20 + private String mediaUrl;
  21 + /**
  22 + * 封面图路径
  23 + */
  24 + private String previewUrl;
  25 + /**
  26 + * 文件相对路径
  27 + */
  28 + private String relativePath;
  29 + /**
  30 + * 文件ID
  31 + */
  32 + private String fileId;
  33 + /**
  34 + * 是否开启AI智能识别 false-否 true-是
  35 + */
  36 + private Boolean isOpenAi;
  37 + /**
  38 + * 云剪Id
  39 + */
  40 + private String clipId;
  41 +}
  1 +package com.wondertek.ivod.cmr.core.entity.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/4 17:28
  10 + */
  11 +@Data
  12 +public class MaterialInjectDto {
  13 + /**
  14 + * 来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控
  15 + */
  16 + private Integer source;
  17 + /**
  18 + * 媒资
  19 + */
  20 + private List<MaterialInfoDto> materialInfos;
  21 + /**
  22 + * 用户ID
  23 + */
  24 + private String userId;
  25 + /**
  26 + * 操作人
  27 + */
  28 + private String userName;
  29 + /**
  30 + * 租户ID
  31 + */
  32 + private String tenantId;
  33 +}
  1 +package com.wondertek.ivod.cmr.core.entity.model;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.ToString;
  7 +import org.hibernate.annotations.DynamicInsert;
  8 +import org.hibernate.annotations.DynamicUpdate;
  9 +
  10 +import javax.persistence.*;
  11 +import java.io.Serializable;
  12 +import java.time.LocalDateTime;
  13 +
  14 +/**
  15 + * @author admin
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@NoArgsConstructor
  20 +@DynamicInsert
  21 +@DynamicUpdate
  22 +@ToString
  23 +@Entity
  24 +@Table(name="cmr_ai_figure")
  25 +public class AiFigure implements Serializable, Cloneable {
  26 + /** 主键 */
  27 + @Id
  28 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  29 + @Column(name = "id")
  30 + private Long id;
  31 + /** 媒资ID */
  32 + @Column(name = "material_id")
  33 + private Long materialId;
  34 + /** 分析器陌生人库ID */
  35 + @Column(name = "figure_id")
  36 + private Long figureId;
  37 + /** 头像 */
  38 + @Column(name = "image_path")
  39 + private String imagePath;
  40 + /** 露出开始时间 */
  41 + @Column(name = "begin_time")
  42 + private String beginTime;
  43 + /** 露出结束时间 */
  44 + @Column(name = "end_time")
  45 + private String endTime;
  46 + /** 创建时间 */
  47 + @Column(name = "create_time")
  48 + private LocalDateTime createTime;
  49 + /** 宽 */
  50 + @Column(name = "wight")
  51 + private String wight;
  52 + /** 高 */
  53 + @Column(name = "high")
  54 + private String high;
  55 + /** 横坐标 */
  56 + @Column(name = "x_pos")
  57 + private String xPos;
  58 + /** 竖坐标 */
  59 + @Column(name = "y_pos")
  60 + private String yPos;
  61 + /** AI分析OCR结果 */
  62 + @Column(name = "content")
  63 + private String content;
  64 + /** AI分析类型空/1为人物 2OCR */
  65 + @Column(name = "type")
  66 + private String type;
  67 +}
  1 +package com.wondertek.ivod.cmr.core.entity.model;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.ToString;
  7 +import org.hibernate.annotations.DynamicInsert;
  8 +import org.hibernate.annotations.DynamicUpdate;
  9 +
  10 +import javax.persistence.*;
  11 +import java.io.Serializable;
  12 +import java.time.LocalDateTime;
  13 +
  14 +/**
  15 + * @author admin
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@NoArgsConstructor
  20 +@DynamicInsert
  21 +@DynamicUpdate
  22 +@ToString
  23 +@Entity
  24 +@Table(name="cmr_logs")
  25 +public class CmrLogs implements Serializable, Cloneable {
  26 + /** 乐观锁 */
  27 + @Id
  28 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  29 + @Column(name = "id")
  30 + private Long id;
  31 + /** 租户ID */
  32 + @Column(name = "tenant_id")
  33 + private String tenantId;
  34 + /** 操作人 */
  35 + @Column(name = "operation_by")
  36 + private String operationBy;
  37 + /** 操作时间 */
  38 + @Column(name = "operation_time")
  39 + private LocalDateTime operationTime;
  40 + /** 对象ID */
  41 + @Column(name = "object_id")
  42 + private String objectId;
  43 + /** 对象类型 */
  44 + @Column(name = "object_type")
  45 + private String objectType;
  46 + /** 操作信息 */
  47 + @Column(name = "operation_msg")
  48 + private String operationMsg;
  49 + /** 操作类型 */
  50 + @Column(name = "operation_type")
  51 + private String operationType;
  52 + /** 请求URL */
  53 + @Column(name = "request_url")
  54 + private String requestUrl;
  55 +}
  1 +package com.wondertek.ivod.cmr.core.entity.model;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.ToString;
  7 +import org.hibernate.annotations.DynamicInsert;
  8 +import org.hibernate.annotations.DynamicUpdate;
  9 +
  10 +import javax.persistence.*;
  11 +import java.io.Serializable;
  12 +import java.time.LocalDateTime;
  13 +
  14 +/**
  15 + * @author admin
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@NoArgsConstructor
  20 +@DynamicInsert
  21 +@DynamicUpdate
  22 +@ToString
  23 +@Entity
  24 +@Table(name="cmr_figure")
  25 +public class Figure implements Serializable, Cloneable {
  26 + /** 人物ID */
  27 + @Id
  28 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  29 + @Column(name = "id")
  30 + private Long id;
  31 + /** 人物名称 */
  32 + @Column(name = "name")
  33 + private String name;
  34 + /** 人物自定义ID */
  35 + @Column(name = "figure_define_id")
  36 + private String figureDefineId;
  37 + /** 性别 0-女 1-男 */
  38 + @Column(name = "gender")
  39 + private Integer gender;
  40 + /** 备注 */
  41 + @Column(name = "remark")
  42 + private String remark;
  43 + /** 分析器熟人id */
  44 + @Column(name = "familiar_figure_id")
  45 + private String familiarFigureId;
  46 + /** 预览路径 */
  47 + @Column(name = "preview_url")
  48 + private String previewUrl;
  49 + /** 租户ID */
  50 + @Column(name = "tenant_id")
  51 + private String tenantId;
  52 + /** 创建人 */
  53 + @Column(name = "create_by")
  54 + private String createBy;
  55 + /** 创建时间 */
  56 + @Column(name = "create_time")
  57 + private LocalDateTime createTime;
  58 + /** 更新人 */
  59 + @Column(name = "update_by")
  60 + private String updateBy;
  61 + /** 更新时间 */
  62 + @Column(name = "update_time")
  63 + private LocalDateTime updateTime;
  64 +}
  1 +package com.wondertek.ivod.cmr.core.entity.model;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.ToString;
  7 +import org.hibernate.annotations.DynamicInsert;
  8 +import org.hibernate.annotations.DynamicUpdate;
  9 +
  10 +import javax.persistence.*;
  11 +import java.io.Serializable;
  12 +
  13 +/**
  14 + * @author admin
  15 + */
  16 +@Data
  17 +@AllArgsConstructor
  18 +@NoArgsConstructor
  19 +@DynamicInsert
  20 +@DynamicUpdate
  21 +@ToString
  22 +@Entity
  23 +@Table(name="cmr_figure_image")
  24 +public class FigureImage implements Serializable, Cloneable {
  25 + /** 主键 */
  26 + @Id
  27 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  28 + @Column(name = "id")
  29 + private Integer id;
  30 + /** 人物ID */
  31 + private String figureId;
  32 + /** 名称 */
  33 + private String name;
  34 + /** 图片类型 */
  35 + private String type;
  36 + /** 图片路径 */
  37 + private String imagePath;
  38 + /** 分辨率 */
  39 + private String resolution;
  40 + /** 宽 */
  41 + private String width;
  42 + /** 高 */
  43 + private String high;
  44 + /** MD5 */
  45 + private String md5;
  46 +}
  1 +package com.wondertek.ivod.cmr.core.entity.model;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.ToString;
  7 +import org.hibernate.annotations.DynamicInsert;
  8 +import org.hibernate.annotations.DynamicUpdate;
  9 +
  10 +import javax.persistence.*;
  11 +import java.io.Serializable;
  12 +
  13 +/**
  14 + * @author xh
  15 + * @date 2023/9/15 17:08
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@NoArgsConstructor
  20 +@DynamicInsert
  21 +@DynamicUpdate
  22 +@ToString
  23 +@Entity
  24 +@Table(name="cmr_image_detail")
  25 +public class ImageDetail implements Serializable, Cloneable {
  26 +
  27 + @Id
  28 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  29 + @Column(name = "id")
  30 + private Long id;
  31 + @Column(name = "material_id")
  32 + private Long materialId;
  33 + /**
  34 + * 拍摄时间
  35 + */
  36 + @Column(name = "shooting_time")
  37 + private String shootingTime;
  38 + /**
  39 + * 作者
  40 + */
  41 + @Column(name = "artist")
  42 + private String artist;
  43 + /**
  44 + * 图片宽
  45 + */
  46 + @Column(name = "image_width")
  47 + private String imageWidth;
  48 + /**
  49 + * 图片高
  50 + */
  51 + @Column(name = "image_height")
  52 + private String imageHeight;
  53 + /**
  54 + * 压缩类型
  55 + */
  56 + @Column(name = "compression_type")
  57 + private String compressionType;
  58 + /**
  59 + * 检测到的文件类型名称
  60 + */
  61 + @Column(name = "detected_file_type_name")
  62 + private String detectedFileTypeName;
  63 + /**
  64 + * 检测到的MIME类型
  65 + */
  66 + @Column(name = "detected_mime_type")
  67 + private String detectedMimeType;
  68 + /**
  69 + * 预期的文件扩展名
  70 + */
  71 + @Column(name = "expected_file_name_extension")
  72 + private String expectedFileNameExtension;
  73 + /**
  74 + * 文件名
  75 + */
  76 + @Column(name = "file_name")
  77 + private String fileName;
  78 + /**
  79 + * 文件大小
  80 + */
  81 + @Column(name = "file_size")
  82 + private String fileSize;
  83 + /**
  84 + * 文件修改时间
  85 + */
  86 + @Column(name = "file_modified_date")
  87 + private String fileModifiedDate;
  88 + /**
  89 + * 维度
  90 + */
  91 + @Column(name = "gps_latitude")
  92 + private String gpsLatitude;
  93 + /**
  94 + * 经度
  95 + */
  96 + @Column(name = "gps_longitude")
  97 + private String gpsLongitude;
  98 + /**
  99 + * 地点
  100 + */
  101 + @Column(name = "location")
  102 + private String location;
  103 +}
  1 +package com.wondertek.ivod.cmr.core.entity.model;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.ToString;
  7 +import org.hibernate.annotations.DynamicInsert;
  8 +import org.hibernate.annotations.DynamicUpdate;
  9 +
  10 +import javax.persistence.*;
  11 +import java.io.Serializable;
  12 +import java.time.LocalDateTime;
  13 +
  14 +/**
  15 + * @author admin
  16 + */
  17 +@Data
  18 +@AllArgsConstructor
  19 +@NoArgsConstructor
  20 +@DynamicInsert
  21 +@DynamicUpdate
  22 +@ToString
  23 +@Entity
  24 +@Table(name="cmr_material")
  25 +public class Material implements Serializable, Cloneable {
  26 + /** 媒资ID */
  27 + @Id
  28 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  29 + @Column(name = "material_id")
  30 + private Long materialId;
  31 + /** 媒资类型 1-视频 2-音频 3-图片 */
  32 + @Column(name = "material_type")
  33 + private Integer materialType;
  34 + /** 名称 */
  35 + @Column(name = "name")
  36 + private String name;
  37 + /** 来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控 */
  38 + @Column(name = "source")
  39 + private Integer source;
  40 + /** 租户ID */
  41 + @Column(name = "tenant_id")
  42 + private String tenantId;
  43 + /** 介质预览路径 */
  44 + @Column(name = "media_url")
  45 + private String mediaUrl;
  46 + /** 封面图 */
  47 + @Column(name = "preview_url")
  48 + private String previewUrl;
  49 + /** 创建人 */
  50 + @Column(name = "create_by")
  51 + private String createBy;
  52 + /** 创建时间 */
  53 + @Column(name = "create_time")
  54 + private LocalDateTime createTime;
  55 + /** 更新人 */
  56 + @Column(name = "updated_by")
  57 + private String updatedBy;
  58 + /** 更新时间 */
  59 + @Column(name = "updated_time")
  60 + private LocalDateTime updatedTime;
  61 + /**
  62 + * 自定义标签,多个逗号分隔
  63 + */
  64 + @Column(name = "custom_label")
  65 + private String customLabel;
  66 +}
  1 +package com.wondertek.ivod.cmr.core.entity.model;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.ToString;
  7 +import org.hibernate.annotations.DynamicInsert;
  8 +import org.hibernate.annotations.DynamicUpdate;
  9 +
  10 +import javax.persistence.*;
  11 +import java.io.Serializable;
  12 +
  13 +/**
  14 + * @author admin
  15 + */
  16 +@Data
  17 +@AllArgsConstructor
  18 +@NoArgsConstructor
  19 +@DynamicInsert
  20 +@DynamicUpdate
  21 +@ToString
  22 +@Entity
  23 +@Table(name="cmr_material_files")
  24 +public class MaterialFiles implements Serializable, Cloneable {
  25 + /** 介质ID */
  26 + @Id
  27 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  28 + @Column(name = "id")
  29 + private Long id ;
  30 + /** 媒资ID */
  31 + @Column(name = "material_id")
  32 + private Long materialId;
  33 + /** 宽 */
  34 + @Column(name = "width")
  35 + private String width;
  36 + /** 高 */
  37 + @Column(name = "height")
  38 + private String height;
  39 + /** MD5 */
  40 + @Column(name = "md5")
  41 + private String md5;
  42 + /** 码率 */
  43 + @Column(name = "bit_rate")
  44 + private String bitRate;
  45 + /** 文件类型 */
  46 + @Column(name = "type")
  47 + private Integer type;
  48 + /** path */
  49 + @Column(name = "path")
  50 + private String path;
  51 +
  52 +}
  1 +package com.wondertek.ivod.cmr.core.entity.model;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Data;
  6 +import lombok.NoArgsConstructor;
  7 +import lombok.ToString;
  8 +import org.hibernate.annotations.DynamicInsert;
  9 +import org.hibernate.annotations.DynamicUpdate;
  10 +import org.springframework.format.annotation.DateTimeFormat;
  11 +
  12 +import javax.persistence.*;
  13 +import java.io.Serializable;
  14 +import java.time.LocalDateTime;
  15 +
  16 +/**
  17 + * @author xh
  18 + * @date 2023/9/18 10:47
  19 + */
  20 +@Data
  21 +@AllArgsConstructor
  22 +@NoArgsConstructor
  23 +@DynamicInsert
  24 +@DynamicUpdate
  25 +@ToString
  26 +@Entity
  27 +@Table(name="cmr_operate_record")
  28 +public class OperateRecord implements Serializable, Cloneable {
  29 + @Id
  30 + @GeneratedValue(strategy = GenerationType.IDENTITY)
  31 + @Column(name = "id")
  32 + private Long id;
  33 + /**
  34 + * 租户id
  35 + */
  36 + @Column(name = "tenant_id")
  37 + private String tenantId;
  38 + /**
  39 + * 操作人名
  40 + */
  41 + @Column(name = "user_name")
  42 + private String userName;
  43 + /**
  44 + * 操作类型 1-下载 2-浏览
  45 + */
  46 + @Column(name = "operate_type")
  47 + private String operateType;
  48 + /**
  49 + * 浏览次数
  50 + */
  51 + @Column(name = "view_count")
  52 + private Integer viewCount;
  53 + /**
  54 + * 下载次数
  55 + */
  56 + @Column(name = "download_count")
  57 + private Integer downLoadCount;
  58 + /**
  59 + * 创建时间
  60 + */
  61 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
  62 + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  63 + @Column(name = "created_time")
  64 + private LocalDateTime createdTime;
  65 + /**
  66 + * 操作对象id
  67 + */
  68 + @Column(name = "operate_object_id")
  69 + private String operateObjectId;
  70 +
  71 +
  72 +}
  1 +package com.wondertek.ivod.cmr.core.entity.vo;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author Hcg
  7 + * @Date 2021/8/23
  8 + * @desc
  9 + */
  10 +@Data
  11 +public class PictureAnalysisVo {
  12 + private String faceId;
  13 + private String name;
  14 +}
  1 +package com.wondertek.ivod.cmr.core.entity.vo;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.math.BigDecimal;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/9/16 10:22
  10 + */
  11 +@Data
  12 +public class SimilarityMatchVo {
  13 + /**
  14 + * 头像路径
  15 + */
  16 + private String previewUrl;
  17 + /**
  18 + * 名称
  19 + */
  20 + private String name;
  21 + /**
  22 + * 可信度
  23 + */
  24 + private BigDecimal score;
  25 + /**
  26 + * 熟人id
  27 + */
  28 + private String familiarFigureId;
  29 + private String[] path;
  30 +}
  1 +package com.wondertek.ivod.cmr.core.repository;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.model.CmrLogs;
  4 +import org.springframework.data.jpa.repository.JpaRepository;
  5 +import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/3 16:32
  10 + */
  11 +public interface CmrLogsRepository extends JpaRepository<CmrLogs, Long>, JpaSpecificationExecutor<CmrLogs> {
  12 +}
  1 +package com.wondertek.ivod.cmr.core.service;
  2 +
  3 +
  4 +/**
  5 + * @Author yubin
  6 + * @Date 2021/8/3 16:27
  7 + */
  8 +public interface ICmrLogsService {
  9 +}
  1 +package com.wondertek.ivod.cmr.core.service.impl;
  2 +
  3 +import com.wondertek.ivod.cmr.core.service.ICmrLogsService;
  4 +import org.springframework.stereotype.Service;
  5 +
  6 +/**
  7 + * @Author yubin
  8 + * @Date 2021/8/3 16:28
  9 + */
  10 +@Service
  11 +public class CmrLogsServiceImpl implements ICmrLogsService {
  12 +
  13 +}
  1 +/.externalToolBuilders
  2 +/.settings
  3 +.svn
  4 +/.project
  5 +/target
  6 +target/
  7 +/.classpath
  8 +/src/main/webapp/temp
  9 +/src/main/webapp/source
  10 +/src/main/webapp/store
  11 +/src/main/webapp/depository
  12 +.idea/
  13 +*.iml
  14 +*.iws
  15 +*.ipr
  16 +*.ids
  17 +*.orig
  18 +classes/
  19 +*.properties
  20 +*.log
  1 +FROM 192.168.1.7/library/java8:centos7
  2 +
  3 +ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
  4 +SPRING_PROFILE_ACTIVE=prod \
  5 +SPRING_OPTS="" \
  6 +JAVA_OPTS=""
  7 +CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=${SPRING_PROFILE_ACTIVE} ${SPRING_OPTS}
  8 +RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
  9 +ADD target/*.jar /app.jar
  1 +FROM 192.168.1.7/library/java8:centos7
  2 +
  3 +ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
  4 +SPRING_PROFILE_ACTIVE=preview \
  5 +SPRING_OPTS="" \
  6 +JAVA_OPTS=""
  7 +CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=${SPRING_PROFILE_ACTIVE} ${SPRING_OPTS}
  8 +RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
  9 +ADD *.jar /app.jar
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>cloud-media-resources</artifactId>
  7 + <groupId>com.wondertek.ivod.cmr</groupId>
  8 + <version>1.0.0</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <groupId>com.wondertek.ivod.cmr.manage</groupId>
  13 + <artifactId>cmr-manage</artifactId>
  14 + <packaging>jar</packaging>
  15 + <version>1.0.0</version>
  16 +
  17 + <dependencies>
  18 + <dependency>
  19 + <groupId>com.wondertek.ivod.cmr.commons</groupId>
  20 + <artifactId>cmr-commons</artifactId>
  21 + <version>1.0.0</version>
  22 + </dependency>
  23 + <dependency>
  24 + <groupId>com.wondertek.ivod.cmr.core</groupId>
  25 + <artifactId>cmr-core</artifactId>
  26 + <version>1.0.0</version>
  27 + </dependency>
  28 + <!--web container-->
  29 + <dependency>
  30 + <groupId>org.springframework.boot</groupId>
  31 + <artifactId>spring-boot-starter-web</artifactId>
  32 + </dependency>
  33 +
  34 + <dependency>
  35 + <groupId>org.springframework.boot</groupId>
  36 + <artifactId>spring-boot-starter</artifactId>
  37 + </dependency>
  38 +
  39 + <dependency>
  40 + <groupId>org.springframework.boot</groupId>
  41 + <artifactId>spring-boot-starter-aop</artifactId>
  42 + </dependency>
  43 +
  44 + <!-- mysql JDBC驱动 代码生成使用-->
  45 + <dependency>
  46 + <groupId>mysql</groupId>
  47 + <artifactId>mysql-connector-java</artifactId>
  48 + <version>8.0.19</version>
  49 + </dependency>
  50 +
  51 + <!--druid-->
  52 + <dependency>
  53 + <groupId>com.alibaba</groupId>
  54 + <artifactId>druid-spring-boot-starter</artifactId>
  55 + <version>1.1.22</version>
  56 + </dependency>
  57 +
  58 + <dependency>
  59 + <groupId>org.springframework.boot</groupId>
  60 + <artifactId>spring-boot-starter-amqp</artifactId>
  61 + </dependency>
  62 +
  63 + <dependency>
  64 + <groupId>com.alibaba.cloud</groupId>
  65 + <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  66 + <version>2.2.5.RELEASE</version>
  67 + </dependency>
  68 +
  69 + <dependency>
  70 + <groupId>com.alibaba.cloud</groupId>
  71 + <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  72 + <version>2.2.5.RELEASE</version>
  73 + </dependency>
  74 + <dependency>
  75 + <groupId>com.drewnoakes</groupId>
  76 + <artifactId>metadata-extractor</artifactId>
  77 + <version>2.14.0</version>
  78 + </dependency>
  79 +
  80 + </dependencies>
  81 +
  82 + <!--如果需要打docker镜像,把注释放开即可-->
  83 + <build>
  84 + <plugins>
  85 + <plugin>
  86 + <groupId>org.springframework.boot</groupId>
  87 + <artifactId>spring-boot-maven-plugin</artifactId>
  88 + </plugin>
  89 + </plugins>
  90 + <pluginManagement>
  91 + <plugins>
  92 + <plugin>
  93 + <groupId>com.spotify</groupId>
  94 + <artifactId>docker-maven-plugin</artifactId>
  95 + <version>1.1.0</version>
  96 + <executions>
  97 + <execution>
  98 + <id>build-image</id>
  99 + <phase>package</phase>
  100 + <goals>
  101 + <goal>build</goal>
  102 + <goal>push</goal>
  103 + </goals>
  104 + </execution>
  105 + </executions>
  106 + <configuration>
  107 + <imageName>192.168.1.69/ai_lib/${project.artifactId}:${project.version}</imageName>
  108 + <dockerHost>http://192.168.1.70:2375</dockerHost>
  109 + <dockerDirectory>${basedir}/docker</dockerDirectory>
  110 + <resources>
  111 + <resource>
  112 + <targetPath>/</targetPath>
  113 + <directory>${project.build.directory}</directory>
  114 + <include>${project.build.finalName}.jar</include>
  115 + </resource>
  116 + </resources>
  117 + </configuration>
  118 + </plugin>
  119 + </plugins>
  120 + </pluginManagement>
  121 + </build>
  122 +
  123 + <profiles>
  124 + <profile>
  125 + <id>docker</id>
  126 + <properties>
  127 + <spring.profiles.active>preview</spring.profiles.active>
  128 + </properties>
  129 + <build>
  130 + <plugins>
  131 + <plugin>
  132 + <groupId>com.spotify</groupId>
  133 + <artifactId>docker-maven-plugin</artifactId>
  134 + <configuration>
  135 + <imageName>192.168.1.7/ivod/${project.artifactId}:${project.version}</imageName>
  136 + <dockerHost>http://192.168.1.70:2375</dockerHost>
  137 + <serverId>wd-harbor</serverId>
  138 + </configuration>
  139 + </plugin>
  140 + </plugins>
  141 + </build>
  142 + </profile>
  143 + </profiles>
  144 +</project>
  1 +package com.wondertek.ivod.cmr.manage;
  2 +
  3 +import cn.hutool.extra.spring.SpringUtil;
  4 +import org.springframework.amqp.rabbit.annotation.EnableRabbit;
  5 +import org.springframework.boot.SpringApplication;
  6 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  7 +import org.springframework.boot.autoconfigure.domain.EntityScan;
  8 +import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  9 +import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  10 +import org.springframework.cloud.openfeign.EnableFeignClients;
  11 +import org.springframework.context.ConfigurableApplicationContext;
  12 +import org.springframework.context.annotation.Bean;
  13 +import org.springframework.context.annotation.ComponentScan;
  14 +import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  15 +import org.springframework.scheduling.annotation.EnableAsync;
  16 +import org.springframework.web.client.RestTemplate;
  17 +
  18 +@SpringBootApplication
  19 +@EnableDiscoveryClient
  20 +@ComponentScan(basePackages = {"com.wondertek.ivod"})
  21 +@EnableJpaRepositories(basePackages = {"com.wondertek.ivod"})
  22 +@EntityScan("com.wondertek.ivod.cmr.core.entity")
  23 +@EnableFeignClients(basePackages = {"com.wondertek.ivod"})
  24 +@EnableRabbit
  25 +@EnableAsync
  26 +public class CMRManageApplication {
  27 +
  28 + public static void main(String[] args) {
  29 +
  30 + ConfigurableApplicationContext applicationContext = SpringApplication.run(CMRManageApplication.class, args);
  31 + SpringUtil springUtil = new SpringUtil();
  32 + springUtil.setApplicationContext(applicationContext);
  33 + }
  34 +
  35 + @Bean
  36 + public RestTemplate getRestTemplate(){
  37 + return new RestTemplate();
  38 + }
  39 +}
  1 +package com.wondertek.ivod.cmr.manage.config;
  2 +
  3 +import cn.hutool.json.JSONUtil;
  4 +import com.wondertek.ivod.cmr.commons.utils.UserUtils;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.apache.commons.lang3.ObjectUtils;
  7 +import org.aspectj.lang.ProceedingJoinPoint;
  8 +import org.aspectj.lang.Signature;
  9 +import org.aspectj.lang.annotation.*;
  10 +import org.aspectj.lang.reflect.MethodSignature;
  11 +import org.springframework.stereotype.Component;
  12 +import org.springframework.web.context.request.RequestContextHolder;
  13 +import org.springframework.web.context.request.ServletRequestAttributes;
  14 +
  15 +import javax.servlet.http.HttpServletRequest;
  16 +import java.lang.reflect.Method;
  17 +import java.lang.reflect.Parameter;
  18 +import java.util.*;
  19 +
  20 +/**
  21 + * 请求参数与响应结果封装
  22 + *
  23 + * @Author: CuiSiBo
  24 + * @Date: 2020/5/6 17:03
  25 + * @Version 1.0
  26 + */
  27 +
  28 +@Aspect
  29 +@Component
  30 +@Slf4j
  31 +public class LogAspect {
  32 +
  33 + @Pointcut("execution(public * com.wondertek.ivod.cmr.manage.controller.*Controller.*(..))")
  34 + public void webLog() {
  35 + }
  36 +
  37 +
  38 + @Around("webLog()")
  39 + public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
  40 + long startTime = System.currentTimeMillis();
  41 + //获取当前请求对象
  42 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  43 + HttpServletRequest request = attributes.getRequest();
  44 + //设置用户信息
  45 + UserUtils.setUser(request);
  46 + String uri = request.getRequestURI();
  47 + //记录入参
  48 + Signature signature = joinPoint.getSignature();
  49 + MethodSignature methodSignature = (MethodSignature) signature;
  50 + Method method = methodSignature.getMethod();
  51 + Object inParameter = getParameter(method, joinPoint.getArgs());
  52 + String paramStr = "{}";
  53 + if (ObjectUtils.isNotEmpty(inParameter)) {
  54 + paramStr = JSONUtil.parse(inParameter).toJSONString(0);
  55 + paramStr = paramStr.length() > 1000 ? paramStr.substring(0, 1000) : paramStr;
  56 + }
  57 + log.info(">>>>>>>>>> {} begin ! parameter:{}", uri, paramStr);
  58 + //执行接口
  59 + Object result = joinPoint.proceed();
  60 + //记录出参
  61 + String resultStr = "{}";
  62 + if (ObjectUtils.isNotEmpty(result)) {
  63 + resultStr = JSONUtil.parse(result).toJSONString(0);
  64 + resultStr = resultStr.length() > 1000 ? resultStr.substring(0, 1000) : resultStr;
  65 + }
  66 + long endTime = System.currentTimeMillis();
  67 + log.info(">>>>>>>>>> {} end, time-consuming:{}ms ! result:{}", uri, endTime - startTime, resultStr);
  68 + return result;
  69 + }
  70 +
  71 + /**
  72 + * 根据方法和传入的参数获取请求参数
  73 + */
  74 + private List<Map> getParameter(Method method, Object[] args) {
  75 + List<Map> argList = new ArrayList<>();
  76 + Parameter[] parameters = method.getParameters();
  77 + for (int i = 0; i < parameters.length; i++) {
  78 + Map<String, Object> map = new HashMap<>();
  79 + map.put(parameters[i].getName(), args[i]);
  80 + argList.add(map);
  81 + }
  82 + return argList;
  83 + }
  84 +}
  1 +package com.wondertek.ivod.cmr.manage.config;
  2 +
  3 +import org.springframework.amqp.core.*;
  4 +import org.springframework.beans.factory.annotation.Qualifier;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +
  8 +/**
  9 + * @Author yubin
  10 + * @Date 2021/8/12 17:32
  11 + */
  12 +@Configuration
  13 +public class RabbitmqConfig {
  14 + //交换机名称
  15 + public static final String ANALYZER_FILE_EXCHANGE = "FileExchange";
  16 + //队列名称
  17 + public static final String ANALYZER_FILE_STORAGE_PATH_QUEUE = "analyzer_file_storage_path";
  18 + //路由
  19 + public static final String ANALYZER_FILE_STORAGE_PATH_ROUTING = "file.storagePath";
  20 + public static final String WORDS_ANALYZER_FILE_EXCHANGE = "ai-analyse";
  21 + public static final String WORDS_ANALYZER_FILE_STORAGE_PATH_ROUTING = "ocr.video";
  22 + //声明交换机
  23 + @Bean("itemTopicExchange")
  24 + public Exchange topicExchange(){
  25 + return ExchangeBuilder.topicExchange(ANALYZER_FILE_EXCHANGE).durable(true).build();
  26 + }
  27 +
  28 + //声明队列
  29 + @Bean("itemQueue")
  30 + public Queue itemQueue(){
  31 + return QueueBuilder.durable(ANALYZER_FILE_STORAGE_PATH_QUEUE).build();
  32 + }
  33 +
  34 + //绑定队列和交换机
  35 + @Bean
  36 + public Binding itemQueueExchange(@Qualifier("itemQueue") Queue queue,
  37 + @Qualifier("itemTopicExchange") Exchange exchange){
  38 + return BindingBuilder.bind(queue).to(exchange).with(ANALYZER_FILE_STORAGE_PATH_ROUTING).noargs();
  39 + }
  40 +}
  1 +package com.wondertek.ivod.cmr.manage.consumer;
  2 +
  3 +import cn.hutool.core.date.DateUtil;
  4 +import cn.hutool.core.util.NumberUtil;
  5 +import cn.hutool.core.util.ObjectUtil;
  6 +import cn.hutool.core.util.StrUtil;
  7 +import cn.hutool.json.JSONArray;
  8 +import cn.hutool.json.JSONObject;
  9 +import cn.hutool.json.JSONUtil;
  10 +import com.wondertek.ivod.cmr.commons.enums.CommonStatusEnum;
  11 +import com.wondertek.ivod.cmr.commons.exception.DefaultException;
  12 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  13 +import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
  14 +import com.wondertek.ivod.cmr.core.entity.bean.VideoFigureData;
  15 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.FigureAnalyseResult;
  16 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.FaceInfo;
  17 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Fragment;
  18 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Slce;
  19 +import com.wondertek.ivod.cmr.core.entity.model.AiFigure;
  20 +import com.wondertek.ivod.cmr.core.entity.model.Material;
  21 +import com.wondertek.ivod.cmr.manage.feign.SearchFeignService;
  22 +import com.wondertek.ivod.cmr.manage.repository.AiFigureRepository;
  23 +import com.wondertek.ivod.cmr.manage.repository.MaterialRepository;
  24 +import lombok.extern.slf4j.Slf4j;
  25 +import org.springframework.amqp.core.ExchangeTypes;
  26 +import org.springframework.amqp.core.Message;
  27 +import org.springframework.amqp.rabbit.annotation.Exchange;
  28 +import org.springframework.amqp.rabbit.annotation.Queue;
  29 +import org.springframework.amqp.rabbit.annotation.QueueBinding;
  30 +import org.springframework.amqp.rabbit.annotation.RabbitListener;
  31 +import org.springframework.beans.factory.annotation.Autowired;
  32 +import org.springframework.beans.factory.annotation.Value;
  33 +import org.springframework.stereotype.Component;
  34 +
  35 +import java.io.File;
  36 +import java.math.BigDecimal;
  37 +import java.nio.charset.StandardCharsets;
  38 +import java.time.LocalDateTime;
  39 +import java.util.*;
  40 +import java.util.concurrent.atomic.AtomicLong;
  41 +
  42 +/**
  43 + * @Author yubin
  44 + * @Date 2021/8/6 16:21
  45 + */
  46 +@Slf4j
  47 +@Component
  48 +public class FigureConsumer {
  49 + @Autowired
  50 + private SearchFeignService searchFeignService;
  51 + @Autowired
  52 + private MaterialRepository materialRepository;
  53 + @Autowired
  54 + private AiFigureRepository aiFigureRepository;
  55 + @Value("${analyser.filePath}")
  56 + private String filePath;
  57 +
  58 + /**
  59 + * 人物分析
  60 + * 解析ai生成的人脸识别文件,更新信息到es
  61 + *
  62 + * @param message
  63 + */
  64 + @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "${mq.anylzer.callbackQueue}", durable = "true"),
  65 + exchange = @Exchange(value = "${mq.anylzer.callbackExchange}", type = ExchangeTypes.TOPIC),
  66 + key = "${analyser.namespace}"), concurrency = "5")
  67 + public void figureAnalyse(Message message) {
  68 + String json = new String(message.getBody(), StandardCharsets.UTF_8);
  69 + log.info(">>>>>>>>>>接收到ai人物分析消息:{}", json);
  70 + FigureAnalyseResult figureAnalyseResult = JSONUtil.toBean(json, FigureAnalyseResult.class);
  71 + if (StrUtil.isBlank(figureAnalyseResult.getTag())) {
  72 + log.info(">>>>>>>>>>人物分析异常,介制ID为空");
  73 + return;
  74 + }
  75 + Long materialId = Long.valueOf(figureAnalyseResult.getTag());
  76 + Optional<Material> optionalMaterial = materialRepository.findById(materialId);
  77 + if (!optionalMaterial.isPresent()) {
  78 + log.info(">>>>>>>>>>人物分析异常,该介制信息不存在:{}", materialId);
  79 + return;
  80 + }
  81 +
  82 + MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
  83 + if (ObjectUtil.isEmpty(materialInfo)) {
  84 + throw new DefaultException("该介质信息在es中不存在");
  85 + }
  86 + log.info(">>>>>>>>>>介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  87 + //人物分析信息
  88 + List<AiFigure> aiFigureList = new ArrayList<>();
  89 + try {
  90 + if (!"success".equals(figureAnalyseResult.getStatus())) {
  91 + throw new DefaultException(">>>>>>>>>>人物分析异常,返回码:" + figureAnalyseResult.getStatus());
  92 + }
  93 + if ("success".equals(figureAnalyseResult.getStatus())) {
  94 + //修改ai分析状态
  95 + materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.SUCCESS.getCode());
  96 + //解析人物分析文件
  97 + if (StrUtil.isBlank(figureAnalyseResult.getPath())) {
  98 + throw new DefaultException(">>>>>>>>>>人物分析异常,文件路径为空");
  99 + }
  100 + //读取json文件,临时保存
  101 + String jsonPath = filePath + figureAnalyseResult.getPath();
  102 + log.info(">>>>>>>>>>人物分析json文件地址:{}", jsonPath);
  103 + File file = new File(jsonPath);
  104 + if (ObjectUtil.isEmpty(file)) {
  105 + throw new DefaultException(">>>>>>>>>>人物分析异常,下载文件失败");
  106 + }
  107 + JSONObject jsonObject = JSONUtil.readJSONObject(file, StandardCharsets.UTF_8);
  108 + JSONArray jsonArray = jsonObject.getJSONArray("faceDataList");
  109 + if (ObjectUtil.isEmpty(jsonArray)) {
  110 + log.info(">>>>>>>>>>人物分析数据为空");
  111 + return;
  112 + }
  113 + //保存人物分析信息
  114 + for (Object o : jsonArray) {
  115 + VideoFigureData videoFigureData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoFigureData.class);
  116 + for (Slce slce : videoFigureData.getSlces()) {
  117 + AiFigure aiFigure = new AiFigure();
  118 + aiFigure.setMaterialId(materialId);
  119 + aiFigure.setFigureId(Long.valueOf(videoFigureData.getStrangerId()));
  120 + aiFigure.setImagePath(videoFigureData.getImage());
  121 + aiFigure.setBeginTime(slce.getStartTime() + "");
  122 + aiFigure.setEndTime(slce.getEndTime() + "");
  123 + aiFigure.setCreateTime(LocalDateTime.now());
  124 + aiFigureList.add(aiFigure);
  125 + }
  126 + }
  127 +
  128 + //人脸识别信息
  129 + List<FaceInfo> faceInfoList = new ArrayList<>();
  130 + //标签
  131 + Set<String> tagInfoSet = new TreeSet<>();
  132 + for (Object o : jsonArray) {
  133 + VideoFigureData videoFigureData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoFigureData.class);
  134 + FaceInfo faceInfo = new FaceInfo();
  135 + faceInfo.setFigureId(videoFigureData.getStrangerId());
  136 + faceInfo.setFigureName(videoFigureData.getFigureName());
  137 + faceInfo.setFace(videoFigureData.getImage());
  138 + if (ObjectUtil.isNotEmpty(videoFigureData.getFigureName())) {
  139 + tagInfoSet.add(videoFigureData.getFigureName());
  140 + }
  141 + //人物出现时间
  142 + List<Fragment> fragmentList = new ArrayList<>();
  143 + //出现总时长
  144 + AtomicLong totalDuration = new AtomicLong(0);
  145 + for (Slce slce : videoFigureData.getSlces()) {
  146 + Fragment fragment = new Fragment();
  147 + fragment.setStart(slce.getStartTime() + "");
  148 + fragment.setEnd(slce.getEndTime() + "");
  149 + fragmentList.add(fragment);
  150 + totalDuration.getAndAdd(slce.getEndTime() - slce.getStartTime());
  151 + }
  152 + faceInfo.setTotalDuration(totalDuration.longValue());
  153 + //出现率
  154 + BigDecimal appearRate = NumberUtil.div(totalDuration.toString(), materialInfo.getMediaInfo().getDuration() + "", 2).multiply(new BigDecimal("100"));
  155 + faceInfo.setAppearRate(appearRate.stripTrailingZeros().toPlainString() + "%");
  156 + faceInfo.setFragments(fragmentList);
  157 + faceInfoList.add(faceInfo);
  158 + }
  159 + materialInfo.setFaceInfo(faceInfoList);
  160 + materialInfo.getBasicInfo().setTagInfoSet(tagInfoSet);
  161 + } else {
  162 + materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
  163 + }
  164 + MaterialInfo originMaterialInfo = searchFeignService.getMaterialInfoById(materialInfo.getMaterialId()).getResult();
  165 + materialInfo.setWordInfo(originMaterialInfo.getWordInfo());
  166 + } catch (Exception e) {
  167 + e.printStackTrace();
  168 + materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
  169 + } finally {
  170 + //更新es
  171 + materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
  172 + log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  173 + ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
  174 + log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  175 + //保存人物分析信息
  176 + if (CommonStatusEnum.SUCCESS.getCode().equals(materialInfo.getMaterialStatus().getAiAnalysisStatus())) {
  177 + aiFigureRepository.saveAll(aiFigureList);
  178 + }
  179 + }
  180 + }
  181 +}
  1 +package com.wondertek.ivod.cmr.manage.consumer;
  2 +
  3 +import cn.hutool.core.collection.CollectionUtil;
  4 +import cn.hutool.core.date.DateUtil;
  5 +import cn.hutool.core.util.NumberUtil;
  6 +import cn.hutool.core.util.ObjectUtil;
  7 +import cn.hutool.core.util.StrUtil;
  8 +import cn.hutool.json.JSONArray;
  9 +import cn.hutool.json.JSONObject;
  10 +import cn.hutool.json.JSONUtil;
  11 +import com.wondertek.ivod.cmr.commons.enums.CommonStatusEnum;
  12 +import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
  13 +import com.wondertek.ivod.cmr.commons.exception.DefaultException;
  14 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  15 +import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
  16 +import com.wondertek.ivod.cmr.core.entity.bean.VideoFigureData;
  17 +import com.wondertek.ivod.cmr.core.entity.bean.VideoWordsData;
  18 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.FigureAnalyseResult;
  19 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.*;
  20 +import com.wondertek.ivod.cmr.core.entity.model.AiFigure;
  21 +import com.wondertek.ivod.cmr.core.entity.model.Material;
  22 +import com.wondertek.ivod.cmr.manage.feign.SearchFeignService;
  23 +import com.wondertek.ivod.cmr.manage.repository.AiFigureRepository;
  24 +import com.wondertek.ivod.cmr.manage.repository.MaterialRepository;
  25 +import lombok.extern.slf4j.Slf4j;
  26 +import org.springframework.amqp.core.ExchangeTypes;
  27 +import org.springframework.amqp.core.Message;
  28 +import org.springframework.amqp.rabbit.annotation.Exchange;
  29 +import org.springframework.amqp.rabbit.annotation.Queue;
  30 +import org.springframework.amqp.rabbit.annotation.QueueBinding;
  31 +import org.springframework.amqp.rabbit.annotation.RabbitListener;
  32 +import org.springframework.beans.factory.annotation.Autowired;
  33 +import org.springframework.beans.factory.annotation.Value;
  34 +import org.springframework.stereotype.Component;
  35 +
  36 +import java.io.File;
  37 +import java.math.BigDecimal;
  38 +import java.nio.charset.StandardCharsets;
  39 +import java.time.LocalDateTime;
  40 +import java.util.*;
  41 +import java.util.concurrent.atomic.AtomicLong;
  42 +
  43 +/**
  44 + * @Author yubin
  45 + * @Date 2021/8/6 16:21
  46 + */
  47 +@Slf4j
  48 +@Component
  49 +public class WordsConsumer {
  50 + @Autowired
  51 + private SearchFeignService searchFeignService;
  52 + @Autowired
  53 + private MaterialRepository materialRepository;
  54 + @Autowired
  55 + private AiFigureRepository aiFigureRepository;
  56 + @Value("${analyser.filePath}")
  57 + private String filePath;
  58 +
  59 + /**
  60 + * 人物分析
  61 + * 解析ai生成的人脸识别文件,更新信息到es
  62 + *
  63 + * @param message
  64 + */
  65 + @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "${mq.anylzer.ocr.callbackQueue}", durable = "true"),
  66 + exchange = @Exchange(value = "${mq.anylzer.ocr.callbackExchange}", type = ExchangeTypes.TOPIC),
  67 + key = "ocr.video.cloud-media-resources"), concurrency = "5")
  68 + public void figureAnalyse(Message message) {
  69 + String json = new String(message.getBody(), StandardCharsets.UTF_8);
  70 + log.info(">>>>>>>>>>接收到ai文字分析消息:{}", json);
  71 + JSONObject jsonResult = JSONUtil.parseObj(json);
  72 + String dataJson = jsonResult.get("data") + "";
  73 + String jsonPath = filePath + JSONUtil.parseObj(dataJson).get("path");
  74 + Long materialId = Long.valueOf((String) JSONUtil.parseObj(dataJson).get("tag"));
  75 + Optional<Material> optionalMaterial = materialRepository.findById(materialId);
  76 + if (!optionalMaterial.isPresent()) {
  77 + log.info(">>>>>>>>>>人物分析异常,该介制信息不存在:{}", materialId);
  78 + return;
  79 + }
  80 +
  81 + MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
  82 + if (ObjectUtil.isEmpty(materialInfo)) {
  83 + throw new DefaultException("该介质信息在es中不存在");
  84 + }
  85 + log.info(">>>>>>>>>>介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  86 + //文字分析信息
  87 + List<AiFigure> aiFigureList = new ArrayList<>();
  88 + try {
  89 +
  90 +
  91 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  92 + log.info(">>>>>>>>>>文字分析失败" + jsonResult.get("msg"));
  93 + materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.FAIL.getCode());
  94 + } else {
  95 +
  96 + log.info(">>>>>>>>>>人物分析json文件地址:{}", jsonPath);
  97 + File file = new File(jsonPath);
  98 + if (ObjectUtil.isEmpty(file)) {
  99 + throw new DefaultException(">>>>>>>>>>人物分析异常,下载文件失败");
  100 + }
  101 + JSONObject jsonObject = JSONUtil.readJSONObject(file, StandardCharsets.UTF_8);
  102 + JSONArray jsonArray = jsonObject.getJSONArray("data");
  103 + if (ObjectUtil.isEmpty(jsonArray)) {
  104 + log.info(">>>>>>>>>>文字分析数据为空");
  105 + return;
  106 + }
  107 +
  108 + //保存文字分析信息
  109 + for (Object o : jsonArray) {
  110 + VideoWordsData videoWordsData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoWordsData.class);
  111 + AiFigure aiFigure = new AiFigure();
  112 + aiFigure.setMaterialId(materialInfo.getMaterialId());
  113 + aiFigure.setContent(String.join(",", videoWordsData.getContent()));
  114 + aiFigure.setType("2");
  115 + aiFigure.setCreateTime(LocalDateTime.now());
  116 + aiFigure.setBeginTime(videoWordsData.getStart());
  117 + aiFigure.setEndTime(videoWordsData.getEnd());
  118 + aiFigureList.add(aiFigure);
  119 + }
  120 +
  121 + //人脸识别信息
  122 + List<WordInfo> wordInfoList = new ArrayList<>();
  123 + //标签
  124 + Set<String> tagInfoSet = new TreeSet<>();
  125 + for (Object o : jsonArray) {
  126 + VideoWordsData videoWordsData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoWordsData.class);
  127 + WordInfo wordInfo = new WordInfo();
  128 + wordInfo.setWord(String.join(",", videoWordsData.getContent()));
  129 + wordInfo.setStart(videoWordsData.getStart());
  130 + wordInfo.setEnd(videoWordsData.getEnd());
  131 +
  132 + wordInfoList.add(wordInfo);
  133 + }
  134 + materialInfo.setWordInfo(wordInfoList);
  135 + materialInfo.getBasicInfo().setTagInfoSet(tagInfoSet);
  136 + }
  137 + } catch (Exception e) {
  138 + e.printStackTrace();
  139 + materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.FAIL.getCode());
  140 + } finally {
  141 + MaterialInfo originMaterialInfo = searchFeignService.getMaterialInfoById(materialInfo.getMaterialId()).getResult();
  142 + materialInfo.setFaceInfo(originMaterialInfo.getFaceInfo());
  143 + //更新es
  144 + materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
  145 + log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  146 + ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
  147 + log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  148 + //保存ocr分析信息
  149 + if (CommonStatusEnum.SUCCESS.getCode().equals(materialInfo.getMaterialStatus().getOcrAnalysisStatus())) {
  150 + aiFigureRepository.saveAll(aiFigureList);
  151 + }
  152 + }
  153 + }
  154 +}
  1 +package com.wondertek.ivod.cmr.manage.controller;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import com.wondertek.ivod.cmr.commons.utils.FileUtils;
  5 +import com.wondertek.ivod.cmr.commons.utils.PageBean;
  6 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  7 +import com.wondertek.ivod.cmr.core.entity.dto.FigureDeleteDto;
  8 +import com.wondertek.ivod.cmr.core.entity.dto.FigureUpdateDto;
  9 +import com.wondertek.ivod.cmr.core.entity.model.Figure;
  10 +import com.wondertek.ivod.cmr.manage.service.IFigureService;
  11 +import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.data.domain.Page;
  13 +import org.springframework.web.bind.annotation.*;
  14 +import org.springframework.web.multipart.MultipartFile;
  15 +
  16 +/**
  17 + * @Author yubin
  18 + * @Date 2021/9/15 14:09
  19 + */
  20 +@RestController
  21 +@RequestMapping("figure")
  22 +public class FigureController {
  23 + @Autowired
  24 + private IFigureService figureService;
  25 +
  26 + /**
  27 + * 查询人物列表
  28 + *
  29 + * @param keywords
  30 + * @param page
  31 + * @param rows
  32 + * @return
  33 + */
  34 + @GetMapping("/pageList")
  35 + public ResultBean pageList(@RequestParam(required = false) String keywords,
  36 + @RequestParam(defaultValue = "1") int page,
  37 + @RequestParam(defaultValue = "10") int rows) {
  38 + Page<Figure> pages = figureService.pageList(keywords, page, rows);
  39 + return PageBean.ok(pages.getTotalPages(), pages.getTotalElements(), pages.getContent());
  40 + }
  41 +
  42 + /**
  43 + * 人脸相似度匹配
  44 + *
  45 + * @param figureImage
  46 + * @param familiarFigureId
  47 + * @return
  48 + */
  49 + @PostMapping("/similarityMatch")
  50 + public ResultBean similarityMatch(MultipartFile figureImage, String familiarFigureId) {
  51 + if (ObjectUtil.isEmpty(figureImage)) {
  52 + return ResultBean.error("请选择要上传的文件");
  53 + }
  54 + String checkResult = FileUtils.checkImageFile(figureImage);
  55 + if (ObjectUtil.isNotEmpty(checkResult)) {
  56 + return ResultBean.error(checkResult);
  57 + }
  58 + return figureService.similarityMatch(figureImage, familiarFigureId);
  59 + }
  60 +
  61 + /**
  62 + * 添加人物
  63 + *
  64 + * @param figureImage
  65 + * @param figure
  66 + * @return
  67 + */
  68 + @PostMapping("/add")
  69 + public ResultBean add(MultipartFile figureImage, Figure figure) {
  70 + if (ObjectUtil.isEmpty(figureImage) || ObjectUtil.isEmpty(figureImage.getOriginalFilename())) {
  71 + return ResultBean.error("请选择要上传的文件");
  72 + }
  73 + return figureService.add(figureImage, figure);
  74 + }
  75 +
  76 + /**
  77 + * 修改人物
  78 + *
  79 + * @param figureImage
  80 + * @param figureUpdateDto
  81 + * @return
  82 + */
  83 + @PutMapping("/update")
  84 + public ResultBean update(MultipartFile figureImage, FigureUpdateDto figureUpdateDto) {
  85 + if (ObjectUtil.isEmpty(figureUpdateDto.getId())) {
  86 + return ResultBean.error("id不能为空");
  87 + }
  88 + return figureService.update(figureImage, figureUpdateDto);
  89 + }
  90 +
  91 + /**
  92 + * 批量删除人物
  93 + *
  94 + * @param figureDeleteDto
  95 + * @return
  96 + */
  97 + @DeleteMapping("/batchDelete")
  98 + public ResultBean batchDelete(@RequestBody FigureDeleteDto figureDeleteDto) {
  99 + if (ObjectUtil.isEmpty(figureDeleteDto.getFigureIds())) {
  100 + return ResultBean.error("请选择要删除的人物");
  101 + }
  102 + figureService.batchDelete(figureDeleteDto.getFigureIds());
  103 + return ResultBean.ok();
  104 + }
  105 +
  106 + /**
  107 + * 人物ID唯一校验
  108 + *
  109 + * @param id
  110 + * @param figureDefineId
  111 + * @return
  112 + */
  113 + @GetMapping("/checkOnlyDefineId")
  114 + public ResultBean checkOnlyDefineId(@RequestParam(required = false) Long id, @RequestParam String figureDefineId) {
  115 + if (ObjectUtil.isEmpty(figureDefineId)) {
  116 + return ResultBean.error("人物ID必传");
  117 + }
  118 + return ResultBean.ok(figureService.checkOnlyDefineId(id, figureDefineId));
  119 + }
  120 +}
  1 +package com.wondertek.ivod.cmr.manage.controller;
  2 +
  3 +import cn.hutool.core.collection.CollectionUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import com.wondertek.ivod.cmr.commons.utils.FileUtils;
  6 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  7 +import com.wondertek.ivod.cmr.core.entity.dto.*;
  8 +import com.wondertek.ivod.cmr.core.entity.model.Material;
  9 +import com.wondertek.ivod.cmr.manage.service.IMaterialService;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.web.bind.annotation.*;
  12 +import org.springframework.web.multipart.MultipartFile;
  13 +
  14 +
  15 +/**
  16 + * @Author yubin
  17 + * @Date 2021/8/3 15:18
  18 + */
  19 +@RestController
  20 +@RequestMapping("material")
  21 +public class MaterialController {
  22 + @Autowired
  23 + private IMaterialService materialService;
  24 +
  25 + /**
  26 + * 介质上传
  27 + *
  28 + * @param materialFile
  29 + * @param materialAddDto
  30 + * @return
  31 + */
  32 + @PostMapping("/upload")
  33 + public ResultBean uploadFiles(MultipartFile materialFile, MaterialAddDto materialAddDto) {
  34 + if (ObjectUtil.isEmpty(materialFile)) {
  35 + return ResultBean.error("请选择要上传的文件");
  36 + }
  37 + String checkResult = FileUtils.checkFile(materialFile);
  38 + if (ObjectUtil.isNotEmpty(checkResult)) {
  39 + return ResultBean.error(checkResult);
  40 + }
  41 + if (ObjectUtil.isEmpty(materialAddDto.getName())) {
  42 + return ResultBean.error("媒资名称必传");
  43 + }
  44 + if (materialAddDto.getName().substring(0, materialAddDto.getName().lastIndexOf(".")).length() > 30) {
  45 + return ResultBean.error("文件名称不能大于30个字符");
  46 + }
  47 + if (ObjectUtil.isEmpty(materialAddDto.getIsOpenAi())) {
  48 + return ResultBean.error("是否开启AI智能识别必传");
  49 + }
  50 + return materialService.uploadFile(materialFile, materialAddDto);
  51 + }
  52 +
  53 + /**
  54 + * 重新下发AI分析
  55 + *
  56 + * @param aiAnalysisDto
  57 + * @return
  58 + */
  59 + @PostMapping("/aiAnalysis")
  60 + public ResultBean aiAnalysis(@RequestBody AiAnalysisDto aiAnalysisDto) {
  61 + if (ObjectUtil.isEmpty(aiAnalysisDto.getMaterialIds())) {
  62 + return ResultBean.error("请选择要AI分析的媒资");
  63 + }
  64 + materialService.aiAnalysis(aiAnalysisDto.getMaterialIds());
  65 + return ResultBean.ok();
  66 + }
  67 +
  68 + /**
  69 + * 修改名称
  70 + *
  71 + * @param material
  72 + * @return
  73 + */
  74 + @PutMapping("/update")
  75 + public ResultBean updateMaterial(@RequestBody Material material) {
  76 + if (ObjectUtil.isEmpty(material.getMaterialId())) {
  77 + return ResultBean.error("媒资id不能为空");
  78 + }
  79 + if (ObjectUtil.isEmpty(material.getName())) {
  80 + return ResultBean.error("文件名不能为空");
  81 + }
  82 + if (material.getName().substring(0, material.getName().lastIndexOf(".")).length() > 30) {
  83 + return ResultBean.error("文件名称不能大于30个字符");
  84 + }
  85 + materialService.updateMaterial(material.getMaterialId(), material.getName());
  86 + return ResultBean.ok();
  87 + }
  88 +
  89 + @PutMapping("/updateLabel")
  90 + public ResultBean batchUpdateCustomLabel(@RequestBody MaterialCustomLabelDto materialCustomLabelDto) {
  91 + if (ObjectUtil.isEmpty(materialCustomLabelDto.getCustomLabel())) {
  92 + return ResultBean.error("自定义标签不能为空");
  93 + }
  94 + if (CollectionUtil.isEmpty(materialCustomLabelDto.getMaterialIds())) {
  95 + return ResultBean.error("媒资ID不能为空");
  96 + }
  97 + materialService.updateMaterialCustomLable(materialCustomLabelDto.getMaterialIds(), materialCustomLabelDto.getCustomLabel());
  98 + return ResultBean.ok();
  99 + }
  100 +
  101 + /**
  102 + * 删除
  103 + *
  104 + * @param materialDeleteDto
  105 + * @return
  106 + */
  107 + @DeleteMapping("/delete")
  108 + public ResultBean deleteMaterails(@RequestBody MaterialDeleteDto materialDeleteDto) {
  109 + if (ObjectUtil.isEmpty(materialDeleteDto.getMaterialIds())) {
  110 + return ResultBean.error("请选择要删除的媒资");
  111 + }
  112 + materialService.deleteMaterails(materialDeleteDto);
  113 + return ResultBean.ok();
  114 + }
  115 +
  116 + /**
  117 + * 检索图片分析
  118 + *
  119 + * @param analysisPictureDto
  120 + * @return
  121 + */
  122 + @PostMapping("/analysisPicture")
  123 + public ResultBean analysisPicture(@RequestBody AnalysisPictureDto analysisPictureDto) {
  124 + if (ObjectUtil.isEmpty(analysisPictureDto.getImageBase64())) {
  125 + return ResultBean.error("检索图片必传");
  126 + }
  127 + return ResultBean.ok(materialService.analysisPicture(analysisPictureDto.getImageBase64()));
  128 + }
  129 +
  130 + /**
  131 + * 注入接口
  132 + *
  133 + * @param materialInjectDto
  134 + * @return
  135 + */
  136 + @PostMapping("/inject")
  137 + public ResultBean inject(@RequestBody MaterialInjectDto materialInjectDto) {
  138 + if (ObjectUtil.isEmpty(materialInjectDto.getSource())) {
  139 + return ResultBean.error("来源必传");
  140 + }
  141 + if (ObjectUtil.isEmpty(materialInjectDto.getMaterialInfos())) {
  142 + return ResultBean.error("媒资信息为空");
  143 + }
  144 + if (ObjectUtil.isEmpty(materialInjectDto.getUserId())) {
  145 + return ResultBean.error("用户id必传");
  146 + }
  147 + if (ObjectUtil.isEmpty(materialInjectDto.getUserName())) {
  148 + return ResultBean.error("用户名必传");
  149 + }
  150 + if (ObjectUtil.isEmpty(materialInjectDto.getTenantId())) {
  151 + return ResultBean.error("租户id必传");
  152 + }
  153 + return ResultBean.ok(materialService.inject(materialInjectDto));
  154 + }
  155 +}
  1 +package com.wondertek.ivod.cmr.manage.controller;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  4 +import com.wondertek.ivod.cmr.manage.service.IMaterialOperateRecordService;
  5 +import org.springframework.web.bind.annotation.GetMapping;
  6 +import org.springframework.web.bind.annotation.RequestMapping;
  7 +import org.springframework.web.bind.annotation.RequestParam;
  8 +import org.springframework.web.bind.annotation.RestController;
  9 +
  10 +import javax.annotation.Resource;
  11 +
  12 +/**
  13 + * @author xh
  14 + * @date 2023/9/18 11:07
  15 + */
  16 +@RestController
  17 +@RequestMapping("/record")
  18 +public class OperateRecordController {
  19 + @Resource
  20 + private IMaterialOperateRecordService iMaterialOperateRecordService;
  21 +
  22 + @GetMapping("/add")
  23 + public void add(@RequestParam String operateType,
  24 + @RequestParam String objectId) {
  25 + iMaterialOperateRecordService.saveOperateRecord(operateType, objectId);
  26 + }
  27 +
  28 + @GetMapping("/getCount")
  29 + public ResultBean getCount(@RequestParam String objectId) {
  30 + return iMaterialOperateRecordService.getCount(objectId);
  31 + }
  32 +
  33 + @GetMapping("/list")
  34 + public ResultBean pageList(@RequestParam(required = false) String objectId,
  35 + @RequestParam(defaultValue = "1") int page,
  36 + @RequestParam(defaultValue = "10") int rows) {
  37 + return iMaterialOperateRecordService.list(objectId, page, rows);
  38 + }
  39 +
  40 +}
  1 +package com.wondertek.ivod.cmr.manage.feign;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  4 +import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
  5 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
  6 +import org.springframework.cloud.openfeign.FeignClient;
  7 +import org.springframework.stereotype.Component;
  8 +import org.springframework.web.bind.annotation.*;
  9 +
  10 +import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +/**
  14 + * @Author yubin
  15 + * @Date 2021/8/6 15:40
  16 + * <p>
  17 + * es搜索
  18 + */
  19 +@Component
  20 +@FeignClient(name = "cmr-search", url = "http://cmr-search:18667")
  21 +public interface SearchFeignService {
  22 + /**
  23 + * 新建介质
  24 + *
  25 + * @param materialInfo
  26 + * @return
  27 + */
  28 + @PostMapping("/cmr-search/es/materialInfo/create")
  29 + ResultBean createMaterialInfo(@RequestBody MaterialInfo materialInfo);
  30 +
  31 + /**
  32 + * 修改介质
  33 + *
  34 + * @param materialInfo
  35 + * @return
  36 + */
  37 + @PutMapping("/cmr-search/es/materialInfo/update")
  38 + ResultBean updateMaterialInfo(@RequestBody MaterialInfo materialInfo);
  39 +
  40 + /**
  41 + * 批量删除介质
  42 + *
  43 + * @param materialDeleteDto
  44 + * @return
  45 + */
  46 + @DeleteMapping("/cmr-search/es/materialInfo/deleteInfos")
  47 + ResultBean deleteInfos(@RequestBody MaterialDeleteDto materialDeleteDto);
  48 +
  49 + /**
  50 + * 通过ID查询介质
  51 + *
  52 + * @param materialId
  53 + * @return
  54 + */
  55 + @GetMapping("/cmr-search/es/materialInfo/getById")
  56 + ResultBean<MaterialInfo> getMaterialInfoById(@RequestParam Long materialId);
  57 +
  58 + /**
  59 + * 批量查询
  60 + *
  61 + * @param map
  62 + * @return
  63 + */
  64 + @PostMapping("/cmr-search/material/getByIds")
  65 + ResultBean<List<MaterialInfo>> getByIds(@RequestBody Map<String, List<Long>> map);
  66 +}
  1 +package com.wondertek.ivod.cmr.manage.feign.fallback;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  4 +import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
  5 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
  6 +import com.wondertek.ivod.cmr.manage.feign.SearchFeignService;
  7 +import feign.hystrix.FallbackFactory;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +
  14 +/**
  15 + * @Author yubin
  16 + * @Date 2021/8/11 15:32
  17 + */
  18 +@Component
  19 +public class SearchFeignFallBack implements FallbackFactory<SearchFeignService> {
  20 + @Override
  21 + public SearchFeignService create(Throwable throwable) {
  22 + return new SearchFeignService() {
  23 + @Override
  24 + public ResultBean createMaterialInfo(MaterialInfo materialInfo) {
  25 + return ResultBean.error("调用熔断了");
  26 + }
  27 +
  28 + @Override
  29 + public ResultBean updateMaterialInfo(MaterialInfo materialInfo) {
  30 + return ResultBean.error("调用熔断了");
  31 + }
  32 +
  33 + @Override
  34 + public ResultBean deleteInfos(MaterialDeleteDto materialDeleteDto) {
  35 + return ResultBean.error("调用熔断了");
  36 + }
  37 +
  38 + @Override
  39 + public ResultBean<MaterialInfo> getMaterialInfoById(Long materialId) {
  40 + return ResultBean.error("调用熔断了");
  41 + }
  42 +
  43 + @Override
  44 + public ResultBean<List<MaterialInfo>> getByIds(Map<String, List<Long>> map) {
  45 + return null;
  46 + }
  47 + };
  48 + }
  49 +}
  1 +package com.wondertek.ivod.cmr.manage.repository;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.model.AiFigure;
  4 +import org.springframework.data.jpa.repository.JpaRepository;
  5 +import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  6 +import org.springframework.data.jpa.repository.Modifying;
  7 +import org.springframework.data.jpa.repository.Query;
  8 +import org.springframework.transaction.annotation.Transactional;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * @Author yubin
  14 + * @Date 2021/8/11 14:27
  15 + */
  16 +public interface AiFigureRepository extends JpaRepository<AiFigure, Long>, JpaSpecificationExecutor<AiFigure> {
  17 + @Modifying
  18 + @Transactional
  19 + @Query("delete from AiFigure a where a.materialId in :materialIds")
  20 + void deleteByMaterialIds(List<Long> materialIds);
  21 +}
  1 +package com.wondertek.ivod.cmr.manage.repository;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.model.Figure;
  4 +import org.springframework.data.jpa.repository.JpaRepository;
  5 +import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/11 14:26
  10 + */
  11 +public interface FigureRepository extends JpaRepository<Figure, Long>, JpaSpecificationExecutor<Figure> {
  12 + /**
  13 + * 根据熟人id删除
  14 + *
  15 + * @param familiarFigureId
  16 + */
  17 + void deleteByFamiliarFigureId(String familiarFigureId);
  18 +
  19 + /**
  20 + * 根据人物自定义id查询
  21 + *
  22 + * @param figureDefineId
  23 + * @return
  24 + */
  25 + Figure findByFigureDefineId(String figureDefineId);
  26 +}
  1 +package com.wondertek.ivod.cmr.manage.repository;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.model.ImageDetail;
  4 +import org.springframework.data.jpa.repository.JpaRepository;
  5 +import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  6 +import org.springframework.data.jpa.repository.Modifying;
  7 +import org.springframework.data.jpa.repository.Query;
  8 +import org.springframework.stereotype.Repository;
  9 +import org.springframework.transaction.annotation.Transactional;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * @author xh
  15 + * @date 2023/9/18 15:17
  16 + */
  17 +@Repository
  18 +public interface ImageDetailRepository extends JpaRepository<ImageDetail, Long>, JpaSpecificationExecutor<ImageDetail> {
  19 +
  20 + @Modifying
  21 + @Transactional
  22 + @Query("delete from ImageDetail a where a.materialId in :materialIds")
  23 + void deleteByMaterialIds(List<Long> materialIds);
  24 +}
  1 +package com.wondertek.ivod.cmr.manage.repository;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.model.Material;
  4 +import com.wondertek.ivod.cmr.core.entity.model.MaterialFiles;
  5 +import org.springframework.data.jpa.repository.JpaRepository;
  6 +import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  7 +import org.springframework.data.jpa.repository.Modifying;
  8 +import org.springframework.data.jpa.repository.Query;
  9 +import org.springframework.transaction.annotation.Transactional;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * @Author yubin
  15 + * @Date 2021/8/11 14:25
  16 + */
  17 +public interface MaterialFilesRepository extends JpaRepository<MaterialFiles, Long>, JpaSpecificationExecutor<MaterialFiles> {
  18 + @Modifying
  19 + @Transactional
  20 + @Query("delete from MaterialFiles m where m.materialId in :materialIds")
  21 + void deleteByMaterialIds(List<Long> materialIds);
  22 +}
  1 +package com.wondertek.ivod.cmr.manage.repository;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.model.Material;
  4 +import org.springframework.data.jpa.repository.JpaRepository;
  5 +import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/3 15:43
  10 + */
  11 +public interface MaterialRepository extends JpaRepository<Material, Long>, JpaSpecificationExecutor<Material> {
  12 +}
  1 +package com.wondertek.ivod.cmr.manage.repository;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.model.OperateRecord;
  4 +import org.springframework.data.jpa.repository.JpaRepository;
  5 +import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  6 +import org.springframework.stereotype.Repository;
  7 +
  8 +/**
  9 + * @author xh
  10 + * @date 2023/9/18 11:03
  11 + */
  12 +@Repository
  13 +public interface OperateRecordRepository extends JpaRepository<OperateRecord, Long>, JpaSpecificationExecutor<OperateRecord> {
  14 +
  15 + /**
  16 + * 根据操作对象id查询记录
  17 + * @param operateObjectId
  18 + * @return
  19 + */
  20 + OperateRecord findFirstByOperateObjectIdOrderByCreatedTimeDesc(String operateObjectId);
  21 +}
  1 +package com.wondertek.ivod.cmr.manage.service;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.model.ImageDetail;
  4 +
  5 +/**
  6 + * @author xh
  7 + * @date 2023/9/18 14:09
  8 + */
  9 +public interface ExtractImageDetailService {
  10 + /**
  11 + * 提取图片信息
  12 + * @param imagePath
  13 + */
  14 + ImageDetail extractImageDetail(String imagePath, Long materialId);
  15 +}
  1 +package com.wondertek.ivod.cmr.manage.service;
  2 +
  3 +
  4 +/**
  5 + * @Author yubin
  6 + * @Date 2021/8/9 13:46
  7 + */
  8 +public interface IAiFigureService {
  9 +}
  1 +package com.wondertek.ivod.cmr.manage.service;
  2 +
  3 +import cn.hutool.json.JSONObject;
  4 +import org.springframework.web.multipart.MultipartFile;
  5 +
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * @Author yubin
  10 + * @Date 2021/9/17 15:14
  11 + * <p>
  12 + * 分析器相关调用
  13 + */
  14 +public interface IAnalyserService {
  15 + /**
  16 + * 上传文件到分析器
  17 + *
  18 + * @param materialFile
  19 + * @return
  20 + */
  21 + JSONObject uploadFile(MultipartFile materialFile);
  22 +
  23 + /**
  24 + * 分析器批量删除
  25 + *
  26 + * @param fileIdList 文件id列表
  27 + * @return
  28 + */
  29 + JSONObject deletefileBatch(List<String> fileIdList);
  30 +
  31 + /**
  32 + * 图片分析
  33 + *
  34 + * @param tag 唯一标识
  35 + * @param fileId 文件id
  36 + * @param relativePath 绝对路径
  37 + * @return
  38 + */
  39 + JSONObject pictureAnalysis(String tag, String fileId, String relativePath);
  40 +
  41 + JSONObject pictureAnalysisToWords(String tag, String fileId, String relativePath);
  42 +
  43 + /**
  44 + * 熟人与人脸一起添加(新增或更新)
  45 + *
  46 + * @param figureImage 人脸
  47 + * @param name 名字
  48 + * @param gender 性别 0-女 1-男
  49 + * @param familiarFigureId 熟人id,为空则创建一个新人物,否则为该ID人物添加人脸
  50 + * @return
  51 + */
  52 + JSONObject addOrUpdateFigureAndFace(MultipartFile figureImage, String name, Integer gender, String familiarFigureId);
  53 +
  54 + /**
  55 + * 删除熟人(多个用“,”分隔)
  56 + *
  57 + * @param familiarFigureIds
  58 + * @return
  59 + */
  60 + JSONObject deleteFigure(String familiarFigureIds);
  61 +
  62 + /**
  63 + * 人脸相似度匹配
  64 + *
  65 + * @param figureImage
  66 + * @return
  67 + */
  68 + JSONObject similarityMatch(MultipartFile figureImage);
  69 +
  70 + /**
  71 + * 删除熟人所有人脸
  72 + *
  73 + * @param familiarFigureId 熟人id。多个用逗号隔开
  74 + * @return
  75 + */
  76 + JSONObject deleteFigureAllFace(String familiarFigureId);
  77 +
  78 + /**
  79 + * 修改熟人
  80 + *
  81 + * @param name 名称
  82 + * @param gender 性别 0-女 1-男
  83 + * @param familiarFigureId 熟人id
  84 + * @return
  85 + */
  86 + JSONObject updateFigure(String name, Integer gender, String familiarFigureId);
  87 +
  88 + /**
  89 + * 图片查陌生人
  90 + *
  91 + * @param imageBase64
  92 + * @return
  93 + */
  94 + JSONObject getPictureAnalysisResult(String imageBase64);
  95 +
  96 + /**
  97 + * 根据特征值查熟人
  98 + *
  99 + * @param feature
  100 + * @return
  101 + */
  102 + JSONObject getFigureByFeature(String feature);
  103 +
  104 +}
  1 +package com.wondertek.ivod.cmr.manage.service;
  2 +
  3 +
  4 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  5 +import com.wondertek.ivod.cmr.core.entity.dto.FigureUpdateDto;
  6 +import com.wondertek.ivod.cmr.core.entity.model.Figure;
  7 +import org.springframework.data.domain.Page;
  8 +import org.springframework.web.multipart.MultipartFile;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * @Author yubin
  14 + * @Date 2021/8/9 14:47
  15 + */
  16 +public interface IFigureService {
  17 + /**
  18 + * 查询人物列表
  19 + *
  20 + * @param keywords
  21 + * @param page
  22 + * @param rows
  23 + * @return
  24 + */
  25 + Page<Figure> pageList(String keywords, int page, int rows);
  26 +
  27 + /**
  28 + * 人脸相似度匹配
  29 + *
  30 + * @param figureImage
  31 + * @param familiarFigureId
  32 + * @return
  33 + */
  34 + ResultBean similarityMatch(MultipartFile figureImage, String familiarFigureId);
  35 +
  36 + /**
  37 + * 添加人物
  38 + *
  39 + * @param figureImage
  40 + * @param figure
  41 + * @return
  42 + */
  43 + ResultBean add(MultipartFile figureImage, Figure figure);
  44 +
  45 + /**
  46 + * 修改人物
  47 + *
  48 + * @param figureImage
  49 + * @param figureUpdateDto
  50 + * @return
  51 + */
  52 + ResultBean update(MultipartFile figureImage, FigureUpdateDto figureUpdateDto);
  53 +
  54 + /**
  55 + * 批量删除人物
  56 + *
  57 + * @param figureIds
  58 + * @return
  59 + */
  60 + void batchDelete(List<Long> figureIds);
  61 +
  62 + /**
  63 + * 人物ID唯一校验
  64 + *
  65 + * @param id
  66 + * @param figureDefineId
  67 + * @return
  68 + */
  69 + Boolean checkOnlyDefineId(Long id, String figureDefineId);
  70 +}
  1 +package com.wondertek.ivod.cmr.manage.service;
  2 +
  3 +
  4 +import cn.hutool.json.JSONObject;
  5 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialInfoDto;
  6 +import com.wondertek.ivod.cmr.core.entity.model.MaterialFiles;
  7 +import org.springframework.web.multipart.MultipartFile;
  8 +
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * @Author yubin
  13 + * @Date 2021/8/4 16:20
  14 + */
  15 +public interface IMaterialFilesService {
  16 + MaterialFiles createMaterialFiles(MaterialInfoDto materialInfoDto);
  17 +}
  1 +package com.wondertek.ivod.cmr.manage.service;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  4 +
  5 +/**
  6 + * @author xh
  7 + * @date 2023/9/18 10:46
  8 + */
  9 +public interface IMaterialOperateRecordService {
  10 + /**
  11 + * 保存操作记录
  12 + * @param type 1-下载 2-浏览
  13 + * @param objectId 操作对象id
  14 + */
  15 + void saveOperateRecord(String type, String objectId);
  16 +
  17 + /**
  18 + * 查询记录列表
  19 + * @param objectId
  20 + * @param page
  21 + * @param rows
  22 + * @return
  23 + */
  24 + ResultBean list(String objectId, int page, int rows);
  25 +
  26 + /**
  27 + * 统计预览、下载次数
  28 + * @param objectId
  29 + * @return
  30 + */
  31 + ResultBean getCount(String objectId);
  32 +}
  1 +package com.wondertek.ivod.cmr.manage.service;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  4 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialAddDto;
  5 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
  6 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialInjectDto;
  7 +import com.wondertek.ivod.cmr.core.entity.vo.PictureAnalysisVo;
  8 +import org.springframework.web.multipart.MultipartFile;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * @Author yubin
  14 + * @Date 2021/8/3 15:41
  15 + */
  16 +public interface IMaterialService {
  17 + ResultBean uploadFile(MultipartFile materialFile, MaterialAddDto materialAddDto);
  18 +
  19 + void aiAnalysis(List<Long> materialIds);
  20 +
  21 + List<Long> inject(MaterialInjectDto materialInjectDto);
  22 +
  23 + void updateMaterial(Long materialId, String name);
  24 +
  25 + void updateMaterialCustomLable(List<Long> materialIds, String customLabels);
  26 +
  27 + void deleteMaterails(MaterialDeleteDto materialDeleteDto);
  28 +
  29 + PictureAnalysisVo analysisPicture(String imageBase64);
  30 +}
  1 +package com.wondertek.ivod.cmr.manage.service.impl;
  2 +
  3 +import com.wondertek.ivod.cmr.manage.service.IAiFigureService;
  4 +import org.springframework.stereotype.Service;
  5 +
  6 +/**
  7 + * @Author yubin
  8 + * @Date 2021/8/9 13:47
  9 + */
  10 +@Service
  11 +public class AiFigureServiceImpl implements IAiFigureService {
  12 +}
  1 +package com.wondertek.ivod.cmr.manage.service.impl;
  2 +
  3 +import cn.hutool.json.JSONObject;
  4 +import cn.hutool.json.JSONUtil;
  5 +import com.wondertek.ivod.cmr.commons.utils.FileUtils;
  6 +import com.wondertek.ivod.cmr.commons.utils.UserUtils;
  7 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.FileInfoToMq;
  8 +import com.wondertek.ivod.cmr.manage.service.IAnalyserService;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.beans.factory.annotation.Value;
  12 +import org.springframework.core.io.FileSystemResource;
  13 +import org.springframework.http.*;
  14 +import org.springframework.stereotype.Service;
  15 +import org.springframework.util.LinkedMultiValueMap;
  16 +import org.springframework.util.MultiValueMap;
  17 +import org.springframework.web.client.RestTemplate;
  18 +import org.springframework.web.multipart.MultipartFile;
  19 +
  20 +import java.io.File;
  21 +import java.util.HashMap;
  22 +import java.util.List;
  23 +import java.util.Map;
  24 +
  25 +/**
  26 + * @Author yubin
  27 + * @Date 2021/9/17 15:15
  28 + */
  29 +@Slf4j
  30 +@Service
  31 +public class AnalyserServiceImpl implements IAnalyserService {
  32 + @Autowired
  33 + private RestTemplate restTemplate;
  34 + @Value("${analyser.namespace}")
  35 + private String namespace;
  36 + @Value("${analyser.uploadUrl}")
  37 + private String uploadUrl;
  38 + @Value("${analyser.fileBatchDeleteUrl}")
  39 + private String fileBatchDeleteUrl;
  40 + @Value("${analyser.pictureAnalysisUrl}")
  41 + private String pictureAnalysisUrl;
  42 + @Value("${analyser.similarityMatchUrl}")
  43 + private String similarityMatchUrl;
  44 + @Value("${analyser.deleteFigureUrl}")
  45 + private String deleteFigureUrl;
  46 + @Value("${analyser.figureFaceUrl}")
  47 + private String figureFaceUrl;
  48 + @Value("${analyser.deleteFigureFaceUrl}")
  49 + private String deleteFigureFaceUrl;
  50 + @Value("${analyser.updateFigureUrl}")
  51 + private String updateFigureUrl;
  52 + @Value("${analyser.picturePersonUrl}")
  53 + private String picturePersonUrl;
  54 + @Value("${analyser.feature2figureUrl}")
  55 + private String feature2figureUrl;
  56 + @Value("${analyser.pictureAnalysisToWordsUrl}")
  57 + private String pictureAnalysisToWordsUrl;
  58 +
  59 + @Override
  60 + public JSONObject uploadFile(MultipartFile materialFile) {
  61 + File file = null;
  62 + try {
  63 + //调用存储云存储文件
  64 + HttpHeaders headers = new HttpHeaders();
  65 + headers.setContentType(MediaType.MULTIPART_FORM_DATA);
  66 + MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
  67 + map.set("namespace", namespace);
  68 + map.set("userId", UserUtils.getUser().getTenantId());
  69 + file = FileUtils.multipartFileToFile(materialFile);
  70 + map.set("file", new FileSystemResource(file));
  71 + HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
  72 + log.info(">>>>>>>>>>开始调用分析器上传接口:{}", JSONUtil.toJsonStr(map));
  73 + Object result = restTemplate.postForObject(uploadUrl, request, Object.class);
  74 + log.info(">>>>>>>>>>调用分析器上传接口结果:{}", JSONUtil.toJsonStr(result));
  75 + return JSONUtil.parseObj(result);
  76 + } finally {
  77 + FileUtils.delteTempFile(file);
  78 + }
  79 + }
  80 +
  81 + @Override
  82 + public JSONObject deletefileBatch(List<String> fileIdList) {
  83 + Map<String, Object> fileMap = new HashMap<>();
  84 + fileMap.put("fileIds", fileIdList);
  85 + fileMap.put("namespace", namespace);
  86 + fileMap.put("userId", UserUtils.getUser().getTenantId());
  87 + log.info(">>>>>>>>>>调用分析器删除文件接口:{}", JSONUtil.toJsonStr(fileMap));
  88 + Object result = restTemplate.postForObject(fileBatchDeleteUrl, fileMap, Object.class);
  89 + log.info(">>>>>>>>>>调用分析器删除文件接口结果:{}", JSONUtil.toJsonStr(result));
  90 + return JSONUtil.parseObj(result);
  91 + }
  92 +
  93 + /**
  94 + * @param tag
  95 + * @param fileId
  96 + * @param relativePath
  97 + * @return
  98 + */
  99 + @Override
  100 + public JSONObject pictureAnalysis(String tag, String fileId, String relativePath) {
  101 + FileInfoToMq fileInfoToMq = new FileInfoToMq();
  102 + fileInfoToMq.setTag(tag);
  103 + fileInfoToMq.setFileId(fileId);
  104 + fileInfoToMq.setRelativePath(relativePath);
  105 + fileInfoToMq.setNamespace(namespace);
  106 + fileInfoToMq.setUserId(UserUtils.getUser().getTenantId());
  107 + log.info(">>>>>>>>>>开始调用分析器图片分析接口:{}", JSONUtil.toJsonStr(fileInfoToMq));
  108 + Object result = restTemplate.postForObject(pictureAnalysisUrl, fileInfoToMq, Object.class);
  109 + log.info(">>>>>>>>>>调用分析器图片分析接口结果:{}", JSONUtil.toJsonStr(result));
  110 + return JSONUtil.parseObj(result);
  111 + }
  112 +
  113 + /**
  114 + * @param tag
  115 + * @param fileId
  116 + * @param relativePath
  117 + * @return
  118 + */
  119 + @Override
  120 + public JSONObject pictureAnalysisToWords(String tag, String fileId, String relativePath) {
  121 + FileInfoToMq fileInfoToMq = new FileInfoToMq();
  122 + fileInfoToMq.setTag(tag);
  123 + fileInfoToMq.setFileId(fileId);
  124 + fileInfoToMq.setRelativePath(relativePath);
  125 + fileInfoToMq.setNamespace(namespace);
  126 + fileInfoToMq.setUserId(UserUtils.getUser().getTenantId());
  127 + fileInfoToMq.setPath(relativePath);
  128 + log.info(">>>>>>>>>>开始调用分析器图片分析接口:{}", JSONUtil.toJsonStr(fileInfoToMq));
  129 + Object result = restTemplate.postForObject(pictureAnalysisToWordsUrl, fileInfoToMq, Object.class);
  130 + log.info(">>>>>>>>>>调用分析器图片分析接口结果:{}", JSONUtil.toJsonStr(result));
  131 + return JSONUtil.parseObj(result);
  132 + }
  133 +
  134 + /**
  135 + * 熟人与人脸一起添加(新增或更新)
  136 + *
  137 + * @param figureImage 人脸
  138 + * @param name 名字
  139 + * @param gender 性别
  140 + * @param familiarFigureId 熟人id,为空则创建一个新人物,否则为该ID人物添加人脸
  141 + * @return
  142 + */
  143 + @Override
  144 + public JSONObject addOrUpdateFigureAndFace(MultipartFile figureImage, String name, Integer gender, String familiarFigureId) {
  145 + File file = null;
  146 + try {
  147 + HttpHeaders headers = new HttpHeaders();
  148 + headers.setContentType(MediaType.MULTIPART_FORM_DATA);
  149 + MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
  150 + map.set("namespace", namespace);
  151 + map.set("userId", UserUtils.getUser().getTenantId());
  152 + map.set("name", name);
  153 + map.set("gender", gender);
  154 + file = FileUtils.multipartFileToFile(figureImage);
  155 + map.set("faceImages", new FileSystemResource(file));
  156 + map.set("familiarFigureId", familiarFigureId);
  157 + HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
  158 + log.info(">>>>>>>>>>开始调用分析器熟人与人脸一起添加(新增或更新)接口:{}", JSONUtil.toJsonStr(map));
  159 + ResponseEntity resultEntity = restTemplate.exchange(figureFaceUrl, HttpMethod.PUT, request, Object.class);
  160 + Object result = resultEntity.getBody();
  161 + log.info(">>>>>>>>>>调用分析器熟人与人脸一起添加(新增或更新)结果:{}", JSONUtil.toJsonStr(result));
  162 + return JSONUtil.parseObj(result);
  163 + } finally {
  164 + FileUtils.delteTempFile(file);
  165 + }
  166 + }
  167 +
  168 + /**
  169 + * 删除熟人(多个用“,”分隔)
  170 + *
  171 + * @param familiarFigureIds
  172 + * @return
  173 + */
  174 + @Override
  175 + public JSONObject deleteFigure(String familiarFigureIds) {
  176 + HttpHeaders headers = new HttpHeaders();
  177 + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
  178 + MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
  179 + map.set("namespace", namespace);
  180 + map.set("userId", UserUtils.getUser().getTenantId());
  181 + map.set("familiarFigureId", familiarFigureIds);
  182 + HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
  183 + log.info(">>>>>>>>>>开始调用分析器删除熟人接口:{}", JSONUtil.toJsonStr(map));
  184 + ResponseEntity resultEntity = restTemplate.exchange(deleteFigureUrl, HttpMethod.DELETE, request, Object.class);
  185 + Object result = resultEntity.getBody();
  186 + log.info(">>>>>>>>>>调用分析器删除熟人接口结果:{}", JSONUtil.toJsonStr(result));
  187 + return JSONUtil.parseObj(result);
  188 + }
  189 +
  190 + /**
  191 + * 人脸相似度匹配
  192 + *
  193 + * @param figureImage
  194 + * @return
  195 + */
  196 + @Override
  197 + public JSONObject similarityMatch(MultipartFile figureImage) {
  198 + File file = null;
  199 + try {
  200 + HttpHeaders headers = new HttpHeaders();
  201 + headers.setContentType(MediaType.MULTIPART_FORM_DATA);
  202 + MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
  203 + map.set("namespace", namespace);
  204 + map.set("userId", UserUtils.getUser().getTenantId());
  205 + file = FileUtils.multipartFileToFile(figureImage);
  206 + map.set("faceImage", new FileSystemResource(file));
  207 + HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
  208 + log.info(">>>>>>>>>>开始调用分析器熟人库图片相似度查询接口:{}", JSONUtil.toJsonStr(map));
  209 + Object result = restTemplate.postForObject(similarityMatchUrl, request, Object.class);
  210 + log.info(">>>>>>>>>>调用分析器熟人库图片相似度查询接口结果:{}", JSONUtil.toJsonStr(result));
  211 + return JSONUtil.parseObj(result);
  212 + } finally {
  213 + FileUtils.delteTempFile(file);
  214 + }
  215 + }
  216 +
  217 + /**
  218 + * 删除熟人人脸
  219 + *
  220 + * @param familiarFigureId
  221 + * @return
  222 + */
  223 + @Override
  224 + public JSONObject deleteFigureAllFace(String familiarFigureId) {
  225 + HttpHeaders headers = new HttpHeaders();
  226 + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
  227 + MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
  228 + map.set("namespace", namespace);
  229 + map.set("userId", UserUtils.getUser().getTenantId());
  230 + map.set("familiarFigureId", familiarFigureId);
  231 + map.set("faceId", "");
  232 + HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
  233 + log.info(">>>>>>>>>>开始调用分析器删除熟人人脸接口:{}", JSONUtil.toJsonStr(map));
  234 + ResponseEntity resultEntity = restTemplate.exchange(deleteFigureFaceUrl, HttpMethod.DELETE, request, Object.class);
  235 + Object result = resultEntity.getBody();
  236 + log.info(">>>>>>>>>>调用分析器删除熟人人脸接口结果:{}", JSONUtil.toJsonStr(result));
  237 + return JSONUtil.parseObj(result);
  238 + }
  239 +
  240 + /**
  241 + * 修改熟人
  242 + *
  243 + * @param name 名称
  244 + * @param gender 性别 0-女 1-男
  245 + * @param familiarFigureId 熟人id
  246 + * @return
  247 + */
  248 + @Override
  249 + public JSONObject updateFigure(String name, Integer gender, String familiarFigureId) {
  250 + HttpHeaders headers = new HttpHeaders();
  251 + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
  252 + MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
  253 + map.set("namespace", namespace);
  254 + map.set("userId", UserUtils.getUser().getTenantId());
  255 + map.set("familiarFigureId", familiarFigureId);
  256 + map.set("name", name);
  257 + map.set("gender", gender);
  258 + HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
  259 + log.info(">>>>>>>>>>开始调用分析器修改熟人接口:{}", JSONUtil.toJsonStr(map));
  260 + ResponseEntity resultEntity = restTemplate.exchange(updateFigureUrl, HttpMethod.PUT, request, Object.class);
  261 + Object result = resultEntity.getBody();
  262 + log.info(">>>>>>>>>>调用分析器修改熟人接口结果:{}", JSONUtil.toJsonStr(result));
  263 + return JSONUtil.parseObj(result);
  264 + }
  265 +
  266 + @Override
  267 + public JSONObject getPictureAnalysisResult(String imageBase64) {
  268 + Map<String, Object> map = new HashMap<>();
  269 + map.put("faceImg", imageBase64);
  270 + map.put("namespace", namespace);
  271 + map.put("userId", UserUtils.getUser().getTenantId());
  272 + log.info(">>>>>>>>>>调用分析器图片查陌生人接口");
  273 + Object result = restTemplate.postForObject(picturePersonUrl, map, Object.class);
  274 + log.info(">>>>>>>>>>调用分析器图片查陌生人接口成功");
  275 + return JSONUtil.parseObj(result);
  276 + }
  277 +
  278 + /**
  279 + * 根据特征值查熟人
  280 + *
  281 + * @param feature
  282 + * @return
  283 + */
  284 + @Override
  285 + public JSONObject getFigureByFeature(String feature) {
  286 + Map<String, Object> map = new HashMap<>();
  287 + map.put("feature", feature);
  288 + map.put("namespace", namespace);
  289 + map.put("userId", UserUtils.getUser().getTenantId());
  290 + log.info(">>>>>>>>>>调用分析器特征值查熟人接口");
  291 + Object result = restTemplate.postForObject(feature2figureUrl, map, Object.class);
  292 + log.info(">>>>>>>>>>调用分析器特征值查熟人接口成功");
  293 + return JSONUtil.parseObj(result);
  294 + }
  295 +}
  1 +package com.wondertek.ivod.cmr.manage.service.impl;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import com.alibaba.fastjson.JSON;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.drew.imaging.ImageMetadataReader;
  7 +import com.wondertek.ivod.cmr.commons.utils.GetLocation;
  8 +import com.wondertek.ivod.cmr.core.entity.model.ImageDetail;
  9 +import com.wondertek.ivod.cmr.manage.repository.ImageDetailRepository;
  10 +import com.wondertek.ivod.cmr.manage.service.ExtractImageDetailService;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.stereotype.Service;
  13 +import com.drew.metadata.Directory;
  14 +import com.drew.metadata.Metadata;
  15 +import com.drew.metadata.Tag;
  16 +
  17 +import javax.annotation.Resource;
  18 +import java.io.File;
  19 +
  20 +/**
  21 + * @author xh
  22 + * @date 2023/9/18 14:09
  23 + */
  24 +@Slf4j
  25 +@Service
  26 +public class ExtractImageDetailServiceImpl implements ExtractImageDetailService {
  27 + @Resource
  28 + private ImageDetailRepository imageDetailRepository;
  29 +
  30 + @Override
  31 + public ImageDetail extractImageDetail(String imagePath, Long materialId) {
  32 + File file = new File(imagePath);
  33 + Metadata metadata;
  34 + try {
  35 + metadata = ImageMetadataReader.readMetadata(file);
  36 + ImageDetail detail = new ImageDetail();
  37 + for (Directory directory : metadata.getDirectories()) {
  38 + for (Tag tag : directory.getTags()) {
  39 + log.info(tag.getTagName() + ":" + tag.getDescription());
  40 + if ("Date/Time Original".equals(tag.getTagName())) {
  41 + detail.setShootingTime(tag.getDescription());
  42 + }
  43 + if ("Artist".equals(tag.getTagName())) {
  44 + detail.setArtist(tag.getDescription());
  45 + }
  46 + if ("Image Height".equals(tag.getTagName())) {
  47 + detail.setImageHeight(tag.getDescription());
  48 + }
  49 + if ("Image Width".equals(tag.getTagName())) {
  50 + detail.setImageWidth(tag.getDescription());
  51 + }
  52 + if ("Compression Type".equals(tag.getTagName())) {
  53 + detail.setCompressionType(tag.getDescription());
  54 + }
  55 + if ("Detected File Type Name".equals(tag.getTagName())) {
  56 + detail.setDetectedFileTypeName(tag.getDescription());
  57 + }
  58 + if ("Detected MIME Type".equals(tag.getTagName())) {
  59 + detail.setDetectedMimeType(tag.getDescription());
  60 + }
  61 + if ("Expected File Name Extension".equals(tag.getTagName())) {
  62 + detail.setExpectedFileNameExtension(tag.getDescription());
  63 + }
  64 + if ("File Name".equals(tag.getTagName())) {
  65 + detail.setFileName(tag.getDescription());
  66 + }
  67 + if ("File Size".equals(tag.getTagName())) {
  68 + detail.setFileSize(tag.getDescription());
  69 + }
  70 + if ("File Modified Date".equals(tag.getTagName())) {
  71 + detail.setFileModifiedDate(tag.getDescription());
  72 + }
  73 + if ("GPS Latitude".equals(tag.getTagName())) {
  74 + detail.setGpsLatitude(tag.getDescription());
  75 + }
  76 + if ("GPS Longitude".equals(tag.getTagName())) {
  77 + detail.setGpsLongitude(tag.getDescription());
  78 + }
  79 + if (StrUtil.isNotBlank(detail.getGpsLongitude()) && StrUtil.isNotBlank(detail.getGpsLatitude())) {
  80 + String area = GetLocation.getAdd(detail.getGpsLongitude(), detail.getGpsLatitude());
  81 + JSONObject jsonObject = JSON.parseObject(area);
  82 + JSONObject jsonArray = JSON.parseObject(jsonObject.getString("result"));
  83 + String location = jsonArray.getString("address");
  84 + log.info(location);
  85 + detail.setLocation(location);
  86 + }
  87 + detail.setMaterialId(materialId);
  88 + }
  89 + }
  90 + return imageDetailRepository.saveAndFlush(detail);
  91 + } catch (Exception e) {
  92 + log.error("提取图片信息失败, imagePath: {}, msg: {}, e: {}", imagePath, e.getMessage(), e);
  93 + return null;
  94 + }
  95 + }
  96 +}
  1 +package com.wondertek.ivod.cmr.manage.service.impl;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import cn.hutool.json.JSONArray;
  5 +import cn.hutool.json.JSONObject;
  6 +import cn.hutool.json.JSONUtil;
  7 +import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
  8 +import com.wondertek.ivod.cmr.commons.exception.DefaultException;
  9 +import com.wondertek.ivod.cmr.commons.utils.FileUtils;
  10 +import com.wondertek.ivod.cmr.commons.utils.PageBean;
  11 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  12 +import com.wondertek.ivod.cmr.commons.utils.UserUtils;
  13 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.FigureFaceResult;
  14 +import com.wondertek.ivod.cmr.core.entity.dto.FigureUpdateDto;
  15 +import com.wondertek.ivod.cmr.core.entity.model.Figure;
  16 +import com.wondertek.ivod.cmr.core.entity.vo.SimilarityMatchVo;
  17 +import com.wondertek.ivod.cmr.manage.repository.FigureRepository;
  18 +import com.wondertek.ivod.cmr.manage.service.IAnalyserService;
  19 +import com.wondertek.ivod.cmr.manage.service.IFigureService;
  20 +import lombok.extern.slf4j.Slf4j;
  21 +import org.springframework.beans.BeanUtils;
  22 +import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.data.domain.Page;
  24 +import org.springframework.data.domain.PageRequest;
  25 +import org.springframework.data.domain.Pageable;
  26 +import org.springframework.data.domain.Sort;
  27 +import org.springframework.data.jpa.domain.Specification;
  28 +import org.springframework.stereotype.Service;
  29 +import org.springframework.transaction.annotation.Transactional;
  30 +import org.springframework.web.multipart.MultipartFile;
  31 +
  32 +import javax.persistence.criteria.Predicate;
  33 +import java.math.BigDecimal;
  34 +import java.time.LocalDateTime;
  35 +import java.util.*;
  36 +
  37 +/**
  38 + * @Author yubin
  39 + * @Date 2021/8/9 14:47
  40 + */
  41 +@Slf4j
  42 +@Service
  43 +public class FigureServiceImpl implements IFigureService {
  44 + @Autowired
  45 + private IAnalyserService analyserService;
  46 + @Autowired
  47 + private FigureRepository figureRepository;
  48 + //只允许用户输入数字1-9,字母a-z,A-Z,只能半角,不能有空格的正则表达式
  49 + public static final String ONLY_LETTER_OR_NUMBER = "^[a-z0-9A-Z]+$";
  50 +
  51 + /**
  52 + * 查询人物列表
  53 + *
  54 + * @param keywords
  55 + * @param page
  56 + * @param rows
  57 + * @return
  58 + */
  59 + @Override
  60 + public Page<Figure> pageList(String keywords, int page, int rows) {
  61 + Pageable pageable = PageRequest.of(page - 1, rows, Sort.Direction.DESC, "createTime");
  62 + Specification<Figure> prdPoolSpecification = (root, query, cb) -> {
  63 + List<Predicate> predicateList = new ArrayList<>();
  64 + predicateList.add(cb.equal(root.get("tenantId"), UserUtils.getUser().getTenantId()));
  65 + if (ObjectUtil.isNotEmpty(keywords)) {
  66 + predicateList.add(cb.or(cb.like(root.get("name"), "%" + keywords + "%"),
  67 + cb.like(root.get("figureDefineId"), "%" + keywords + "%")));
  68 + }
  69 + return query.where(predicateList.toArray(new Predicate[predicateList.size()])).getRestriction();
  70 + };
  71 + return figureRepository.findAll(prdPoolSpecification, pageable);
  72 + }
  73 +
  74 + /**
  75 + * 人脸相似度匹配
  76 + *
  77 + * @param figureImage
  78 + * @return
  79 + */
  80 + @Override
  81 + public ResultBean similarityMatch(MultipartFile figureImage, String familiarFigureId) {
  82 + JSONObject jsonResult = analyserService.similarityMatch(figureImage);
  83 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  84 + return ResultBean.error("人脸相似度匹配失败:" + jsonResult.get("msg"));
  85 + }
  86 + JSONArray jsonArray = jsonResult.getJSONArray("data");
  87 + List<SimilarityMatchVo> similarityMatchVoList = new ArrayList<>();
  88 + for (Object o : jsonArray) {
  89 + SimilarityMatchVo similarityMatchVo = JSONUtil.toBean(JSONUtil.toJsonStr(o), SimilarityMatchVo.class);
  90 + //自己不展示
  91 + if (ObjectUtil.isNotEmpty(familiarFigureId) && similarityMatchVo.getFamiliarFigureId().equals(familiarFigureId)) {
  92 + break;
  93 + }
  94 + //只需要展示可信度大于60的
  95 + if (similarityMatchVo.getScore().compareTo(new BigDecimal("0.6")) < 0) {
  96 + continue;
  97 + }
  98 + //小数点后一位
  99 + BigDecimal score = similarityMatchVo.getScore().multiply(new BigDecimal("100")).setScale(1, BigDecimal.ROUND_HALF_UP);
  100 + similarityMatchVo.setScore(new BigDecimal(score.stripTrailingZeros().toPlainString()));
  101 + similarityMatchVo.setPreviewUrl(similarityMatchVo.getPath()[0]);
  102 + similarityMatchVo.setPath(null);
  103 + similarityMatchVoList.add(similarityMatchVo);
  104 + }
  105 +
  106 + //只展示匹配度最高的10个
  107 + Collections.sort(similarityMatchVoList, (figure1, figure2) -> figure2.getScore().compareTo(figure1.getScore()));
  108 + return ResultBean.ok(similarityMatchVoList.size() > 10 ? similarityMatchVoList.subList(0, 10) : similarityMatchVoList);
  109 + }
  110 +
  111 + /**
  112 + * 添加人物
  113 + *
  114 + * @param figureImage
  115 + * @param figure
  116 + * @return
  117 + */
  118 + @Transactional(rollbackFor = Exception.class)
  119 + @Override
  120 + public ResultBean add(MultipartFile figureImage, Figure figure) {
  121 + String checkResult = validateFigure(figureImage, figure);
  122 + if (ObjectUtil.isNotEmpty(checkResult)) {
  123 + return ResultBean.error(checkResult);
  124 + }
  125 + //人物自定义id唯一
  126 + if (checkOnlyDefineId(null, figure.getFigureDefineId())) {
  127 + return ResultBean.error("该人物ID已存在,不可重复使用");
  128 + }
  129 + //如果熟人id不为空则是替换,先删除替换人物再添加新人物
  130 + if (ObjectUtil.isNotEmpty(figure.getFamiliarFigureId())) {
  131 + JSONObject jsonResult = analyserService.deleteFigure(figure.getFamiliarFigureId());
  132 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  133 + return ResultBean.error("删除人物失败:" + jsonResult.get("msg"));
  134 + }
  135 + figureRepository.deleteByFamiliarFigureId(figure.getFamiliarFigureId());
  136 + }
  137 +
  138 + //添加新人物
  139 + JSONObject jsonResult = analyserService.addOrUpdateFigureAndFace(figureImage, figure.getName(), figure.getGender(), null);
  140 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  141 + return ResultBean.error("添加人物库失败:" + jsonResult.get("msg"));
  142 + }
  143 + //添加人物库
  144 + JSONObject jsonObject = jsonResult.getJSONObject("data");
  145 + FigureFaceResult figureFaceResult = JSONUtil.toBean(JSONUtil.toJsonStr(jsonObject), FigureFaceResult.class);
  146 + figure.setFamiliarFigureId(figureFaceResult.getFamiliarFigureId());
  147 + figure.setPreviewUrl(figureFaceResult.getFaces().get(0).getPreviewPath());
  148 + figure.setTenantId(UserUtils.getUser().getTenantId());
  149 + figure.setCreateBy(UserUtils.getUser().getUserName());
  150 + figure.setCreateTime(LocalDateTime.now());
  151 + figureRepository.save(figure);
  152 + return ResultBean.ok();
  153 + }
  154 +
  155 + /**
  156 + * 修改人物
  157 + *
  158 + * @param figureImage
  159 + * @param figureUpdateDto
  160 + * @return
  161 + */
  162 + @Transactional(rollbackFor = Exception.class)
  163 + @Override
  164 + public ResultBean update(MultipartFile figureImage, FigureUpdateDto figureUpdateDto) {
  165 + Figure updateFigure = new Figure();
  166 + BeanUtils.copyProperties(figureUpdateDto, updateFigure);
  167 + String checkResult = validateFigure(figureImage, updateFigure);
  168 + if (ObjectUtil.isNotEmpty(checkResult)) {
  169 + return ResultBean.error(checkResult);
  170 + }
  171 + Optional<Figure> optional = figureRepository.findById(updateFigure.getId());
  172 + if (!optional.isPresent()) {
  173 + return ResultBean.error("该人物不存在");
  174 + }
  175 + Figure figure = optional.get();
  176 + //人物自定义id唯一
  177 + Figure figure2 = figureRepository.findByFigureDefineId(updateFigure.getFigureDefineId());
  178 + if (ObjectUtil.isNotEmpty(figure2) && !updateFigure.getId().equals(figure2.getId())) {
  179 + return ResultBean.error("该人物ID已存在,不可重复使用");
  180 + }
  181 +
  182 + //如果熟人id不为空则是替换,先删除替换人物再修改人物
  183 + if (ObjectUtil.isNotEmpty(updateFigure.getFamiliarFigureId())) {
  184 + if (ObjectUtil.isEmpty(figureImage) || ObjectUtil.isEmpty(figureImage.getOriginalFilename())) {
  185 + return ResultBean.error("替换人物照片必传");
  186 + }
  187 + JSONObject jsonResult = analyserService.deleteFigure(updateFigure.getFamiliarFigureId());
  188 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  189 + return ResultBean.error("删除人物失败:" + jsonResult.get("msg"));
  190 + }
  191 + figureRepository.deleteByFamiliarFigureId(updateFigure.getFamiliarFigureId());
  192 + }
  193 +
  194 + if (ObjectUtil.isNotEmpty(figureImage) && ObjectUtil.isNotEmpty(figureImage.getOriginalFilename())) {
  195 + //如果重新上传了照片先删除这个人之前的所有人脸
  196 + JSONObject jsonResult = analyserService.deleteFigureAllFace(figure.getFamiliarFigureId());
  197 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  198 + return ResultBean.error("删除人物人脸失败:" + jsonResult.get("msg"));
  199 + }
  200 +
  201 + //修改人物并添加新人脸
  202 + JSONObject jsonResult2 = analyserService.addOrUpdateFigureAndFace(figureImage, updateFigure.getName(), updateFigure.getGender(), figure.getFamiliarFigureId());
  203 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult2.get("code"))) {
  204 + return ResultBean.error("修改人物失败:" + jsonResult2.get("msg"));
  205 + }
  206 + JSONObject jsonObject = jsonResult2.getJSONObject("data");
  207 + FigureFaceResult figureFaceResult = JSONUtil.toBean(JSONUtil.toJsonStr(jsonObject), FigureFaceResult.class);
  208 + figure.setPreviewUrl(figureFaceResult.getFaces().get(0).getPreviewPath());
  209 + }
  210 +
  211 + //修改人物基础信息
  212 + JSONObject jsonResult = analyserService.updateFigure(updateFigure.getName(), updateFigure.getGender(), figure.getFamiliarFigureId());
  213 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  214 + return ResultBean.error("修改人物失败:" + jsonResult.get("msg"));
  215 + }
  216 +
  217 + //保存库
  218 + figure.setName(updateFigure.getName());
  219 + figure.setFigureDefineId(updateFigure.getFigureDefineId());
  220 + figure.setGender(updateFigure.getGender());
  221 + figure.setRemark(updateFigure.getRemark());
  222 + figure.setUpdateBy(UserUtils.getUser().getUserName());
  223 + figure.setUpdateTime(LocalDateTime.now());
  224 + figureRepository.save(figure);
  225 + return ResultBean.ok();
  226 + }
  227 +
  228 + /**
  229 + * 批量删除人物
  230 + *
  231 + * @param figureIds
  232 + * @return
  233 + */
  234 + @Transactional(rollbackFor = Exception.class)
  235 + @Override
  236 + public void batchDelete(List<Long> figureIds) {
  237 + List<Figure> figureList = figureRepository.findAllById(figureIds);
  238 + if (ObjectUtil.isEmpty(figureList)) {
  239 + throw new DefaultException("人物不存在");
  240 + }
  241 + StringJoiner familiarFigureIds = new StringJoiner(",");
  242 + figureList.forEach(figure -> familiarFigureIds.add(figure.getFamiliarFigureId()));
  243 + //删除分析器人物库
  244 + JSONObject jsonResult = analyserService.deleteFigure(familiarFigureIds.toString());
  245 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  246 + throw new DefaultException("删除人物失败:" + jsonResult.get("msg"));
  247 + }
  248 + figureRepository.deleteInBatch(figureList);
  249 + }
  250 +
  251 + /**
  252 + * 人物ID唯一校验
  253 + *
  254 + * @param figureDefineId
  255 + * @return
  256 + */
  257 + @Override
  258 + public Boolean checkOnlyDefineId(Long id, String figureDefineId) {
  259 + Figure figure = figureRepository.findByFigureDefineId(figureDefineId);
  260 + return ObjectUtil.isNotEmpty(figure) && !figure.getId().equals(id);
  261 + }
  262 +
  263 + /**
  264 + * 校验
  265 + *
  266 + * @param figureImage
  267 + * @param figure
  268 + * @return
  269 + */
  270 + public String validateFigure(MultipartFile figureImage, Figure figure) {
  271 + if (ObjectUtil.isNotEmpty(figureImage) && ObjectUtil.isNotEmpty(figureImage.getOriginalFilename())) {
  272 + String result = FileUtils.checkImageFile(figureImage);
  273 + if (ObjectUtil.isNotEmpty(result)) {
  274 + return result;
  275 + }
  276 + }
  277 + if (ObjectUtil.isEmpty(figure.getName())) {
  278 + return "人物名称必填";
  279 + }
  280 + if (figure.getName().length() > 20) {
  281 + return "人物名称不能大于20个字符";
  282 + }
  283 + if (ObjectUtil.isEmpty(figure.getFigureDefineId())) {
  284 + return "人物ID必填";
  285 + }
  286 + if (figure.getFigureDefineId().length() > 50 || !figure.getFigureDefineId().matches(ONLY_LETTER_OR_NUMBER)) {
  287 + return "人物ID不能大于50个字符且只能是数字大小写字母";
  288 + }
  289 + if (ObjectUtil.isEmpty(figure.getGender())) {
  290 + return "性别必填";
  291 + }
  292 + if (figure.getGender() != 0 && figure.getGender() != 1) {
  293 + return "性别类型错误";
  294 + }
  295 + if (ObjectUtil.isNotEmpty(figure.getRemark()) && figure.getRemark().length() > 100) {
  296 + return "备注不能大于100个字符";
  297 + }
  298 + return null;
  299 + }
  300 +}
  1 +package com.wondertek.ivod.cmr.manage.service.impl;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import com.wondertek.ivod.cmr.commons.enums.OperateTypeEnum;
  5 +import com.wondertek.ivod.cmr.commons.utils.PageBean;
  6 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  7 +import com.wondertek.ivod.cmr.commons.utils.UserUtils;
  8 +import com.wondertek.ivod.cmr.core.entity.model.OperateRecord;
  9 +import com.wondertek.ivod.cmr.manage.repository.OperateRecordRepository;
  10 +import com.wondertek.ivod.cmr.manage.service.IMaterialOperateRecordService;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.data.domain.Page;
  13 +import org.springframework.data.domain.PageRequest;
  14 +import org.springframework.data.domain.Pageable;
  15 +import org.springframework.data.domain.Sort;
  16 +import org.springframework.data.jpa.domain.Specification;
  17 +import org.springframework.stereotype.Service;
  18 +
  19 +import javax.annotation.Resource;
  20 +import javax.persistence.criteria.Predicate;
  21 +import java.time.LocalDateTime;
  22 +import java.util.ArrayList;
  23 +import java.util.List;
  24 +
  25 +/**
  26 + * @author xh
  27 + * @date 2023/9/18 10:46
  28 + */
  29 +@Slf4j
  30 +@Service
  31 +public class IMaterialOperateRecordServiceImpl implements IMaterialOperateRecordService {
  32 + @Resource
  33 + private OperateRecordRepository operateRecordRepository;
  34 +
  35 + @Override
  36 + public void saveOperateRecord(String type, String objectId) {
  37 + String tenantId = UserUtils.getUser().getTenantId();
  38 + String userName = UserUtils.getUser().getUserName();
  39 + OperateRecord record = new OperateRecord();
  40 + record.setCreatedTime(LocalDateTime.now());
  41 + record.setOperateObjectId(objectId);
  42 + record.setTenantId(tenantId);
  43 + record.setUserName(userName);
  44 + OperateRecord operateRecord = operateRecordRepository.findFirstByOperateObjectIdOrderByCreatedTimeDesc(objectId);
  45 + if (null == operateRecord) {
  46 + if (OperateTypeEnum.DOWNLOAD.getCode().equals(type)) {
  47 + record.setDownLoadCount(1);
  48 + }
  49 + if (OperateTypeEnum.VIEW.getCode().equals(type)) {
  50 + record.setViewCount(1);
  51 + }
  52 + } else {
  53 + log.info(operateRecord.toString());
  54 + if (OperateTypeEnum.DOWNLOAD.getCode().equals(type)) {
  55 + record.setDownLoadCount(StrUtil.isBlankIfStr(operateRecord.getDownLoadCount()) ? 1 : operateRecord.getDownLoadCount() + 1);
  56 + record.setViewCount(operateRecord.getViewCount());
  57 + }
  58 + if (OperateTypeEnum.VIEW.getCode().equals(type)) {
  59 + record.setViewCount(StrUtil.isBlankIfStr(operateRecord.getViewCount()) ? 1 : operateRecord.getViewCount() + 1);
  60 + record.setDownLoadCount(operateRecord.getDownLoadCount());
  61 + }
  62 + }
  63 + record.setOperateType(type);
  64 + operateRecordRepository.saveAndFlush(record);
  65 + }
  66 +
  67 + @Override
  68 + public ResultBean list(String objectId, int page, int rows) {
  69 + Pageable pageable = PageRequest.of(page - 1, rows, Sort.Direction.DESC, "createdTime");
  70 + Specification<OperateRecord> prdPoolSpecification = (root, query, cb) -> {
  71 + List<Predicate> predicateList = new ArrayList<>();
  72 + predicateList.add(cb.equal(root.get("operateObjectId"), objectId));
  73 + return query.where(predicateList.toArray(new Predicate[predicateList.size()])).getRestriction();
  74 + };
  75 + Page<OperateRecord> recordPage = operateRecordRepository.findAll(prdPoolSpecification, pageable);
  76 + return PageBean.ok(recordPage.getTotalPages(), recordPage.getTotalElements(), recordPage.getContent());
  77 +
  78 + }
  79 +
  80 + @Override
  81 + public ResultBean getCount(String objectId) {
  82 + OperateRecord operateRecord = operateRecordRepository.findFirstByOperateObjectIdOrderByCreatedTimeDesc(objectId);
  83 + if (null == operateRecord) {
  84 + return ResultBean.error("未统计到记录");
  85 + }
  86 + return ResultBean.ok(operateRecord);
  87 + }
  88 +}
  1 +package com.wondertek.ivod.cmr.manage.service.impl;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialInfoDto;
  5 +import com.wondertek.ivod.cmr.core.entity.model.MaterialFiles;
  6 +import com.wondertek.ivod.cmr.manage.service.IMaterialFilesService;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.beans.BeanUtils;
  9 +import org.springframework.stereotype.Service;
  10 +
  11 +/**
  12 + * @Author yubin
  13 + * @Date 2021/8/4 16:21
  14 + */
  15 +@Slf4j
  16 +@Service
  17 +public class MaterialFilesServiceImpl implements IMaterialFilesService {
  18 +
  19 + @Override
  20 + public MaterialFiles createMaterialFiles(MaterialInfoDto materialInfoDto) {
  21 + MaterialFiles materialFiles = new MaterialFiles();
  22 + BeanUtils.copyProperties(materialInfoDto, materialFiles);
  23 + materialFiles.setPath(materialInfoDto.getRelativePath());
  24 + materialFiles.setWidth(ObjectUtil.isNotEmpty(materialInfoDto.getWidth()) ? materialInfoDto.getWidth() + "" : null);
  25 + materialFiles.setHeight(ObjectUtil.isNotEmpty(materialInfoDto.getHeight()) ? materialInfoDto.getHeight() + "" : null);
  26 + materialFiles.setBitRate(ObjectUtil.isNotEmpty(materialInfoDto.getBitRate()) ? materialInfoDto.getBitRate() + "" : null);
  27 + return materialFiles;
  28 + }
  29 +}
  1 +package com.wondertek.ivod.cmr.manage.service.impl;
  2 +
  3 +import cn.hutool.core.collection.CollectionUtil;
  4 +import cn.hutool.core.date.DateUtil;
  5 +import cn.hutool.core.util.ObjectUtil;
  6 +import cn.hutool.json.JSONArray;
  7 +import cn.hutool.json.JSONObject;
  8 +import cn.hutool.json.JSONUtil;
  9 +import com.wondertek.ivod.cmr.commons.enums.CommonStatusEnum;
  10 +import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
  11 +import com.wondertek.ivod.cmr.commons.enums.MaterialSourceEnum;
  12 +import com.wondertek.ivod.cmr.commons.enums.MaterialTypeEnum;
  13 +import com.wondertek.ivod.cmr.commons.exception.DefaultException;
  14 +import com.wondertek.ivod.cmr.commons.utils.FileUtils;
  15 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  16 +import com.wondertek.ivod.cmr.commons.utils.UserUtils;
  17 +import com.wondertek.ivod.cmr.core.entity.bean.*;
  18 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.AnalysisUploadResult;
  19 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.Feature2FigureResult;
  20 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.FileInfoToMq;
  21 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.PictureAnalysisResult;
  22 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.*;
  23 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialAddDto;
  24 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
  25 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialInfoDto;
  26 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialInjectDto;
  27 +import com.wondertek.ivod.cmr.core.entity.model.AiFigure;
  28 +import com.wondertek.ivod.cmr.core.entity.model.ImageDetail;
  29 +import com.wondertek.ivod.cmr.core.entity.model.Material;
  30 +import com.wondertek.ivod.cmr.core.entity.model.MaterialFiles;
  31 +import com.wondertek.ivod.cmr.core.entity.vo.PictureAnalysisVo;
  32 +import com.wondertek.ivod.cmr.manage.config.RabbitmqConfig;
  33 +import com.wondertek.ivod.cmr.manage.feign.SearchFeignService;
  34 +import com.wondertek.ivod.cmr.manage.repository.AiFigureRepository;
  35 +import com.wondertek.ivod.cmr.manage.repository.ImageDetailRepository;
  36 +import com.wondertek.ivod.cmr.manage.repository.MaterialFilesRepository;
  37 +import com.wondertek.ivod.cmr.manage.repository.MaterialRepository;
  38 +import com.wondertek.ivod.cmr.manage.service.ExtractImageDetailService;
  39 +import com.wondertek.ivod.cmr.manage.service.IAnalyserService;
  40 +import com.wondertek.ivod.cmr.manage.service.IMaterialFilesService;
  41 +import com.wondertek.ivod.cmr.manage.service.IMaterialService;
  42 +import lombok.extern.slf4j.Slf4j;
  43 +import org.apache.commons.lang3.StringUtils;
  44 +import org.springframework.amqp.rabbit.core.RabbitTemplate;
  45 +import org.springframework.beans.BeanUtils;
  46 +import org.springframework.beans.factory.annotation.Autowired;
  47 +import org.springframework.beans.factory.annotation.Value;
  48 +import org.springframework.scheduling.annotation.Async;
  49 +import org.springframework.stereotype.Service;
  50 +import org.springframework.transaction.annotation.Transactional;
  51 +import org.springframework.web.multipart.MultipartFile;
  52 +
  53 +import javax.annotation.Resource;
  54 +import java.io.File;
  55 +import java.nio.charset.StandardCharsets;
  56 +import java.time.LocalDateTime;
  57 +import java.util.*;
  58 +
  59 +/**
  60 + * @Author yubin
  61 + * @Date 2021/8/3 15:41
  62 + */
  63 +@Slf4j
  64 +@Service
  65 +public class MaterialServiceImpl implements IMaterialService {
  66 + @Autowired
  67 + private IMaterialFilesService materialFilesService;
  68 + @Autowired
  69 + private SearchFeignService searchFeignService;
  70 + @Autowired
  71 + private IAnalyserService analyserService;
  72 + @Autowired
  73 + private RabbitTemplate rabbitTemplate;
  74 + @Autowired
  75 + private MaterialRepository materialRepository;
  76 + @Autowired
  77 + private MaterialFilesRepository materialFilesRepository;
  78 + @Autowired
  79 + private AiFigureRepository aiFigureRepository;
  80 + @Value("${analyser.namespace}")
  81 + private String namespace;
  82 + @Value("${analyser.filePath}")
  83 + private String filePath;
  84 + @Value("${cmr.image.basePath}")
  85 + private String basePath;
  86 + @Value("${cmr.image.startPath}")
  87 + private String startPath;
  88 + @Autowired
  89 + private ExtractImageDetailService extractImageDetailService;
  90 + @Resource
  91 + private ImageDetailRepository imageDetailRepository;
  92 +
  93 + /**
  94 + * 介质上传
  95 + *
  96 + * @param materialFile
  97 + * @return
  98 + */
  99 + @Override
  100 + public ResultBean uploadFile(MultipartFile materialFile, MaterialAddDto materialAddDto) {
  101 + Long materialId = materialAddDto.getMaterialId();
  102 + //不是空则为重新上传
  103 + if (ObjectUtil.isNotEmpty(materialId)) {
  104 + Optional<Material> optional = materialRepository.findById(materialId);
  105 + if (!optional.isPresent()) {
  106 + throw new DefaultException("该媒资不存在");
  107 + }
  108 + } else {
  109 + //先存一条数据
  110 + materialId = createMaterialBasic(materialFile);
  111 + }
  112 + updateUploadStatus(materialId, CommonStatusEnum.WAIT.getCode());
  113 +
  114 + //上传文件到分析器
  115 + JSONObject jsonObject = analyserService.uploadFile(materialFile);
  116 + if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonObject.get("code"))) {
  117 + updateUploadStatus(materialId, CommonStatusEnum.SUCCESS.getCode());
  118 + } else {
  119 + updateUploadStatus(materialId, CommonStatusEnum.FAIL.getCode());
  120 + return ResultBean.error(materialAddDto.getName() + "上传失败:" + jsonObject.get("msg"), materialId);
  121 + }
  122 +
  123 + //创建注入数据
  124 + AnalysisUploadResult analysisUploadResult = JSONUtil.toBean(JSONUtil.toJsonStr(jsonObject.get("data")), AnalysisUploadResult.class);
  125 + MaterialInfoDto materialInfoDto = new MaterialInfoDto();
  126 + materialInfoDto.setMaterialId(materialId);
  127 + BeanUtils.copyProperties(analysisUploadResult, materialInfoDto);
  128 + materialInfoDto.setName(materialAddDto.getName());
  129 + materialInfoDto.setMediaUrl(analysisUploadResult.getPreviewUrl());
  130 + materialInfoDto.setPreviewUrl(ObjectUtil.isNotEmpty(analysisUploadResult.getCoverMap()) ? analysisUploadResult.getCoverMap() : analysisUploadResult.getPreviewUrl());
  131 + materialInfoDto.setMediaType(FileUtils.getFileType(analysisUploadResult.getOriginalName()));
  132 + materialInfoDto.setIsOpenAi(materialAddDto.getIsOpenAi());
  133 + materialInfoDto.setClipId(analysisUploadResult.getClipId());
  134 +
  135 + List<MaterialInfoDto> materials = new ArrayList<>();
  136 + materials.add(materialInfoDto);
  137 + MaterialInjectDto materialInjectDto = new MaterialInjectDto();
  138 + materialInjectDto.setSource(MaterialSourceEnum.LOCAL_UPLOAD.getCode());
  139 + materialInjectDto.setMaterialInfos(materials);
  140 + /* // 提取图片信息
  141 + Integer fileType = FileUtils.getFileType(materialFile.getOriginalFilename());
  142 + if (MaterialTypeEnum.PICTURE.getCode().equals(fileType)) {
  143 + String relativePath = materialInfoDto.getRelativePath();
  144 + if (StringUtils.isNotBlank(relativePath)) {
  145 + extractImageDetailService.extractImageDetail(relativePath.replace(startPath, basePath));
  146 + }
  147 + }*/
  148 + //注入
  149 + inject(materialInjectDto);
  150 +
  151 + return ResultBean.ok(materialId);
  152 + }
  153 +
  154 + /**
  155 + * 注入接口
  156 + * 1.存储cmr_material
  157 + * 2.存储cmr_material_files
  158 + * 3.介制信息存储es
  159 + * 4.发送ai能力人物分析
  160 + *
  161 + * @param materialInjectDto
  162 + */
  163 + @Transactional(rollbackFor = Exception.class)
  164 + @Override
  165 + public List<Long> inject(MaterialInjectDto materialInjectDto) {
  166 + log.info(">>>>>>>>>>注入流程开始:{}", JSONUtil.toJsonStr(materialInjectDto));
  167 + //用户信息设置
  168 + UserUtils.setUser(materialInjectDto.getUserId(), materialInjectDto.getUserName(), materialInjectDto.getTenantId());
  169 + List<Long> materialIdList = new ArrayList<>();
  170 + for (MaterialInfoDto materialInfoDto : materialInjectDto.getMaterialInfos()) {
  171 + materialInfoDto.setDuration(ObjectUtil.isNotEmpty(materialInfoDto.getDuration()) ? materialInfoDto.getDuration() / 1000000 : null);
  172 + //存储cmr_material
  173 + Material material = createMaterial(materialInfoDto);
  174 + material.setMaterialType(materialInfoDto.getMediaType());
  175 + material.setSource(materialInjectDto.getSource());
  176 + materialRepository.save(material);
  177 + materialIdList.add(material.getMaterialId());
  178 + //存储cmr_material_files
  179 + MaterialFiles materialFiles = materialFilesService.createMaterialFiles(materialInfoDto);
  180 + materialFiles.setType(materialInfoDto.getMediaType());
  181 + materialFiles.setMaterialId(material.getMaterialId());
  182 + materialFilesRepository.save(materialFiles);
  183 +
  184 + //es存储对象
  185 + MaterialInfo materialInfo = new MaterialInfo();
  186 + materialInfo.setMaterialId(material.getMaterialId());
  187 + //基础信息
  188 + BasicInfo basicInfo = new BasicInfo();
  189 + BeanUtils.copyProperties(material, basicInfo);
  190 + basicInfo.setMaterialId(material.getMaterialId());
  191 + basicInfo.setOwner(UserUtils.getUser());
  192 + basicInfo.setCreateTime(DateUtil.formatLocalDateTime(material.getCreateTime()));
  193 + basicInfo.setUpdateTime(DateUtil.formatLocalDateTime(material.getUpdatedTime()));
  194 + basicInfo.setFileId(materialInfoDto.getFileId());
  195 + basicInfo.setClipId(materialInfoDto.getClipId());
  196 + basicInfo.setRelativePath(materialInfoDto.getRelativePath());
  197 + // 提取图片信息
  198 + if (MaterialTypeEnum.PICTURE.getCode().equals(materialInfoDto.getMediaType())) {
  199 + String relativePath = materialInfoDto.getRelativePath();
  200 + if (StringUtils.isNotBlank(relativePath)) {
  201 + ImageDetail imageDetail = extractImageDetailService.extractImageDetail(basePath + relativePath, material.getMaterialId());
  202 + ImageAttr imageAttr = new ImageAttr();
  203 + if (null != imageDetail) {
  204 + imageAttr.setArtist(imageDetail.getArtist());
  205 + imageAttr.setLocation(imageDetail.getLocation());
  206 + imageAttr.setShootingTime(imageDetail.getShootingTime());
  207 + basicInfo.setImageAttr(imageAttr);
  208 + }
  209 + }
  210 + }
  211 +
  212 + materialInfo.setBasicInfo(basicInfo);
  213 + //文件详细信息
  214 + MediaInfo mediaInfo = new MediaInfo();
  215 + BeanUtils.copyProperties(materialInfoDto, mediaInfo);
  216 + mediaInfo.setMediaType(materialInfoDto.getMediaType());
  217 + materialInfo.setMediaInfo(mediaInfo);
  218 + //状态信息
  219 + MaterialStatus materialStatus = new MaterialStatus();
  220 + materialStatus.setAiAnalysisStatus(ObjectUtil.isNotEmpty(materialInfoDto.getIsOpenAi()) && materialInfoDto.getIsOpenAi() ? CommonStatusEnum.WAIT.getCode() : CommonStatusEnum.INIT.getCode());
  221 + materialStatus.setUploadStatus(CommonStatusEnum.SUCCESS.getCode());
  222 + materialStatus.setEmbodyStatus(CommonStatusEnum.SUCCESS.getCode());
  223 + materialInfo.setMaterialStatus(materialStatus);
  224 +
  225 + //保存介质信息es
  226 + ResultBean resultBean;
  227 + if (ObjectUtil.isEmpty(materialInfoDto.getMaterialId())) {
  228 + log.info(">>>>>>>>>>保存介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  229 + resultBean = searchFeignService.createMaterialInfo(materialInfo);
  230 + log.info(">>>>>>>>>>保存介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  231 + } else {
  232 + log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  233 + resultBean = searchFeignService.updateMaterialInfo(materialInfo);
  234 + log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  235 + }
  236 +
  237 + //发送ai能力分析
  238 + if (ObjectUtil.isNotEmpty(materialInfoDto.getIsOpenAi()) && materialInfoDto.getIsOpenAi()) {
  239 + aiAnalysis(materialInfo);
  240 + }
  241 + }
  242 + return materialIdList;
  243 + }
  244 +
  245 + /**
  246 + * ai分析
  247 + *
  248 + * @param materialInfo
  249 + */
  250 + @Async
  251 + public void aiAnalysis(MaterialInfo materialInfo) {
  252 + //人物分析
  253 + aiFigureAnalysis(materialInfo);
  254 +
  255 + //todo 文字分析
  256 + aiWordAnalysis(materialInfo);
  257 + }
  258 +
  259 + /**
  260 + * ai人物分析
  261 + *
  262 + * @param materialInfo
  263 + */
  264 + public void aiFigureAnalysis(MaterialInfo materialInfo) {
  265 + if (MaterialTypeEnum.VIDEO.getCode().equals(materialInfo.getBasicInfo().getMaterialType())) {
  266 + videoAiFigureAnalysis(materialInfo);
  267 + } else if (MaterialTypeEnum.PICTURE.getCode().equals(materialInfo.getBasicInfo().getMaterialType())) {
  268 + pictureAiFigureAnalysis(materialInfo);
  269 + }
  270 + }
  271 +
  272 + /**
  273 + * ai文字分析
  274 + *
  275 + * @param materialInfo
  276 + */
  277 + public void aiWordAnalysis(MaterialInfo materialInfo) {
  278 + List<WordInfo> wordInfoList = new ArrayList<>();
  279 + //WordInfo wordInfo = new WordInfo();
  280 + //wordInfo.setWord("文字识别敬请期待");
  281 + if (MaterialTypeEnum.VIDEO.getCode().equals(materialInfo.getBasicInfo().getMaterialType())) {
  282 + //wordInfo.setStart("0");
  283 + //wordInfo.setEnd("120");
  284 + videoAiWordsAnalysis(materialInfo);
  285 + } else if (MaterialTypeEnum.PICTURE.getCode().equals(materialInfo.getBasicInfo().getMaterialType())) {
  286 + pictureAiWordsAnalysis(materialInfo);
  287 + }
  288 + //wordInfoList.add(wordInfo);
  289 + //materialInfo.setWordInfo(wordInfoList);
  290 + //searchFeignService.updateMaterialInfo(materialInfo);
  291 + }
  292 +
  293 + /**
  294 + * 视频ai人物分析 消费类FigureConsumer
  295 + *
  296 + * @param materialInfo
  297 + */
  298 + public void videoAiFigureAnalysis(MaterialInfo materialInfo) {
  299 + log.info(">>>>>>>>>>视频分析:{}", materialInfo.getMaterialId());
  300 + FileInfoToMq fileInfoToMq = new FileInfoToMq();
  301 + fileInfoToMq.setTag(materialInfo.getMaterialId() + "");
  302 + fileInfoToMq.setFileId(materialInfo.getBasicInfo().getFileId());
  303 + fileInfoToMq.setRelativePath(materialInfo.getBasicInfo().getRelativePath());
  304 + fileInfoToMq.setNamespace(namespace);
  305 + fileInfoToMq.setUserId(UserUtils.getUser().getTenantId());
  306 + log.info(">>>>>>>>>>发送ai人物分析mq:{}", JSONUtil.toJsonStr(fileInfoToMq));
  307 + rabbitTemplate.convertAndSend(RabbitmqConfig.ANALYZER_FILE_EXCHANGE, RabbitmqConfig.ANALYZER_FILE_STORAGE_PATH_ROUTING, JSONUtil.toJsonStr(fileInfoToMq).getBytes());
  308 + }
  309 +
  310 + /**
  311 + * 图片ai人物分析
  312 + *
  313 + * @param materialInfo
  314 + */
  315 + public void pictureAiFigureAnalysis(MaterialInfo materialInfo) {
  316 + log.info(">>>>>>>>>>图片分析:{}", materialInfo.getMaterialId());
  317 + Optional<Material> optionalMaterial = materialRepository.findById(materialInfo.getMaterialId());
  318 + if (!optionalMaterial.isPresent()) {
  319 + log.info(">>>>>>>>>>人物分析异常,该介制信息不存在:{}", materialInfo.getMaterialId());
  320 + return;
  321 + }
  322 + //人物分析信息
  323 + List<AiFigure> aiFigureList = new ArrayList<>();
  324 + try {
  325 + //调用分析器图片分析接口
  326 + JSONObject jsonResult = analyserService.pictureAnalysis(materialInfo.getMaterialId() + "", materialInfo.getBasicInfo().getFileId(), materialInfo.getBasicInfo().getRelativePath());
  327 + if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  328 + //修改ai分析状态
  329 + materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.SUCCESS.getCode());
  330 + //读取json文件,临时保存
  331 + String jsonPath = filePath + jsonResult.get("data");
  332 + log.info(">>>>>>>>>>人物分析json文件地址:{}", jsonPath);
  333 + File file = new File(jsonPath);
  334 + if (ObjectUtil.isEmpty(file)) {
  335 + throw new DefaultException(">>>>>>>>>>人物分析异常,下载文件失败");
  336 + }
  337 + JSONObject jsonObject = JSONUtil.readJSONObject(file, StandardCharsets.UTF_8);
  338 + JSONArray jsonArray = jsonObject.getJSONArray("faceDataList");
  339 + if (ObjectUtil.isEmpty(jsonArray)) {
  340 + log.info(">>>>>>>>>>人物分析数据为空");
  341 + return;
  342 + }
  343 + //保存人物分析信息
  344 + for (Object o : jsonArray) {
  345 + VideoFigureData videoFigureData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoFigureData.class);
  346 + AiFigure aiFigure = new AiFigure();
  347 + aiFigure.setMaterialId(materialInfo.getMaterialId());
  348 + aiFigure.setFigureId(Long.valueOf(videoFigureData.getStrangerId()));
  349 + aiFigure.setImagePath(videoFigureData.getImage());
  350 + aiFigure.setCreateTime(LocalDateTime.now());
  351 + Box box = videoFigureData.getBox();
  352 + aiFigure.setWight(box.getW() + "");
  353 + aiFigure.setHigh(box.getH() + "");
  354 + aiFigure.setXPos(box.getX() + "");
  355 + aiFigure.setYPos(box.getY() + "");
  356 + aiFigure.setType("1");
  357 + aiFigureList.add(aiFigure);
  358 + }
  359 +
  360 + //人脸识别信息
  361 + List<FaceInfo> faceInfoList = new ArrayList<>();
  362 + //标签
  363 + Set<String> tagInfoSet = new TreeSet<>();
  364 + for (Object o : jsonArray) {
  365 + VideoFigureData videoFigureData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoFigureData.class);
  366 + log.info(videoFigureData.toString());
  367 + FaceInfo faceInfo = new FaceInfo();
  368 + faceInfo.setFigureId(videoFigureData.getStrangerId());
  369 + faceInfo.setFigureName(videoFigureData.getFigureName());
  370 + faceInfo.setFace(videoFigureData.getImage());
  371 + if (ObjectUtil.isNotEmpty(videoFigureData.getFigureName())) {
  372 + tagInfoSet.add(videoFigureData.getFigureName());
  373 + }
  374 + //出现率
  375 + faceInfo.setAppearRate("100%");
  376 + faceInfo.setWight(videoFigureData.getBox().getW() + "");
  377 + faceInfo.setHigh(videoFigureData.getBox().getH() + "");
  378 + faceInfo.setX(videoFigureData.getBox().getX() + "");
  379 + faceInfo.setY(videoFigureData.getBox().getY() + "");
  380 + faceInfoList.add(faceInfo);
  381 + }
  382 + materialInfo.setFaceInfo(faceInfoList);
  383 + materialInfo.getBasicInfo().setTagInfoSet(tagInfoSet);
  384 + } else {
  385 + materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
  386 + }
  387 + } catch (Exception e) {
  388 + e.printStackTrace();
  389 + materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
  390 + } finally {
  391 + //更新es
  392 + materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
  393 + log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  394 + ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
  395 + log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  396 + //保存人物分析信息
  397 + if (CommonStatusEnum.SUCCESS.getCode().equals(materialInfo.getMaterialStatus().getAiAnalysisStatus())) {
  398 + aiFigureRepository.saveAll(aiFigureList);
  399 + }
  400 + }
  401 + }
  402 +
  403 + /**
  404 + * 视频ai文字分析 消费类FigureConsumer
  405 + *
  406 + * @param materialInfo
  407 + */
  408 + public void videoAiWordsAnalysis(MaterialInfo materialInfo) {
  409 + log.info(">>>>>>>>>>视频分析:{}", materialInfo.getMaterialId());
  410 + FileInfoToMq fileInfoToMq = new FileInfoToMq();
  411 + fileInfoToMq.setTag(materialInfo.getMaterialId() + "");
  412 + fileInfoToMq.setFileId(materialInfo.getBasicInfo().getFileId());
  413 + fileInfoToMq.setRelativePath(materialInfo.getBasicInfo().getRelativePath());
  414 + fileInfoToMq.setNamespace(namespace);
  415 + fileInfoToMq.setUserId(UserUtils.getUser().getTenantId());
  416 + fileInfoToMq.setPath(materialInfo.getBasicInfo().getRelativePath());
  417 + log.info(">>>>>>>>>>发送ai文字分析mq:{}", JSONUtil.toJsonStr(fileInfoToMq));
  418 + rabbitTemplate.convertAndSend(RabbitmqConfig.WORDS_ANALYZER_FILE_EXCHANGE, RabbitmqConfig.WORDS_ANALYZER_FILE_STORAGE_PATH_ROUTING, JSONUtil.toJsonStr(fileInfoToMq).getBytes());
  419 + }
  420 +
  421 + /**
  422 + * 图片ai人物分析
  423 + *
  424 + * @param materialInfo
  425 + */
  426 + public void pictureAiWordsAnalysis(MaterialInfo materialInfo) {
  427 + log.info(">>>>>>>>>>图片分析:{}", materialInfo.toString());
  428 + Optional<Material> optionalMaterial = materialRepository.findById(materialInfo.getMaterialId());
  429 + if (!optionalMaterial.isPresent()) {
  430 + log.info(">>>>>>>>>>人物分析异常,该介制信息不存在:{}", materialInfo.getMaterialId());
  431 + return;
  432 + }
  433 + //文字分析信息
  434 + List<AiFigure> aiFigureList = new ArrayList<>();
  435 + try {
  436 + //调用分析器图片分析接口
  437 + JSONObject jsonResult = analyserService.pictureAnalysisToWords(materialInfo.getMaterialId() + "", materialInfo.getBasicInfo().getFileId(), materialInfo.getBasicInfo().getRelativePath());
  438 + if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
  439 + //修改ai分析状态
  440 + materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.SUCCESS.getCode());
  441 + //读取json文件,临时保存
  442 + String dataJson = jsonResult.get("data") + "";
  443 + String jsonPath = filePath + JSONUtil.parseObj(dataJson).get("path");
  444 + log.info(">>>>>>>>>>文字分析json文件地址:{}", jsonPath);
  445 + File file = new File(jsonPath);
  446 + if (ObjectUtil.isEmpty(file)) {
  447 + throw new DefaultException(">>>>>>>>>>文字分析异常,下载文件失败");
  448 + }
  449 + JSONObject jsonObject = JSONUtil.readJSONObject(file, StandardCharsets.UTF_8);
  450 + JSONArray jsonArray = jsonObject.getJSONArray("data");
  451 + if (ObjectUtil.isEmpty(jsonArray)) {
  452 + log.info(">>>>>>>>>>文字分析数据为空");
  453 + return;
  454 + }
  455 + //保存文字分析信息
  456 + for (Object o : jsonArray) {
  457 + ImageWordsData imageWordsData = JSONUtil.toBean(JSONUtil.toJsonStr(o), ImageWordsData.class);
  458 + AiFigure aiFigure = new AiFigure();
  459 + aiFigure.setMaterialId(materialInfo.getMaterialId());
  460 + aiFigure.setContent(imageWordsData.getContent());
  461 + aiFigure.setType("2");
  462 + aiFigure.setCreateTime(LocalDateTime.now());
  463 + if (CollectionUtil.isNotEmpty(imageWordsData.getPolygon())) {
  464 + String xPos = null,ypos = null;
  465 + for (Polygon polygonTemp : imageWordsData.getPolygon()) {
  466 + xPos = xPos + "," + polygonTemp.getX();
  467 + ypos = ypos + "," + polygonTemp.getY();
  468 + }
  469 + if (xPos.startsWith(",")) {
  470 + xPos = xPos.substring(1);
  471 + ypos = ypos.substring(1);
  472 + }
  473 + aiFigure.setXPos(xPos);
  474 + aiFigure.setYPos(ypos);
  475 + }
  476 + aiFigureList.add(aiFigure);
  477 + }
  478 + //文字识别信息
  479 + List<WordInfo> wordInfoList = new ArrayList<>();
  480 + for (Object o : jsonArray) {
  481 + ImageWordsData imageWordsData = JSONUtil.toBean(JSONUtil.toJsonStr(o), ImageWordsData.class);
  482 + WordInfo wordInfo = new WordInfo();
  483 + wordInfo.setWord(imageWordsData.getContent());
  484 + //出现率
  485 + List<Polygon> polygons = new ArrayList<>();
  486 + if (CollectionUtil.isNotEmpty(imageWordsData.getPolygon())) {
  487 + for (Polygon polygonTemp : imageWordsData.getPolygon()) {
  488 + Polygon polygon = new Polygon();
  489 + polygon.setX(polygonTemp.getX());
  490 + polygon.setY(polygonTemp.getY());
  491 + polygons.add(polygon);
  492 + }
  493 + wordInfo.setPolygons(polygons);
  494 + }
  495 +
  496 + wordInfoList.add(wordInfo);
  497 + }
  498 + materialInfo.setWordInfo(wordInfoList);
  499 + } else {
  500 + materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.FAIL.getCode());
  501 + }
  502 + } catch (Exception e) {
  503 + e.printStackTrace();
  504 + materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.FAIL.getCode());
  505 + } finally {
  506 + //更新es
  507 + materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
  508 + log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  509 + ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
  510 + log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  511 + //保存ocr分析信息
  512 + if (CommonStatusEnum.SUCCESS.getCode().equals(materialInfo.getMaterialStatus().getOcrAnalysisStatus())) {
  513 + aiFigureRepository.saveAll(aiFigureList);
  514 + }
  515 + }
  516 + }
  517 +
  518 + /**
  519 + * 重新下发AI分析
  520 + *
  521 + * @param materialIds
  522 + * @return
  523 + */
  524 + @Transactional(rollbackFor = Exception.class)
  525 + @Override
  526 + public void aiAnalysis(List<Long> materialIds) {
  527 + for (Long materialId : materialIds) {
  528 + Optional<Material> optional = materialRepository.findById(materialId);
  529 + if (!optional.isPresent()) {
  530 + throw new DefaultException("该媒资不存在:" + materialId);
  531 + }
  532 + Material material = optional.get();
  533 + //更新操作人
  534 + updateUserInfo(material);
  535 + materialRepository.save(material);
  536 + //修改es中的状态
  537 + MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
  538 + if (ObjectUtil.isEmpty(materialInfo)) {
  539 + throw new DefaultException("该介质信息在es中不存在:" + materialId);
  540 + }
  541 + materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.WAIT.getCode());
  542 + materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
  543 + log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  544 + ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
  545 + log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  546 + if (GlobalCodeEnum.SUCCESS.getCode().equals(resultBean.getCode())) {
  547 + //ai人物分析
  548 + aiAnalysis(materialInfo);
  549 + }
  550 + }
  551 + }
  552 +
  553 + /**
  554 + * 修改名称
  555 + *
  556 + * @param materialId
  557 + * @param name
  558 + */
  559 + @Transactional(rollbackFor = Exception.class)
  560 + @Override
  561 + public void updateMaterial(Long materialId, String name) {
  562 + Optional<Material> optional = materialRepository.findById(materialId);
  563 + if (!optional.isPresent()) {
  564 + throw new DefaultException("该媒资不存在");
  565 + }
  566 + Material material = optional.get();
  567 + material.setName(name);
  568 + //更新操作人
  569 + updateUserInfo(material);
  570 + materialRepository.save(material);
  571 +
  572 + //修改es中的名称
  573 + MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
  574 + if (ObjectUtil.isEmpty(materialInfo)) {
  575 + throw new DefaultException("该介质信息在es中不存在");
  576 + }
  577 + materialInfo.getBasicInfo().setName(name);
  578 + materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
  579 + log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  580 + ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
  581 + log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  582 + }
  583 +
  584 + /**
  585 + * 批量设置标签
  586 + * @param materialIds
  587 + * @param customLabel
  588 + */
  589 + @Transactional(rollbackFor = Exception.class)
  590 + @Override
  591 + public void updateMaterialCustomLable(List<Long> materialIds, String customLabel) {
  592 + Set<String> labelSet = new HashSet<>();
  593 + String[] labels = customLabel.split(",");
  594 + Collections.addAll(labelSet, labels);
  595 + for (Long materialId : materialIds) {
  596 + Optional<Material> optional = materialRepository.findById(materialId);
  597 + if (!optional.isPresent()) {
  598 + throw new DefaultException(materialId + "该媒资不存在");
  599 + }
  600 + Material material = optional.get();
  601 + material.setCustomLabel(customLabel);
  602 + //更新操作人
  603 + updateUserInfo(material);
  604 + materialRepository.save(material);
  605 +
  606 + //修改es中的名称
  607 + MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
  608 + if (ObjectUtil.isEmpty(materialInfo)) {
  609 + throw new DefaultException("该介质信息在es中不存在");
  610 + }
  611 + materialInfo.getBasicInfo().setCustomLabelSet(labelSet);
  612 + materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
  613 + log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  614 + ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
  615 + log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  616 + }
  617 + }
  618 +
  619 + /**
  620 + * 删除
  621 + *
  622 + * @param materialDeleteDto
  623 + */
  624 + @Transactional(rollbackFor = Exception.class)
  625 + @Override
  626 + public void deleteMaterails(MaterialDeleteDto materialDeleteDto) {
  627 + Map<String, List<Long>> map = new HashMap<>();
  628 + map.put("materialIds", materialDeleteDto.getMaterialIds());
  629 + List<MaterialInfo> materialInfos = searchFeignService.getByIds(map).getResult();
  630 + List<String> fileIdList = new ArrayList<>();
  631 + for (MaterialInfo materialInfo : materialInfos) {
  632 + fileIdList.add(materialInfo.getBasicInfo().getFileId());
  633 + }
  634 + if (CollectionUtil.isNotEmpty(fileIdList)) {
  635 + JSONObject jsonObject = analyserService.deletefileBatch(fileIdList);
  636 + if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonObject.get("code")) && !"没有该文件".equals(jsonObject.get("msg"))) {
  637 + throw new DefaultException("删除失败:" + jsonObject.get("msg"));
  638 + }
  639 + }
  640 + //删除介质信息es
  641 + log.info(">>>>>>>>>>删除介制信息es:{}", JSONUtil.toJsonStr(materialDeleteDto));
  642 + ResultBean deleteResultBean = searchFeignService.deleteInfos(materialDeleteDto);
  643 + log.info(">>>>>>>>>>删除介制信息es结果:{}", JSONUtil.toJsonStr(deleteResultBean));
  644 + if (GlobalCodeEnum.SUCCESS.getCode().equals(deleteResultBean.getCode())) {
  645 + List<Material> materialList = new ArrayList<>();
  646 + materialDeleteDto.getMaterialIds().forEach(materialId -> {
  647 + Material material = new Material();
  648 + material.setMaterialId(materialId);
  649 + materialList.add(material);
  650 + });
  651 + materialRepository.deleteInBatch(materialList);
  652 + materialFilesRepository.deleteByMaterialIds(materialDeleteDto.getMaterialIds());
  653 + aiFigureRepository.deleteByMaterialIds(materialDeleteDto.getMaterialIds());
  654 + imageDetailRepository.deleteByMaterialIds(materialDeleteDto.getMaterialIds());
  655 + }
  656 + }
  657 +
  658 + /**
  659 + * 更新操作人
  660 + *
  661 + * @param material
  662 + */
  663 + public void updateUserInfo(Material material) {
  664 + UserInfo userInfo = UserUtils.getUser();
  665 + material.setUpdatedBy(userInfo.getUserName());
  666 + material.setUpdatedTime(LocalDateTime.now());
  667 + }
  668 +
  669 + public Material createMaterial(MaterialInfoDto materialInfoDto) {
  670 + Material material = new Material();
  671 + BeanUtils.copyProperties(materialInfoDto, material);
  672 + UserInfo userInfo = UserUtils.getUser();
  673 + material.setTenantId(userInfo.getTenantId());
  674 + material.setCreateBy(userInfo.getUserName());
  675 + material.setCreateTime(LocalDateTime.now());
  676 + material.setUpdatedBy(userInfo.getUserName());
  677 + material.setUpdatedTime(LocalDateTime.now());
  678 + return material;
  679 + }
  680 +
  681 + /**
  682 + * 创建基础信息
  683 + *
  684 + * @param materialFile
  685 + */
  686 + public Long createMaterialBasic(MultipartFile materialFile) {
  687 + //存储cmr_material
  688 + Material material = createMaterial(new MaterialInfoDto());
  689 + material.setName(materialFile.getOriginalFilename());
  690 + material.setSource(MaterialSourceEnum.LOCAL_UPLOAD.getCode());
  691 + material.setMaterialType(FileUtils.getFileType(materialFile.getOriginalFilename()));
  692 + materialRepository.save(material);
  693 +
  694 + //es存储对象
  695 + MaterialInfo materialInfo = new MaterialInfo();
  696 + materialInfo.setMaterialId(material.getMaterialId());
  697 + //基础信息
  698 + BasicInfo basicInfo = new BasicInfo();
  699 + BeanUtils.copyProperties(material, basicInfo);
  700 + basicInfo.setMaterialId(material.getMaterialId());
  701 + basicInfo.setOwner(UserUtils.getUser());
  702 + basicInfo.setCreateTime(DateUtil.formatLocalDateTime(material.getCreateTime()));
  703 + basicInfo.setUpdateTime(DateUtil.formatLocalDateTime(material.getUpdatedTime()));
  704 + materialInfo.setBasicInfo(basicInfo);
  705 + //状态信息
  706 + MaterialStatus materialStatus = new MaterialStatus();
  707 + materialStatus.setUploadStatus(CommonStatusEnum.WAIT.getCode());
  708 + materialInfo.setMaterialStatus(materialStatus);
  709 + //保存介质信息es
  710 + log.info(">>>>>>>>>>保存介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  711 + ResultBean resultBean = searchFeignService.createMaterialInfo(materialInfo);
  712 + log.info(">>>>>>>>>>保存介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  713 + return material.getMaterialId();
  714 + }
  715 +
  716 + /**
  717 + * 修改上传状态
  718 + *
  719 + * @param materialId
  720 + * @param uploadStatus
  721 + */
  722 + private void updateUploadStatus(Long materialId, Integer uploadStatus) {
  723 + Optional<Material> optional = materialRepository.findById(materialId);
  724 + if (!optional.isPresent()) {
  725 + throw new DefaultException("该媒资不存在");
  726 + }
  727 + Material material = optional.get();
  728 + //更新操作人
  729 + updateUserInfo(material);
  730 + materialRepository.save(material);
  731 +
  732 + //修改es中的名称
  733 + MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
  734 + if (ObjectUtil.isEmpty(materialInfo)) {
  735 + throw new DefaultException("该介质信息在es中不存在");
  736 + }
  737 + materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
  738 + materialInfo.getMaterialStatus().setUploadStatus(uploadStatus);
  739 + materialInfo.getMaterialStatus().setEmbodyStatus(uploadStatus);
  740 + log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
  741 + ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
  742 + log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
  743 + }
  744 +
  745 + @Override
  746 + public PictureAnalysisVo analysisPicture(String imageBase64) {
  747 + PictureAnalysisVo pictureAnalysisVo = null;
  748 + //图片查陌生人
  749 + JSONObject jsonObject = analyserService.getPictureAnalysisResult(imageBase64);
  750 + if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonObject.get("code"))) {
  751 + //如果data是null,说明不是人脸图片
  752 + if (!JSONUtil.isNull(jsonObject.get("data"))) {
  753 + pictureAnalysisVo = new PictureAnalysisVo();
  754 + List<PictureAnalysisResult> pictureAnalysisResultList = JSONUtil.toList(JSONUtil.parseArray(jsonObject.get("data")), PictureAnalysisResult.class);
  755 + if (ObjectUtil.isNotEmpty(pictureAnalysisResultList)) {
  756 + PictureAnalysisResult pictureAnalysisResult = pictureAnalysisResultList.get(0);
  757 + //如果陌生人库没查到,则faceId返回null
  758 + if (ObjectUtil.isNotEmpty(pictureAnalysisResult.getFaceId())) {
  759 + pictureAnalysisVo.setFaceId(String.valueOf(pictureAnalysisResult.getFaceId()));
  760 + //根据特征值查熟人获取名字
  761 + jsonObject = analyserService.getFigureByFeature(pictureAnalysisResult.getFeature());
  762 + if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonObject.get("code"))) {
  763 + Feature2FigureResult feature2FigureResult = JSONUtil.toBean(JSONUtil.toJsonStr(jsonObject.get("data")), Feature2FigureResult.class);
  764 + pictureAnalysisVo.setName(feature2FigureResult.getName());
  765 + } else {
  766 + log.info(">>>>>>>>>>特征值查熟人异常:{}", jsonObject.get("msg"));
  767 + }
  768 + }
  769 + }
  770 + }
  771 + return pictureAnalysisVo;
  772 + } else {
  773 + throw new DefaultException("调用分析器异常");
  774 + }
  775 + }
  776 +}
  1 +spring:
  2 + #------------------------------------------mysql---------------------------------------------------
  3 + datasource:
  4 + type: com.alibaba.druid.pool.DruidDataSource
  5 + url: jdbc:mysql://192.168.1.41:3306/cmrdb?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=GMT%2B8
  6 + username: root
  7 + password: root
  8 + driver-class-name: com.mysql.cj.jdbc.Driver
  9 + druid:
  10 + ##配置初始化大小、最小、最大
  11 + initial-size: 5
  12 + max-active: 100
  13 + min-idle: 5
  14 + #配置获取连接等待超时的时间
  15 + max-wait: 60000
  16 + ##打开PSCache,并且指定每个连接上PSCache的大小
  17 + pool-prepared-statements: true
  18 + max-pool-prepared-statement-per-connection-size: 20
  19 + validation-query: SELECT 1 FROM DUAL
  20 + validation-query-timeout: 60000
  21 + ##这里建议配置为TRUE,防止取到的连接不可用
  22 + test-on-borrow: true
  23 + test-on-return: false
  24 + test-while-idle: true
  25 + ##配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  26 + time-between-eviction-runs-millis: 60000
  27 + min-evictable-idle-time-millis: 100000
  28 +
  29 + jpa:
  30 + show-sql: true
  31 + database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
  32 +
  33 + #----------------------------------------rabbitmq---------------------------------------------------
  34 + rabbitmq:
  35 + host: 127.0.0.1
  36 + port: 5672
  37 + username: admin
  38 + password: admin
  39 + virtual-host: /
  40 + #设置发送确认
  41 + publisher-confirm-type: correlated
  42 + template:
  43 + mandatory: true
  44 + listener:
  45 + simple:
  46 + #决定被拒绝的消息是否重新入队
  47 + default-requeue-rejected: true
  48 + retry:
  49 + #时间间隔5秒
  50 + initial-interval: 5000ms
  51 + enabled: true
  52 + #最大重试次数
  53 + max-attempts: 4
  54 +
  55 +analyser:
  56 + #分析器上传接口
  57 + uploadUrl: http://192.168.1.99/file-upload-service/file/upload/
  58 + #分析器批量删除文件接口
  59 + fileBatchDeleteUrl: http://192.168.1.99/file-upload-service/file/batch-delete
  60 + #图片分析
  61 + pictureAnalysisUrl: http://192.168.0.14:20005/file-figure-analyzer/picture/analysis/person
  62 +cmr:
  63 + image:
  64 + basePath:
  65 +
  1 +spring:
  2 + #------------------------------------------mysql---------------------------------------------------
  3 + datasource:
  4 + type: com.alibaba.druid.pool.DruidDataSource
  5 + url: jdbc:mysql://192.168.1.41:3306/cmrdb?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=GMT%2B8
  6 + username: root
  7 + password: root
  8 + driver-class-name: com.mysql.cj.jdbc.Driver
  9 + druid:
  10 + ##配置初始化大小、最小、最大
  11 + initial-size: 5
  12 + max-active: 100
  13 + min-idle: 5
  14 + #配置获取连接等待超时的时间
  15 + max-wait: 60000
  16 + ##打开PSCache,并且指定每个连接上PSCache的大小
  17 + pool-prepared-statements: true
  18 + max-pool-prepared-statement-per-connection-size: 20
  19 + validation-query: SELECT 1 FROM DUAL
  20 + validation-query-timeout: 60000
  21 + ##这里建议配置为TRUE,防止取到的连接不可用
  22 + test-on-borrow: true
  23 + test-on-return: false
  24 + test-while-idle: true
  25 + ##配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  26 + time-between-eviction-runs-millis: 60000
  27 + min-evictable-idle-time-millis: 100000
  28 +
  29 + jpa:
  30 + show-sql: false
  31 + database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
  32 +
  33 + #----------------------------------------rabbitmq---------------------------------------------------
  34 + rabbitmq:
  35 + host: 192.168.0.14
  36 + port: 5672
  37 + username: admin
  38 + password: admin
  39 + virtual-host: /
  40 + #设置发送确认
  41 + publisher-confirm-type: correlated
  42 + template:
  43 + mandatory: true
  44 + listener:
  45 + simple:
  46 + #决定被拒绝的消息是否重新入队
  47 + default-requeue-rejected: true
  48 + retry:
  49 + #时间间隔5秒
  50 + initial-interval: 5000ms
  51 + enabled: true
  52 + #最大重试次数
  53 + max-attempts: 4
  54 +
  55 +analyser:
  56 + #分析器上传接口
  57 + uploadUrl: http://192.168.1.99/file-upload-service/file/upload/
  58 + #分析器批量删除文件接口
  59 + fileBatchDeleteUrl: http://192.168.1.99/file-upload-service/file/batch-delete
  60 + #图片分析
  61 + pictureAnalysisUrl: http://192.168.0.14:20005/file-figure-analyzer/picture/analysis/person
  62 + #熟人库图片相似度查询
  63 + similarityMatchUrl: http://192.168.1.99/figure-data-service/familiar-figure-lib/image2figures
  64 + #删除熟人
  65 + deleteFigureUrl: http://192.168.1.99/figure-data-service/familiar-figure-lib/figure
  66 + #删除人脸
  67 + deleteFigureFaceUrl: http://192.168.1.99/figure-data-service/familiar-figure-lib/figure/face
  68 + #熟人与人脸一起添加(新增或更新)
  69 + figureFaceUrl: http://192.168.1.99/figure-data-service/familiar-figure/figure-face
  70 + #修改熟人
  71 + updateFigureUrl: http://192.168.1.99/figure-data-service/familiar-figure/figure-face/modify
  72 + #图片查陌生人
  73 + picturePersonUrl: http://192.168.1.99/figure-data-service/picture/person
  74 + #特征值字符串查熟人
  75 + feature2figureUrl: http://192.168.1.99/figure-data-service/familiar-figure-lib/feature2figure
  76 + #挂载路径
  77 + filePath: "/upload_data/"
  78 +cmr:
  79 + image:
  80 + basePath:
  1 +spring:
  2 + #------------------------------------------mysql---------------------------------------------------
  3 + datasource:
  4 + type: com.alibaba.druid.pool.DruidDataSource
  5 + url: jdbc:mysql://192.168.0.14:13306/cmrdb?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=GMT%2B8
  6 + username: root
  7 + password: 38128
  8 + driver-class-name: com.mysql.cj.jdbc.Driver
  9 + druid:
  10 + ##配置初始化大小、最小、最大
  11 + initial-size: 5
  12 + max-active: 100
  13 + min-idle: 5
  14 + #配置获取连接等待超时的时间
  15 + max-wait: 60000
  16 + ##打开PSCache,并且指定每个连接上PSCache的大小
  17 + pool-prepared-statements: true
  18 + max-pool-prepared-statement-per-connection-size: 20
  19 + validation-query: SELECT 1 FROM DUAL
  20 + validation-query-timeout: 60000
  21 + ##这里建议配置为TRUE,防止取到的连接不可用
  22 + test-on-borrow: true
  23 + test-on-return: false
  24 + test-while-idle: true
  25 + ##配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  26 + time-between-eviction-runs-millis: 60000
  27 + min-evictable-idle-time-millis: 100000
  28 +
  29 + jpa:
  30 + show-sql: false
  31 + database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
  32 +
  33 + #----------------------------------------rabbitmq---------------------------------------------------
  34 + rabbitmq:
  35 + host: 192.168.0.14
  36 + port: 5672
  37 + username: admin
  38 + password: admin
  39 + virtual-host: /
  40 + #设置发送确认
  41 + publisher-confirm-type: correlated
  42 + template:
  43 + mandatory: true
  44 + listener:
  45 + simple:
  46 + #决定被拒绝的消息是否重新入队
  47 + default-requeue-rejected: true
  48 + retry:
  49 + #时间间隔5秒
  50 + initial-interval: 5000ms
  51 + enabled: true
  52 + #最大重试次数
  53 + max-attempts: 4
  54 +
  55 +analyser:
  56 + #分析器上传接口
  57 + uploadUrl: http://file-upload-service:18010/file/upload/
  58 + #分析器批量删除文件接口
  59 + fileBatchDeleteUrl: http://file-upload-service:18010/file/batch-delete
  60 + #图片分析
  61 + pictureAnalysisUrl: http://file-figure-analyzer:18011/picture/analysis/person
  62 + #熟人库图片相似度查询
  63 + similarityMatchUrl: http://figure-data-service/familiar-figure-lib/image2figures
  64 + #删除熟人
  65 + deleteFigureUrl: http://figure-data-service/familiar-figure-lib/figure
  66 + #删除人脸
  67 + deleteFigureFaceUrl: http://figure-data-service/familiar-figure-lib/figure/face
  68 + #熟人与人脸一起添加(新增或更新)
  69 + figureFaceUrl: http://figure-data-service/familiar-figure/figure-face
  70 + #修改熟人
  71 + updateFigureUrl: http://figure-data-service/familiar-figure/figure-face/modify
  72 + #特征值字符串查熟人
  73 + feature2figureUrl: http://figure-data-service/familiar-figure-lib/feature2figure
  74 + #挂载路径
  75 + filePath: "/upload_data/"
  76 + #图片查陌生人
  77 + picturePersonUrl: http://figure-data-service/picture/person
  78 + pictureAnalysisToWordsUrl: http://file-ocr-analysis/ocr/image
  79 +cmr:
  80 + image:
  81 + basePath: upload_data/
  82 + startPath: ay-file/upload/
  1 +spring:
  2 + profiles:
  3 + active: @spring.profiles.active@
  4 +
  5 +ribbon:
  6 + ReadTimeout: 60000
  7 + ConnectTimeout: 60000
  8 +
  9 +logging:
  10 + level:
  11 + com.wondertek.ivod.*: info
  12 + springfox.documentation.*: error
  13 + org.springframework.*: error
  14 + #org.hibernate.type.descriptor.sql.BasicBinder: trace
  15 +
  16 +
  17 +#分析器侧命名空间
  18 +analyser:
  19 + namespace: cloud-media-resources
  20 +mq:
  21 + anylzer:
  22 + #人物分析回调mq
  23 + callbackExchange: VideoExchange
  24 + callbackQueue: video.anylzer_callback
  25 + ocr:
  26 + callbackExchange: ai-analyse-return
  27 + callbackQueue: ai-analyse-return-cloud-media
  28 +
  29 +file:
  30 + uploadPath: /upload
  31 + downloadPath: /download
  1 +common:
  2 + group: SAAS_GROUP
  3 + nacos:
  4 + username: nacos
  5 + password: nacos
  6 + server-addr: localhost:8848
  1 +common:
  2 + group: SAAS_GROUP
  3 + nacos:
  4 + username: nacos
  5 + password: nacos
  6 + server-addr: 192.168.1.84:8848
  1 +common:
  2 + group: SAAS_GROUP
  3 + nacos:
  4 + username: nacos
  5 + password: nacos
  6 + server-addr: 192.168.0.14:8848
  1 +spring:
  2 + servlet:
  3 + multipart:
  4 + max-file-size: 500MB
  5 + max-request-size: 2500MB
  6 + application:
  7 + name: cmr-manage
  8 + cloud:
  9 + nacos:
  10 + discovery:
  11 + server-addr: ${common.nacos.server-addr}
  12 + namespace: ${spring.profiles.active}
  13 + group: ${common.group}
  14 + username: ${common.nacos.username}
  15 + password: ${common.nacos.password}
  16 +# enabled: false
  17 + config:
  18 + server-addr: ${common.nacos.server-addr}
  19 + namespace: ${spring.profiles.active}
  20 + group: ${common.group}
  21 + username: ${common.nacos.username}
  22 + password: ${common.nacos.password}
  23 + file-extension: yml
  24 + shared-configs:
  25 + - data-id: ${spring.application.name}-base.yaml
  26 + group: ${common.group}
  27 + refresh: true
  28 + extension-configs:
  29 + - data-id: ${spring.application.name}-fallback-resp.yml
  30 + group: ${common.group}
  31 + refresh: true
  32 + enabled: false
  33 +server:
  34 + port: 18666
  35 + servlet:
  36 + context-path: /cmr-manage
  37 +logging:
  38 + file:
  39 + path: ./logs
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<configuration debug="false" scan="false">
  3 + <springProperty scop="context" name="app_name" source="spring.application.name" defaultValue="cmr-manage"/>
  4 + <property name="log.path" value="logs" />
  5 + <property name="CONSOLE_LOG_PATTERN"
  6 + value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%msg%n"/>
  7 + <property name="CONSOLE_LOG_PATTERN_DETAIL"
  8 + value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|${PID:-}|%thread|${app_name:-}|%X{X-B3-TraceId:-}|%X{X-B3-SpanId:-}|%X{X-Span-Export:-}|%class.%method-%line|%msg%n"/>
  9 + <!-- Console log output -->
  10 + <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
  11 + <encoder>
  12 + <pattern>${CONSOLE_LOG_PATTERN_DETAIL}</pattern>
  13 + <charset>UTF-8</charset>
  14 + </encoder>
  15 + </appender>
  16 +
  17 + <!-- Log file debug output -->
  18 + <appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
  19 + <file>${log.path}/${app_name:-}.info.log</file>
  20 + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  21 + <fileNamePattern>logs/%d{yyyy-MM-dd}/${app_name:-}.%d{yyyy-MM-dd}.info.log</fileNamePattern>
  22 + <maxHistory>60</maxHistory>
  23 + </rollingPolicy>
  24 + <encoder>
  25 + <pattern>${CONSOLE_LOG_PATTERN}</pattern>
  26 + <charset>UTF-8</charset>
  27 + </encoder>
  28 + </appender>
  29 +
  30 + <!-- Log file error output -->
  31 + <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
  32 + <file>${log.path}/${app_name:-}.error.log</file>
  33 + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  34 + <!-- 按天回滚 daily -->
  35 + <fileNamePattern>logs/%d{yyyy-MM-dd}/${app_name:-}.%d{yyyy-MM-dd}.error.log</fileNamePattern>
  36 + <!-- 日志最大的历史 60天 -->
  37 + <maxHistory>60</maxHistory>
  38 + </rollingPolicy>
  39 + <encoder>
  40 + <pattern>${CONSOLE_LOG_PATTERN}</pattern>
  41 + <charset>UTF-8</charset>
  42 + </encoder>
  43 + <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
  44 + <level>ERROR</level>
  45 + </filter>
  46 + </appender>
  47 +
  48 + <!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
  49 + <root level="INFO">
  50 + <appender-ref ref="console" />
  51 + <appender-ref ref="logFile" />
  52 + <appender-ref ref="error" />
  53 + </root>
  54 +</configuration>
  1 +
  2 +import com.wondertek.ivod.cmr.commons.utils.FileUtils;
  3 +import com.wondertek.ivod.cmr.manage.CMRManageApplication;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.junit.Test;
  6 +import org.junit.runner.RunWith;
  7 +import org.springframework.boot.test.context.SpringBootTest;
  8 +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  9 +
  10 +import java.io.File;
  11 +
  12 +
  13 +// 第一种方式,推荐这种使用更方便
  14 +@RunWith(SpringJUnit4ClassRunner.class)
  15 +@SpringBootTest(classes = CMRManageApplication.class)
  16 +@Slf4j
  17 +public class MyTest {
  18 +
  19 + @Test
  20 + public void testHello() {
  21 + File file = FileUtils.downLoadFromUrl("https://dev.aivideo.cn/preview/ay-file/upload/cloud-media-resources/10000000019/0/2021/9/26/18/a07483d8b1ef4856a11411fce5e0c5e8.mp4.figuredot/data.json","aa.json");
  22 + log.info(file.getName());
  23 + }
  24 +
  25 +}
  1 +FROM 192.168.1.7/library/java8:centos7
  2 +
  3 +ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
  4 +SPRING_PROFILE_ACTIVE=prod \
  5 +SPRING_OPTS="" \
  6 +JAVA_OPTS=""
  7 +CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=${SPRING_PROFILE_ACTIVE} ${SPRING_OPTS}
  8 +RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
  9 +ADD target/*.jar /app.jar
  1 +FROM 192.168.1.7/library/java8:centos7
  2 +
  3 +ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
  4 +SPRING_PROFILE_ACTIVE=preview \
  5 +SPRING_OPTS="" \
  6 +JAVA_OPTS=""
  7 +CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=${SPRING_PROFILE_ACTIVE} ${SPRING_OPTS}
  8 +RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
  9 +ADD *.jar /app.jar
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>cloud-media-resources</artifactId>
  7 + <groupId>com.wondertek.ivod.cmr</groupId>
  8 + <version>1.0.0</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <groupId>com.wondertek.ivod.cmr.search</groupId>
  13 + <artifactId>cmr-search</artifactId>
  14 + <packaging>jar</packaging>
  15 + <version>1.0.0</version>
  16 +
  17 + <dependencies>
  18 + <dependency>
  19 + <groupId>com.wondertek.ivod.cmr.commons</groupId>
  20 + <artifactId>cmr-commons</artifactId>
  21 + <version>1.0.0</version>
  22 + </dependency>
  23 + <dependency>
  24 + <groupId>com.wondertek.ivod.cmr.core</groupId>
  25 + <artifactId>cmr-core</artifactId>
  26 + <version>1.0.0</version>
  27 + </dependency>
  28 + <dependency>
  29 + <groupId>com.alibaba.cloud</groupId>
  30 + <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  31 + <version>2.2.5.RELEASE</version>
  32 + </dependency>
  33 + <dependency>
  34 + <groupId>com.alibaba.cloud</groupId>
  35 + <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  36 + <version>2.2.5.RELEASE</version>
  37 + </dependency>
  38 + </dependencies>
  39 +
  40 + <!--如果需要打docker镜像,把注释放开即可-->
  41 + <build>
  42 + <plugins>
  43 + <plugin>
  44 + <groupId>org.springframework.boot</groupId>
  45 + <artifactId>spring-boot-maven-plugin</artifactId>
  46 + </plugin>
  47 + </plugins>
  48 + <pluginManagement>
  49 + <plugins>
  50 + <plugin>
  51 + <groupId>com.spotify</groupId>
  52 + <artifactId>docker-maven-plugin</artifactId>
  53 + <version>1.1.0</version>
  54 + <executions>
  55 + <execution>
  56 + <id>build-image</id>
  57 + <phase>package</phase>
  58 + <goals>
  59 + <goal>build</goal>
  60 + <goal>push</goal>
  61 + </goals>
  62 + </execution>
  63 + </executions>
  64 + <configuration>
  65 + <imageName>192.168.1.69/ai_lib/${project.artifactId}:${project.version}</imageName>
  66 + <dockerHost>http://192.168.1.70:2375</dockerHost>
  67 + <dockerDirectory>${basedir}/docker</dockerDirectory>
  68 + <resources>
  69 + <resource>
  70 + <targetPath>/</targetPath>
  71 + <directory>${project.build.directory}</directory>
  72 + <include>${project.build.finalName}.jar</include>
  73 + </resource>
  74 + </resources>
  75 + </configuration>
  76 + </plugin>
  77 + </plugins>
  78 + </pluginManagement>
  79 + </build>
  80 +
  81 + <profiles>
  82 + <profile>
  83 + <id>docker</id>
  84 + <properties>
  85 + <spring.profiles.active>preview</spring.profiles.active>
  86 + </properties>
  87 + <build>
  88 + <plugins>
  89 + <plugin>
  90 + <groupId>com.spotify</groupId>
  91 + <artifactId>docker-maven-plugin</artifactId>
  92 + <configuration>
  93 + <imageName>192.168.1.7/ivod/${project.artifactId}:${project.version}</imageName>
  94 + <dockerHost>http://192.168.1.70:2375</dockerHost>
  95 + <serverId>wd-harbor</serverId>
  96 + </configuration>
  97 + </plugin>
  98 + </plugins>
  99 + </build>
  100 + </profile>
  101 + </profiles>
  102 +</project>
  1 +package com.wondertek.ivod.cmr.search;
  2 +
  3 +import cn.hutool.extra.spring.SpringUtil;
  4 +import org.springframework.boot.SpringApplication;
  5 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  6 +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  7 +import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  8 +import org.springframework.context.ConfigurableApplicationContext;
  9 +import org.springframework.context.annotation.Bean;
  10 +import org.springframework.context.annotation.ComponentScan;
  11 +import org.springframework.web.client.RestTemplate;
  12 +
  13 +@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
  14 +@EnableDiscoveryClient
  15 +public class CMRSearchApplication {
  16 +
  17 + public static void main(String[] args) {
  18 +
  19 + ConfigurableApplicationContext applicationContext = SpringApplication.run(CMRSearchApplication.class, args);
  20 + SpringUtil springUtil = new SpringUtil();
  21 + springUtil.setApplicationContext(applicationContext);
  22 + }
  23 +
  24 + @Bean
  25 + public RestTemplate getRestTemplate(){
  26 + return new RestTemplate();
  27 + }
  28 +
  29 +}
  1 +package com.wondertek.ivod.cmr.search.config;
  2 +
  3 +import cn.hutool.json.JSONUtil;
  4 +import com.wondertek.ivod.cmr.commons.utils.UserUtils;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.apache.commons.lang3.ObjectUtils;
  7 +import org.aspectj.lang.ProceedingJoinPoint;
  8 +import org.aspectj.lang.Signature;
  9 +import org.aspectj.lang.annotation.*;
  10 +import org.aspectj.lang.reflect.MethodSignature;
  11 +import org.springframework.stereotype.Component;
  12 +import org.springframework.web.context.request.RequestContextHolder;
  13 +import org.springframework.web.context.request.ServletRequestAttributes;
  14 +
  15 +import javax.servlet.http.HttpServletRequest;
  16 +import java.lang.reflect.Method;
  17 +import java.lang.reflect.Parameter;
  18 +import java.util.*;
  19 +
  20 +/**
  21 + * 请求参数与响应结果封装
  22 + * @Author: CuiSiBo
  23 + * @Date: 2020/5/6 17:03
  24 + * @Version 1.0
  25 + */
  26 +
  27 +@Aspect
  28 +@Component
  29 +@Slf4j
  30 +public class LogAspect {
  31 +
  32 + @Pointcut("execution(public * com.wondertek.ivod.cmr.search.controller.*Controller.*(..))")
  33 + public void webLog() {
  34 + }
  35 +
  36 +
  37 + @Around("webLog()")
  38 + public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
  39 + long startTime = System.currentTimeMillis();
  40 + //获取当前请求对象
  41 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  42 + HttpServletRequest request = attributes.getRequest();
  43 + //设置用户信息
  44 + UserUtils.setUser(request);
  45 + String uri = request.getRequestURI();
  46 + //记录入参
  47 + Signature signature = joinPoint.getSignature();
  48 + MethodSignature methodSignature = (MethodSignature) signature;
  49 + Method method = methodSignature.getMethod();
  50 + Object inParameter = getParameter(method, joinPoint.getArgs());
  51 + String paramStr = "{}";
  52 + if (ObjectUtils.isNotEmpty(inParameter)) {
  53 + paramStr = JSONUtil.parse(inParameter).toJSONString(0);
  54 + //paramStr = paramStr.length() > 1000 ? paramStr.substring(0, 1000) : paramStr;
  55 + }
  56 + log.info(">>>>>>>>>> {} begin ! parameter:{}", uri, paramStr);
  57 + //执行接口
  58 + Object result = joinPoint.proceed();
  59 + //记录出参
  60 + String resultStr = "{}";
  61 + if (ObjectUtils.isNotEmpty(result)){
  62 + resultStr = JSONUtil.parse(result).toJSONString(0);
  63 + //resultStr = resultStr.length() > 1000 ? resultStr.substring(0, 1000) : resultStr;
  64 + }
  65 + long endTime = System.currentTimeMillis();
  66 + log.info(">>>>>>>>>> {} end, time-consuming:{}ms ! result:{}", uri, endTime - startTime, resultStr);
  67 + return result;
  68 + }
  69 +
  70 + /**
  71 + * 根据方法和传入的参数获取请求参数
  72 + */
  73 + private List<Map> getParameter(Method method, Object[] args) {
  74 + List<Map> argList = new ArrayList<>();
  75 + Parameter[] parameters = method.getParameters();
  76 + for (int i = 0; i < parameters.length; i++) {
  77 + Map<String, Object> map = new HashMap<>();
  78 + map.put(parameters[i].getName(), args[i]);
  79 + argList.add(map);
  80 + }
  81 + return argList;
  82 + }
  83 +}
  1 +package com.wondertek.ivod.cmr.search.controller;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import com.wondertek.ivod.cmr.commons.utils.PageBean;
  5 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  6 +import com.wondertek.ivod.cmr.search.service.MaterialService;
  7 +import com.wondertek.ivod.cmr.search.vo.MaterialPageReqVo;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.web.bind.annotation.*;
  10 +
  11 +import java.text.ParseException;
  12 +import java.util.Collections;
  13 +import java.util.List;
  14 +import java.util.Map;
  15 +
  16 +/**
  17 + * @Author Hcg
  18 + * @Date 2021/8/13
  19 + * @desc
  20 + */
  21 +@RestController
  22 +@RequestMapping("/material")
  23 +public class MaterialController {
  24 + @Autowired
  25 + private MaterialService materialService;
  26 +
  27 + /**
  28 + * 列表查询
  29 + *
  30 + * @param vo
  31 + * @return
  32 + */
  33 + @PostMapping("/list")
  34 + public ResultBean list(@RequestBody MaterialPageReqVo vo) {
  35 + return materialService.list(vo);
  36 + }
  37 +
  38 + /**
  39 + * 人脸识别信息
  40 + *
  41 + * @param materialId
  42 + * @param keywords
  43 + * @param page
  44 + * @param rows
  45 + * @return
  46 + */
  47 + @GetMapping("/get-figure")
  48 + public ResultBean getFigure(@RequestParam(value = "materialId") Long materialId, String keywords, Integer page, Integer rows) {
  49 + return materialService.getFigure(materialId, keywords, page, rows);
  50 + }
  51 +
  52 + /**
  53 + * 媒资详情
  54 + *
  55 + * @param materialId
  56 + * @return
  57 + */
  58 + @GetMapping("/get")
  59 + public ResultBean getFigure(@RequestParam(value = "materialId") Long materialId) {
  60 + return materialService.getInfo(materialId);
  61 + }
  62 +
  63 + /**
  64 + * 批量查询详情
  65 + *
  66 + * @param map
  67 + * @return
  68 + * @throws ParseException
  69 + */
  70 + @PostMapping("/getByIds")
  71 + public ResultBean getByIds(@RequestBody Map<String, List<Long>> map) throws ParseException {
  72 + List<Long> materialIds = map.get("materialIds");
  73 + materialIds.removeAll(Collections.singleton(null));
  74 + return materialService.getByIds(materialIds);
  75 + }
  76 +
  77 + /**
  78 + * 文字识别信息
  79 + *
  80 + * @param materialId
  81 + * @param keywords
  82 + * @return
  83 + */
  84 + @GetMapping("/getAiWords")
  85 + public ResultBean getAiWords(@RequestParam Long materialId, @RequestParam(required = false) String keywords) {
  86 + if (ObjectUtil.isEmpty(materialId)) {
  87 + return ResultBean.error("媒资id必传");
  88 + }
  89 + return ResultBean.ok(materialService.getAiWords(materialId, keywords));
  90 + }
  91 +}
  1 +package com.wondertek.ivod.cmr.search.controller;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
  5 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  6 +import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
  7 +import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
  8 +import com.wondertek.ivod.cmr.search.service.IMaterialInfoService;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.web.bind.annotation.*;
  11 +
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * @Author yubin
  16 + * @Date 2021/8/6 15:29
  17 + * <p>
  18 + * 介质信息
  19 + */
  20 +@RestController
  21 +@RequestMapping("es/materialInfo")
  22 +public class MaterialInfoController {
  23 + @Autowired
  24 + private IMaterialInfoService materialInfoService;
  25 +
  26 + /**
  27 + * 新建
  28 + *
  29 + * @param materialInfo
  30 + * @return
  31 + */
  32 + @PostMapping("/create")
  33 + public ResultBean create(@RequestBody MaterialInfo materialInfo) {
  34 + materialInfoService.create(materialInfo);
  35 + return ResultBean.ok();
  36 + }
  37 +
  38 + /**
  39 + * 修改
  40 + *
  41 + * @param materialInfo
  42 + * @return
  43 + */
  44 + @PutMapping("/update")
  45 + public ResultBean update(@RequestBody MaterialInfo materialInfo) {
  46 + materialInfoService.update(materialInfo);
  47 + return ResultBean.ok();
  48 + }
  49 +
  50 + /**
  51 + * 批量删除
  52 + *
  53 + * @param materialDeleteDto
  54 + * @return
  55 + */
  56 + @DeleteMapping("/deleteInfos")
  57 + public ResultBean deleteInfos(@RequestBody MaterialDeleteDto materialDeleteDto) {
  58 + if (ObjectUtil.isEmpty(materialDeleteDto.getMaterialIds())) {
  59 + return ResultBean.error("媒资ID不能为空");
  60 + }
  61 + materialInfoService.deleteByIds(materialDeleteDto.getMaterialIds());
  62 + return ResultBean.ok();
  63 + }
  64 +
  65 + /**
  66 + * 通过ID查询
  67 + *
  68 + * @param materialId
  69 + * @return
  70 + */
  71 + @GetMapping("/getById")
  72 + public ResultBean getById(@RequestParam Long materialId) {
  73 + if (ObjectUtil.isEmpty(materialId)){
  74 + return ResultBean.error("媒资ID不能为空");
  75 + }
  76 + return ResultBean.ok(materialInfoService.getById(materialId));
  77 + }
  78 +}
  1 +package com.wondertek.ivod.cmr.search.enums;
  2 +
  3 +import java.util.Arrays;
  4 +
  5 +/**
  6 + * 全局枚举属性
  7 + * @date: 2021/4/6
  8 + */
  9 +public enum GlobalCodeEnum {
  10 + //错误枚举
  11 + UNKNOWN_ERROR("-1", "服务器异常"),
  12 + FAILURE("0", "failure"),
  13 + SUCCESS("1", "success"),
  14 + INVALID_PARAMS("2", "请求参数无效"),
  15 + UNSUPPORTED_URI("3", "未知URI"),
  16 + LACK_PARAMS("4", "请求参数缺失"),
  17 + PASS_URL_ERR("5", "组装pass层公共参数出现异常"),
  18 + DATE_ISNULL_ERR("6", "数据不存在!"),
  19 + REQUEST_PASS_ERROR("7", "请求pass层出现异常"),
  20 +
  21 + AI_CLOUD_ERR("3001","Ai云调度服务响应异常"),
  22 + ACCESS_CLOUD_ERR("3001","接入云调度服务响应异常"),
  23 + DATA_CLOUD_ERR("3001","数据云服务响应异常"),
  24 + ICLOUD_ERR("3001","存储云调度服务响应异常"),
  25 + MAINTENANCE_ERR("3001","营维中台服务响应异常"),
  26 + ;
  27 +
  28 + private String code;
  29 + private String msg;
  30 +
  31 + private GlobalCodeEnum(String code, String msg) {
  32 + this.code = code;
  33 + this.msg = msg;
  34 + }
  35 +
  36 + public String getCode() {
  37 + return code;
  38 + }
  39 +
  40 + public String getMsg() {
  41 + return msg;
  42 + }
  43 +
  44 + /**
  45 + * 根据Key得到枚举的Value
  46 + * Lambda表达式,比较判断(JDK 1.8)
  47 + *
  48 + * @param key
  49 + * @return
  50 + */
  51 + public static String getMsg(String key) {
  52 + return Arrays.stream(GlobalCodeEnum.values())
  53 + .filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
  54 + .findFirst().orElse(GlobalCodeEnum.UNKNOWN_ERROR).getMsg();
  55 + }
  56 +}
  1 +package com.wondertek.ivod.cmr.search.exception;
  2 +
  3 +import com.wondertek.ivod.cmr.search.enums.GlobalCodeEnum;
  4 +
  5 +/**
  6 + * <p><b>BusinessException Description:</b> 业务类运行时异常, 所有业务类运行时异常继承于该异常</p>
  7 + * @author douzi
  8 + * <b>DATE</b> 2019年2月18日 上午10:27:00
  9 + */
  10 +public class DefaultException extends RuntimeException {
  11 +
  12 + private static final long serialVersionUID = 1L;
  13 +
  14 + protected int errorCode;
  15 +
  16 + public DefaultException(GlobalCodeEnum globalCodeEnum) {
  17 + super(globalCodeEnum.getMsg());
  18 + this.errorCode = Integer.parseInt(globalCodeEnum.getCode());
  19 + }
  20 + public DefaultException(GlobalCodeEnum globalCodeEnum, String message) {
  21 + super(message);
  22 + this.errorCode = Integer.parseInt(globalCodeEnum.getCode());
  23 + }
  24 +
  25 + public DefaultException(Throwable cause) {
  26 + super(cause);
  27 + }
  28 +
  29 + /**
  30 + * @param message
  31 + * @param cause
  32 + */
  33 + public DefaultException(int errorCode, String message, Throwable cause) {
  34 + super(message, cause);
  35 + this.errorCode = errorCode;
  36 + }
  37 +
  38 + /**
  39 + * @param message
  40 + */
  41 + public DefaultException(int errorCode, String message) {
  42 + super(message);
  43 + this.errorCode = errorCode;
  44 + }
  45 +
  46 + public DefaultException(String message) {
  47 + super(message);
  48 + this.errorCode = Integer.parseInt(GlobalCodeEnum.FAILURE.getCode());
  49 + }
  50 +
  51 + public DefaultException(String message,Throwable throwable) {
  52 + super(message + throwable.getMessage());
  53 + this.errorCode = Integer.parseInt(GlobalCodeEnum.FAILURE.getCode());
  54 + }
  55 + /**
  56 + * @param cause
  57 + */
  58 + public DefaultException(int errorCode, Throwable cause) {
  59 + super(cause);
  60 + this.errorCode = errorCode;
  61 + }
  62 +
  63 + public int getErrorCode() {
  64 + return this.errorCode;
  65 + }
  66 +}
  1 +package com.wondertek.ivod.cmr.search.exception;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  4 +import com.wondertek.ivod.cmr.search.enums.GlobalCodeEnum;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.http.converter.HttpMessageNotReadableException;
  7 +import org.springframework.validation.BindException;
  8 +import org.springframework.web.HttpRequestMethodNotSupportedException;
  9 +import org.springframework.web.bind.MissingServletRequestParameterException;
  10 +import org.springframework.web.bind.annotation.ExceptionHandler;
  11 +import org.springframework.web.bind.annotation.ResponseBody;
  12 +import org.springframework.web.bind.annotation.RestControllerAdvice;
  13 +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
  14 +
  15 +import javax.servlet.http.HttpServletRequest;
  16 +
  17 +/**
  18 + * @Title com.migu.editor.cloudeditor.advice
  19 + * @Author beckhamyht
  20 + * @Created 2019/5/23 19:01
  21 + */
  22 +
  23 +@RestControllerAdvice
  24 +@Slf4j
  25 +public class ExceptionHandlerAdvice {
  26 +
  27 +
  28 + @ExceptionHandler(Exception.class)
  29 + @ResponseBody
  30 + public ResultBean handlerException(HttpServletRequest req, Exception e) {
  31 + log.error(e.getMessage(), e);
  32 + return ResultBean.error(GlobalCodeEnum.UNKNOWN_ERROR.getCode(), GlobalCodeEnum.UNKNOWN_ERROR.getMsg());
  33 + }
  34 +
  35 +
  36 + @ExceptionHandler({BindException.class})
  37 + @ResponseBody
  38 + public ResultBean handlerBindException(BindException e) {
  39 + log.error(e.getMessage(), e);
  40 + return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
  41 + }
  42 +
  43 + @ExceptionHandler({HttpMessageNotReadableException.class})
  44 + @ResponseBody
  45 + public ResultBean handlerParseException(HttpMessageNotReadableException e) {
  46 + log.error(e.getMessage(), e);
  47 + return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
  48 + }
  49 +
  50 + @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
  51 + @ResponseBody
  52 + public ResultBean handlerParseException(HttpRequestMethodNotSupportedException e) {
  53 + log.error(e.getMessage(), e);
  54 + return ResultBean.error(GlobalCodeEnum.FAILURE.getCode(), e.getMessage());
  55 + }
  56 +
  57 + @ExceptionHandler(MethodArgumentTypeMismatchException.class)
  58 + @ResponseBody
  59 + public ResultBean handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
  60 + log.error(e.getMessage(), e);
  61 + return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
  62 + }
  63 +
  64 + @ExceptionHandler(MissingServletRequestParameterException.class)
  65 + @ResponseBody
  66 + public ResultBean missingServletRequestParameterException(MissingServletRequestParameterException e) {
  67 + log.error(e.getMessage(), e);
  68 + return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
  69 + }
  70 +
  71 + /**
  72 + * 自定义异常拦截
  73 + *
  74 + * @param ex
  75 + * @return
  76 + */
  77 + @ExceptionHandler({DefaultException.class})
  78 + public ResultBean DefaultException(DefaultException ex) {
  79 + log.error("{},{}",ex.getErrorCode(),ex.getMessage());
  80 + return ResultBean.error(ex.getErrorCode() + "", ex.getMessage());
  81 + }
  82 +
  83 +}
  1 +package com.wondertek.ivod.cmr.search.repository;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
  4 +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
  5 +
  6 +/**
  7 + * @Author yubin
  8 + * @Date 2021/8/6 15:27
  9 + */
  10 +public interface MaterialInfoRepository extends ElasticsearchRepository<MaterialInfo, Long> {
  11 +}
  1 +package com.wondertek.ivod.cmr.search.service;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * @Author yubin
  9 + * @Date 2021/8/6 15:28
  10 + */
  11 +public interface IMaterialInfoService {
  12 + void create(MaterialInfo materialInfo);
  13 +
  14 + void update(MaterialInfo materialInfo);
  15 +
  16 + void deleteByIds(List<Long> materialIds);
  17 +
  18 + MaterialInfo getById(Long materialId);
  19 +}
  1 +package com.wondertek.ivod.cmr.search.service;
  2 +
  3 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  4 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.WordInfo;
  5 +import com.wondertek.ivod.cmr.search.vo.MaterialPageReqVo;
  6 +
  7 +import java.text.ParseException;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * @Author Hcg
  12 + * @Date 2021/8/13
  13 + * @desc
  14 + */
  15 +public interface MaterialService {
  16 + /**
  17 + *人脸识别信息
  18 + * @param materialId 媒资id
  19 + * @param keywords 关键字
  20 + * @return ResultBean
  21 + */
  22 + ResultBean getFigure(Long materialId, String keywords,Integer page,Integer rows);
  23 +
  24 + /**
  25 + * 详情
  26 + * @param materialId 媒资id
  27 + * @return ResultBean
  28 + */
  29 + ResultBean getInfo(Long materialId);
  30 +
  31 + /**
  32 + * 列表分页查询
  33 + * @param vo 入参
  34 + * @return PageBean
  35 + */
  36 + ResultBean list(MaterialPageReqVo vo);
  37 +
  38 + /**
  39 + * 批量查询
  40 + * @param materialIds 媒资id数组
  41 + * @return ResultBean
  42 + */
  43 + ResultBean getByIds(List<Long> materialIds) throws ParseException;
  44 +
  45 + /**
  46 + * 文字识别信息
  47 + *
  48 + * @param materialId
  49 + * @param keywords
  50 + * @return
  51 + */
  52 + List<WordInfo> getAiWords(Long materialId, String keywords);
  53 +}
  1 +package com.wondertek.ivod.cmr.search.service.impl;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
  4 +import com.wondertek.ivod.cmr.search.repository.MaterialInfoRepository;
  5 +import com.wondertek.ivod.cmr.search.service.IMaterialInfoService;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.stereotype.Service;
  9 +
  10 +import java.util.ArrayList;
  11 +import java.util.List;
  12 +import java.util.Optional;
  13 +
  14 +/**
  15 + * @Author yubin
  16 + * @Date 2021/8/6 15:28
  17 + */
  18 +@Service
  19 +@Slf4j
  20 +public class MaterialInfoServiceImpl implements IMaterialInfoService {
  21 + @Autowired
  22 + private MaterialInfoRepository materialInfoRepository;
  23 +
  24 + @Override
  25 + public void create(MaterialInfo materialInfo) {
  26 + materialInfoRepository.save(materialInfo);
  27 + }
  28 +
  29 + @Override
  30 + public void update(MaterialInfo materialInfo) {
  31 + materialInfoRepository.save(materialInfo);
  32 + }
  33 +
  34 + @Override
  35 + public void deleteByIds(List<Long> materialIds) {
  36 + List<MaterialInfo> materialInfoList = new ArrayList<>();
  37 + materialIds.forEach(materialId -> {
  38 + MaterialInfo materialInfo = new MaterialInfo();
  39 + materialInfo.setMaterialId(materialId);
  40 + materialInfoList.add(materialInfo);
  41 + });
  42 + materialInfoRepository.deleteAll(materialInfoList);
  43 + }
  44 +
  45 + @Override
  46 + public MaterialInfo getById(Long materialId) {
  47 + Optional<MaterialInfo> optional = materialInfoRepository.findById(materialId);
  48 + if (optional.isPresent()) {
  49 + return optional.get();
  50 + }
  51 + return null;
  52 + }
  53 +}
  1 +package com.wondertek.ivod.cmr.search.service.impl;
  2 +
  3 +import cn.hutool.core.util.ObjectUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.hutool.json.JSONUtil;
  6 +import com.google.common.base.Joiner;
  7 +import com.google.common.collect.Lists;
  8 +import com.wondertek.ivod.cmr.commons.enums.CommonStatusEnum;
  9 +import com.wondertek.ivod.cmr.commons.enums.MaterialTypeEnum;
  10 +import com.wondertek.ivod.cmr.commons.exception.DefaultException;
  11 +import com.wondertek.ivod.cmr.commons.utils.PageBean;
  12 +import com.wondertek.ivod.cmr.commons.utils.ResultBean;
  13 +import com.wondertek.ivod.cmr.commons.utils.UserUtils;
  14 +import com.wondertek.ivod.cmr.core.entity.bean.*;
  15 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.PictureAnalysisResult;
  16 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.*;
  17 +import com.wondertek.ivod.cmr.search.repository.MaterialInfoRepository;
  18 +import com.wondertek.ivod.cmr.search.service.MaterialService;
  19 +import com.wondertek.ivod.cmr.search.vo.*;
  20 +import lombok.extern.slf4j.Slf4j;
  21 +import org.apache.lucene.search.join.ScoreMode;
  22 +import org.elasticsearch.index.query.BoolQueryBuilder;
  23 +import org.elasticsearch.index.query.QueryBuilders;
  24 +import org.elasticsearch.search.sort.FieldSortBuilder;
  25 +import org.elasticsearch.search.sort.SortBuilders;
  26 +import org.elasticsearch.search.sort.SortOrder;
  27 +import org.springframework.beans.BeanUtils;
  28 +import org.springframework.beans.factory.annotation.Autowired;
  29 +import org.springframework.data.domain.Page;
  30 +import org.springframework.data.domain.PageRequest;
  31 +import org.springframework.data.domain.Pageable;
  32 +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
  33 +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
  34 +import org.springframework.stereotype.Service;
  35 +import org.springframework.util.CollectionUtils;
  36 +
  37 +import java.text.ParseException;
  38 +import java.text.SimpleDateFormat;
  39 +import java.util.*;
  40 +import java.util.stream.Collectors;
  41 +
  42 +/**
  43 + * @Author Hcg
  44 + * @Date 2021/8/13
  45 + * @desc
  46 + */
  47 +@Slf4j
  48 +@Service
  49 +public class MaterialServiceImpl implements MaterialService {
  50 + @Autowired
  51 + private MaterialInfoRepository materialInfoRepository;
  52 +
  53 + @Override
  54 + public ResultBean getFigure(Long materialId, String keywords, Integer page, Integer rows) {
  55 + log.info("【视频详情】人脸识别信息入参:materialId={},keywords={}", materialId, keywords);
  56 + if (materialId == null) {
  57 + return PageBean.error("媒资id不能为空");
  58 + }
  59 + MaterialInfo materialInfo = materialInfoRepository.findById(materialId).orElse(null);
  60 + if (materialInfo == null) {
  61 + return PageBean.error("媒资信息不存在或者数据库媒资信息错误");
  62 + }
  63 + if (null == page || page < 1) {
  64 + page = 1;
  65 + }
  66 + if (null == rows || rows < 1) {
  67 + rows = 20;
  68 + }
  69 + log.info(materialInfo.toString());
  70 + List<FaceInfo> faceInfos = materialInfo.getFaceInfo();
  71 + //根据出现次数排序
  72 + if (!CollectionUtils.isEmpty(faceInfos)) {
  73 + Collections.sort(faceInfos, Comparator.comparing((FaceInfo faceInfo) ->
  74 + Integer.valueOf(faceInfo.getAppearRate() == null ? "0" : faceInfo.getAppearRate().replace("%", ""))).reversed());
  75 + int total = faceInfos.size();
  76 + int pageSum = (total - 1) / rows + 1;
  77 + if (!StrUtil.isBlank(keywords)) {
  78 + ArrayList<FaceInfo> list = Lists.newArrayList();
  79 + faceInfos.forEach(faceInfo -> {
  80 + if (StrUtil.isNotBlank(faceInfo.getFigureName())) {
  81 + if (faceInfo.getFigureName().contains(keywords)) {
  82 + list.add(faceInfo);
  83 + }
  84 + }
  85 + });
  86 + int total1 = list.size();
  87 + int pageSum1 = (total1 - 1) / rows + 1;
  88 + List<FaceInfo> collect1 = list.stream().skip((page - 1) * rows).limit(rows).collect(Collectors.toList());
  89 + return PageBean.ok(pageSum1, (long) total1, collect1);
  90 + }
  91 + List<FaceInfo> collect = faceInfos.stream().skip((page - 1) * rows).limit(rows).
  92 + collect(Collectors.toList());
  93 + return PageBean.ok(pageSum, (long) total, collect);
  94 + }
  95 + return PageBean.ok();
  96 + }
  97 +
  98 +
  99 + @Override
  100 + public ResultBean getInfo(Long materialId) {
  101 + log.info("【视频详情】获取详情信息入参:materialId={}", materialId);
  102 + if (materialId == null) {
  103 + return ResultBean.error("媒资id不能为空");
  104 + }
  105 + MaterialInfo materialInfo = materialInfoRepository.findById(materialId).orElse(null);
  106 + if (materialInfo == null) {
  107 + return ResultBean.error("媒资信息不存在或者数据库媒资信息错误");
  108 + }
  109 + BasicInfo basicInfo = materialInfo.getBasicInfo();
  110 + MaterialInfoVo materialInfoVo = new MaterialInfoVo();
  111 + if (null != basicInfo) {
  112 + BeanUtils.copyProperties(basicInfo, materialInfoVo);
  113 + if (!CollectionUtils.isEmpty(basicInfo.getTagInfoSet())) {
  114 + materialInfoVo.setLabel(Joiner.on(",").join(basicInfo.getTagInfoSet()));
  115 + }
  116 + if (null != basicInfo.getImageAttr()) {
  117 + materialInfoVo.setArtist(basicInfo.getImageAttr().getArtist());
  118 + materialInfoVo.setShootingTime(basicInfo.getImageAttr().getShootingTime());
  119 + materialInfoVo.setLocation(basicInfo.getImageAttr().getLocation());
  120 + }
  121 + if (!CollectionUtils.isEmpty(basicInfo.getCustomLabelSet())) {
  122 + materialInfoVo.setCustomLabel(Joiner.on(",").join(basicInfo.getCustomLabelSet()));
  123 + }
  124 + }
  125 + MediaInfo mediaInfo = materialInfo.getMediaInfo();
  126 + if (null != mediaInfo) {
  127 + materialInfoVo.setDuration(mediaInfo.getDuration() + "");
  128 + }
  129 + materialInfoVo.setAiAnalysisStatus(materialInfo.getMaterialStatus().getAiAnalysisStatus());
  130 + return ResultBean.ok(materialInfoVo);
  131 + }
  132 +
  133 + @Override
  134 + public ResultBean list(MaterialPageReqVo vo) {
  135 + Integer page = vo.getPage();
  136 + Integer rows = vo.getRows();
  137 + if (ObjectUtil.isEmpty(page) || ObjectUtil.isEmpty(rows) || page < 1 || rows < 1) {
  138 + return PageBean.error("分页参数不正确");
  139 + }
  140 + log.info("【视频列表查询】获取列表信息入参:{}", JSONUtil.toJsonStr(vo));
  141 + if (ObjectUtil.isNotEmpty(vo.getFaceId()) && ObjectUtil.isNotEmpty(vo.getKeywords())) {
  142 + return PageBean.error("图片同关键字只能有一个");
  143 + }
  144 +
  145 + String tenantId = UserUtils.getUser().getTenantId();
  146 + if (StrUtil.isBlank(tenantId)) {
  147 + return PageBean.error("租户id不存在");
  148 + }
  149 + //检索条件
  150 + BoolQueryBuilder query = getQuery(vo, vo.getFaceId(), tenantId);
  151 + //排序条件
  152 + FieldSortBuilder fsb = SortBuilders.fieldSort("basicInfo." + vo.getSidx()).order("asc".equals(vo.getSord()) ? SortOrder.ASC : SortOrder.DESC);
  153 + FieldSortBuilder fsb1 = SortBuilders.fieldSort("basicInfo.materialType").order(SortOrder.DESC);
  154 + //分页条件
  155 + Pageable pageable = PageRequest.of(vo.getPage() - 1, vo.getRows());
  156 + //构建查询
  157 + NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
  158 + .withQuery(query)
  159 + .withSort(fsb)
  160 + .withSort(fsb1)
  161 + .withPageable(pageable).withTrackScores(false)
  162 + .build();
  163 + Page<MaterialInfo> search = materialInfoRepository.search(searchQuery);
  164 + Long videoCount = 0L;
  165 + Long imgCount = 0L;
  166 + //添加条件,查询视频和图片数量
  167 + if (ObjectUtil.isNotEmpty(vo.getMaterialType())) {
  168 + if (MaterialTypeEnum.VIDEO.getCode().equals(vo.getMaterialType())) {
  169 + videoCount = search.getTotalElements();
  170 + }
  171 + if (MaterialTypeEnum.PICTURE.getCode().equals(vo.getMaterialType())) {
  172 + imgCount = search.getTotalElements();
  173 + }
  174 + } else {
  175 + query.must(QueryBuilders.termQuery("basicInfo.materialType", MaterialTypeEnum.VIDEO.getCode()));
  176 + NativeSearchQuery searchQuery1 = new NativeSearchQueryBuilder()
  177 + .withQuery(query)
  178 + .withSort(fsb)
  179 + .withPageable(pageable).withTrackScores(false)
  180 + .build();
  181 + Page<MaterialInfo> searchVideo = materialInfoRepository.search(searchQuery1);
  182 + videoCount = searchVideo.getTotalElements();
  183 + //查询图片数量
  184 + imgCount = search.getTotalElements() - videoCount;
  185 + }
  186 + ResultBean list = getVideoAndImageCount(search, vo.getFaceId(), vo.getKeywords(), videoCount, imgCount);
  187 + if (list != null) {
  188 + return list;
  189 + }
  190 + return PageBean.ok(search.getTotalPages(), search.getTotalElements(), search.getContent());
  191 + }
  192 +
  193 + @Override
  194 + public ResultBean getByIds(List<Long> materialIds) throws ParseException {
  195 + log.info("【视频批量查询】获取批量信息入参:{}", materialIds);
  196 + if (CollectionUtils.isEmpty(materialIds)) {
  197 + return ResultBean.error("媒资id不能为空");
  198 + }
  199 + ArrayList<MaterialInfo> list = Lists.newArrayList();
  200 + for (Long materialId : materialIds) {
  201 + MaterialInfo materialInfo = materialInfoRepository.findById(materialId).orElse(null);
  202 + if (null != materialInfo) {
  203 + //如果修改时间一天后还是分析中或上传中的改成失败
  204 + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  205 + BasicInfo basicInfo = materialInfo.getBasicInfo();
  206 + String updateTime = basicInfo.getUpdateTime();
  207 + Date parse = simpleDateFormat.parse(updateTime);
  208 + long time = parse.getTime();
  209 + MaterialStatus materialStatus = materialInfo.getMaterialStatus();
  210 + if (null != materialStatus) {
  211 + long currentTimeMillis = System.currentTimeMillis();
  212 + long l = (currentTimeMillis - time) / 1000;
  213 + if (l > (60 * 60 * 24)) {
  214 + if (CommonStatusEnum.WAIT.getCode().equals(materialStatus.getUploadStatus())) {
  215 + materialStatus.setUploadStatus(CommonStatusEnum.FAIL.getCode());
  216 + }
  217 + if (CommonStatusEnum.WAIT.getCode().equals(materialStatus.getAiAnalysisStatus())) {
  218 + materialStatus.setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
  219 + }
  220 + materialInfo.setMaterialStatus(materialStatus);
  221 + materialInfoRepository.save(materialInfo);
  222 + }
  223 +
  224 + }
  225 +
  226 + list.add(materialInfo);
  227 + }
  228 + }
  229 +
  230 + return ResultBean.ok(list);
  231 + }
  232 +
  233 + /**
  234 + * 设置查询条件
  235 + *
  236 + * @param vo 入参
  237 + * @param faceId 分析器结果
  238 + */
  239 + private BoolQueryBuilder getQuery(MaterialPageReqVo vo, String faceId, String tenantId) {
  240 + BoolQueryBuilder query = QueryBuilders.boolQuery();
  241 + query.must(QueryBuilders.termQuery("basicInfo.owner.tenantId", tenantId));
  242 + String keywords = vo.getKeywords();
  243 + if (StrUtil.isNotBlank(keywords)) {
  244 + query.should(QueryBuilders.wildcardQuery("basicInfo.name", "*" + keywords + "*"))
  245 + .should(QueryBuilders.wildcardQuery("basicInfo.tagInfoSet", keywords)).minimumShouldMatch(1);
  246 + }
  247 + if (ObjectUtil.isNotEmpty(faceId)) {
  248 + query.must(QueryBuilders.nestedQuery("faceInfo", QueryBuilders.termsQuery("faceInfo.figureId", faceId), ScoreMode.None));
  249 + }
  250 + if (ObjectUtil.isNotEmpty(vo.getMaterialType())) {
  251 + query.must(QueryBuilders.termQuery("basicInfo.materialType", vo.getMaterialType()));
  252 + }
  253 + if (ObjectUtil.isNotEmpty(vo.getSource())) {
  254 + query.must(QueryBuilders.termQuery("basicInfo.source", vo.getSource()));
  255 + }
  256 + if (ObjectUtil.isNotEmpty(vo.getStatus())) {
  257 + if (CommonStatusEnum.EXT.getCode().equals(vo.getStatus())) {
  258 + query.must(QueryBuilders.termQuery("materialStatus.embodyStatus", CommonStatusEnum.FAIL.getCode()));
  259 + } else {
  260 + query.must(QueryBuilders.termQuery("materialStatus.aiAnalysisStatus", vo.getStatus()));
  261 + }
  262 + }
  263 + return query;
  264 + }
  265 +
  266 +
  267 + /**
  268 + * 查询图片视频总数
  269 + *
  270 + * @param search 分页查询结果
  271 + * @param faceId 分析器结果
  272 + * @param keywords 关键字
  273 + * @param videoCount 视频数量
  274 + * @param imgCount 图片数量
  275 + * @return
  276 + */
  277 + private ResultBean getVideoAndImageCount(Page<MaterialInfo> search, String faceId, String keywords, Long videoCount, Long imgCount) {
  278 + List<MaterialInfo> content = search.getContent();
  279 + if (!CollectionUtils.isEmpty(content)) {
  280 + ArrayList<MaterialListVo> list = Lists.newArrayList();
  281 + content.forEach(materialInfo -> {
  282 + MaterialListVo materialListVo = new MaterialListVo();
  283 + BeanUtils.copyProperties(materialInfo, materialListVo);
  284 + materialListVo.setImgCount(imgCount);
  285 + materialListVo.setVideoCount(videoCount);
  286 + List<FaceInfo> faceInfo = materialInfo.getFaceInfo();
  287 + getFirstFaceInfo(faceId, keywords, materialListVo, faceInfo);
  288 + list.add(materialListVo);
  289 + });
  290 + return PageBean.ok(search.getTotalPages(), search.getTotalElements(), list);
  291 + }
  292 + return null;
  293 + }
  294 +
  295 +
  296 + /**
  297 + * 获取列表页人物展示
  298 + *
  299 + * @param faceId
  300 + * @param keywords
  301 + * @param materialListVo
  302 + * @param faceInfo
  303 + */
  304 + private void getFirstFaceInfo(String faceId, String keywords, MaterialListVo materialListVo, List<FaceInfo> faceInfo) {
  305 + FaceInfoVo faceInfoVo = new FaceInfoVo();
  306 + //当图片分析不为空时:
  307 + if (!CollectionUtils.isEmpty(faceInfo)) {
  308 + if (ObjectUtil.isNotEmpty(faceId)) {
  309 + //采用函数,当内循环结束满足条件时,结束外循环
  310 + lab:
  311 + for (FaceInfo info : faceInfo) {
  312 + if (StrUtil.isNotBlank(info.getFigureId())) {
  313 + if (info.getFigureId().equals(faceId)) {
  314 + BeanUtils.copyProperties(info, faceInfoVo);
  315 + if (!CollectionUtils.isEmpty(info.getFragments())) {
  316 + faceInfoVo.setAppearCount(info.getFragments().size());
  317 + }
  318 + break lab;
  319 + }
  320 + }
  321 + }
  322 + }
  323 + //当关键字不为空时:
  324 + if (StrUtil.isNotBlank(keywords)) {
  325 + for (FaceInfo info : faceInfo) {
  326 + if (StrUtil.isNotBlank(info.getFigureName())) {
  327 + if (info.getFigureName().contains(keywords)) {
  328 + BeanUtils.copyProperties(info, faceInfoVo);
  329 + if (!CollectionUtils.isEmpty(info.getFragments())) {
  330 + faceInfoVo.setAppearCount(info.getFragments().size());
  331 + }
  332 + break;
  333 + }
  334 + }
  335 + }
  336 + }
  337 + if (StrUtil.isBlank(faceInfoVo.getFigureName()) && StrUtil.isBlank(faceInfoVo.getFigureId())) {
  338 + Collections.sort(faceInfo, Comparator.comparing(FaceInfo::getAppearRate).reversed());
  339 + BeanUtils.copyProperties(faceInfo.get(0), faceInfoVo);
  340 + if (faceInfo.get(0).getFragments() != null && !CollectionUtils.isEmpty(faceInfo.get(0).getFragments())) {
  341 + faceInfoVo.setAppearCount(faceInfo.get(0).getFragments().size());
  342 + }
  343 + }
  344 + }
  345 + materialListVo.setFaceInfo(faceInfoVo);
  346 + }
  347 +
  348 + /**
  349 + * 文字识别信息
  350 + *
  351 + * @param materialId
  352 + * @param keywords
  353 + * @return
  354 + */
  355 + @Override
  356 + public List<WordInfo> getAiWords(Long materialId, String keywords) {
  357 + Optional<MaterialInfo> optional = materialInfoRepository.findById(materialId);
  358 + if (!optional.isPresent()) {
  359 + throw new DefaultException("该媒资不存在");
  360 + }
  361 + List<WordInfo> wordInfoList = optional.get().getWordInfo();
  362 + if (ObjectUtil.isNotEmpty(keywords)) {
  363 + wordInfoList = wordInfoList.stream().filter(wordInfo -> wordInfo.getWord().contains(keywords)).collect(Collectors.toList());
  364 + }
  365 + return wordInfoList;
  366 + }
  367 +}
  1 +package com.wondertek.ivod.cmr.search.vo;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.FaceInfo;
  4 +import lombok.Data;
  5 +
  6 +/**
  7 + * @Author Hcg
  8 + * @Date 2021/8/23
  9 + * @desc
  10 + */
  11 +@Data
  12 +public class FaceInfoVo extends FaceInfo {
  13 +
  14 + private Integer appearCount;
  15 +}
  1 +package com.wondertek.ivod.cmr.search.vo;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author Hcg
  7 + * @Date 2021/8/13
  8 + * @desc
  9 + */
  10 +@Data
  11 +public class MaterialInfoVo {
  12 +
  13 + private String duration;
  14 + /**
  15 + * 媒资类型
  16 + */
  17 + private Integer materialType;
  18 + /**
  19 + * 名称
  20 + */
  21 + private String name;
  22 + /**
  23 + * 来源
  24 + */
  25 + private Integer source;
  26 + /**
  27 + * 标签
  28 + */
  29 + private String label;
  30 + /**
  31 + * 封面图路径
  32 + */
  33 + private String previewUrl;
  34 + /**
  35 + * 视频路径
  36 + */
  37 + private String mediaUrl;
  38 + /**
  39 + * AI分析状态 0-未开启 1-成功 2-失败 3-进行中
  40 + */
  41 + private Integer aiAnalysisStatus;
  42 + /**
  43 + * 自定义标签
  44 + */
  45 + private String customLabel;
  46 + /**
  47 + * 图片拍摄时间
  48 + */
  49 + private String shootingTime;
  50 + /**
  51 + * 地点
  52 + */
  53 + private String location;
  54 + /**
  55 + * 作者
  56 + */
  57 + private String artist;
  58 +}
  1 +package com.wondertek.ivod.cmr.search.vo;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.PictureAnalysisResult;
  4 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.BasicInfo;
  5 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.MaterialStatus;
  6 +import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.MediaInfo;
  7 +import lombok.Data;
  8 +
  9 +import java.util.List;
  10 +
  11 +
  12 +/**
  13 + * @Author Hcg
  14 + * @Date 2021/8/18
  15 + * @desc
  16 + */
  17 +@Data
  18 +public class MaterialListVo {
  19 +
  20 + /**
  21 + * 视频数量
  22 + */
  23 + private Long videoCount;
  24 +
  25 + /**
  26 + * 图片数量
  27 + */
  28 + private Long imgCount;
  29 +
  30 + /**
  31 + * 媒资ID
  32 + */
  33 + private Long materialId;
  34 + /**
  35 + * 基本信息
  36 + */
  37 + private BasicInfo basicInfo;
  38 + /**
  39 + * 介质信息
  40 + */
  41 + private MediaInfo mediaInfo;
  42 + /**
  43 + * 人脸识别信息
  44 + */
  45 + private FaceInfoVo faceInfo;
  46 + /**
  47 + * 状态信息
  48 + */
  49 + private MaterialStatus materialStatus;
  50 +}
  1 +package com.wondertek.ivod.cmr.search.vo;
  2 +
  3 +import com.wondertek.ivod.cmr.core.entity.bean.analyser.PictureAnalysisResult;
  4 +import lombok.Data;
  5 +
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * @Author Hcg
  10 + * @Date 2021/8/13
  11 + * @desc
  12 + */
  13 +@Data
  14 +public class MaterialPageReqVo {
  15 + /**
  16 + * 关键词
  17 + */
  18 + private String keywords;
  19 +
  20 + /**
  21 + * 类型 1-视频 2-音频 3-图片
  22 + */
  23 + private Integer materialType;
  24 +
  25 + /**
  26 + * 来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控
  27 + */
  28 + private Integer source;
  29 +
  30 + /**
  31 + * 人脸检索陌生人id
  32 + */
  33 + private String faceId;
  34 +
  35 + private Integer page;
  36 + private Integer rows;
  37 +
  38 + private String sidx = "createTime";
  39 + private String sord = "desc";
  40 +
  41 + /**
  42 + * 状态 -1-收录失败 0-未开启AI 1-AI识别成功 2-AI识别失败
  43 + */
  44 + private Integer status;
  45 +}
  1 +package com.wondertek.ivod.cmr.search.vo;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * @Author Hcg
  7 + * @Date 2021/8/20
  8 + * @desc
  9 + */
  10 +@Data
  11 +public class PictureAnalysis {
  12 + private String namespace;
  13 +
  14 + private String faceImg;
  15 +
  16 + private String userId;
  17 +}
  1 +spring:
  2 +# elasticsearch:
  3 +# rest:
  4 +# uris: 127.0.0.1:9300
  5 + data:
  6 + elasticsearch:
  7 + cluster-name: elasticsearch
  8 + cluster-nodes: localhost:9300
  9 + repositories:
  10 + enabled: true
  1 +spring:
  2 + data:
  3 + elasticsearch:
  4 + cluster-name: elasticsearch
  5 + cluster-nodes: 192.168.1.72:9300
  6 + repositories:
  7 + enabled: true
  1 +spring:
  2 + data:
  3 + elasticsearch:
  4 + cluster-name: elasticsearch
  5 + cluster-nodes: 192.168.0.25:9301
  6 + repositories:
  7 + enabled: true
  8 +
  9 +#分析器上传接口
  10 +file:
  11 + pictureAnalysisUrl: http://figure-data-service/picture/person
  12 +#分析器侧命名空间
  13 +analyser:
  14 + namespace: cloud-media-resources
  1 +spring:
  2 + profiles:
  3 + active: preview #@spring.profiles.active@
  4 +
  5 +logging:
  6 + level:
  7 + com.wondertek.ivod.*: info
  8 + springfox.documentation.*: error
  9 + org.springframework.*: error
  1 +common:
  2 + group: SAAS_GROUP
  3 + nacos:
  4 + username: nacos
  5 + password: nacos
  6 + server-addr: localhost:8848
  1 +common:
  2 + group: SAAS_GROUP
  3 + nacos:
  4 + username: nacos
  5 + password: nacos
  6 + server-addr: 192.168.1.84:8848
  1 +common:
  2 + group: SAAS_GROUP
  3 + nacos:
  4 + username: nacos
  5 + password: nacos
  6 + server-addr: 192.168.0.14:8848
  1 +spring:
  2 + servlet:
  3 + multipart:
  4 + max-file-size: 104857600
  5 + max-request-size: 104857600
  6 + application:
  7 + name: cmr-search
  8 + cloud:
  9 + nacos:
  10 + discovery:
  11 + server-addr: ${common.nacos.server-addr}
  12 + namespace: ${spring.profiles.active}
  13 + group: ${common.group}
  14 + username: ${common.nacos.username}
  15 + password: ${common.nacos.password}
  16 +# enabled: false
  17 + config:
  18 + server-addr: ${common.nacos.server-addr}
  19 + namespace: ${spring.profiles.active}
  20 + group: ${common.group}
  21 + username: ${common.nacos.username}
  22 + password: ${common.nacos.password}
  23 + file-extension: yml
  24 + shared-configs:
  25 + - data-id: ${spring.application.name}-base.yaml
  26 + group: ${common.group}
  27 + refresh: true
  28 + extension-configs:
  29 + - data-id: ${spring.application.name}-fallback-resp.yml
  30 + group: ${common.group}
  31 + refresh: true
  32 + enabled: true
  33 +server:
  34 + port: 18667
  35 + servlet:
  36 + context-path: /cmr-search
  37 +logging:
  38 + file:
  39 + path: ./logs
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<configuration debug="false" scan="false">
  3 + <springProperty scop="context" name="app_name" source="spring.application.name" defaultValue="cmr-search"/>
  4 + <property name="log.path" value="logs" />
  5 + <property name="CONSOLE_LOG_PATTERN"
  6 + value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%msg%n"/>
  7 + <property name="CONSOLE_LOG_PATTERN_DETAIL"
  8 + value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|${PID:-}|%thread|${app_name:-}|%X{X-B3-TraceId:-}|%X{X-B3-SpanId:-}|%X{X-Span-Export:-}|%class.%method-%line|%msg%n"/>
  9 + <!-- Console log output -->
  10 + <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
  11 + <encoder>
  12 + <pattern>${CONSOLE_LOG_PATTERN_DETAIL}</pattern>
  13 + <charset>UTF-8</charset>
  14 + </encoder>
  15 + </appender>
  16 +
  17 + <!-- Log file debug output -->
  18 + <appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
  19 + <file>${log.path}/${app_name:-}.info.log</file>
  20 + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  21 + <fileNamePattern>logs/%d{yyyy-MM-dd}/${app_name:-}.%d{yyyy-MM-dd}.info.log</fileNamePattern>
  22 + <maxHistory>60</maxHistory>
  23 + </rollingPolicy>
  24 + <encoder>
  25 + <pattern>${CONSOLE_LOG_PATTERN}</pattern>
  26 + <charset>UTF-8</charset>
  27 + </encoder>
  28 + </appender>
  29 +
  30 + <!-- Log file error output -->
  31 + <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
  32 + <file>${log.path}/${app_name:-}.error.log</file>
  33 + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  34 + <!-- 按天回滚 daily -->
  35 + <fileNamePattern>logs/%d{yyyy-MM-dd}/${app_name:-}.%d{yyyy-MM-dd}.error.log</fileNamePattern>
  36 + <!-- 日志最大的历史 60天 -->
  37 + <maxHistory>60</maxHistory>
  38 + </rollingPolicy>
  39 + <encoder>
  40 + <pattern>${CONSOLE_LOG_PATTERN}</pattern>
  41 + <charset>UTF-8</charset>
  42 + </encoder>
  43 + <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
  44 + <level>ERROR</level>
  45 + </filter>
  46 + </appender>
  47 +
  48 + <!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
  49 + <root level="INFO">
  50 + <appender-ref ref="console" />
  51 + <appender-ref ref="logFile" />
  52 + <appender-ref ref="error" />
  53 + </root>
  54 +</configuration>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <groupId>org.springframework.boot</groupId>
  7 + <artifactId>spring-boot-starter-parent</artifactId>
  8 + <version>2.2.5.RELEASE</version>
  9 + <relativePath/>
  10 + </parent>
  11 + <modelVersion>4.0.0</modelVersion>
  12 +
  13 + <groupId>com.wondertek.ivod.cmr</groupId>
  14 + <artifactId>cloud-media-resources</artifactId>
  15 + <packaging>pom</packaging>
  16 + <version>1.0.0</version>
  17 + <modules>
  18 + <module>cmr-manage</module>
  19 + <module>cmr-commons</module>
  20 + <module>cmr-search</module>
  21 + <module>cmr-core</module>
  22 + </modules>
  23 +
  24 + <repositories>
  25 + <repository>
  26 + <id>wd-releases</id>
  27 + <name>wd-releases</name>
  28 + <url>http://180.167.180.242:7881/repository/3rd_part/</url>
  29 + </repository>
  30 + </repositories>
  31 +
  32 + <properties>
  33 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  34 + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  35 + <java.version>1.8</java.version>
  36 + <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
  37 + </properties>
  38 +
  39 + <dependencies>
  40 +
  41 + <dependency>
  42 + <groupId>org.springframework.cloud</groupId>
  43 + <artifactId>spring-cloud-context</artifactId>
  44 + <version>2.2.2.RELEASE</version>
  45 + </dependency>
  46 + <!--服务调用-->
  47 + <dependency>
  48 + <groupId>org.springframework.cloud</groupId>
  49 + <artifactId>spring-cloud-starter-openfeign</artifactId>
  50 + <version>2.2.5.RELEASE</version>
  51 + </dependency>
  52 + <!-- spring boot-->
  53 + <dependency>
  54 + <groupId>org.springframework.boot</groupId>
  55 + <artifactId>spring-boot-starter-web</artifactId>
  56 + </dependency>
  57 + <!-- search 基础依赖包 -->
  58 + <dependency>
  59 + <groupId>org.springframework.boot</groupId>
  60 + <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  61 + <version>2.0.8.RELEASE</version>
  62 + </dependency>
  63 + <dependency>
  64 + <groupId>org.elasticsearch.plugin</groupId>
  65 + <artifactId>transport-netty3-client</artifactId>
  66 + <version>5.6.14</version>
  67 + </dependency>
  68 + <dependency>
  69 + <groupId>org.apache.commons</groupId>
  70 + <artifactId>commons-lang3</artifactId>
  71 + <version>3.10</version>
  72 + </dependency>
  73 +
  74 + <!--Lombok-->
  75 + <dependency>
  76 + <groupId>org.projectlombok</groupId>
  77 + <artifactId>lombok</artifactId>
  78 + <version>1.18.12</version>
  79 + </dependency>
  80 +
  81 + <dependency>
  82 + <groupId>com.google.guava</groupId>
  83 + <artifactId>guava</artifactId>
  84 + <version>29.0-jre</version>
  85 + </dependency>
  86 +
  87 + <!-- 添加data jpa依赖 -->
  88 + <dependency>
  89 + <groupId>org.springframework.boot</groupId>
  90 + <artifactId>spring-boot-starter-data-jpa</artifactId>
  91 + </dependency>
  92 + <dependency>
  93 + <groupId>com.alibaba</groupId>
  94 + <artifactId>fastjson</artifactId>
  95 + <version>1.2.75</version>
  96 + </dependency>
  97 +
  98 + <dependency>
  99 + <groupId>cn.hutool</groupId>
  100 + <artifactId>hutool-all</artifactId>
  101 + <version>5.3.1</version>
  102 + </dependency>
  103 +
  104 + <dependency>
  105 + <groupId>com.fasterxml.jackson.core</groupId>
  106 + <artifactId>jackson-databind</artifactId>
  107 + <version>2.9.8</version>
  108 + </dependency>
  109 + <dependency>
  110 + <groupId>com.fasterxml.jackson.datatype</groupId>
  111 + <artifactId>jackson-datatype-jsr310</artifactId>
  112 + <version>2.7.4</version>
  113 + </dependency>
  114 + <dependency>
  115 + <groupId>org.codehaus.jackson</groupId>
  116 + <artifactId>jackson-mapper-asl</artifactId>
  117 + <version>1.8.7</version>
  118 + </dependency>
  119 +
  120 + <!-- https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-core-asl -->
  121 + <dependency>
  122 + <groupId>org.codehaus.jackson</groupId>
  123 + <artifactId>jackson-core-asl</artifactId>
  124 + <version>1.8.7</version>
  125 + </dependency>
  126 + <dependency>
  127 + <groupId>org.springframework.boot</groupId>
  128 + <artifactId>spring-boot-starter-test</artifactId>
  129 + <scope>test</scope>
  130 + </dependency>
  131 + </dependencies>
  132 +
  133 + <build>
  134 + <plugins>
  135 + <plugin>
  136 + <groupId>org.apache.maven.plugins</groupId>
  137 + <artifactId>maven-surefire-plugin</artifactId>
  138 + <configuration>
  139 + <skipTests>true</skipTests>
  140 + </configuration>
  141 + </plugin>
  142 + </plugins>
  143 + </build>
  144 +
  145 +</project>
  1 +CREATE TABLE `cmr_ai_figure` (
  2 + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  3 + `material_Id` bigint(20) DEFAULT NULL COMMENT '媒资ID',
  4 + `figure_id` bigint(20) DEFAULT NULL COMMENT '分析器陌生人库ID',
  5 + `image_path` varchar(1024) DEFAULT NULL COMMENT '头像',
  6 + `begin_time` varchar(32) DEFAULT NULL COMMENT '露出开始时间',
  7 + `end_time` varchar(32) DEFAULT NULL COMMENT '露出结束时间',
  8 + `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  9 + PRIMARY KEY (`id`),
  10 + KEY `idx_ai_ids` (`material_Id`,`figure_id`)
  11 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='人物识别表 ';
  12 +
  13 +CREATE TABLE `cmr_figure` (
  14 + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '人物ID',
  15 + `name` varchar(128) DEFAULT NULL COMMENT '人物名称',
  16 + `figure_define_id` varchar(128) DEFAULT NULL COMMENT '人物自定义ID',
  17 + `gender` int(1) DEFAULT NULL COMMENT '性别 0-女 1-男',
  18 + `remark` varchar(128) DEFAULT NULL COMMENT '备注',
  19 + `familiar_figure_id` varchar(128) DEFAULT NULL COMMENT '分析器熟人id',
  20 + `preview_url` varchar(1024) DEFAULT NULL COMMENT '预览路径',
  21 + `tenant_Id` varchar(32) DEFAULT NULL COMMENT '租户ID',
  22 + `create_by` varchar(128) DEFAULT NULL COMMENT '创建人',
  23 + `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  24 + `update_by` varchar(128) DEFAULT NULL COMMENT '更新人',
  25 + `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  26 + PRIMARY KEY (`id`)
  27 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='人物表 ';
  28 +
  29 +CREATE TABLE `cmr_figure_image` (
  30 + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  31 + `figure_id` varchar(32) DEFAULT NULL COMMENT '人物ID',
  32 + `name` datetime DEFAULT NULL COMMENT '名称',
  33 + `type` varchar(32) DEFAULT NULL COMMENT '图片类型',
  34 + `image_path` datetime DEFAULT NULL COMMENT '图片路径',
  35 + `resolution` varchar(32) DEFAULT NULL COMMENT '分辨率',
  36 + `width` varchar(32) DEFAULT NULL COMMENT '宽',
  37 + `high` varchar(32) DEFAULT NULL COMMENT '高',
  38 + `md5` varchar(32) DEFAULT NULL COMMENT 'MD5',
  39 + PRIMARY KEY (`id`),
  40 + KEY `idx_image_figureid` (`figure_id`)
  41 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='人物图片表 ';
  42 +
  43 +CREATE TABLE `cmr_logs` (
  44 + `ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '乐观锁',
  45 + `operation_BY` varchar(32) DEFAULT NULL COMMENT '操作人',
  46 + `operation_TIME` datetime DEFAULT NULL COMMENT '操作时间',
  47 + `object_id` varchar(32) DEFAULT NULL COMMENT '对象ID',
  48 + `object_type` varchar(32) DEFAULT NULL COMMENT '对象类型',
  49 + `operation__msg` varchar(512) DEFAULT NULL COMMENT '操作信息',
  50 + `operation__type` varchar(32) DEFAULT NULL COMMENT '操作类型',
  51 + `request_url` varchar(128) DEFAULT NULL COMMENT '请求URL',
  52 + PRIMARY KEY (`ID`),
  53 + KEY `idx_logs_objectid` (`object_id`)
  54 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作记录表 ';
  55 +
  56 +CREATE TABLE `cmr_material` (
  57 + `material_Id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '媒资ID',
  58 + `material_type` int(10) DEFAULT NULL COMMENT '媒资类型 1-视频 2-音频 3-图片',
  59 + `name` varchar(128) DEFAULT NULL COMMENT '名称',
  60 + `source` int(10) DEFAULT NULL COMMENT '来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控 ',
  61 + `tenant_Id` varchar(32) DEFAULT NULL COMMENT '租户ID',
  62 + `media_url` varchar(1024) DEFAULT NULL COMMENT '介质预览路径',
  63 + `preview_url` varchar(1024) DEFAULT NULL COMMENT '封面图',
  64 + `create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
  65 + `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  66 + `updated_by` varchar(32) DEFAULT NULL COMMENT '更新人',
  67 + `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
  68 + PRIMARY KEY (`material_Id`)
  69 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频表 ';
  70 +
  71 +CREATE TABLE `cmr_material_files` (
  72 + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '介质ID',
  73 + `material_Id` bigint(20) DEFAULT NULL COMMENT '媒资ID',
  74 + `width` varchar(32) DEFAULT NULL COMMENT '宽',
  75 + `height` varchar(32) DEFAULT NULL COMMENT '高',
  76 + `md5` varchar(1024) DEFAULT NULL COMMENT 'MD5',
  77 + `bit_rate` varchar(32) DEFAULT NULL COMMENT '码率',
  78 + `type` varchar(32) DEFAULT NULL COMMENT '文件类型 VIDEO-视频 AUDIO-音频 PICTURE-图片',
  79 + `path` varchar(128) DEFAULT NULL COMMENT '文件路径',
  80 + PRIMARY KEY (`id`),
  81 + KEY `idx_files_Materialid` (`material_Id`)
  82 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频文件表 ';