root

云媒资

Showing 93 changed files with 4683 additions and 0 deletions

Too many changes to show.

To preserve performance only 93 of 93+ files are displayed.

  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 +}