root

云媒资

Showing 137 changed files with 7642 additions and 0 deletions
/.externalToolBuilders
/.settings
.svn
/.project
/target
target/
/.classpath
/src/main/webapp/temp
/src/main/webapp/source
/src/main/webapp/store
/src/main/webapp/depository
.idea/
*.iml
*.iws
*.ipr
*.ids
*.orig
classes/
*.properties
*.log
\ No newline at end of file
... ...
/.externalToolBuilders
/.settings
.svn
/.project
/target
target/
/.classpath
/src/main/webapp/temp
/src/main/webapp/source
/src/main/webapp/store
/src/main/webapp/depository
.idea/
*.iml
*.iws
*.ipr
*.ids
*.orig
classes/
*.properties
*.log
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud-media-resources</artifactId>
<groupId>com.wondertek.ivod.cmr</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.wondertek.ivod.cmr.commons</groupId>
<artifactId>cmr-commons</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>com.wondertek.ivod.cmr.core</groupId>
<artifactId>cmr-core</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
... ...
package com.wondertek.ivod.cmr.commons.constant;
/**
* @Author yubin
* @Date 2021/8/20 10:20
*/
public class FileConstant {
/**
* 视频类型
*/
public static final String VIDEO_TYPE = "mp4";
/**
* 视频最大
*/
public static final Long VIDEO_MAX_SIZE = 500L * 1024 * 1024;
/**
* 图片类型
*/
public static final String IMAGE_TYPE = "png,jpg,jpeg";
/**
* 图片最大
*/
public static final Long IMAGE_MAX_SIZE = 10L * 1024 * 1024;
}
... ...
package com.wondertek.ivod.cmr.commons.enums;
import java.util.Arrays;
/**
* @Author yubin
* @Date 2021/8/11 13:46
*
* 通用状态
*/
public enum CommonStatusEnum {
EXT(-1, "额外补充特殊状态"),
INIT(0, "初始化"),
SUCCESS(1, "成功"),
FAIL(2, "失败"),
WAIT(3, "进行中");
private Integer code;
private String msg;
CommonStatusEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
/**
* 根据Key得到枚举的Value
* Lambda表达式,比较判断(JDK 1.8)
*
* @param key
* @return
*/
public static String getMsg(String key) {
return Arrays.stream(CommonStatusEnum.values())
.filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
.findFirst().orElse(null).getMsg();
}
}
... ...
package com.wondertek.ivod.cmr.commons.enums;
import java.util.Arrays;
/**
* 全局枚举属性
* @date: 2021/4/6
*/
public enum GlobalCodeEnum {
//错误枚举
UNKNOWN_ERROR("-1", "服务器异常"),
FAILURE("0", "failure"),
SUCCESS("1", "success"),
INVALID_PARAMS("2", "请求参数无效"),
UNSUPPORTED_URI("3", "未知URI"),
LACK_PARAMS("4", "请求参数缺失"),
PASS_URL_ERR("5", "组装pass层公共参数出现异常"),
DATE_ISNULL_ERR("6", "数据不存在!"),
REQUEST_PASS_ERROR("7", "请求pass层出现异常"),
AI_CLOUD_ERR("3001","Ai云调度服务响应异常"),
ACCESS_CLOUD_ERR("3001","接入云调度服务响应异常"),
DATA_CLOUD_ERR("3001","数据云服务响应异常"),
ICLOUD_ERR("3001","存储云调度服务响应异常"),
MAINTENANCE_ERR("3001","营维中台服务响应异常"),
;
private String code;
private String msg;
private GlobalCodeEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
/**
* 根据Key得到枚举的Value
* Lambda表达式,比较判断(JDK 1.8)
*
* @param key
* @return
*/
public static String getMsg(String key) {
return Arrays.stream(GlobalCodeEnum.values())
.filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
.findFirst().orElse(GlobalCodeEnum.UNKNOWN_ERROR).getMsg();
}
}
... ...
package com.wondertek.ivod.cmr.commons.enums;
import java.util.Arrays;
/**
* @Author yubin
* @Date 2021/8/3 15:24
* <p>
* 媒资来源
*/
public enum MaterialSourceEnum {
LOCAL_UPLOAD(1, "本地上传"),
VIDEO_REMOVAL(2, "视频搬迁"),
LIVE_RECORDING(3, "直播录制"),
CLOUD_EDITING(4, "云剪辑"),
VIDEO_MONITORING(5, "视频监控");
private Integer code;
private String msg;
MaterialSourceEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
/**
* 根据Key得到枚举的Value
* Lambda表达式,比较判断(JDK 1.8)
*
* @param key
* @return
*/
public static String getMsg(String key) {
return Arrays.stream(MaterialSourceEnum.values())
.filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
.findFirst().orElse(null).getMsg();
}
}
... ...
package com.wondertek.ivod.cmr.commons.enums;
import java.util.Arrays;
/**
* @Author yubin
* @Date 2021/8/3 15:24
* <p>
* 媒资类型
*/
public enum MaterialTypeEnum {
VIDEO(1, "视频"),
AUDIO(2, "音频"),
PICTURE(3, "图片");
private Integer code;
private String msg;
MaterialTypeEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
/**
* 根据Key得到枚举的Value
* Lambda表达式,比较判断(JDK 1.8)
*
* @param key
* @return
*/
public static String getMsg(String key) {
return Arrays.stream(MaterialTypeEnum.values())
.filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
.findFirst().orElse(null).getMsg();
}
}
... ...
package com.wondertek.ivod.cmr.commons.enums;
/**
* @author xh
* @date 2023/9/18 11:18
*/
public enum OperateTypeEnum {
/**
* 下载
*/
DOWNLOAD("1", "下载"),
/**
* 浏览
*/
VIEW("2", "浏览");
private String code;
private String msg;
OperateTypeEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
... ...
package com.wondertek.ivod.cmr.commons.exception;
import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
/**
* <p><b>BusinessException Description:</b> 业务类运行时异常, 所有业务类运行时异常继承于该异常</p>
* @author douzi
* <b>DATE</b> 2019年2月18日 上午10:27:00
*/
public class DefaultException extends RuntimeException {
private static final long serialVersionUID = 1L;
protected int errorCode;
public DefaultException(GlobalCodeEnum globalCodeEnum) {
super(globalCodeEnum.getMsg());
this.errorCode = Integer.parseInt(globalCodeEnum.getCode());
}
public DefaultException(GlobalCodeEnum globalCodeEnum,String message) {
super(message);
this.errorCode = Integer.parseInt(globalCodeEnum.getCode());
}
public DefaultException(Throwable cause) {
super(cause);
}
/**
* @param message
* @param cause
*/
public DefaultException(int errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
/**
* @param message
*/
public DefaultException(int errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public DefaultException(String message) {
super(message);
this.errorCode = Integer.parseInt(GlobalCodeEnum.FAILURE.getCode());
}
public DefaultException(String message,Throwable throwable) {
super(message + throwable.getMessage());
this.errorCode = Integer.parseInt(GlobalCodeEnum.FAILURE.getCode());
}
/**
* @param cause
*/
public DefaultException(int errorCode, Throwable cause) {
super(cause);
this.errorCode = errorCode;
}
public int getErrorCode() {
return this.errorCode;
}
}
... ...
package com.wondertek.ivod.cmr.commons.exception;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import javax.servlet.http.HttpServletRequest;
/**
* @Title com.migu.editor.cloudeditor.advice
* @Author beckhamyht
* @Created 2019/5/23 19:01
*/
@RestControllerAdvice
@Slf4j
public class ExceptionHandlerAdvice {
@ExceptionHandler(Exception.class)
@ResponseBody
public ResultBean handlerException(HttpServletRequest req, Exception e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.UNKNOWN_ERROR.getCode(), GlobalCodeEnum.UNKNOWN_ERROR.getMsg());
}
@ExceptionHandler({BindException.class})
@ResponseBody
public ResultBean handlerBindException(BindException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
}
@ExceptionHandler({HttpMessageNotReadableException.class})
@ResponseBody
public ResultBean handlerParseException(HttpMessageNotReadableException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
}
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
@ResponseBody
public ResultBean handlerParseException(HttpRequestMethodNotSupportedException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.FAILURE.getCode(), e.getMessage());
}
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
@ResponseBody
public ResultBean handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
}
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseBody
public ResultBean missingServletRequestParameterException(MissingServletRequestParameterException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
}
/**
* 自定义异常拦截
*
* @param ex
* @return
*/
@ExceptionHandler({DefaultException.class})
public ResultBean DefaultException(DefaultException ex) {
log.error("{},{}",ex.getErrorCode(),ex.getMessage());
return ResultBean.error(ex.getErrorCode() + "", ex.getMessage());
}
}
... ...
package com.wondertek.ivod.cmr.commons.utils;
import cn.hutool.core.util.ObjectUtil;
import com.wondertek.ivod.cmr.commons.constant.FileConstant;
import com.wondertek.ivod.cmr.commons.enums.MaterialTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/4 14:48
*/
@Slf4j
@Component
public class FileUtils {
private static String uploadPath;
private static String downloadPath;
@Value("${file.uploadPath}")
public void setUploadPath(String uploadPath) {
FileUtils.uploadPath = uploadPath;
}
@Value("${file.downloadPath}")
public void setDownloadPath(String downloadPath) {
FileUtils.downloadPath = downloadPath;
}
/**
* MultipartFile 转 File
*
* @param file
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile file) {
File toFile = null;
String fileName = file.getOriginalFilename();
try {
InputStream ins = file.getInputStream();
//文件保存位置
String path = System.getProperty("user.dir");
File saveDir = new File(path + uploadPath);
if (!saveDir.exists()) {
saveDir.mkdir();
}
toFile = new File(saveDir + File.separator + fileName);
inputStreamToFile(ins, toFile);
ins.close();
} catch (Exception e) {
e.printStackTrace();
log.info("MultipartFile转File失败:{}", fileName);
}
return toFile;
}
//获取流文件
private static void inputStreamToFile(InputStream ins, File file) throws Exception {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
}
/**
* 删除本地临时文件
*
* @param file
*/
public static void delteTempFile(File file) {
if (file != null) {
File del = new File(file.toURI());
del.delete();
}
}
/**
* 从网络Url中下载文件
*
* @param urlStr
* @throws IOException
*/
public static File downLoadFromUrl(String urlStr, String fileName) {
File file = null;
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(false);
conn.setDoInput(true);
//连接建立超时时间还有读取数据超时时间
conn.setConnectTimeout(600000);
conn.setReadTimeout(600000);
conn.setRequestMethod("GET");
conn.connect();
//获取状态码
int code = conn.getResponseCode();
log.info(">>>>>>>>>>网络连接情况:{}", code);
//得到输入流
InputStream inputStream = conn.getInputStream();
//获取自己数组
byte[] getData = readInputStream(inputStream);
//文件保存位置
String path = System.getProperty("user.dir");
File saveDir = new File(path + downloadPath);
if (!saveDir.exists()) {
saveDir.mkdir();
}
//得到最后一个分隔符后的名字
file = new File(saveDir + File.separator + fileName);
FileOutputStream fos = new FileOutputStream(file);
fos.write(getData);
if (fos != null) {
fos.close();
}
if (inputStream != null) {
inputStream.close();
}
log.info("info:" + url + " download success");
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
/**
* 从输入流中获取字节数组
*
* @param inputStream
* @return
* @throws IOException
*/
public static byte[] readInputStream(InputStream inputStream) throws IOException {
byte[] buffer = new byte[1024];
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.close();
return bos.toByteArray();
}
/**
* 文件校验
*
* @param materialFile
* @return
*/
public static String checkFile(MultipartFile materialFile) {
List<String> videoType = Arrays.asList(FileConstant.VIDEO_TYPE.split(","));
List<String> imageType = Arrays.asList(FileConstant.IMAGE_TYPE.split(","));
String fileName = materialFile.getOriginalFilename();
if (ObjectUtil.isEmpty(fileName)) {
return "请选择要上传的文件";
}
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
long size = materialFile.getSize();
if (videoType.contains(fileType)) {
if (FileConstant.VIDEO_MAX_SIZE < size) {
return "不支持大于" + (FileConstant.VIDEO_MAX_SIZE / 1024 / 1024) + "M的视频文件上传";
}
} else if (imageType.contains(fileType)) {
if (FileConstant.IMAGE_MAX_SIZE < size) {
return "不支持大于" + (FileConstant.IMAGE_MAX_SIZE / 1024 / 1024) + "M的图片文件上传";
}
} else {
return "文件格式错误";
}
return null;
}
/**
* 图片文件校验
*
* @param materialFile
* @return
*/
public static String checkImageFile(MultipartFile materialFile) {
List<String> imageType = Arrays.asList(FileConstant.IMAGE_TYPE.split(","));
String fileName = materialFile.getOriginalFilename();
if (ObjectUtil.isEmpty(fileName)) {
return "请选择要上传的文件";
}
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
long size = materialFile.getSize();
if (imageType.contains(fileType)) {
if (FileConstant.IMAGE_MAX_SIZE < size) {
return "选择人脸照不能大于" + (FileConstant.IMAGE_MAX_SIZE / 1024 / 1024) + "M";
}
} else {
return "选择人脸照格式不符合要求";
}
return null;
}
/**
* 获取文件类型
*
* @param fileName
* @return
*/
public static Integer getFileType(String fileName) {
List<String> videoType = Arrays.asList(FileConstant.VIDEO_TYPE.split(","));
List<String> imageType = Arrays.asList(FileConstant.IMAGE_TYPE.split(","));
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
if (videoType.contains(fileType)) {
return MaterialTypeEnum.VIDEO.getCode();
} else if (imageType.contains(fileType)) {
return MaterialTypeEnum.PICTURE.getCode();
}
return null;
}
}
... ...
package com.wondertek.ivod.cmr.commons.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.net.URL;
/**
* @author admin
*/
@Slf4j
@Component
public class GetLocation {
/*public static void main(String[] args) {
// lat 39.97646
//log 116.3039
String add = getAdd("116.3039", "39.97646");
JSONObject jsonObject = JSONObject.parseObject(add);
JSONObject jsonArray = JSONArray.parseObject(jsonObject.getString("addrList"));
JSONObject j_2 = JSONObject.parseObject((String) jsonArray.get(0));
String allAdd = j_2.getString("admName");
String arr[] = allAdd.split(",");
System.out.println("省:"+arr[0]+"\n市:"+arr[1]+"\n区:"+arr[2]);
}*/
public static String getAdd(String Longitude, String Latitude ){
//lat 小 log 大
//参数解释: 纬度,经度 type 001 (100代表道路,010代表POI,001代表门址,111可以同时显示前三项)
String urlString = "https://apis.map.qq.com/ws/geocoder/v1/?location="+Latitude+","+Longitude+"&key=UUMBZ-PJLCI-KWMGL-UCFWF-XXKKS-XGF67&get_poi=1";
String res = "";
try {
URL url = new URL(urlString);
java.net.HttpURLConnection conn = (java.net.HttpURLConnection)url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("GET");
java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream(),"UTF-8"));
String line;
while ((line = in.readLine()) != null) {
res += line+"\n";
}
in.close();
} catch (Exception e) {
log.error("error in wapaction,and e is " + e.getMessage());
}
log.info(res);
return res;
}
}
... ...
package com.wondertek.ivod.cmr.commons.utils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.ArrayList;
import java.util.List;
/**
* 分页对象
*
* @author beckhamyht
* @param <T>
*/
@Data
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PageBean<T> extends ResultBean<Object> {
/**
* 总的页数
*/
private Integer totalPage;
/**
* 总记录数
*/
private Long totalCount;
/**
* 分页数据
*/
private List<T> result;
public PageBean(){}
/**
*
* @param totalPage 总页数
* @param totalCount 总数
* @param result
*/
public PageBean(Integer totalPage, Long totalCount, List<T> result) {
super(GlobalCodeEnum.SUCCESS.getCode(), GlobalCodeEnum.SUCCESS.getMsg());
this.totalPage = totalPage;
this.totalCount = totalCount;
this.result = result;
}
public static <T> PageBean<T> ok(Integer totalPage, Long totalCount, List<T> result){
return new PageBean<>(totalPage, totalCount, result);
}
public static <T> PageBean<T> empty() {
return new PageBean<>(0, 0L, new ArrayList<>());
}
}
... ...
package com.wondertek.ivod.cmr.commons.utils;
import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
import lombok.Data;
@Data
public class ResultBean<T> {
private String code;
private String msg;
private T result;
protected ResultBean() {
}
public ResultBean(String code, String msg) {
this.code = code;
this.msg = msg;
}
public ResultBean(String code, String msg, T result) {
super();
this.code = code;
this.msg = msg;
this.result = result;
}
public static ResultBean ok() {
return new ResultBean(GlobalCodeEnum.SUCCESS.getCode(), GlobalCodeEnum.SUCCESS.getMsg(), null);
}
public static ResultBean ok(Object data) {
return new ResultBean(GlobalCodeEnum.SUCCESS.getCode(), GlobalCodeEnum.SUCCESS.getMsg(), data);
}
public static ResultBean error(String msg) {
return new ResultBean(GlobalCodeEnum.FAILURE.getCode(), msg, null);
}
public static ResultBean error(String msg, Object data) {
return new ResultBean(GlobalCodeEnum.FAILURE.getCode(), msg, data);
}
public static ResultBean error(String code, String msg) {
return new ResultBean(code, msg, null);
}
}
... ...
package com.wondertek.ivod.cmr.commons.utils;
import cn.hutool.core.util.ObjectUtil;
import com.wondertek.ivod.cmr.commons.exception.DefaultException;
import com.wondertek.ivod.cmr.core.entity.bean.UserInfo;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
/**
* @Author yubin
* @Date 2021/8/4 13:54
*/
public class UserUtils {
private static ThreadLocal<UserInfo> loginUser = new ThreadLocal<>();
public static void setUser(HttpServletRequest request) {
UserInfo userInfo = new UserInfo();
Cookie[] cookies = request.getCookies();
if (ObjectUtil.isNotEmpty(cookies)) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("userId")) {
userInfo.setId(cookie.getValue());
continue;
}
if (cookie.getName().equals("userName")) {
userInfo.setUserName(cookie.getValue());
continue;
}
if (cookie.getName().equals("tenantId")) {
userInfo.setTenantId(cookie.getValue());
continue;
}
}
}
loginUser.set(userInfo);
}
public static void setUser(String userId, String userName, String tenantId) {
UserInfo userInfo = loginUser.get();
if (ObjectUtil.isEmpty(userInfo.getId())) {
userInfo = new UserInfo();
userInfo.setId(userId);
userInfo.setUserName(userName);
userInfo.setTenantId(tenantId);
loginUser.set(userInfo);
}
}
public static UserInfo getUser() {
return loginUser.get();
}
}
... ...
/.externalToolBuilders
/.settings
.svn
/.project
/target
target/
/.classpath
/src/main/webapp/temp
/src/main/webapp/source
/src/main/webapp/store
/src/main/webapp/depository
.idea/
*.iml
*.iws
*.ipr
*.ids
*.orig
classes/
*.properties
*.log
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud-media-resources</artifactId>
<groupId>com.wondertek.ivod.cmr</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cmr-core</artifactId>
<groupId>com.wondertek.ivod.cmr.core</groupId>
<packaging>jar</packaging>
<version>1.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
</dependencies>
</project>
\ No newline at end of file
... ...
package com.wondertek.ivod.cmr.core.entity.bean;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Polygon;
import lombok.Data;
import java.util.List;
/**
* @Author lyf
* @Date 2023/9/18 11:13
*/
@Data
public class ImageWordsData {
private String content;
private String confidence;
private List<Polygon> polygon;
private String start;
private String end;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.*;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/5 17:00
* <p>
* 介质es存储对象
*/
@Data
@Document(indexName = "cloud_media_resource", type = "material_info")
public class MaterialInfo {
/**
* 媒资ID
*/
@Id
@Field(type = FieldType.Long)
private Long materialId;
/**
* 基本信息
*/
@Field(type = FieldType.Object)
private BasicInfo basicInfo;
/**
* 介质信息
*/
@Field(type = FieldType.Object)
private MediaInfo mediaInfo;
/**
* 人脸识别信息
*/
@Field(type = FieldType.Nested)
private List<FaceInfo> faceInfo;
/**
* 文字识别信息
*/
@Field(type = FieldType.Nested)
private List<WordInfo> wordInfo;
/**
* 状态信息
*/
@Field(type = FieldType.Object)
private MaterialStatus materialStatus;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* @Author yubin
* @Date 2021/8/4 13:57
*/
@Data
public class UserInfo {
/**
* 用户ID
*/
@Field(type = FieldType.Keyword)
private String id;
/**
* 操作人
*/
@Field(type = FieldType.Keyword)
private String userName;
/**
* 租户ID
*/
@Field(type = FieldType.Keyword)
private String tenantId;
/**
* 所属类型
*/
@Field(type = FieldType.Keyword)
private String type;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Box;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Slce;
import lombok.Data;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/9 11:13
*/
@Data
public class VideoFigureData {
private String strangerId;
private String image;
private String featureStr;
private List<Slce> slces;
private String figureName;
private Box box;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Polygon;
import lombok.Data;
import java.util.List;
/**
* @Author lyf
* @Date 2023/9/18 11:13
*/
@Data
public class VideoWordsData {
private String[] content;
private String confidence;
private List<Polygon> polygon;
private String start;
private String end;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.analyser;
import lombok.Data;
/**
* @Author yubin
* @Date 2021/8/17 10:31
*
* 分析器上传接口返回结果
*/
@Data
public class AnalysisUploadResult {
/**
* 预览路径
*/
private String previewUrl;
/**
* 文件ID
*/
private String fileId;
/**
* 文件原名
*/
private String originalName;
/**
* 文件相对路径
*/
private String relativePath;
/**
* 封面图
*/
private String coverMap;
/**
* md5
*/
private String md5;
/**
* 宽
*/
private Integer height;
/**
* 长
*/
private Integer width;
/**
* 文件大小
*/
private Long size;
/**
* 时长
*/
private Long duration;
/**
* 码率
*/
private Long bitRate;
/**
* 文件类型
*/
private String fileType;
/**
* 文件格式
*/
private String format;
/**
* 云剪Id
*/
private String clipId;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.analyser;
import lombok.Data;
/**
* @Author yubin
* @Date 2021/10/19 14:33
*/
@Data
public class Feature2FigureResult {
private String familiarFigureId;
private String name;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.analyser;
import lombok.Data;
import java.io.Serializable;
/**
* @Author yubin
* @Date 2021/8/6 17:23
*
* 人物分析mq消息
*/
@Data
public class FigureAnalyseResult implements Serializable {
/**
* 媒资ID
*/
private String tag;
/**
* 分析结果存储路径
*/
private String path;
/**
* 状态 success:成功 file_decode_error:文件解析错误 file_notfund:文件找不到 error:未知错误 read_auth_error:文件读取权限 write_auth_error:结果无法写入
*/
private String status;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.analyser;
import lombok.Data;
import java.util.List;
/**
* @Author yubin
* @Date 2021/9/16 14:43
* <p>
* 熟人与人脸一起添加结果
*/
@Data
public class FigureFaceResult {
/**
* 熟人ID
*/
private String familiarFigureId;
private String namespace;
private List<Face> faces;
@Data
public class Face {
/**
* 人脸ID
*/
private String faceId;
/**
* 图片预览路径
*/
private String previewPath;
}
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.analyser;
import lombok.Data;
/**
* @Author yubin
* @Date 2021/8/19 16:01
*/
@Data
public class FileInfoToMq {
private String tag;
private String fileId;
private String relativePath;
private String namespace;
private String userId;
private String path;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.analyser;
import lombok.Data;
import java.io.Serializable;
/**
* @Author yubin
* @Date 2021/8/6 17:23
*
* 人物分析mq消息
*/
@Data
public class OcrAnalyseResult implements Serializable {
/**
* 媒资ID
*/
private String tag;
/**
* 分析结果存储路径
*/
private String path;
/**
* 状态 success:成功 file_decode_error:文件解析错误 file_notfund:文件找不到 error:未知错误 read_auth_error:文件读取权限 write_auth_error:结果无法写入
*/
private String status;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.analyser;
import lombok.Data;
/**
* @Author Hcg
* @Date 2021/8/23
* @desc
*/
@Data
public class PictureAnalysisResult {
private Long faceId;
private String feature;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import com.wondertek.ivod.cmr.core.entity.bean.UserInfo;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.Set;
/**
* @Author yubin
* @Date 2021/8/5 16:26
* <p>
* 基本信息
*/
@Data
public class BasicInfo {
/**
* 媒资ID
*/
@Field(type = FieldType.Long)
private Long materialId;
/**
* 媒资类型 1-视频 2-音频 3-图片
*/
@Field(type = FieldType.Integer)
private Integer materialType;
/**
* 名称
*/
@Field(type = FieldType.Keyword)
private String name;
/**
* 创建时间
*/
@Field(type = FieldType.Keyword)
private String createTime;
/**
* 更新时间
*/
@Field(type = FieldType.Keyword)
private String updateTime;
/**
* 来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控
*/
@Field(type = FieldType.Integer)
private Integer source;
/**
* 标签
*/
@Field(type = FieldType.Keyword)
private Set<String> tagInfoSet;
/**
* 封面图路径
*/
@Field(type = FieldType.Keyword, index = false)
private String previewUrl;
/**
* 视频路径
*/
@Field(type = FieldType.Keyword, index = false)
private String mediaUrl;
/**
* 用户
*/
@Field(type = FieldType.Object)
private UserInfo owner;
/**
* 文件ID
*/
@Field(type = FieldType.Keyword, index = false)
private String fileId;
/**
* 云剪ID
*/
@Field(type = FieldType.Keyword, index = false)
private String clipId;
/**
* 文件相对路径
*/
@Field(type = FieldType.Keyword, index = false)
private String relativePath;
/**
* 标签
*/
@Field(type = FieldType.Keyword)
private Set<String> customLabelSet;
/**
* 标签
*/
@Field(type = FieldType.Keyword)
private ImageAttr imageAttr;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import lombok.Data;
/**
* @Author lyf
* @Date 2023/9/18 11:14
*/
@Data
public class Box {
private Long w;
private Long h;
private Long x;
private Long y;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import javax.persistence.Column;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/5 16:47
* <p>
* 人脸识别信息
*/
@Data
public class FaceInfo {
/**
* 人物ID
*/
@Field(type = FieldType.Keyword)
private String figureId;
/**
* 人物名称
*/
@Field(type = FieldType.Keyword)
private String figureName;
/**
* 人物图片路径
*/
@Field(type = FieldType.Keyword, index = false)
private String face;
/**
* 出现率
*/
@Field(type = FieldType.Keyword, index = false)
private String appearRate;
/**
* 出现总时长
*/
@Field(type = FieldType.Long, index = false)
private Long totalDuration;
/**
* 出现时间列表
*/
@Field(type = FieldType.Nested)
private List<Fragment> fragments;
/** 宽 */
@Field(type = FieldType.Keyword, index = false)
private String wight;
/** 高 */
@Field(type = FieldType.Keyword, index = false)
private String high;
/** 横坐标 */
@Field(type = FieldType.Keyword, index = false)
private String x;
/** 竖坐标 */
@Field(type = FieldType.Keyword, index = false)
private String y;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* @Author yubin
* @Date 2021/8/5 16:54
*
* 人物出现时间
*/
@Data
public class Fragment {
@Field(type = FieldType.Keyword, index = false)
private String start;
@Field(type = FieldType.Keyword, index = false)
private String end;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import javax.persistence.Column;
/**
* @author admin
*/
@Data
public class ImageAttr {
/**
* 拍摄时间
*/
@Field(type = FieldType.Keyword, index = false)
private String shootingTime;
/**
* 作者
*/
@Field(type = FieldType.Keyword, index = false)
private String artist;
/**
* 地点
*/
@Field(type = FieldType.Keyword, index = false)
private String location;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* @Author yubin
* @Date 2021/8/5 16:58
* <p>
* 状态信息
*/
@Data
public class MaterialStatus {
/**
* AI分析状态 0-未开启 1-成功 2-失败 3-进行中
*/
@Field(type = FieldType.Integer)
private Integer aiAnalysisStatus;
/**
* ocr分析状态 0-未开启 1-成功 2-失败 3-进行中
*/
@Field(type = FieldType.Integer)
private Integer ocrAnalysisStatus;
/**
* 上传状态 1-成功 2-失败 3-进行中
*/
@Field(type = FieldType.Integer)
private Integer uploadStatus;
/**
* 收录状态 1-成功 2-失败 3-进行中
*/
@Field(type = FieldType.Integer)
private Integer embodyStatus;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* @Author yubin
* @Date 2021/8/4 15:35
* <p>
* 介质信息
*/
@Data
public class MediaInfo {
/**
* 宽
*/
@Field(type = FieldType.Integer, index = false)
private Integer width;
/**
* 高
*/
@Field(type = FieldType.Integer, index = false)
private Integer height;
/**
* 时长
*/
@Field(type = FieldType.Long, index = false)
private Long duration;
/**
* 大小
*/
@Field(type = FieldType.Long, index = false)
private Long size;
/**
* md5
*/
@Field(type = FieldType.Keyword, index = false)
private String md5;
/**
* 码率
*/
@Field(type = FieldType.Long, index = false)
private Long bitRate;
/**
* 介质类型
*/
@Field(type = FieldType.Integer)
private Integer mediaType;
/**
* 图片属性
*/
@Field(type = FieldType.Keyword)
private ImageAttr imageAttr;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* @Author lyf
* @Date 2023/9/18 11:14
*/
@Data
public class Polygon {
@Field(type = FieldType.Keyword, index = false)
private Long x;
@Field(type = FieldType.Keyword, index = false)
private Long y;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import lombok.Data;
/**
* @Author yubin
* @Date 2021/8/9 11:14
*/
@Data
public class Slce {
private Long startTime;
private Long endTime;
}
... ...
package com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.List;
/**
* @Author yubin
* @Date 2021/10/14 10:12
* <p>
* 文字识别
*/
@Data
public class WordInfo {
@Field(type = FieldType.Keyword)
private String word;
/**
* 出现时间列表
*//*
@Field(type = FieldType.Nested)
private List<Fragment> fragments;*/
@Field(type = FieldType.Keyword, index = false)
private String start;
@Field(type = FieldType.Keyword, index = false)
private String end;
/**
* 坐标列表
*/
@Field(type = FieldType.Nested)
private List<Polygon> polygons;
}
... ...
package com.wondertek.ivod.cmr.core.entity.dto;
import lombok.Data;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/11 16:43
*/
@Data
public class AiAnalysisDto {
private List<Long> materialIds;
}
... ...
package com.wondertek.ivod.cmr.core.entity.dto;
import lombok.Data;
/**
* @Author yubin
* @Date 2021/10/18 10:26
*/
@Data
public class AnalysisPictureDto {
private String imageBase64;
}
... ...
package com.wondertek.ivod.cmr.core.entity.dto;
import lombok.Data;
import java.util.List;
/**
* @Author yubin
* @Date 2021/9/16 16:35
*/
@Data
public class FigureDeleteDto {
private List<Long> figureIds;
}
... ...
package com.wondertek.ivod.cmr.core.entity.dto;
import lombok.Data;
/**
* @Author yubin
* @Date 2021/9/18 14:25
*/
@Data
public class FigureUpdateDto {
private Long id;
private String name;
private String figureDefineId;
private Integer gender;
private String familiarFigureId;
private String remark;
}
... ...
package com.wondertek.ivod.cmr.core.entity.dto;
import lombok.Data;
/**
* @Author yubin
* @Date 2021/10/13 16:31
*/
@Data
public class MaterialAddDto {
/**
* 媒资名称
*/
private String name;
/**
* 是否开启AI智能识别 false-否 true-是
*/
private Boolean isOpenAi;
/**
* 媒资id,重新上传需要
*/
private Long materialId;
}
... ...
package com.wondertek.ivod.cmr.core.entity.dto;
import lombok.Data;
import java.util.List;
/**
* @Author yubin
* @Date 2021/10/13 16:31
*/
@Data
public class MaterialCustomLabelDto {
/**
* 自定义标签
*/
private String customLabel;
/**
* 媒资id
*/
private List<Long> materialIds;
}
... ...
package com.wondertek.ivod.cmr.core.entity.dto;
import lombok.Data;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/11 16:43
*/
@Data
public class MaterialDeleteDto {
private List<Long> materialIds;
}
... ...
package com.wondertek.ivod.cmr.core.entity.dto;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.MediaInfo;
import lombok.Data;
/**
* @Author yubin
* @Date 2021/8/17 10:59
*/
@Data
public class MaterialInfoDto extends MediaInfo {
private Long materialId;
/**
* 名称
*/
private String name;
/**
* 视频路径
*/
private String mediaUrl;
/**
* 封面图路径
*/
private String previewUrl;
/**
* 文件相对路径
*/
private String relativePath;
/**
* 文件ID
*/
private String fileId;
/**
* 是否开启AI智能识别 false-否 true-是
*/
private Boolean isOpenAi;
/**
* 云剪Id
*/
private String clipId;
}
... ...
package com.wondertek.ivod.cmr.core.entity.dto;
import lombok.Data;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/4 17:28
*/
@Data
public class MaterialInjectDto {
/**
* 来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控
*/
private Integer source;
/**
* 媒资
*/
private List<MaterialInfoDto> materialInfos;
/**
* 用户ID
*/
private String userId;
/**
* 操作人
*/
private String userName;
/**
* 租户ID
*/
private String tenantId;
}
... ...
package com.wondertek.ivod.cmr.core.entity.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author admin
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamicInsert
@DynamicUpdate
@ToString
@Entity
@Table(name="cmr_ai_figure")
public class AiFigure implements Serializable, Cloneable {
/** 主键 */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
/** 媒资ID */
@Column(name = "material_id")
private Long materialId;
/** 分析器陌生人库ID */
@Column(name = "figure_id")
private Long figureId;
/** 头像 */
@Column(name = "image_path")
private String imagePath;
/** 露出开始时间 */
@Column(name = "begin_time")
private String beginTime;
/** 露出结束时间 */
@Column(name = "end_time")
private String endTime;
/** 创建时间 */
@Column(name = "create_time")
private LocalDateTime createTime;
/** 宽 */
@Column(name = "wight")
private String wight;
/** 高 */
@Column(name = "high")
private String high;
/** 横坐标 */
@Column(name = "x_pos")
private String xPos;
/** 竖坐标 */
@Column(name = "y_pos")
private String yPos;
/** AI分析OCR结果 */
@Column(name = "content")
private String content;
/** AI分析类型空/1为人物 2OCR */
@Column(name = "type")
private String type;
}
... ...
package com.wondertek.ivod.cmr.core.entity.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author admin
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamicInsert
@DynamicUpdate
@ToString
@Entity
@Table(name="cmr_logs")
public class CmrLogs implements Serializable, Cloneable {
/** 乐观锁 */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
/** 租户ID */
@Column(name = "tenant_id")
private String tenantId;
/** 操作人 */
@Column(name = "operation_by")
private String operationBy;
/** 操作时间 */
@Column(name = "operation_time")
private LocalDateTime operationTime;
/** 对象ID */
@Column(name = "object_id")
private String objectId;
/** 对象类型 */
@Column(name = "object_type")
private String objectType;
/** 操作信息 */
@Column(name = "operation_msg")
private String operationMsg;
/** 操作类型 */
@Column(name = "operation_type")
private String operationType;
/** 请求URL */
@Column(name = "request_url")
private String requestUrl;
}
... ...
package com.wondertek.ivod.cmr.core.entity.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author admin
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamicInsert
@DynamicUpdate
@ToString
@Entity
@Table(name="cmr_figure")
public class Figure implements Serializable, Cloneable {
/** 人物ID */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
/** 人物名称 */
@Column(name = "name")
private String name;
/** 人物自定义ID */
@Column(name = "figure_define_id")
private String figureDefineId;
/** 性别 0-女 1-男 */
@Column(name = "gender")
private Integer gender;
/** 备注 */
@Column(name = "remark")
private String remark;
/** 分析器熟人id */
@Column(name = "familiar_figure_id")
private String familiarFigureId;
/** 预览路径 */
@Column(name = "preview_url")
private String previewUrl;
/** 租户ID */
@Column(name = "tenant_id")
private String tenantId;
/** 创建人 */
@Column(name = "create_by")
private String createBy;
/** 创建时间 */
@Column(name = "create_time")
private LocalDateTime createTime;
/** 更新人 */
@Column(name = "update_by")
private String updateBy;
/** 更新时间 */
@Column(name = "update_time")
private LocalDateTime updateTime;
}
... ...
package com.wondertek.ivod.cmr.core.entity.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author admin
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamicInsert
@DynamicUpdate
@ToString
@Entity
@Table(name="cmr_figure_image")
public class FigureImage implements Serializable, Cloneable {
/** 主键 */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
/** 人物ID */
private String figureId;
/** 名称 */
private String name;
/** 图片类型 */
private String type;
/** 图片路径 */
private String imagePath;
/** 分辨率 */
private String resolution;
/** 宽 */
private String width;
/** 高 */
private String high;
/** MD5 */
private String md5;
}
... ...
package com.wondertek.ivod.cmr.core.entity.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author xh
* @date 2023/9/15 17:08
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamicInsert
@DynamicUpdate
@ToString
@Entity
@Table(name="cmr_image_detail")
public class ImageDetail implements Serializable, Cloneable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "material_id")
private Long materialId;
/**
* 拍摄时间
*/
@Column(name = "shooting_time")
private String shootingTime;
/**
* 作者
*/
@Column(name = "artist")
private String artist;
/**
* 图片宽
*/
@Column(name = "image_width")
private String imageWidth;
/**
* 图片高
*/
@Column(name = "image_height")
private String imageHeight;
/**
* 压缩类型
*/
@Column(name = "compression_type")
private String compressionType;
/**
* 检测到的文件类型名称
*/
@Column(name = "detected_file_type_name")
private String detectedFileTypeName;
/**
* 检测到的MIME类型
*/
@Column(name = "detected_mime_type")
private String detectedMimeType;
/**
* 预期的文件扩展名
*/
@Column(name = "expected_file_name_extension")
private String expectedFileNameExtension;
/**
* 文件名
*/
@Column(name = "file_name")
private String fileName;
/**
* 文件大小
*/
@Column(name = "file_size")
private String fileSize;
/**
* 文件修改时间
*/
@Column(name = "file_modified_date")
private String fileModifiedDate;
/**
* 维度
*/
@Column(name = "gps_latitude")
private String gpsLatitude;
/**
* 经度
*/
@Column(name = "gps_longitude")
private String gpsLongitude;
/**
* 地点
*/
@Column(name = "location")
private String location;
}
... ...
package com.wondertek.ivod.cmr.core.entity.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author admin
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamicInsert
@DynamicUpdate
@ToString
@Entity
@Table(name="cmr_material")
public class Material implements Serializable, Cloneable {
/** 媒资ID */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "material_id")
private Long materialId;
/** 媒资类型 1-视频 2-音频 3-图片 */
@Column(name = "material_type")
private Integer materialType;
/** 名称 */
@Column(name = "name")
private String name;
/** 来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控 */
@Column(name = "source")
private Integer source;
/** 租户ID */
@Column(name = "tenant_id")
private String tenantId;
/** 介质预览路径 */
@Column(name = "media_url")
private String mediaUrl;
/** 封面图 */
@Column(name = "preview_url")
private String previewUrl;
/** 创建人 */
@Column(name = "create_by")
private String createBy;
/** 创建时间 */
@Column(name = "create_time")
private LocalDateTime createTime;
/** 更新人 */
@Column(name = "updated_by")
private String updatedBy;
/** 更新时间 */
@Column(name = "updated_time")
private LocalDateTime updatedTime;
/**
* 自定义标签,多个逗号分隔
*/
@Column(name = "custom_label")
private String customLabel;
}
... ...
package com.wondertek.ivod.cmr.core.entity.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author admin
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamicInsert
@DynamicUpdate
@ToString
@Entity
@Table(name="cmr_material_files")
public class MaterialFiles implements Serializable, Cloneable {
/** 介质ID */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id ;
/** 媒资ID */
@Column(name = "material_id")
private Long materialId;
/** 宽 */
@Column(name = "width")
private String width;
/** 高 */
@Column(name = "height")
private String height;
/** MD5 */
@Column(name = "md5")
private String md5;
/** 码率 */
@Column(name = "bit_rate")
private String bitRate;
/** 文件类型 */
@Column(name = "type")
private Integer type;
/** path */
@Column(name = "path")
private String path;
}
... ...
package com.wondertek.ivod.cmr.core.entity.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author xh
* @date 2023/9/18 10:47
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@DynamicInsert
@DynamicUpdate
@ToString
@Entity
@Table(name="cmr_operate_record")
public class OperateRecord implements Serializable, Cloneable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
/**
* 租户id
*/
@Column(name = "tenant_id")
private String tenantId;
/**
* 操作人名
*/
@Column(name = "user_name")
private String userName;
/**
* 操作类型 1-下载 2-浏览
*/
@Column(name = "operate_type")
private String operateType;
/**
* 浏览次数
*/
@Column(name = "view_count")
private Integer viewCount;
/**
* 下载次数
*/
@Column(name = "download_count")
private Integer downLoadCount;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(name = "created_time")
private LocalDateTime createdTime;
/**
* 操作对象id
*/
@Column(name = "operate_object_id")
private String operateObjectId;
}
... ...
package com.wondertek.ivod.cmr.core.entity.vo;
import lombok.Data;
/**
* @Author Hcg
* @Date 2021/8/23
* @desc
*/
@Data
public class PictureAnalysisVo {
private String faceId;
private String name;
}
... ...
package com.wondertek.ivod.cmr.core.entity.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* @Author yubin
* @Date 2021/9/16 10:22
*/
@Data
public class SimilarityMatchVo {
/**
* 头像路径
*/
private String previewUrl;
/**
* 名称
*/
private String name;
/**
* 可信度
*/
private BigDecimal score;
/**
* 熟人id
*/
private String familiarFigureId;
private String[] path;
}
... ...
package com.wondertek.ivod.cmr.core.repository;
import com.wondertek.ivod.cmr.core.entity.model.CmrLogs;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @Author yubin
* @Date 2021/8/3 16:32
*/
public interface CmrLogsRepository extends JpaRepository<CmrLogs, Long>, JpaSpecificationExecutor<CmrLogs> {
}
... ...
package com.wondertek.ivod.cmr.core.service;
/**
* @Author yubin
* @Date 2021/8/3 16:27
*/
public interface ICmrLogsService {
}
... ...
package com.wondertek.ivod.cmr.core.service.impl;
import com.wondertek.ivod.cmr.core.service.ICmrLogsService;
import org.springframework.stereotype.Service;
/**
* @Author yubin
* @Date 2021/8/3 16:28
*/
@Service
public class CmrLogsServiceImpl implements ICmrLogsService {
}
... ...
/.externalToolBuilders
/.settings
.svn
/.project
/target
target/
/.classpath
/src/main/webapp/temp
/src/main/webapp/source
/src/main/webapp/store
/src/main/webapp/depository
.idea/
*.iml
*.iws
*.ipr
*.ids
*.orig
classes/
*.properties
*.log
\ No newline at end of file
... ...
FROM 192.168.1.7/library/java8:centos7
ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
SPRING_PROFILE_ACTIVE=prod \
SPRING_OPTS="" \
JAVA_OPTS=""
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=${SPRING_PROFILE_ACTIVE} ${SPRING_OPTS}
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ADD target/*.jar /app.jar
\ No newline at end of file
... ...
FROM 192.168.1.7/library/java8:centos7
ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
SPRING_PROFILE_ACTIVE=preview \
SPRING_OPTS="" \
JAVA_OPTS=""
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=${SPRING_PROFILE_ACTIVE} ${SPRING_OPTS}
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ADD *.jar /app.jar
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud-media-resources</artifactId>
<groupId>com.wondertek.ivod.cmr</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.wondertek.ivod.cmr.manage</groupId>
<artifactId>cmr-manage</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.wondertek.ivod.cmr.commons</groupId>
<artifactId>cmr-commons</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.wondertek.ivod.cmr.core</groupId>
<artifactId>cmr-core</artifactId>
<version>1.0.0</version>
</dependency>
<!--web container-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- mysql JDBC驱动 代码生成使用-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.14.0</version>
</dependency>
</dependencies>
<!--如果需要打docker镜像,把注释放开即可-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.1.0</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>192.168.1.69/ai_lib/${project.artifactId}:${project.version}</imageName>
<dockerHost>http://192.168.1.70:2375</dockerHost>
<dockerDirectory>${basedir}/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<profiles>
<profile>
<id>docker</id>
<properties>
<spring.profiles.active>preview</spring.profiles.active>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<imageName>192.168.1.7/ivod/${project.artifactId}:${project.version}</imageName>
<dockerHost>http://192.168.1.70:2375</dockerHost>
<serverId>wd-harbor</serverId>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
\ No newline at end of file
... ...
package com.wondertek.ivod.cmr.manage;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(basePackages = {"com.wondertek.ivod"})
@EnableJpaRepositories(basePackages = {"com.wondertek.ivod"})
@EntityScan("com.wondertek.ivod.cmr.core.entity")
@EnableFeignClients(basePackages = {"com.wondertek.ivod"})
@EnableRabbit
@EnableAsync
public class CMRManageApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(CMRManageApplication.class, args);
SpringUtil springUtil = new SpringUtil();
springUtil.setApplicationContext(applicationContext);
}
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
... ...
package com.wondertek.ivod.cmr.manage.config;
import cn.hutool.json.JSONUtil;
import com.wondertek.ivod.cmr.commons.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
/**
* 请求参数与响应结果封装
*
* @Author: CuiSiBo
* @Date: 2020/5/6 17:03
* @Version 1.0
*/
@Aspect
@Component
@Slf4j
public class LogAspect {
@Pointcut("execution(public * com.wondertek.ivod.cmr.manage.controller.*Controller.*(..))")
public void webLog() {
}
@Around("webLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
//获取当前请求对象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//设置用户信息
UserUtils.setUser(request);
String uri = request.getRequestURI();
//记录入参
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
Object inParameter = getParameter(method, joinPoint.getArgs());
String paramStr = "{}";
if (ObjectUtils.isNotEmpty(inParameter)) {
paramStr = JSONUtil.parse(inParameter).toJSONString(0);
paramStr = paramStr.length() > 1000 ? paramStr.substring(0, 1000) : paramStr;
}
log.info(">>>>>>>>>> {} begin ! parameter:{}", uri, paramStr);
//执行接口
Object result = joinPoint.proceed();
//记录出参
String resultStr = "{}";
if (ObjectUtils.isNotEmpty(result)) {
resultStr = JSONUtil.parse(result).toJSONString(0);
resultStr = resultStr.length() > 1000 ? resultStr.substring(0, 1000) : resultStr;
}
long endTime = System.currentTimeMillis();
log.info(">>>>>>>>>> {} end, time-consuming:{}ms ! result:{}", uri, endTime - startTime, resultStr);
return result;
}
/**
* 根据方法和传入的参数获取请求参数
*/
private List<Map> getParameter(Method method, Object[] args) {
List<Map> argList = new ArrayList<>();
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
Map<String, Object> map = new HashMap<>();
map.put(parameters[i].getName(), args[i]);
argList.add(map);
}
return argList;
}
}
... ...
package com.wondertek.ivod.cmr.manage.config;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author yubin
* @Date 2021/8/12 17:32
*/
@Configuration
public class RabbitmqConfig {
//交换机名称
public static final String ANALYZER_FILE_EXCHANGE = "FileExchange";
//队列名称
public static final String ANALYZER_FILE_STORAGE_PATH_QUEUE = "analyzer_file_storage_path";
//路由
public static final String ANALYZER_FILE_STORAGE_PATH_ROUTING = "file.storagePath";
public static final String WORDS_ANALYZER_FILE_EXCHANGE = "ai-analyse";
public static final String WORDS_ANALYZER_FILE_STORAGE_PATH_ROUTING = "ocr.video";
//声明交换机
@Bean("itemTopicExchange")
public Exchange topicExchange(){
return ExchangeBuilder.topicExchange(ANALYZER_FILE_EXCHANGE).durable(true).build();
}
//声明队列
@Bean("itemQueue")
public Queue itemQueue(){
return QueueBuilder.durable(ANALYZER_FILE_STORAGE_PATH_QUEUE).build();
}
//绑定队列和交换机
@Bean
public Binding itemQueueExchange(@Qualifier("itemQueue") Queue queue,
@Qualifier("itemTopicExchange") Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with(ANALYZER_FILE_STORAGE_PATH_ROUTING).noargs();
}
}
... ...
package com.wondertek.ivod.cmr.manage.consumer;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.wondertek.ivod.cmr.commons.enums.CommonStatusEnum;
import com.wondertek.ivod.cmr.commons.exception.DefaultException;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
import com.wondertek.ivod.cmr.core.entity.bean.VideoFigureData;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.FigureAnalyseResult;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.FaceInfo;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Fragment;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.Slce;
import com.wondertek.ivod.cmr.core.entity.model.AiFigure;
import com.wondertek.ivod.cmr.core.entity.model.Material;
import com.wondertek.ivod.cmr.manage.feign.SearchFeignService;
import com.wondertek.ivod.cmr.manage.repository.AiFigureRepository;
import com.wondertek.ivod.cmr.manage.repository.MaterialRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
/**
* @Author yubin
* @Date 2021/8/6 16:21
*/
@Slf4j
@Component
public class FigureConsumer {
@Autowired
private SearchFeignService searchFeignService;
@Autowired
private MaterialRepository materialRepository;
@Autowired
private AiFigureRepository aiFigureRepository;
@Value("${analyser.filePath}")
private String filePath;
/**
* 人物分析
* 解析ai生成的人脸识别文件,更新信息到es
*
* @param message
*/
@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "${mq.anylzer.callbackQueue}", durable = "true"),
exchange = @Exchange(value = "${mq.anylzer.callbackExchange}", type = ExchangeTypes.TOPIC),
key = "${analyser.namespace}"), concurrency = "5")
public void figureAnalyse(Message message) {
String json = new String(message.getBody(), StandardCharsets.UTF_8);
log.info(">>>>>>>>>>接收到ai人物分析消息:{}", json);
FigureAnalyseResult figureAnalyseResult = JSONUtil.toBean(json, FigureAnalyseResult.class);
if (StrUtil.isBlank(figureAnalyseResult.getTag())) {
log.info(">>>>>>>>>>人物分析异常,介制ID为空");
return;
}
Long materialId = Long.valueOf(figureAnalyseResult.getTag());
Optional<Material> optionalMaterial = materialRepository.findById(materialId);
if (!optionalMaterial.isPresent()) {
log.info(">>>>>>>>>>人物分析异常,该介制信息不存在:{}", materialId);
return;
}
MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
if (ObjectUtil.isEmpty(materialInfo)) {
throw new DefaultException("该介质信息在es中不存在");
}
log.info(">>>>>>>>>>介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
//人物分析信息
List<AiFigure> aiFigureList = new ArrayList<>();
try {
if (!"success".equals(figureAnalyseResult.getStatus())) {
throw new DefaultException(">>>>>>>>>>人物分析异常,返回码:" + figureAnalyseResult.getStatus());
}
if ("success".equals(figureAnalyseResult.getStatus())) {
//修改ai分析状态
materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.SUCCESS.getCode());
//解析人物分析文件
if (StrUtil.isBlank(figureAnalyseResult.getPath())) {
throw new DefaultException(">>>>>>>>>>人物分析异常,文件路径为空");
}
//读取json文件,临时保存
String jsonPath = filePath + figureAnalyseResult.getPath();
log.info(">>>>>>>>>>人物分析json文件地址:{}", jsonPath);
File file = new File(jsonPath);
if (ObjectUtil.isEmpty(file)) {
throw new DefaultException(">>>>>>>>>>人物分析异常,下载文件失败");
}
JSONObject jsonObject = JSONUtil.readJSONObject(file, StandardCharsets.UTF_8);
JSONArray jsonArray = jsonObject.getJSONArray("faceDataList");
if (ObjectUtil.isEmpty(jsonArray)) {
log.info(">>>>>>>>>>人物分析数据为空");
return;
}
//保存人物分析信息
for (Object o : jsonArray) {
VideoFigureData videoFigureData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoFigureData.class);
for (Slce slce : videoFigureData.getSlces()) {
AiFigure aiFigure = new AiFigure();
aiFigure.setMaterialId(materialId);
aiFigure.setFigureId(Long.valueOf(videoFigureData.getStrangerId()));
aiFigure.setImagePath(videoFigureData.getImage());
aiFigure.setBeginTime(slce.getStartTime() + "");
aiFigure.setEndTime(slce.getEndTime() + "");
aiFigure.setCreateTime(LocalDateTime.now());
aiFigureList.add(aiFigure);
}
}
//人脸识别信息
List<FaceInfo> faceInfoList = new ArrayList<>();
//标签
Set<String> tagInfoSet = new TreeSet<>();
for (Object o : jsonArray) {
VideoFigureData videoFigureData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoFigureData.class);
FaceInfo faceInfo = new FaceInfo();
faceInfo.setFigureId(videoFigureData.getStrangerId());
faceInfo.setFigureName(videoFigureData.getFigureName());
faceInfo.setFace(videoFigureData.getImage());
if (ObjectUtil.isNotEmpty(videoFigureData.getFigureName())) {
tagInfoSet.add(videoFigureData.getFigureName());
}
//人物出现时间
List<Fragment> fragmentList = new ArrayList<>();
//出现总时长
AtomicLong totalDuration = new AtomicLong(0);
for (Slce slce : videoFigureData.getSlces()) {
Fragment fragment = new Fragment();
fragment.setStart(slce.getStartTime() + "");
fragment.setEnd(slce.getEndTime() + "");
fragmentList.add(fragment);
totalDuration.getAndAdd(slce.getEndTime() - slce.getStartTime());
}
faceInfo.setTotalDuration(totalDuration.longValue());
//出现率
BigDecimal appearRate = NumberUtil.div(totalDuration.toString(), materialInfo.getMediaInfo().getDuration() + "", 2).multiply(new BigDecimal("100"));
faceInfo.setAppearRate(appearRate.stripTrailingZeros().toPlainString() + "%");
faceInfo.setFragments(fragmentList);
faceInfoList.add(faceInfo);
}
materialInfo.setFaceInfo(faceInfoList);
materialInfo.getBasicInfo().setTagInfoSet(tagInfoSet);
} else {
materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
}
MaterialInfo originMaterialInfo = searchFeignService.getMaterialInfoById(materialInfo.getMaterialId()).getResult();
materialInfo.setWordInfo(originMaterialInfo.getWordInfo());
} catch (Exception e) {
e.printStackTrace();
materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
} finally {
//更新es
materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
//保存人物分析信息
if (CommonStatusEnum.SUCCESS.getCode().equals(materialInfo.getMaterialStatus().getAiAnalysisStatus())) {
aiFigureRepository.saveAll(aiFigureList);
}
}
}
}
... ...
package com.wondertek.ivod.cmr.manage.consumer;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.wondertek.ivod.cmr.commons.enums.CommonStatusEnum;
import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
import com.wondertek.ivod.cmr.commons.exception.DefaultException;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
import com.wondertek.ivod.cmr.core.entity.bean.VideoFigureData;
import com.wondertek.ivod.cmr.core.entity.bean.VideoWordsData;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.FigureAnalyseResult;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.*;
import com.wondertek.ivod.cmr.core.entity.model.AiFigure;
import com.wondertek.ivod.cmr.core.entity.model.Material;
import com.wondertek.ivod.cmr.manage.feign.SearchFeignService;
import com.wondertek.ivod.cmr.manage.repository.AiFigureRepository;
import com.wondertek.ivod.cmr.manage.repository.MaterialRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
/**
* @Author yubin
* @Date 2021/8/6 16:21
*/
@Slf4j
@Component
public class WordsConsumer {
@Autowired
private SearchFeignService searchFeignService;
@Autowired
private MaterialRepository materialRepository;
@Autowired
private AiFigureRepository aiFigureRepository;
@Value("${analyser.filePath}")
private String filePath;
/**
* 人物分析
* 解析ai生成的人脸识别文件,更新信息到es
*
* @param message
*/
@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "${mq.anylzer.ocr.callbackQueue}", durable = "true"),
exchange = @Exchange(value = "${mq.anylzer.ocr.callbackExchange}", type = ExchangeTypes.TOPIC),
key = "ocr.video.cloud-media-resources"), concurrency = "5")
public void figureAnalyse(Message message) {
String json = new String(message.getBody(), StandardCharsets.UTF_8);
log.info(">>>>>>>>>>接收到ai文字分析消息:{}", json);
JSONObject jsonResult = JSONUtil.parseObj(json);
String dataJson = jsonResult.get("data") + "";
String jsonPath = filePath + JSONUtil.parseObj(dataJson).get("path");
Long materialId = Long.valueOf((String) JSONUtil.parseObj(dataJson).get("tag"));
Optional<Material> optionalMaterial = materialRepository.findById(materialId);
if (!optionalMaterial.isPresent()) {
log.info(">>>>>>>>>>人物分析异常,该介制信息不存在:{}", materialId);
return;
}
MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
if (ObjectUtil.isEmpty(materialInfo)) {
throw new DefaultException("该介质信息在es中不存在");
}
log.info(">>>>>>>>>>介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
//文字分析信息
List<AiFigure> aiFigureList = new ArrayList<>();
try {
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
log.info(">>>>>>>>>>文字分析失败" + jsonResult.get("msg"));
materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.FAIL.getCode());
} else {
log.info(">>>>>>>>>>人物分析json文件地址:{}", jsonPath);
File file = new File(jsonPath);
if (ObjectUtil.isEmpty(file)) {
throw new DefaultException(">>>>>>>>>>人物分析异常,下载文件失败");
}
JSONObject jsonObject = JSONUtil.readJSONObject(file, StandardCharsets.UTF_8);
JSONArray jsonArray = jsonObject.getJSONArray("data");
if (ObjectUtil.isEmpty(jsonArray)) {
log.info(">>>>>>>>>>文字分析数据为空");
return;
}
//保存文字分析信息
for (Object o : jsonArray) {
VideoWordsData videoWordsData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoWordsData.class);
AiFigure aiFigure = new AiFigure();
aiFigure.setMaterialId(materialInfo.getMaterialId());
aiFigure.setContent(String.join(",", videoWordsData.getContent()));
aiFigure.setType("2");
aiFigure.setCreateTime(LocalDateTime.now());
aiFigure.setBeginTime(videoWordsData.getStart());
aiFigure.setEndTime(videoWordsData.getEnd());
aiFigureList.add(aiFigure);
}
//人脸识别信息
List<WordInfo> wordInfoList = new ArrayList<>();
//标签
Set<String> tagInfoSet = new TreeSet<>();
for (Object o : jsonArray) {
VideoWordsData videoWordsData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoWordsData.class);
WordInfo wordInfo = new WordInfo();
wordInfo.setWord(String.join(",", videoWordsData.getContent()));
wordInfo.setStart(videoWordsData.getStart());
wordInfo.setEnd(videoWordsData.getEnd());
wordInfoList.add(wordInfo);
}
materialInfo.setWordInfo(wordInfoList);
materialInfo.getBasicInfo().setTagInfoSet(tagInfoSet);
}
} catch (Exception e) {
e.printStackTrace();
materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.FAIL.getCode());
} finally {
MaterialInfo originMaterialInfo = searchFeignService.getMaterialInfoById(materialInfo.getMaterialId()).getResult();
materialInfo.setFaceInfo(originMaterialInfo.getFaceInfo());
//更新es
materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
//保存ocr分析信息
if (CommonStatusEnum.SUCCESS.getCode().equals(materialInfo.getMaterialStatus().getOcrAnalysisStatus())) {
aiFigureRepository.saveAll(aiFigureList);
}
}
}
}
... ...
package com.wondertek.ivod.cmr.manage.controller;
import cn.hutool.core.util.ObjectUtil;
import com.wondertek.ivod.cmr.commons.utils.FileUtils;
import com.wondertek.ivod.cmr.commons.utils.PageBean;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.dto.FigureDeleteDto;
import com.wondertek.ivod.cmr.core.entity.dto.FigureUpdateDto;
import com.wondertek.ivod.cmr.core.entity.model.Figure;
import com.wondertek.ivod.cmr.manage.service.IFigureService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* @Author yubin
* @Date 2021/9/15 14:09
*/
@RestController
@RequestMapping("figure")
public class FigureController {
@Autowired
private IFigureService figureService;
/**
* 查询人物列表
*
* @param keywords
* @param page
* @param rows
* @return
*/
@GetMapping("/pageList")
public ResultBean pageList(@RequestParam(required = false) String keywords,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int rows) {
Page<Figure> pages = figureService.pageList(keywords, page, rows);
return PageBean.ok(pages.getTotalPages(), pages.getTotalElements(), pages.getContent());
}
/**
* 人脸相似度匹配
*
* @param figureImage
* @param familiarFigureId
* @return
*/
@PostMapping("/similarityMatch")
public ResultBean similarityMatch(MultipartFile figureImage, String familiarFigureId) {
if (ObjectUtil.isEmpty(figureImage)) {
return ResultBean.error("请选择要上传的文件");
}
String checkResult = FileUtils.checkImageFile(figureImage);
if (ObjectUtil.isNotEmpty(checkResult)) {
return ResultBean.error(checkResult);
}
return figureService.similarityMatch(figureImage, familiarFigureId);
}
/**
* 添加人物
*
* @param figureImage
* @param figure
* @return
*/
@PostMapping("/add")
public ResultBean add(MultipartFile figureImage, Figure figure) {
if (ObjectUtil.isEmpty(figureImage) || ObjectUtil.isEmpty(figureImage.getOriginalFilename())) {
return ResultBean.error("请选择要上传的文件");
}
return figureService.add(figureImage, figure);
}
/**
* 修改人物
*
* @param figureImage
* @param figureUpdateDto
* @return
*/
@PutMapping("/update")
public ResultBean update(MultipartFile figureImage, FigureUpdateDto figureUpdateDto) {
if (ObjectUtil.isEmpty(figureUpdateDto.getId())) {
return ResultBean.error("id不能为空");
}
return figureService.update(figureImage, figureUpdateDto);
}
/**
* 批量删除人物
*
* @param figureDeleteDto
* @return
*/
@DeleteMapping("/batchDelete")
public ResultBean batchDelete(@RequestBody FigureDeleteDto figureDeleteDto) {
if (ObjectUtil.isEmpty(figureDeleteDto.getFigureIds())) {
return ResultBean.error("请选择要删除的人物");
}
figureService.batchDelete(figureDeleteDto.getFigureIds());
return ResultBean.ok();
}
/**
* 人物ID唯一校验
*
* @param id
* @param figureDefineId
* @return
*/
@GetMapping("/checkOnlyDefineId")
public ResultBean checkOnlyDefineId(@RequestParam(required = false) Long id, @RequestParam String figureDefineId) {
if (ObjectUtil.isEmpty(figureDefineId)) {
return ResultBean.error("人物ID必传");
}
return ResultBean.ok(figureService.checkOnlyDefineId(id, figureDefineId));
}
}
... ...
package com.wondertek.ivod.cmr.manage.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.wondertek.ivod.cmr.commons.utils.FileUtils;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.dto.*;
import com.wondertek.ivod.cmr.core.entity.model.Material;
import com.wondertek.ivod.cmr.manage.service.IMaterialService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* @Author yubin
* @Date 2021/8/3 15:18
*/
@RestController
@RequestMapping("material")
public class MaterialController {
@Autowired
private IMaterialService materialService;
/**
* 介质上传
*
* @param materialFile
* @param materialAddDto
* @return
*/
@PostMapping("/upload")
public ResultBean uploadFiles(MultipartFile materialFile, MaterialAddDto materialAddDto) {
if (ObjectUtil.isEmpty(materialFile)) {
return ResultBean.error("请选择要上传的文件");
}
String checkResult = FileUtils.checkFile(materialFile);
if (ObjectUtil.isNotEmpty(checkResult)) {
return ResultBean.error(checkResult);
}
if (ObjectUtil.isEmpty(materialAddDto.getName())) {
return ResultBean.error("媒资名称必传");
}
if (materialAddDto.getName().substring(0, materialAddDto.getName().lastIndexOf(".")).length() > 30) {
return ResultBean.error("文件名称不能大于30个字符");
}
if (ObjectUtil.isEmpty(materialAddDto.getIsOpenAi())) {
return ResultBean.error("是否开启AI智能识别必传");
}
return materialService.uploadFile(materialFile, materialAddDto);
}
/**
* 重新下发AI分析
*
* @param aiAnalysisDto
* @return
*/
@PostMapping("/aiAnalysis")
public ResultBean aiAnalysis(@RequestBody AiAnalysisDto aiAnalysisDto) {
if (ObjectUtil.isEmpty(aiAnalysisDto.getMaterialIds())) {
return ResultBean.error("请选择要AI分析的媒资");
}
materialService.aiAnalysis(aiAnalysisDto.getMaterialIds());
return ResultBean.ok();
}
/**
* 修改名称
*
* @param material
* @return
*/
@PutMapping("/update")
public ResultBean updateMaterial(@RequestBody Material material) {
if (ObjectUtil.isEmpty(material.getMaterialId())) {
return ResultBean.error("媒资id不能为空");
}
if (ObjectUtil.isEmpty(material.getName())) {
return ResultBean.error("文件名不能为空");
}
if (material.getName().substring(0, material.getName().lastIndexOf(".")).length() > 30) {
return ResultBean.error("文件名称不能大于30个字符");
}
materialService.updateMaterial(material.getMaterialId(), material.getName());
return ResultBean.ok();
}
@PutMapping("/updateLabel")
public ResultBean batchUpdateCustomLabel(@RequestBody MaterialCustomLabelDto materialCustomLabelDto) {
if (ObjectUtil.isEmpty(materialCustomLabelDto.getCustomLabel())) {
return ResultBean.error("自定义标签不能为空");
}
if (CollectionUtil.isEmpty(materialCustomLabelDto.getMaterialIds())) {
return ResultBean.error("媒资ID不能为空");
}
materialService.updateMaterialCustomLable(materialCustomLabelDto.getMaterialIds(), materialCustomLabelDto.getCustomLabel());
return ResultBean.ok();
}
/**
* 删除
*
* @param materialDeleteDto
* @return
*/
@DeleteMapping("/delete")
public ResultBean deleteMaterails(@RequestBody MaterialDeleteDto materialDeleteDto) {
if (ObjectUtil.isEmpty(materialDeleteDto.getMaterialIds())) {
return ResultBean.error("请选择要删除的媒资");
}
materialService.deleteMaterails(materialDeleteDto);
return ResultBean.ok();
}
/**
* 检索图片分析
*
* @param analysisPictureDto
* @return
*/
@PostMapping("/analysisPicture")
public ResultBean analysisPicture(@RequestBody AnalysisPictureDto analysisPictureDto) {
if (ObjectUtil.isEmpty(analysisPictureDto.getImageBase64())) {
return ResultBean.error("检索图片必传");
}
return ResultBean.ok(materialService.analysisPicture(analysisPictureDto.getImageBase64()));
}
/**
* 注入接口
*
* @param materialInjectDto
* @return
*/
@PostMapping("/inject")
public ResultBean inject(@RequestBody MaterialInjectDto materialInjectDto) {
if (ObjectUtil.isEmpty(materialInjectDto.getSource())) {
return ResultBean.error("来源必传");
}
if (ObjectUtil.isEmpty(materialInjectDto.getMaterialInfos())) {
return ResultBean.error("媒资信息为空");
}
if (ObjectUtil.isEmpty(materialInjectDto.getUserId())) {
return ResultBean.error("用户id必传");
}
if (ObjectUtil.isEmpty(materialInjectDto.getUserName())) {
return ResultBean.error("用户名必传");
}
if (ObjectUtil.isEmpty(materialInjectDto.getTenantId())) {
return ResultBean.error("租户id必传");
}
return ResultBean.ok(materialService.inject(materialInjectDto));
}
}
... ...
package com.wondertek.ivod.cmr.manage.controller;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.manage.service.IMaterialOperateRecordService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author xh
* @date 2023/9/18 11:07
*/
@RestController
@RequestMapping("/record")
public class OperateRecordController {
@Resource
private IMaterialOperateRecordService iMaterialOperateRecordService;
@GetMapping("/add")
public void add(@RequestParam String operateType,
@RequestParam String objectId) {
iMaterialOperateRecordService.saveOperateRecord(operateType, objectId);
}
@GetMapping("/getCount")
public ResultBean getCount(@RequestParam String objectId) {
return iMaterialOperateRecordService.getCount(objectId);
}
@GetMapping("/list")
public ResultBean pageList(@RequestParam(required = false) String objectId,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int rows) {
return iMaterialOperateRecordService.list(objectId, page, rows);
}
}
... ...
package com.wondertek.ivod.cmr.manage.feign;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* @Author yubin
* @Date 2021/8/6 15:40
* <p>
* es搜索
*/
@Component
@FeignClient(name = "cmr-search", url = "http://cmr-search:18667")
public interface SearchFeignService {
/**
* 新建介质
*
* @param materialInfo
* @return
*/
@PostMapping("/cmr-search/es/materialInfo/create")
ResultBean createMaterialInfo(@RequestBody MaterialInfo materialInfo);
/**
* 修改介质
*
* @param materialInfo
* @return
*/
@PutMapping("/cmr-search/es/materialInfo/update")
ResultBean updateMaterialInfo(@RequestBody MaterialInfo materialInfo);
/**
* 批量删除介质
*
* @param materialDeleteDto
* @return
*/
@DeleteMapping("/cmr-search/es/materialInfo/deleteInfos")
ResultBean deleteInfos(@RequestBody MaterialDeleteDto materialDeleteDto);
/**
* 通过ID查询介质
*
* @param materialId
* @return
*/
@GetMapping("/cmr-search/es/materialInfo/getById")
ResultBean<MaterialInfo> getMaterialInfoById(@RequestParam Long materialId);
/**
* 批量查询
*
* @param map
* @return
*/
@PostMapping("/cmr-search/material/getByIds")
ResultBean<List<MaterialInfo>> getByIds(@RequestBody Map<String, List<Long>> map);
}
... ...
package com.wondertek.ivod.cmr.manage.feign.fallback;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
import com.wondertek.ivod.cmr.manage.feign.SearchFeignService;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* @Author yubin
* @Date 2021/8/11 15:32
*/
@Component
public class SearchFeignFallBack implements FallbackFactory<SearchFeignService> {
@Override
public SearchFeignService create(Throwable throwable) {
return new SearchFeignService() {
@Override
public ResultBean createMaterialInfo(MaterialInfo materialInfo) {
return ResultBean.error("调用熔断了");
}
@Override
public ResultBean updateMaterialInfo(MaterialInfo materialInfo) {
return ResultBean.error("调用熔断了");
}
@Override
public ResultBean deleteInfos(MaterialDeleteDto materialDeleteDto) {
return ResultBean.error("调用熔断了");
}
@Override
public ResultBean<MaterialInfo> getMaterialInfoById(Long materialId) {
return ResultBean.error("调用熔断了");
}
@Override
public ResultBean<List<MaterialInfo>> getByIds(Map<String, List<Long>> map) {
return null;
}
};
}
}
... ...
package com.wondertek.ivod.cmr.manage.repository;
import com.wondertek.ivod.cmr.core.entity.model.AiFigure;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/11 14:27
*/
public interface AiFigureRepository extends JpaRepository<AiFigure, Long>, JpaSpecificationExecutor<AiFigure> {
@Modifying
@Transactional
@Query("delete from AiFigure a where a.materialId in :materialIds")
void deleteByMaterialIds(List<Long> materialIds);
}
... ...
package com.wondertek.ivod.cmr.manage.repository;
import com.wondertek.ivod.cmr.core.entity.model.Figure;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @Author yubin
* @Date 2021/8/11 14:26
*/
public interface FigureRepository extends JpaRepository<Figure, Long>, JpaSpecificationExecutor<Figure> {
/**
* 根据熟人id删除
*
* @param familiarFigureId
*/
void deleteByFamiliarFigureId(String familiarFigureId);
/**
* 根据人物自定义id查询
*
* @param figureDefineId
* @return
*/
Figure findByFigureDefineId(String figureDefineId);
}
... ...
package com.wondertek.ivod.cmr.manage.repository;
import com.wondertek.ivod.cmr.core.entity.model.ImageDetail;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author xh
* @date 2023/9/18 15:17
*/
@Repository
public interface ImageDetailRepository extends JpaRepository<ImageDetail, Long>, JpaSpecificationExecutor<ImageDetail> {
@Modifying
@Transactional
@Query("delete from ImageDetail a where a.materialId in :materialIds")
void deleteByMaterialIds(List<Long> materialIds);
}
... ...
package com.wondertek.ivod.cmr.manage.repository;
import com.wondertek.ivod.cmr.core.entity.model.Material;
import com.wondertek.ivod.cmr.core.entity.model.MaterialFiles;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/11 14:25
*/
public interface MaterialFilesRepository extends JpaRepository<MaterialFiles, Long>, JpaSpecificationExecutor<MaterialFiles> {
@Modifying
@Transactional
@Query("delete from MaterialFiles m where m.materialId in :materialIds")
void deleteByMaterialIds(List<Long> materialIds);
}
... ...
package com.wondertek.ivod.cmr.manage.repository;
import com.wondertek.ivod.cmr.core.entity.model.Material;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @Author yubin
* @Date 2021/8/3 15:43
*/
public interface MaterialRepository extends JpaRepository<Material, Long>, JpaSpecificationExecutor<Material> {
}
... ...
package com.wondertek.ivod.cmr.manage.repository;
import com.wondertek.ivod.cmr.core.entity.model.OperateRecord;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
/**
* @author xh
* @date 2023/9/18 11:03
*/
@Repository
public interface OperateRecordRepository extends JpaRepository<OperateRecord, Long>, JpaSpecificationExecutor<OperateRecord> {
/**
* 根据操作对象id查询记录
* @param operateObjectId
* @return
*/
OperateRecord findFirstByOperateObjectIdOrderByCreatedTimeDesc(String operateObjectId);
}
... ...
package com.wondertek.ivod.cmr.manage.service;
import com.wondertek.ivod.cmr.core.entity.model.ImageDetail;
/**
* @author xh
* @date 2023/9/18 14:09
*/
public interface ExtractImageDetailService {
/**
* 提取图片信息
* @param imagePath
*/
ImageDetail extractImageDetail(String imagePath, Long materialId);
}
... ...
package com.wondertek.ivod.cmr.manage.service;
/**
* @Author yubin
* @Date 2021/8/9 13:46
*/
public interface IAiFigureService {
}
... ...
package com.wondertek.ivod.cmr.manage.service;
import cn.hutool.json.JSONObject;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* @Author yubin
* @Date 2021/9/17 15:14
* <p>
* 分析器相关调用
*/
public interface IAnalyserService {
/**
* 上传文件到分析器
*
* @param materialFile
* @return
*/
JSONObject uploadFile(MultipartFile materialFile);
/**
* 分析器批量删除
*
* @param fileIdList 文件id列表
* @return
*/
JSONObject deletefileBatch(List<String> fileIdList);
/**
* 图片分析
*
* @param tag 唯一标识
* @param fileId 文件id
* @param relativePath 绝对路径
* @return
*/
JSONObject pictureAnalysis(String tag, String fileId, String relativePath);
JSONObject pictureAnalysisToWords(String tag, String fileId, String relativePath);
/**
* 熟人与人脸一起添加(新增或更新)
*
* @param figureImage 人脸
* @param name 名字
* @param gender 性别 0-女 1-男
* @param familiarFigureId 熟人id,为空则创建一个新人物,否则为该ID人物添加人脸
* @return
*/
JSONObject addOrUpdateFigureAndFace(MultipartFile figureImage, String name, Integer gender, String familiarFigureId);
/**
* 删除熟人(多个用“,”分隔)
*
* @param familiarFigureIds
* @return
*/
JSONObject deleteFigure(String familiarFigureIds);
/**
* 人脸相似度匹配
*
* @param figureImage
* @return
*/
JSONObject similarityMatch(MultipartFile figureImage);
/**
* 删除熟人所有人脸
*
* @param familiarFigureId 熟人id。多个用逗号隔开
* @return
*/
JSONObject deleteFigureAllFace(String familiarFigureId);
/**
* 修改熟人
*
* @param name 名称
* @param gender 性别 0-女 1-男
* @param familiarFigureId 熟人id
* @return
*/
JSONObject updateFigure(String name, Integer gender, String familiarFigureId);
/**
* 图片查陌生人
*
* @param imageBase64
* @return
*/
JSONObject getPictureAnalysisResult(String imageBase64);
/**
* 根据特征值查熟人
*
* @param feature
* @return
*/
JSONObject getFigureByFeature(String feature);
}
... ...
package com.wondertek.ivod.cmr.manage.service;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.dto.FigureUpdateDto;
import com.wondertek.ivod.cmr.core.entity.model.Figure;
import org.springframework.data.domain.Page;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/9 14:47
*/
public interface IFigureService {
/**
* 查询人物列表
*
* @param keywords
* @param page
* @param rows
* @return
*/
Page<Figure> pageList(String keywords, int page, int rows);
/**
* 人脸相似度匹配
*
* @param figureImage
* @param familiarFigureId
* @return
*/
ResultBean similarityMatch(MultipartFile figureImage, String familiarFigureId);
/**
* 添加人物
*
* @param figureImage
* @param figure
* @return
*/
ResultBean add(MultipartFile figureImage, Figure figure);
/**
* 修改人物
*
* @param figureImage
* @param figureUpdateDto
* @return
*/
ResultBean update(MultipartFile figureImage, FigureUpdateDto figureUpdateDto);
/**
* 批量删除人物
*
* @param figureIds
* @return
*/
void batchDelete(List<Long> figureIds);
/**
* 人物ID唯一校验
*
* @param id
* @param figureDefineId
* @return
*/
Boolean checkOnlyDefineId(Long id, String figureDefineId);
}
... ...
package com.wondertek.ivod.cmr.manage.service;
import cn.hutool.json.JSONObject;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialInfoDto;
import com.wondertek.ivod.cmr.core.entity.model.MaterialFiles;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/4 16:20
*/
public interface IMaterialFilesService {
MaterialFiles createMaterialFiles(MaterialInfoDto materialInfoDto);
}
... ...
package com.wondertek.ivod.cmr.manage.service;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
/**
* @author xh
* @date 2023/9/18 10:46
*/
public interface IMaterialOperateRecordService {
/**
* 保存操作记录
* @param type 1-下载 2-浏览
* @param objectId 操作对象id
*/
void saveOperateRecord(String type, String objectId);
/**
* 查询记录列表
* @param objectId
* @param page
* @param rows
* @return
*/
ResultBean list(String objectId, int page, int rows);
/**
* 统计预览、下载次数
* @param objectId
* @return
*/
ResultBean getCount(String objectId);
}
... ...
package com.wondertek.ivod.cmr.manage.service;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialAddDto;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialInjectDto;
import com.wondertek.ivod.cmr.core.entity.vo.PictureAnalysisVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/3 15:41
*/
public interface IMaterialService {
ResultBean uploadFile(MultipartFile materialFile, MaterialAddDto materialAddDto);
void aiAnalysis(List<Long> materialIds);
List<Long> inject(MaterialInjectDto materialInjectDto);
void updateMaterial(Long materialId, String name);
void updateMaterialCustomLable(List<Long> materialIds, String customLabels);
void deleteMaterails(MaterialDeleteDto materialDeleteDto);
PictureAnalysisVo analysisPicture(String imageBase64);
}
... ...
package com.wondertek.ivod.cmr.manage.service.impl;
import com.wondertek.ivod.cmr.manage.service.IAiFigureService;
import org.springframework.stereotype.Service;
/**
* @Author yubin
* @Date 2021/8/9 13:47
*/
@Service
public class AiFigureServiceImpl implements IAiFigureService {
}
... ...
package com.wondertek.ivod.cmr.manage.service.impl;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.wondertek.ivod.cmr.commons.utils.FileUtils;
import com.wondertek.ivod.cmr.commons.utils.UserUtils;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.FileInfoToMq;
import com.wondertek.ivod.cmr.manage.service.IAnalyserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author yubin
* @Date 2021/9/17 15:15
*/
@Slf4j
@Service
public class AnalyserServiceImpl implements IAnalyserService {
@Autowired
private RestTemplate restTemplate;
@Value("${analyser.namespace}")
private String namespace;
@Value("${analyser.uploadUrl}")
private String uploadUrl;
@Value("${analyser.fileBatchDeleteUrl}")
private String fileBatchDeleteUrl;
@Value("${analyser.pictureAnalysisUrl}")
private String pictureAnalysisUrl;
@Value("${analyser.similarityMatchUrl}")
private String similarityMatchUrl;
@Value("${analyser.deleteFigureUrl}")
private String deleteFigureUrl;
@Value("${analyser.figureFaceUrl}")
private String figureFaceUrl;
@Value("${analyser.deleteFigureFaceUrl}")
private String deleteFigureFaceUrl;
@Value("${analyser.updateFigureUrl}")
private String updateFigureUrl;
@Value("${analyser.picturePersonUrl}")
private String picturePersonUrl;
@Value("${analyser.feature2figureUrl}")
private String feature2figureUrl;
@Value("${analyser.pictureAnalysisToWordsUrl}")
private String pictureAnalysisToWordsUrl;
@Override
public JSONObject uploadFile(MultipartFile materialFile) {
File file = null;
try {
//调用存储云存储文件
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.set("namespace", namespace);
map.set("userId", UserUtils.getUser().getTenantId());
file = FileUtils.multipartFileToFile(materialFile);
map.set("file", new FileSystemResource(file));
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
log.info(">>>>>>>>>>开始调用分析器上传接口:{}", JSONUtil.toJsonStr(map));
Object result = restTemplate.postForObject(uploadUrl, request, Object.class);
log.info(">>>>>>>>>>调用分析器上传接口结果:{}", JSONUtil.toJsonStr(result));
return JSONUtil.parseObj(result);
} finally {
FileUtils.delteTempFile(file);
}
}
@Override
public JSONObject deletefileBatch(List<String> fileIdList) {
Map<String, Object> fileMap = new HashMap<>();
fileMap.put("fileIds", fileIdList);
fileMap.put("namespace", namespace);
fileMap.put("userId", UserUtils.getUser().getTenantId());
log.info(">>>>>>>>>>调用分析器删除文件接口:{}", JSONUtil.toJsonStr(fileMap));
Object result = restTemplate.postForObject(fileBatchDeleteUrl, fileMap, Object.class);
log.info(">>>>>>>>>>调用分析器删除文件接口结果:{}", JSONUtil.toJsonStr(result));
return JSONUtil.parseObj(result);
}
/**
* @param tag
* @param fileId
* @param relativePath
* @return
*/
@Override
public JSONObject pictureAnalysis(String tag, String fileId, String relativePath) {
FileInfoToMq fileInfoToMq = new FileInfoToMq();
fileInfoToMq.setTag(tag);
fileInfoToMq.setFileId(fileId);
fileInfoToMq.setRelativePath(relativePath);
fileInfoToMq.setNamespace(namespace);
fileInfoToMq.setUserId(UserUtils.getUser().getTenantId());
log.info(">>>>>>>>>>开始调用分析器图片分析接口:{}", JSONUtil.toJsonStr(fileInfoToMq));
Object result = restTemplate.postForObject(pictureAnalysisUrl, fileInfoToMq, Object.class);
log.info(">>>>>>>>>>调用分析器图片分析接口结果:{}", JSONUtil.toJsonStr(result));
return JSONUtil.parseObj(result);
}
/**
* @param tag
* @param fileId
* @param relativePath
* @return
*/
@Override
public JSONObject pictureAnalysisToWords(String tag, String fileId, String relativePath) {
FileInfoToMq fileInfoToMq = new FileInfoToMq();
fileInfoToMq.setTag(tag);
fileInfoToMq.setFileId(fileId);
fileInfoToMq.setRelativePath(relativePath);
fileInfoToMq.setNamespace(namespace);
fileInfoToMq.setUserId(UserUtils.getUser().getTenantId());
fileInfoToMq.setPath(relativePath);
log.info(">>>>>>>>>>开始调用分析器图片分析接口:{}", JSONUtil.toJsonStr(fileInfoToMq));
Object result = restTemplate.postForObject(pictureAnalysisToWordsUrl, fileInfoToMq, Object.class);
log.info(">>>>>>>>>>调用分析器图片分析接口结果:{}", JSONUtil.toJsonStr(result));
return JSONUtil.parseObj(result);
}
/**
* 熟人与人脸一起添加(新增或更新)
*
* @param figureImage 人脸
* @param name 名字
* @param gender 性别
* @param familiarFigureId 熟人id,为空则创建一个新人物,否则为该ID人物添加人脸
* @return
*/
@Override
public JSONObject addOrUpdateFigureAndFace(MultipartFile figureImage, String name, Integer gender, String familiarFigureId) {
File file = null;
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.set("namespace", namespace);
map.set("userId", UserUtils.getUser().getTenantId());
map.set("name", name);
map.set("gender", gender);
file = FileUtils.multipartFileToFile(figureImage);
map.set("faceImages", new FileSystemResource(file));
map.set("familiarFigureId", familiarFigureId);
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
log.info(">>>>>>>>>>开始调用分析器熟人与人脸一起添加(新增或更新)接口:{}", JSONUtil.toJsonStr(map));
ResponseEntity resultEntity = restTemplate.exchange(figureFaceUrl, HttpMethod.PUT, request, Object.class);
Object result = resultEntity.getBody();
log.info(">>>>>>>>>>调用分析器熟人与人脸一起添加(新增或更新)结果:{}", JSONUtil.toJsonStr(result));
return JSONUtil.parseObj(result);
} finally {
FileUtils.delteTempFile(file);
}
}
/**
* 删除熟人(多个用“,”分隔)
*
* @param familiarFigureIds
* @return
*/
@Override
public JSONObject deleteFigure(String familiarFigureIds) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.set("namespace", namespace);
map.set("userId", UserUtils.getUser().getTenantId());
map.set("familiarFigureId", familiarFigureIds);
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
log.info(">>>>>>>>>>开始调用分析器删除熟人接口:{}", JSONUtil.toJsonStr(map));
ResponseEntity resultEntity = restTemplate.exchange(deleteFigureUrl, HttpMethod.DELETE, request, Object.class);
Object result = resultEntity.getBody();
log.info(">>>>>>>>>>调用分析器删除熟人接口结果:{}", JSONUtil.toJsonStr(result));
return JSONUtil.parseObj(result);
}
/**
* 人脸相似度匹配
*
* @param figureImage
* @return
*/
@Override
public JSONObject similarityMatch(MultipartFile figureImage) {
File file = null;
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.set("namespace", namespace);
map.set("userId", UserUtils.getUser().getTenantId());
file = FileUtils.multipartFileToFile(figureImage);
map.set("faceImage", new FileSystemResource(file));
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
log.info(">>>>>>>>>>开始调用分析器熟人库图片相似度查询接口:{}", JSONUtil.toJsonStr(map));
Object result = restTemplate.postForObject(similarityMatchUrl, request, Object.class);
log.info(">>>>>>>>>>调用分析器熟人库图片相似度查询接口结果:{}", JSONUtil.toJsonStr(result));
return JSONUtil.parseObj(result);
} finally {
FileUtils.delteTempFile(file);
}
}
/**
* 删除熟人人脸
*
* @param familiarFigureId
* @return
*/
@Override
public JSONObject deleteFigureAllFace(String familiarFigureId) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.set("namespace", namespace);
map.set("userId", UserUtils.getUser().getTenantId());
map.set("familiarFigureId", familiarFigureId);
map.set("faceId", "");
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
log.info(">>>>>>>>>>开始调用分析器删除熟人人脸接口:{}", JSONUtil.toJsonStr(map));
ResponseEntity resultEntity = restTemplate.exchange(deleteFigureFaceUrl, HttpMethod.DELETE, request, Object.class);
Object result = resultEntity.getBody();
log.info(">>>>>>>>>>调用分析器删除熟人人脸接口结果:{}", JSONUtil.toJsonStr(result));
return JSONUtil.parseObj(result);
}
/**
* 修改熟人
*
* @param name 名称
* @param gender 性别 0-女 1-男
* @param familiarFigureId 熟人id
* @return
*/
@Override
public JSONObject updateFigure(String name, Integer gender, String familiarFigureId) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.set("namespace", namespace);
map.set("userId", UserUtils.getUser().getTenantId());
map.set("familiarFigureId", familiarFigureId);
map.set("name", name);
map.set("gender", gender);
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
log.info(">>>>>>>>>>开始调用分析器修改熟人接口:{}", JSONUtil.toJsonStr(map));
ResponseEntity resultEntity = restTemplate.exchange(updateFigureUrl, HttpMethod.PUT, request, Object.class);
Object result = resultEntity.getBody();
log.info(">>>>>>>>>>调用分析器修改熟人接口结果:{}", JSONUtil.toJsonStr(result));
return JSONUtil.parseObj(result);
}
@Override
public JSONObject getPictureAnalysisResult(String imageBase64) {
Map<String, Object> map = new HashMap<>();
map.put("faceImg", imageBase64);
map.put("namespace", namespace);
map.put("userId", UserUtils.getUser().getTenantId());
log.info(">>>>>>>>>>调用分析器图片查陌生人接口");
Object result = restTemplate.postForObject(picturePersonUrl, map, Object.class);
log.info(">>>>>>>>>>调用分析器图片查陌生人接口成功");
return JSONUtil.parseObj(result);
}
/**
* 根据特征值查熟人
*
* @param feature
* @return
*/
@Override
public JSONObject getFigureByFeature(String feature) {
Map<String, Object> map = new HashMap<>();
map.put("feature", feature);
map.put("namespace", namespace);
map.put("userId", UserUtils.getUser().getTenantId());
log.info(">>>>>>>>>>调用分析器特征值查熟人接口");
Object result = restTemplate.postForObject(feature2figureUrl, map, Object.class);
log.info(">>>>>>>>>>调用分析器特征值查熟人接口成功");
return JSONUtil.parseObj(result);
}
}
... ...
package com.wondertek.ivod.cmr.manage.service.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.drew.imaging.ImageMetadataReader;
import com.wondertek.ivod.cmr.commons.utils.GetLocation;
import com.wondertek.ivod.cmr.core.entity.model.ImageDetail;
import com.wondertek.ivod.cmr.manage.repository.ImageDetailRepository;
import com.wondertek.ivod.cmr.manage.service.ExtractImageDetailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import javax.annotation.Resource;
import java.io.File;
/**
* @author xh
* @date 2023/9/18 14:09
*/
@Slf4j
@Service
public class ExtractImageDetailServiceImpl implements ExtractImageDetailService {
@Resource
private ImageDetailRepository imageDetailRepository;
@Override
public ImageDetail extractImageDetail(String imagePath, Long materialId) {
File file = new File(imagePath);
Metadata metadata;
try {
metadata = ImageMetadataReader.readMetadata(file);
ImageDetail detail = new ImageDetail();
for (Directory directory : metadata.getDirectories()) {
for (Tag tag : directory.getTags()) {
log.info(tag.getTagName() + ":" + tag.getDescription());
if ("Date/Time Original".equals(tag.getTagName())) {
detail.setShootingTime(tag.getDescription());
}
if ("Artist".equals(tag.getTagName())) {
detail.setArtist(tag.getDescription());
}
if ("Image Height".equals(tag.getTagName())) {
detail.setImageHeight(tag.getDescription());
}
if ("Image Width".equals(tag.getTagName())) {
detail.setImageWidth(tag.getDescription());
}
if ("Compression Type".equals(tag.getTagName())) {
detail.setCompressionType(tag.getDescription());
}
if ("Detected File Type Name".equals(tag.getTagName())) {
detail.setDetectedFileTypeName(tag.getDescription());
}
if ("Detected MIME Type".equals(tag.getTagName())) {
detail.setDetectedMimeType(tag.getDescription());
}
if ("Expected File Name Extension".equals(tag.getTagName())) {
detail.setExpectedFileNameExtension(tag.getDescription());
}
if ("File Name".equals(tag.getTagName())) {
detail.setFileName(tag.getDescription());
}
if ("File Size".equals(tag.getTagName())) {
detail.setFileSize(tag.getDescription());
}
if ("File Modified Date".equals(tag.getTagName())) {
detail.setFileModifiedDate(tag.getDescription());
}
if ("GPS Latitude".equals(tag.getTagName())) {
detail.setGpsLatitude(tag.getDescription());
}
if ("GPS Longitude".equals(tag.getTagName())) {
detail.setGpsLongitude(tag.getDescription());
}
if (StrUtil.isNotBlank(detail.getGpsLongitude()) && StrUtil.isNotBlank(detail.getGpsLatitude())) {
String area = GetLocation.getAdd(detail.getGpsLongitude(), detail.getGpsLatitude());
JSONObject jsonObject = JSON.parseObject(area);
JSONObject jsonArray = JSON.parseObject(jsonObject.getString("result"));
String location = jsonArray.getString("address");
log.info(location);
detail.setLocation(location);
}
detail.setMaterialId(materialId);
}
}
return imageDetailRepository.saveAndFlush(detail);
} catch (Exception e) {
log.error("提取图片信息失败, imagePath: {}, msg: {}, e: {}", imagePath, e.getMessage(), e);
return null;
}
}
}
... ...
package com.wondertek.ivod.cmr.manage.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
import com.wondertek.ivod.cmr.commons.exception.DefaultException;
import com.wondertek.ivod.cmr.commons.utils.FileUtils;
import com.wondertek.ivod.cmr.commons.utils.PageBean;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.commons.utils.UserUtils;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.FigureFaceResult;
import com.wondertek.ivod.cmr.core.entity.dto.FigureUpdateDto;
import com.wondertek.ivod.cmr.core.entity.model.Figure;
import com.wondertek.ivod.cmr.core.entity.vo.SimilarityMatchVo;
import com.wondertek.ivod.cmr.manage.repository.FigureRepository;
import com.wondertek.ivod.cmr.manage.service.IAnalyserService;
import com.wondertek.ivod.cmr.manage.service.IFigureService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
/**
* @Author yubin
* @Date 2021/8/9 14:47
*/
@Slf4j
@Service
public class FigureServiceImpl implements IFigureService {
@Autowired
private IAnalyserService analyserService;
@Autowired
private FigureRepository figureRepository;
//只允许用户输入数字1-9,字母a-z,A-Z,只能半角,不能有空格的正则表达式
public static final String ONLY_LETTER_OR_NUMBER = "^[a-z0-9A-Z]+$";
/**
* 查询人物列表
*
* @param keywords
* @param page
* @param rows
* @return
*/
@Override
public Page<Figure> pageList(String keywords, int page, int rows) {
Pageable pageable = PageRequest.of(page - 1, rows, Sort.Direction.DESC, "createTime");
Specification<Figure> prdPoolSpecification = (root, query, cb) -> {
List<Predicate> predicateList = new ArrayList<>();
predicateList.add(cb.equal(root.get("tenantId"), UserUtils.getUser().getTenantId()));
if (ObjectUtil.isNotEmpty(keywords)) {
predicateList.add(cb.or(cb.like(root.get("name"), "%" + keywords + "%"),
cb.like(root.get("figureDefineId"), "%" + keywords + "%")));
}
return query.where(predicateList.toArray(new Predicate[predicateList.size()])).getRestriction();
};
return figureRepository.findAll(prdPoolSpecification, pageable);
}
/**
* 人脸相似度匹配
*
* @param figureImage
* @return
*/
@Override
public ResultBean similarityMatch(MultipartFile figureImage, String familiarFigureId) {
JSONObject jsonResult = analyserService.similarityMatch(figureImage);
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
return ResultBean.error("人脸相似度匹配失败:" + jsonResult.get("msg"));
}
JSONArray jsonArray = jsonResult.getJSONArray("data");
List<SimilarityMatchVo> similarityMatchVoList = new ArrayList<>();
for (Object o : jsonArray) {
SimilarityMatchVo similarityMatchVo = JSONUtil.toBean(JSONUtil.toJsonStr(o), SimilarityMatchVo.class);
//自己不展示
if (ObjectUtil.isNotEmpty(familiarFigureId) && similarityMatchVo.getFamiliarFigureId().equals(familiarFigureId)) {
break;
}
//只需要展示可信度大于60的
if (similarityMatchVo.getScore().compareTo(new BigDecimal("0.6")) < 0) {
continue;
}
//小数点后一位
BigDecimal score = similarityMatchVo.getScore().multiply(new BigDecimal("100")).setScale(1, BigDecimal.ROUND_HALF_UP);
similarityMatchVo.setScore(new BigDecimal(score.stripTrailingZeros().toPlainString()));
similarityMatchVo.setPreviewUrl(similarityMatchVo.getPath()[0]);
similarityMatchVo.setPath(null);
similarityMatchVoList.add(similarityMatchVo);
}
//只展示匹配度最高的10个
Collections.sort(similarityMatchVoList, (figure1, figure2) -> figure2.getScore().compareTo(figure1.getScore()));
return ResultBean.ok(similarityMatchVoList.size() > 10 ? similarityMatchVoList.subList(0, 10) : similarityMatchVoList);
}
/**
* 添加人物
*
* @param figureImage
* @param figure
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Override
public ResultBean add(MultipartFile figureImage, Figure figure) {
String checkResult = validateFigure(figureImage, figure);
if (ObjectUtil.isNotEmpty(checkResult)) {
return ResultBean.error(checkResult);
}
//人物自定义id唯一
if (checkOnlyDefineId(null, figure.getFigureDefineId())) {
return ResultBean.error("该人物ID已存在,不可重复使用");
}
//如果熟人id不为空则是替换,先删除替换人物再添加新人物
if (ObjectUtil.isNotEmpty(figure.getFamiliarFigureId())) {
JSONObject jsonResult = analyserService.deleteFigure(figure.getFamiliarFigureId());
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
return ResultBean.error("删除人物失败:" + jsonResult.get("msg"));
}
figureRepository.deleteByFamiliarFigureId(figure.getFamiliarFigureId());
}
//添加新人物
JSONObject jsonResult = analyserService.addOrUpdateFigureAndFace(figureImage, figure.getName(), figure.getGender(), null);
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
return ResultBean.error("添加人物库失败:" + jsonResult.get("msg"));
}
//添加人物库
JSONObject jsonObject = jsonResult.getJSONObject("data");
FigureFaceResult figureFaceResult = JSONUtil.toBean(JSONUtil.toJsonStr(jsonObject), FigureFaceResult.class);
figure.setFamiliarFigureId(figureFaceResult.getFamiliarFigureId());
figure.setPreviewUrl(figureFaceResult.getFaces().get(0).getPreviewPath());
figure.setTenantId(UserUtils.getUser().getTenantId());
figure.setCreateBy(UserUtils.getUser().getUserName());
figure.setCreateTime(LocalDateTime.now());
figureRepository.save(figure);
return ResultBean.ok();
}
/**
* 修改人物
*
* @param figureImage
* @param figureUpdateDto
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Override
public ResultBean update(MultipartFile figureImage, FigureUpdateDto figureUpdateDto) {
Figure updateFigure = new Figure();
BeanUtils.copyProperties(figureUpdateDto, updateFigure);
String checkResult = validateFigure(figureImage, updateFigure);
if (ObjectUtil.isNotEmpty(checkResult)) {
return ResultBean.error(checkResult);
}
Optional<Figure> optional = figureRepository.findById(updateFigure.getId());
if (!optional.isPresent()) {
return ResultBean.error("该人物不存在");
}
Figure figure = optional.get();
//人物自定义id唯一
Figure figure2 = figureRepository.findByFigureDefineId(updateFigure.getFigureDefineId());
if (ObjectUtil.isNotEmpty(figure2) && !updateFigure.getId().equals(figure2.getId())) {
return ResultBean.error("该人物ID已存在,不可重复使用");
}
//如果熟人id不为空则是替换,先删除替换人物再修改人物
if (ObjectUtil.isNotEmpty(updateFigure.getFamiliarFigureId())) {
if (ObjectUtil.isEmpty(figureImage) || ObjectUtil.isEmpty(figureImage.getOriginalFilename())) {
return ResultBean.error("替换人物照片必传");
}
JSONObject jsonResult = analyserService.deleteFigure(updateFigure.getFamiliarFigureId());
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
return ResultBean.error("删除人物失败:" + jsonResult.get("msg"));
}
figureRepository.deleteByFamiliarFigureId(updateFigure.getFamiliarFigureId());
}
if (ObjectUtil.isNotEmpty(figureImage) && ObjectUtil.isNotEmpty(figureImage.getOriginalFilename())) {
//如果重新上传了照片先删除这个人之前的所有人脸
JSONObject jsonResult = analyserService.deleteFigureAllFace(figure.getFamiliarFigureId());
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
return ResultBean.error("删除人物人脸失败:" + jsonResult.get("msg"));
}
//修改人物并添加新人脸
JSONObject jsonResult2 = analyserService.addOrUpdateFigureAndFace(figureImage, updateFigure.getName(), updateFigure.getGender(), figure.getFamiliarFigureId());
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult2.get("code"))) {
return ResultBean.error("修改人物失败:" + jsonResult2.get("msg"));
}
JSONObject jsonObject = jsonResult2.getJSONObject("data");
FigureFaceResult figureFaceResult = JSONUtil.toBean(JSONUtil.toJsonStr(jsonObject), FigureFaceResult.class);
figure.setPreviewUrl(figureFaceResult.getFaces().get(0).getPreviewPath());
}
//修改人物基础信息
JSONObject jsonResult = analyserService.updateFigure(updateFigure.getName(), updateFigure.getGender(), figure.getFamiliarFigureId());
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
return ResultBean.error("修改人物失败:" + jsonResult.get("msg"));
}
//保存库
figure.setName(updateFigure.getName());
figure.setFigureDefineId(updateFigure.getFigureDefineId());
figure.setGender(updateFigure.getGender());
figure.setRemark(updateFigure.getRemark());
figure.setUpdateBy(UserUtils.getUser().getUserName());
figure.setUpdateTime(LocalDateTime.now());
figureRepository.save(figure);
return ResultBean.ok();
}
/**
* 批量删除人物
*
* @param figureIds
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void batchDelete(List<Long> figureIds) {
List<Figure> figureList = figureRepository.findAllById(figureIds);
if (ObjectUtil.isEmpty(figureList)) {
throw new DefaultException("人物不存在");
}
StringJoiner familiarFigureIds = new StringJoiner(",");
figureList.forEach(figure -> familiarFigureIds.add(figure.getFamiliarFigureId()));
//删除分析器人物库
JSONObject jsonResult = analyserService.deleteFigure(familiarFigureIds.toString());
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
throw new DefaultException("删除人物失败:" + jsonResult.get("msg"));
}
figureRepository.deleteInBatch(figureList);
}
/**
* 人物ID唯一校验
*
* @param figureDefineId
* @return
*/
@Override
public Boolean checkOnlyDefineId(Long id, String figureDefineId) {
Figure figure = figureRepository.findByFigureDefineId(figureDefineId);
return ObjectUtil.isNotEmpty(figure) && !figure.getId().equals(id);
}
/**
* 校验
*
* @param figureImage
* @param figure
* @return
*/
public String validateFigure(MultipartFile figureImage, Figure figure) {
if (ObjectUtil.isNotEmpty(figureImage) && ObjectUtil.isNotEmpty(figureImage.getOriginalFilename())) {
String result = FileUtils.checkImageFile(figureImage);
if (ObjectUtil.isNotEmpty(result)) {
return result;
}
}
if (ObjectUtil.isEmpty(figure.getName())) {
return "人物名称必填";
}
if (figure.getName().length() > 20) {
return "人物名称不能大于20个字符";
}
if (ObjectUtil.isEmpty(figure.getFigureDefineId())) {
return "人物ID必填";
}
if (figure.getFigureDefineId().length() > 50 || !figure.getFigureDefineId().matches(ONLY_LETTER_OR_NUMBER)) {
return "人物ID不能大于50个字符且只能是数字大小写字母";
}
if (ObjectUtil.isEmpty(figure.getGender())) {
return "性别必填";
}
if (figure.getGender() != 0 && figure.getGender() != 1) {
return "性别类型错误";
}
if (ObjectUtil.isNotEmpty(figure.getRemark()) && figure.getRemark().length() > 100) {
return "备注不能大于100个字符";
}
return null;
}
}
... ...
package com.wondertek.ivod.cmr.manage.service.impl;
import cn.hutool.core.util.StrUtil;
import com.wondertek.ivod.cmr.commons.enums.OperateTypeEnum;
import com.wondertek.ivod.cmr.commons.utils.PageBean;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.commons.utils.UserUtils;
import com.wondertek.ivod.cmr.core.entity.model.OperateRecord;
import com.wondertek.ivod.cmr.manage.repository.OperateRecordRepository;
import com.wondertek.ivod.cmr.manage.service.IMaterialOperateRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* @author xh
* @date 2023/9/18 10:46
*/
@Slf4j
@Service
public class IMaterialOperateRecordServiceImpl implements IMaterialOperateRecordService {
@Resource
private OperateRecordRepository operateRecordRepository;
@Override
public void saveOperateRecord(String type, String objectId) {
String tenantId = UserUtils.getUser().getTenantId();
String userName = UserUtils.getUser().getUserName();
OperateRecord record = new OperateRecord();
record.setCreatedTime(LocalDateTime.now());
record.setOperateObjectId(objectId);
record.setTenantId(tenantId);
record.setUserName(userName);
OperateRecord operateRecord = operateRecordRepository.findFirstByOperateObjectIdOrderByCreatedTimeDesc(objectId);
if (null == operateRecord) {
if (OperateTypeEnum.DOWNLOAD.getCode().equals(type)) {
record.setDownLoadCount(1);
}
if (OperateTypeEnum.VIEW.getCode().equals(type)) {
record.setViewCount(1);
}
} else {
log.info(operateRecord.toString());
if (OperateTypeEnum.DOWNLOAD.getCode().equals(type)) {
record.setDownLoadCount(StrUtil.isBlankIfStr(operateRecord.getDownLoadCount()) ? 1 : operateRecord.getDownLoadCount() + 1);
record.setViewCount(operateRecord.getViewCount());
}
if (OperateTypeEnum.VIEW.getCode().equals(type)) {
record.setViewCount(StrUtil.isBlankIfStr(operateRecord.getViewCount()) ? 1 : operateRecord.getViewCount() + 1);
record.setDownLoadCount(operateRecord.getDownLoadCount());
}
}
record.setOperateType(type);
operateRecordRepository.saveAndFlush(record);
}
@Override
public ResultBean list(String objectId, int page, int rows) {
Pageable pageable = PageRequest.of(page - 1, rows, Sort.Direction.DESC, "createdTime");
Specification<OperateRecord> prdPoolSpecification = (root, query, cb) -> {
List<Predicate> predicateList = new ArrayList<>();
predicateList.add(cb.equal(root.get("operateObjectId"), objectId));
return query.where(predicateList.toArray(new Predicate[predicateList.size()])).getRestriction();
};
Page<OperateRecord> recordPage = operateRecordRepository.findAll(prdPoolSpecification, pageable);
return PageBean.ok(recordPage.getTotalPages(), recordPage.getTotalElements(), recordPage.getContent());
}
@Override
public ResultBean getCount(String objectId) {
OperateRecord operateRecord = operateRecordRepository.findFirstByOperateObjectIdOrderByCreatedTimeDesc(objectId);
if (null == operateRecord) {
return ResultBean.error("未统计到记录");
}
return ResultBean.ok(operateRecord);
}
}
... ...
package com.wondertek.ivod.cmr.manage.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialInfoDto;
import com.wondertek.ivod.cmr.core.entity.model.MaterialFiles;
import com.wondertek.ivod.cmr.manage.service.IMaterialFilesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
/**
* @Author yubin
* @Date 2021/8/4 16:21
*/
@Slf4j
@Service
public class MaterialFilesServiceImpl implements IMaterialFilesService {
@Override
public MaterialFiles createMaterialFiles(MaterialInfoDto materialInfoDto) {
MaterialFiles materialFiles = new MaterialFiles();
BeanUtils.copyProperties(materialInfoDto, materialFiles);
materialFiles.setPath(materialInfoDto.getRelativePath());
materialFiles.setWidth(ObjectUtil.isNotEmpty(materialInfoDto.getWidth()) ? materialInfoDto.getWidth() + "" : null);
materialFiles.setHeight(ObjectUtil.isNotEmpty(materialInfoDto.getHeight()) ? materialInfoDto.getHeight() + "" : null);
materialFiles.setBitRate(ObjectUtil.isNotEmpty(materialInfoDto.getBitRate()) ? materialInfoDto.getBitRate() + "" : null);
return materialFiles;
}
}
... ...
package com.wondertek.ivod.cmr.manage.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.wondertek.ivod.cmr.commons.enums.CommonStatusEnum;
import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
import com.wondertek.ivod.cmr.commons.enums.MaterialSourceEnum;
import com.wondertek.ivod.cmr.commons.enums.MaterialTypeEnum;
import com.wondertek.ivod.cmr.commons.exception.DefaultException;
import com.wondertek.ivod.cmr.commons.utils.FileUtils;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.commons.utils.UserUtils;
import com.wondertek.ivod.cmr.core.entity.bean.*;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.AnalysisUploadResult;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.Feature2FigureResult;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.FileInfoToMq;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.PictureAnalysisResult;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.*;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialAddDto;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialInfoDto;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialInjectDto;
import com.wondertek.ivod.cmr.core.entity.model.AiFigure;
import com.wondertek.ivod.cmr.core.entity.model.ImageDetail;
import com.wondertek.ivod.cmr.core.entity.model.Material;
import com.wondertek.ivod.cmr.core.entity.model.MaterialFiles;
import com.wondertek.ivod.cmr.core.entity.vo.PictureAnalysisVo;
import com.wondertek.ivod.cmr.manage.config.RabbitmqConfig;
import com.wondertek.ivod.cmr.manage.feign.SearchFeignService;
import com.wondertek.ivod.cmr.manage.repository.AiFigureRepository;
import com.wondertek.ivod.cmr.manage.repository.ImageDetailRepository;
import com.wondertek.ivod.cmr.manage.repository.MaterialFilesRepository;
import com.wondertek.ivod.cmr.manage.repository.MaterialRepository;
import com.wondertek.ivod.cmr.manage.service.ExtractImageDetailService;
import com.wondertek.ivod.cmr.manage.service.IAnalyserService;
import com.wondertek.ivod.cmr.manage.service.IMaterialFilesService;
import com.wondertek.ivod.cmr.manage.service.IMaterialService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
/**
* @Author yubin
* @Date 2021/8/3 15:41
*/
@Slf4j
@Service
public class MaterialServiceImpl implements IMaterialService {
@Autowired
private IMaterialFilesService materialFilesService;
@Autowired
private SearchFeignService searchFeignService;
@Autowired
private IAnalyserService analyserService;
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private MaterialRepository materialRepository;
@Autowired
private MaterialFilesRepository materialFilesRepository;
@Autowired
private AiFigureRepository aiFigureRepository;
@Value("${analyser.namespace}")
private String namespace;
@Value("${analyser.filePath}")
private String filePath;
@Value("${cmr.image.basePath}")
private String basePath;
@Value("${cmr.image.startPath}")
private String startPath;
@Autowired
private ExtractImageDetailService extractImageDetailService;
@Resource
private ImageDetailRepository imageDetailRepository;
/**
* 介质上传
*
* @param materialFile
* @return
*/
@Override
public ResultBean uploadFile(MultipartFile materialFile, MaterialAddDto materialAddDto) {
Long materialId = materialAddDto.getMaterialId();
//不是空则为重新上传
if (ObjectUtil.isNotEmpty(materialId)) {
Optional<Material> optional = materialRepository.findById(materialId);
if (!optional.isPresent()) {
throw new DefaultException("该媒资不存在");
}
} else {
//先存一条数据
materialId = createMaterialBasic(materialFile);
}
updateUploadStatus(materialId, CommonStatusEnum.WAIT.getCode());
//上传文件到分析器
JSONObject jsonObject = analyserService.uploadFile(materialFile);
if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonObject.get("code"))) {
updateUploadStatus(materialId, CommonStatusEnum.SUCCESS.getCode());
} else {
updateUploadStatus(materialId, CommonStatusEnum.FAIL.getCode());
return ResultBean.error(materialAddDto.getName() + "上传失败:" + jsonObject.get("msg"), materialId);
}
//创建注入数据
AnalysisUploadResult analysisUploadResult = JSONUtil.toBean(JSONUtil.toJsonStr(jsonObject.get("data")), AnalysisUploadResult.class);
MaterialInfoDto materialInfoDto = new MaterialInfoDto();
materialInfoDto.setMaterialId(materialId);
BeanUtils.copyProperties(analysisUploadResult, materialInfoDto);
materialInfoDto.setName(materialAddDto.getName());
materialInfoDto.setMediaUrl(analysisUploadResult.getPreviewUrl());
materialInfoDto.setPreviewUrl(ObjectUtil.isNotEmpty(analysisUploadResult.getCoverMap()) ? analysisUploadResult.getCoverMap() : analysisUploadResult.getPreviewUrl());
materialInfoDto.setMediaType(FileUtils.getFileType(analysisUploadResult.getOriginalName()));
materialInfoDto.setIsOpenAi(materialAddDto.getIsOpenAi());
materialInfoDto.setClipId(analysisUploadResult.getClipId());
List<MaterialInfoDto> materials = new ArrayList<>();
materials.add(materialInfoDto);
MaterialInjectDto materialInjectDto = new MaterialInjectDto();
materialInjectDto.setSource(MaterialSourceEnum.LOCAL_UPLOAD.getCode());
materialInjectDto.setMaterialInfos(materials);
/* // 提取图片信息
Integer fileType = FileUtils.getFileType(materialFile.getOriginalFilename());
if (MaterialTypeEnum.PICTURE.getCode().equals(fileType)) {
String relativePath = materialInfoDto.getRelativePath();
if (StringUtils.isNotBlank(relativePath)) {
extractImageDetailService.extractImageDetail(relativePath.replace(startPath, basePath));
}
}*/
//注入
inject(materialInjectDto);
return ResultBean.ok(materialId);
}
/**
* 注入接口
* 1.存储cmr_material
* 2.存储cmr_material_files
* 3.介制信息存储es
* 4.发送ai能力人物分析
*
* @param materialInjectDto
*/
@Transactional(rollbackFor = Exception.class)
@Override
public List<Long> inject(MaterialInjectDto materialInjectDto) {
log.info(">>>>>>>>>>注入流程开始:{}", JSONUtil.toJsonStr(materialInjectDto));
//用户信息设置
UserUtils.setUser(materialInjectDto.getUserId(), materialInjectDto.getUserName(), materialInjectDto.getTenantId());
List<Long> materialIdList = new ArrayList<>();
for (MaterialInfoDto materialInfoDto : materialInjectDto.getMaterialInfos()) {
materialInfoDto.setDuration(ObjectUtil.isNotEmpty(materialInfoDto.getDuration()) ? materialInfoDto.getDuration() / 1000000 : null);
//存储cmr_material
Material material = createMaterial(materialInfoDto);
material.setMaterialType(materialInfoDto.getMediaType());
material.setSource(materialInjectDto.getSource());
materialRepository.save(material);
materialIdList.add(material.getMaterialId());
//存储cmr_material_files
MaterialFiles materialFiles = materialFilesService.createMaterialFiles(materialInfoDto);
materialFiles.setType(materialInfoDto.getMediaType());
materialFiles.setMaterialId(material.getMaterialId());
materialFilesRepository.save(materialFiles);
//es存储对象
MaterialInfo materialInfo = new MaterialInfo();
materialInfo.setMaterialId(material.getMaterialId());
//基础信息
BasicInfo basicInfo = new BasicInfo();
BeanUtils.copyProperties(material, basicInfo);
basicInfo.setMaterialId(material.getMaterialId());
basicInfo.setOwner(UserUtils.getUser());
basicInfo.setCreateTime(DateUtil.formatLocalDateTime(material.getCreateTime()));
basicInfo.setUpdateTime(DateUtil.formatLocalDateTime(material.getUpdatedTime()));
basicInfo.setFileId(materialInfoDto.getFileId());
basicInfo.setClipId(materialInfoDto.getClipId());
basicInfo.setRelativePath(materialInfoDto.getRelativePath());
// 提取图片信息
if (MaterialTypeEnum.PICTURE.getCode().equals(materialInfoDto.getMediaType())) {
String relativePath = materialInfoDto.getRelativePath();
if (StringUtils.isNotBlank(relativePath)) {
ImageDetail imageDetail = extractImageDetailService.extractImageDetail(basePath + relativePath, material.getMaterialId());
ImageAttr imageAttr = new ImageAttr();
if (null != imageDetail) {
imageAttr.setArtist(imageDetail.getArtist());
imageAttr.setLocation(imageDetail.getLocation());
imageAttr.setShootingTime(imageDetail.getShootingTime());
basicInfo.setImageAttr(imageAttr);
}
}
}
materialInfo.setBasicInfo(basicInfo);
//文件详细信息
MediaInfo mediaInfo = new MediaInfo();
BeanUtils.copyProperties(materialInfoDto, mediaInfo);
mediaInfo.setMediaType(materialInfoDto.getMediaType());
materialInfo.setMediaInfo(mediaInfo);
//状态信息
MaterialStatus materialStatus = new MaterialStatus();
materialStatus.setAiAnalysisStatus(ObjectUtil.isNotEmpty(materialInfoDto.getIsOpenAi()) && materialInfoDto.getIsOpenAi() ? CommonStatusEnum.WAIT.getCode() : CommonStatusEnum.INIT.getCode());
materialStatus.setUploadStatus(CommonStatusEnum.SUCCESS.getCode());
materialStatus.setEmbodyStatus(CommonStatusEnum.SUCCESS.getCode());
materialInfo.setMaterialStatus(materialStatus);
//保存介质信息es
ResultBean resultBean;
if (ObjectUtil.isEmpty(materialInfoDto.getMaterialId())) {
log.info(">>>>>>>>>>保存介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
resultBean = searchFeignService.createMaterialInfo(materialInfo);
log.info(">>>>>>>>>>保存介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
} else {
log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
resultBean = searchFeignService.updateMaterialInfo(materialInfo);
log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
}
//发送ai能力分析
if (ObjectUtil.isNotEmpty(materialInfoDto.getIsOpenAi()) && materialInfoDto.getIsOpenAi()) {
aiAnalysis(materialInfo);
}
}
return materialIdList;
}
/**
* ai分析
*
* @param materialInfo
*/
@Async
public void aiAnalysis(MaterialInfo materialInfo) {
//人物分析
aiFigureAnalysis(materialInfo);
//todo 文字分析
aiWordAnalysis(materialInfo);
}
/**
* ai人物分析
*
* @param materialInfo
*/
public void aiFigureAnalysis(MaterialInfo materialInfo) {
if (MaterialTypeEnum.VIDEO.getCode().equals(materialInfo.getBasicInfo().getMaterialType())) {
videoAiFigureAnalysis(materialInfo);
} else if (MaterialTypeEnum.PICTURE.getCode().equals(materialInfo.getBasicInfo().getMaterialType())) {
pictureAiFigureAnalysis(materialInfo);
}
}
/**
* ai文字分析
*
* @param materialInfo
*/
public void aiWordAnalysis(MaterialInfo materialInfo) {
List<WordInfo> wordInfoList = new ArrayList<>();
//WordInfo wordInfo = new WordInfo();
//wordInfo.setWord("文字识别敬请期待");
if (MaterialTypeEnum.VIDEO.getCode().equals(materialInfo.getBasicInfo().getMaterialType())) {
//wordInfo.setStart("0");
//wordInfo.setEnd("120");
videoAiWordsAnalysis(materialInfo);
} else if (MaterialTypeEnum.PICTURE.getCode().equals(materialInfo.getBasicInfo().getMaterialType())) {
pictureAiWordsAnalysis(materialInfo);
}
//wordInfoList.add(wordInfo);
//materialInfo.setWordInfo(wordInfoList);
//searchFeignService.updateMaterialInfo(materialInfo);
}
/**
* 视频ai人物分析 消费类FigureConsumer
*
* @param materialInfo
*/
public void videoAiFigureAnalysis(MaterialInfo materialInfo) {
log.info(">>>>>>>>>>视频分析:{}", materialInfo.getMaterialId());
FileInfoToMq fileInfoToMq = new FileInfoToMq();
fileInfoToMq.setTag(materialInfo.getMaterialId() + "");
fileInfoToMq.setFileId(materialInfo.getBasicInfo().getFileId());
fileInfoToMq.setRelativePath(materialInfo.getBasicInfo().getRelativePath());
fileInfoToMq.setNamespace(namespace);
fileInfoToMq.setUserId(UserUtils.getUser().getTenantId());
log.info(">>>>>>>>>>发送ai人物分析mq:{}", JSONUtil.toJsonStr(fileInfoToMq));
rabbitTemplate.convertAndSend(RabbitmqConfig.ANALYZER_FILE_EXCHANGE, RabbitmqConfig.ANALYZER_FILE_STORAGE_PATH_ROUTING, JSONUtil.toJsonStr(fileInfoToMq).getBytes());
}
/**
* 图片ai人物分析
*
* @param materialInfo
*/
public void pictureAiFigureAnalysis(MaterialInfo materialInfo) {
log.info(">>>>>>>>>>图片分析:{}", materialInfo.getMaterialId());
Optional<Material> optionalMaterial = materialRepository.findById(materialInfo.getMaterialId());
if (!optionalMaterial.isPresent()) {
log.info(">>>>>>>>>>人物分析异常,该介制信息不存在:{}", materialInfo.getMaterialId());
return;
}
//人物分析信息
List<AiFigure> aiFigureList = new ArrayList<>();
try {
//调用分析器图片分析接口
JSONObject jsonResult = analyserService.pictureAnalysis(materialInfo.getMaterialId() + "", materialInfo.getBasicInfo().getFileId(), materialInfo.getBasicInfo().getRelativePath());
if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
//修改ai分析状态
materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.SUCCESS.getCode());
//读取json文件,临时保存
String jsonPath = filePath + jsonResult.get("data");
log.info(">>>>>>>>>>人物分析json文件地址:{}", jsonPath);
File file = new File(jsonPath);
if (ObjectUtil.isEmpty(file)) {
throw new DefaultException(">>>>>>>>>>人物分析异常,下载文件失败");
}
JSONObject jsonObject = JSONUtil.readJSONObject(file, StandardCharsets.UTF_8);
JSONArray jsonArray = jsonObject.getJSONArray("faceDataList");
if (ObjectUtil.isEmpty(jsonArray)) {
log.info(">>>>>>>>>>人物分析数据为空");
return;
}
//保存人物分析信息
for (Object o : jsonArray) {
VideoFigureData videoFigureData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoFigureData.class);
AiFigure aiFigure = new AiFigure();
aiFigure.setMaterialId(materialInfo.getMaterialId());
aiFigure.setFigureId(Long.valueOf(videoFigureData.getStrangerId()));
aiFigure.setImagePath(videoFigureData.getImage());
aiFigure.setCreateTime(LocalDateTime.now());
Box box = videoFigureData.getBox();
aiFigure.setWight(box.getW() + "");
aiFigure.setHigh(box.getH() + "");
aiFigure.setXPos(box.getX() + "");
aiFigure.setYPos(box.getY() + "");
aiFigure.setType("1");
aiFigureList.add(aiFigure);
}
//人脸识别信息
List<FaceInfo> faceInfoList = new ArrayList<>();
//标签
Set<String> tagInfoSet = new TreeSet<>();
for (Object o : jsonArray) {
VideoFigureData videoFigureData = JSONUtil.toBean(JSONUtil.toJsonStr(o), VideoFigureData.class);
log.info(videoFigureData.toString());
FaceInfo faceInfo = new FaceInfo();
faceInfo.setFigureId(videoFigureData.getStrangerId());
faceInfo.setFigureName(videoFigureData.getFigureName());
faceInfo.setFace(videoFigureData.getImage());
if (ObjectUtil.isNotEmpty(videoFigureData.getFigureName())) {
tagInfoSet.add(videoFigureData.getFigureName());
}
//出现率
faceInfo.setAppearRate("100%");
faceInfo.setWight(videoFigureData.getBox().getW() + "");
faceInfo.setHigh(videoFigureData.getBox().getH() + "");
faceInfo.setX(videoFigureData.getBox().getX() + "");
faceInfo.setY(videoFigureData.getBox().getY() + "");
faceInfoList.add(faceInfo);
}
materialInfo.setFaceInfo(faceInfoList);
materialInfo.getBasicInfo().setTagInfoSet(tagInfoSet);
} else {
materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
}
} catch (Exception e) {
e.printStackTrace();
materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
} finally {
//更新es
materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
//保存人物分析信息
if (CommonStatusEnum.SUCCESS.getCode().equals(materialInfo.getMaterialStatus().getAiAnalysisStatus())) {
aiFigureRepository.saveAll(aiFigureList);
}
}
}
/**
* 视频ai文字分析 消费类FigureConsumer
*
* @param materialInfo
*/
public void videoAiWordsAnalysis(MaterialInfo materialInfo) {
log.info(">>>>>>>>>>视频分析:{}", materialInfo.getMaterialId());
FileInfoToMq fileInfoToMq = new FileInfoToMq();
fileInfoToMq.setTag(materialInfo.getMaterialId() + "");
fileInfoToMq.setFileId(materialInfo.getBasicInfo().getFileId());
fileInfoToMq.setRelativePath(materialInfo.getBasicInfo().getRelativePath());
fileInfoToMq.setNamespace(namespace);
fileInfoToMq.setUserId(UserUtils.getUser().getTenantId());
fileInfoToMq.setPath(materialInfo.getBasicInfo().getRelativePath());
log.info(">>>>>>>>>>发送ai文字分析mq:{}", JSONUtil.toJsonStr(fileInfoToMq));
rabbitTemplate.convertAndSend(RabbitmqConfig.WORDS_ANALYZER_FILE_EXCHANGE, RabbitmqConfig.WORDS_ANALYZER_FILE_STORAGE_PATH_ROUTING, JSONUtil.toJsonStr(fileInfoToMq).getBytes());
}
/**
* 图片ai人物分析
*
* @param materialInfo
*/
public void pictureAiWordsAnalysis(MaterialInfo materialInfo) {
log.info(">>>>>>>>>>图片分析:{}", materialInfo.toString());
Optional<Material> optionalMaterial = materialRepository.findById(materialInfo.getMaterialId());
if (!optionalMaterial.isPresent()) {
log.info(">>>>>>>>>>人物分析异常,该介制信息不存在:{}", materialInfo.getMaterialId());
return;
}
//文字分析信息
List<AiFigure> aiFigureList = new ArrayList<>();
try {
//调用分析器图片分析接口
JSONObject jsonResult = analyserService.pictureAnalysisToWords(materialInfo.getMaterialId() + "", materialInfo.getBasicInfo().getFileId(), materialInfo.getBasicInfo().getRelativePath());
if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonResult.get("code"))) {
//修改ai分析状态
materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.SUCCESS.getCode());
//读取json文件,临时保存
String dataJson = jsonResult.get("data") + "";
String jsonPath = filePath + JSONUtil.parseObj(dataJson).get("path");
log.info(">>>>>>>>>>文字分析json文件地址:{}", jsonPath);
File file = new File(jsonPath);
if (ObjectUtil.isEmpty(file)) {
throw new DefaultException(">>>>>>>>>>文字分析异常,下载文件失败");
}
JSONObject jsonObject = JSONUtil.readJSONObject(file, StandardCharsets.UTF_8);
JSONArray jsonArray = jsonObject.getJSONArray("data");
if (ObjectUtil.isEmpty(jsonArray)) {
log.info(">>>>>>>>>>文字分析数据为空");
return;
}
//保存文字分析信息
for (Object o : jsonArray) {
ImageWordsData imageWordsData = JSONUtil.toBean(JSONUtil.toJsonStr(o), ImageWordsData.class);
AiFigure aiFigure = new AiFigure();
aiFigure.setMaterialId(materialInfo.getMaterialId());
aiFigure.setContent(imageWordsData.getContent());
aiFigure.setType("2");
aiFigure.setCreateTime(LocalDateTime.now());
if (CollectionUtil.isNotEmpty(imageWordsData.getPolygon())) {
String xPos = null,ypos = null;
for (Polygon polygonTemp : imageWordsData.getPolygon()) {
xPos = xPos + "," + polygonTemp.getX();
ypos = ypos + "," + polygonTemp.getY();
}
if (xPos.startsWith(",")) {
xPos = xPos.substring(1);
ypos = ypos.substring(1);
}
aiFigure.setXPos(xPos);
aiFigure.setYPos(ypos);
}
aiFigureList.add(aiFigure);
}
//文字识别信息
List<WordInfo> wordInfoList = new ArrayList<>();
for (Object o : jsonArray) {
ImageWordsData imageWordsData = JSONUtil.toBean(JSONUtil.toJsonStr(o), ImageWordsData.class);
WordInfo wordInfo = new WordInfo();
wordInfo.setWord(imageWordsData.getContent());
//出现率
List<Polygon> polygons = new ArrayList<>();
if (CollectionUtil.isNotEmpty(imageWordsData.getPolygon())) {
for (Polygon polygonTemp : imageWordsData.getPolygon()) {
Polygon polygon = new Polygon();
polygon.setX(polygonTemp.getX());
polygon.setY(polygonTemp.getY());
polygons.add(polygon);
}
wordInfo.setPolygons(polygons);
}
wordInfoList.add(wordInfo);
}
materialInfo.setWordInfo(wordInfoList);
} else {
materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.FAIL.getCode());
}
} catch (Exception e) {
e.printStackTrace();
materialInfo.getMaterialStatus().setOcrAnalysisStatus(CommonStatusEnum.FAIL.getCode());
} finally {
//更新es
materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
//保存ocr分析信息
if (CommonStatusEnum.SUCCESS.getCode().equals(materialInfo.getMaterialStatus().getOcrAnalysisStatus())) {
aiFigureRepository.saveAll(aiFigureList);
}
}
}
/**
* 重新下发AI分析
*
* @param materialIds
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void aiAnalysis(List<Long> materialIds) {
for (Long materialId : materialIds) {
Optional<Material> optional = materialRepository.findById(materialId);
if (!optional.isPresent()) {
throw new DefaultException("该媒资不存在:" + materialId);
}
Material material = optional.get();
//更新操作人
updateUserInfo(material);
materialRepository.save(material);
//修改es中的状态
MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
if (ObjectUtil.isEmpty(materialInfo)) {
throw new DefaultException("该介质信息在es中不存在:" + materialId);
}
materialInfo.getMaterialStatus().setAiAnalysisStatus(CommonStatusEnum.WAIT.getCode());
materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
if (GlobalCodeEnum.SUCCESS.getCode().equals(resultBean.getCode())) {
//ai人物分析
aiAnalysis(materialInfo);
}
}
}
/**
* 修改名称
*
* @param materialId
* @param name
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void updateMaterial(Long materialId, String name) {
Optional<Material> optional = materialRepository.findById(materialId);
if (!optional.isPresent()) {
throw new DefaultException("该媒资不存在");
}
Material material = optional.get();
material.setName(name);
//更新操作人
updateUserInfo(material);
materialRepository.save(material);
//修改es中的名称
MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
if (ObjectUtil.isEmpty(materialInfo)) {
throw new DefaultException("该介质信息在es中不存在");
}
materialInfo.getBasicInfo().setName(name);
materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
}
/**
* 批量设置标签
* @param materialIds
* @param customLabel
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void updateMaterialCustomLable(List<Long> materialIds, String customLabel) {
Set<String> labelSet = new HashSet<>();
String[] labels = customLabel.split(",");
Collections.addAll(labelSet, labels);
for (Long materialId : materialIds) {
Optional<Material> optional = materialRepository.findById(materialId);
if (!optional.isPresent()) {
throw new DefaultException(materialId + "该媒资不存在");
}
Material material = optional.get();
material.setCustomLabel(customLabel);
//更新操作人
updateUserInfo(material);
materialRepository.save(material);
//修改es中的名称
MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
if (ObjectUtil.isEmpty(materialInfo)) {
throw new DefaultException("该介质信息在es中不存在");
}
materialInfo.getBasicInfo().setCustomLabelSet(labelSet);
materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
}
}
/**
* 删除
*
* @param materialDeleteDto
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void deleteMaterails(MaterialDeleteDto materialDeleteDto) {
Map<String, List<Long>> map = new HashMap<>();
map.put("materialIds", materialDeleteDto.getMaterialIds());
List<MaterialInfo> materialInfos = searchFeignService.getByIds(map).getResult();
List<String> fileIdList = new ArrayList<>();
for (MaterialInfo materialInfo : materialInfos) {
fileIdList.add(materialInfo.getBasicInfo().getFileId());
}
if (CollectionUtil.isNotEmpty(fileIdList)) {
JSONObject jsonObject = analyserService.deletefileBatch(fileIdList);
if (!GlobalCodeEnum.SUCCESS.getCode().equals(jsonObject.get("code")) && !"没有该文件".equals(jsonObject.get("msg"))) {
throw new DefaultException("删除失败:" + jsonObject.get("msg"));
}
}
//删除介质信息es
log.info(">>>>>>>>>>删除介制信息es:{}", JSONUtil.toJsonStr(materialDeleteDto));
ResultBean deleteResultBean = searchFeignService.deleteInfos(materialDeleteDto);
log.info(">>>>>>>>>>删除介制信息es结果:{}", JSONUtil.toJsonStr(deleteResultBean));
if (GlobalCodeEnum.SUCCESS.getCode().equals(deleteResultBean.getCode())) {
List<Material> materialList = new ArrayList<>();
materialDeleteDto.getMaterialIds().forEach(materialId -> {
Material material = new Material();
material.setMaterialId(materialId);
materialList.add(material);
});
materialRepository.deleteInBatch(materialList);
materialFilesRepository.deleteByMaterialIds(materialDeleteDto.getMaterialIds());
aiFigureRepository.deleteByMaterialIds(materialDeleteDto.getMaterialIds());
imageDetailRepository.deleteByMaterialIds(materialDeleteDto.getMaterialIds());
}
}
/**
* 更新操作人
*
* @param material
*/
public void updateUserInfo(Material material) {
UserInfo userInfo = UserUtils.getUser();
material.setUpdatedBy(userInfo.getUserName());
material.setUpdatedTime(LocalDateTime.now());
}
public Material createMaterial(MaterialInfoDto materialInfoDto) {
Material material = new Material();
BeanUtils.copyProperties(materialInfoDto, material);
UserInfo userInfo = UserUtils.getUser();
material.setTenantId(userInfo.getTenantId());
material.setCreateBy(userInfo.getUserName());
material.setCreateTime(LocalDateTime.now());
material.setUpdatedBy(userInfo.getUserName());
material.setUpdatedTime(LocalDateTime.now());
return material;
}
/**
* 创建基础信息
*
* @param materialFile
*/
public Long createMaterialBasic(MultipartFile materialFile) {
//存储cmr_material
Material material = createMaterial(new MaterialInfoDto());
material.setName(materialFile.getOriginalFilename());
material.setSource(MaterialSourceEnum.LOCAL_UPLOAD.getCode());
material.setMaterialType(FileUtils.getFileType(materialFile.getOriginalFilename()));
materialRepository.save(material);
//es存储对象
MaterialInfo materialInfo = new MaterialInfo();
materialInfo.setMaterialId(material.getMaterialId());
//基础信息
BasicInfo basicInfo = new BasicInfo();
BeanUtils.copyProperties(material, basicInfo);
basicInfo.setMaterialId(material.getMaterialId());
basicInfo.setOwner(UserUtils.getUser());
basicInfo.setCreateTime(DateUtil.formatLocalDateTime(material.getCreateTime()));
basicInfo.setUpdateTime(DateUtil.formatLocalDateTime(material.getUpdatedTime()));
materialInfo.setBasicInfo(basicInfo);
//状态信息
MaterialStatus materialStatus = new MaterialStatus();
materialStatus.setUploadStatus(CommonStatusEnum.WAIT.getCode());
materialInfo.setMaterialStatus(materialStatus);
//保存介质信息es
log.info(">>>>>>>>>>保存介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
ResultBean resultBean = searchFeignService.createMaterialInfo(materialInfo);
log.info(">>>>>>>>>>保存介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
return material.getMaterialId();
}
/**
* 修改上传状态
*
* @param materialId
* @param uploadStatus
*/
private void updateUploadStatus(Long materialId, Integer uploadStatus) {
Optional<Material> optional = materialRepository.findById(materialId);
if (!optional.isPresent()) {
throw new DefaultException("该媒资不存在");
}
Material material = optional.get();
//更新操作人
updateUserInfo(material);
materialRepository.save(material);
//修改es中的名称
MaterialInfo materialInfo = searchFeignService.getMaterialInfoById(materialId).getResult();
if (ObjectUtil.isEmpty(materialInfo)) {
throw new DefaultException("该介质信息在es中不存在");
}
materialInfo.getBasicInfo().setUpdateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
materialInfo.getMaterialStatus().setUploadStatus(uploadStatus);
materialInfo.getMaterialStatus().setEmbodyStatus(uploadStatus);
log.info(">>>>>>>>>>修改介制信息es:{}", JSONUtil.toJsonStr(materialInfo));
ResultBean resultBean = searchFeignService.updateMaterialInfo(materialInfo);
log.info(">>>>>>>>>>修改介制信息es结果:{}", JSONUtil.toJsonStr(resultBean));
}
@Override
public PictureAnalysisVo analysisPicture(String imageBase64) {
PictureAnalysisVo pictureAnalysisVo = null;
//图片查陌生人
JSONObject jsonObject = analyserService.getPictureAnalysisResult(imageBase64);
if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonObject.get("code"))) {
//如果data是null,说明不是人脸图片
if (!JSONUtil.isNull(jsonObject.get("data"))) {
pictureAnalysisVo = new PictureAnalysisVo();
List<PictureAnalysisResult> pictureAnalysisResultList = JSONUtil.toList(JSONUtil.parseArray(jsonObject.get("data")), PictureAnalysisResult.class);
if (ObjectUtil.isNotEmpty(pictureAnalysisResultList)) {
PictureAnalysisResult pictureAnalysisResult = pictureAnalysisResultList.get(0);
//如果陌生人库没查到,则faceId返回null
if (ObjectUtil.isNotEmpty(pictureAnalysisResult.getFaceId())) {
pictureAnalysisVo.setFaceId(String.valueOf(pictureAnalysisResult.getFaceId()));
//根据特征值查熟人获取名字
jsonObject = analyserService.getFigureByFeature(pictureAnalysisResult.getFeature());
if (GlobalCodeEnum.SUCCESS.getCode().equals(jsonObject.get("code"))) {
Feature2FigureResult feature2FigureResult = JSONUtil.toBean(JSONUtil.toJsonStr(jsonObject.get("data")), Feature2FigureResult.class);
pictureAnalysisVo.setName(feature2FigureResult.getName());
} else {
log.info(">>>>>>>>>>特征值查熟人异常:{}", jsonObject.get("msg"));
}
}
}
}
return pictureAnalysisVo;
} else {
throw new DefaultException("调用分析器异常");
}
}
}
... ...
spring:
#------------------------------------------mysql---------------------------------------------------
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.1.41:3306/cmrdb?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
##配置初始化大小、最小、最大
initial-size: 5
max-active: 100
min-idle: 5
#配置获取连接等待超时的时间
max-wait: 60000
##打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
validation-query: SELECT 1 FROM DUAL
validation-query-timeout: 60000
##这里建议配置为TRUE,防止取到的连接不可用
test-on-borrow: true
test-on-return: false
test-while-idle: true
##配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 100000
jpa:
show-sql: true
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
#----------------------------------------rabbitmq---------------------------------------------------
rabbitmq:
host: 127.0.0.1
port: 5672
username: admin
password: admin
virtual-host: /
#设置发送确认
publisher-confirm-type: correlated
template:
mandatory: true
listener:
simple:
#决定被拒绝的消息是否重新入队
default-requeue-rejected: true
retry:
#时间间隔5秒
initial-interval: 5000ms
enabled: true
#最大重试次数
max-attempts: 4
analyser:
#分析器上传接口
uploadUrl: http://192.168.1.99/file-upload-service/file/upload/
#分析器批量删除文件接口
fileBatchDeleteUrl: http://192.168.1.99/file-upload-service/file/batch-delete
#图片分析
pictureAnalysisUrl: http://192.168.0.14:20005/file-figure-analyzer/picture/analysis/person
cmr:
image:
basePath:
... ...
spring:
#------------------------------------------mysql---------------------------------------------------
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.1.41:3306/cmrdb?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
##配置初始化大小、最小、最大
initial-size: 5
max-active: 100
min-idle: 5
#配置获取连接等待超时的时间
max-wait: 60000
##打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
validation-query: SELECT 1 FROM DUAL
validation-query-timeout: 60000
##这里建议配置为TRUE,防止取到的连接不可用
test-on-borrow: true
test-on-return: false
test-while-idle: true
##配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 100000
jpa:
show-sql: false
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
#----------------------------------------rabbitmq---------------------------------------------------
rabbitmq:
host: 192.168.0.14
port: 5672
username: admin
password: admin
virtual-host: /
#设置发送确认
publisher-confirm-type: correlated
template:
mandatory: true
listener:
simple:
#决定被拒绝的消息是否重新入队
default-requeue-rejected: true
retry:
#时间间隔5秒
initial-interval: 5000ms
enabled: true
#最大重试次数
max-attempts: 4
analyser:
#分析器上传接口
uploadUrl: http://192.168.1.99/file-upload-service/file/upload/
#分析器批量删除文件接口
fileBatchDeleteUrl: http://192.168.1.99/file-upload-service/file/batch-delete
#图片分析
pictureAnalysisUrl: http://192.168.0.14:20005/file-figure-analyzer/picture/analysis/person
#熟人库图片相似度查询
similarityMatchUrl: http://192.168.1.99/figure-data-service/familiar-figure-lib/image2figures
#删除熟人
deleteFigureUrl: http://192.168.1.99/figure-data-service/familiar-figure-lib/figure
#删除人脸
deleteFigureFaceUrl: http://192.168.1.99/figure-data-service/familiar-figure-lib/figure/face
#熟人与人脸一起添加(新增或更新)
figureFaceUrl: http://192.168.1.99/figure-data-service/familiar-figure/figure-face
#修改熟人
updateFigureUrl: http://192.168.1.99/figure-data-service/familiar-figure/figure-face/modify
#图片查陌生人
picturePersonUrl: http://192.168.1.99/figure-data-service/picture/person
#特征值字符串查熟人
feature2figureUrl: http://192.168.1.99/figure-data-service/familiar-figure-lib/feature2figure
#挂载路径
filePath: "/upload_data/"
cmr:
image:
basePath:
\ No newline at end of file
... ...
spring:
#------------------------------------------mysql---------------------------------------------------
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.0.14:13306/cmrdb?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=GMT%2B8
username: root
password: 38128
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
##配置初始化大小、最小、最大
initial-size: 5
max-active: 100
min-idle: 5
#配置获取连接等待超时的时间
max-wait: 60000
##打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
validation-query: SELECT 1 FROM DUAL
validation-query-timeout: 60000
##这里建议配置为TRUE,防止取到的连接不可用
test-on-borrow: true
test-on-return: false
test-while-idle: true
##配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 100000
jpa:
show-sql: false
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
#----------------------------------------rabbitmq---------------------------------------------------
rabbitmq:
host: 192.168.0.14
port: 5672
username: admin
password: admin
virtual-host: /
#设置发送确认
publisher-confirm-type: correlated
template:
mandatory: true
listener:
simple:
#决定被拒绝的消息是否重新入队
default-requeue-rejected: true
retry:
#时间间隔5秒
initial-interval: 5000ms
enabled: true
#最大重试次数
max-attempts: 4
analyser:
#分析器上传接口
uploadUrl: http://file-upload-service:18010/file/upload/
#分析器批量删除文件接口
fileBatchDeleteUrl: http://file-upload-service:18010/file/batch-delete
#图片分析
pictureAnalysisUrl: http://file-figure-analyzer:18011/picture/analysis/person
#熟人库图片相似度查询
similarityMatchUrl: http://figure-data-service/familiar-figure-lib/image2figures
#删除熟人
deleteFigureUrl: http://figure-data-service/familiar-figure-lib/figure
#删除人脸
deleteFigureFaceUrl: http://figure-data-service/familiar-figure-lib/figure/face
#熟人与人脸一起添加(新增或更新)
figureFaceUrl: http://figure-data-service/familiar-figure/figure-face
#修改熟人
updateFigureUrl: http://figure-data-service/familiar-figure/figure-face/modify
#特征值字符串查熟人
feature2figureUrl: http://figure-data-service/familiar-figure-lib/feature2figure
#挂载路径
filePath: "/upload_data/"
#图片查陌生人
picturePersonUrl: http://figure-data-service/picture/person
pictureAnalysisToWordsUrl: http://file-ocr-analysis/ocr/image
cmr:
image:
basePath: upload_data/
startPath: ay-file/upload/
\ No newline at end of file
... ...
spring:
profiles:
active: @spring.profiles.active@
ribbon:
ReadTimeout: 60000
ConnectTimeout: 60000
logging:
level:
com.wondertek.ivod.*: info
springfox.documentation.*: error
org.springframework.*: error
#org.hibernate.type.descriptor.sql.BasicBinder: trace
#分析器侧命名空间
analyser:
namespace: cloud-media-resources
mq:
anylzer:
#人物分析回调mq
callbackExchange: VideoExchange
callbackQueue: video.anylzer_callback
ocr:
callbackExchange: ai-analyse-return
callbackQueue: ai-analyse-return-cloud-media
file:
uploadPath: /upload
downloadPath: /download
\ No newline at end of file
... ...
common:
group: SAAS_GROUP
nacos:
username: nacos
password: nacos
server-addr: localhost:8848
... ...
common:
group: SAAS_GROUP
nacos:
username: nacos
password: nacos
server-addr: 192.168.1.84:8848
... ...
common:
group: SAAS_GROUP
nacos:
username: nacos
password: nacos
server-addr: 192.168.0.14:8848
\ No newline at end of file
... ...
spring:
servlet:
multipart:
max-file-size: 500MB
max-request-size: 2500MB
application:
name: cmr-manage
cloud:
nacos:
discovery:
server-addr: ${common.nacos.server-addr}
namespace: ${spring.profiles.active}
group: ${common.group}
username: ${common.nacos.username}
password: ${common.nacos.password}
# enabled: false
config:
server-addr: ${common.nacos.server-addr}
namespace: ${spring.profiles.active}
group: ${common.group}
username: ${common.nacos.username}
password: ${common.nacos.password}
file-extension: yml
shared-configs:
- data-id: ${spring.application.name}-base.yaml
group: ${common.group}
refresh: true
extension-configs:
- data-id: ${spring.application.name}-fallback-resp.yml
group: ${common.group}
refresh: true
enabled: false
server:
port: 18666
servlet:
context-path: /cmr-manage
logging:
file:
path: ./logs
... ...
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false">
<springProperty scop="context" name="app_name" source="spring.application.name" defaultValue="cmr-manage"/>
<property name="log.path" value="logs" />
<property name="CONSOLE_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%msg%n"/>
<property name="CONSOLE_LOG_PATTERN_DETAIL"
value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|${PID:-}|%thread|${app_name:-}|%X{X-B3-TraceId:-}|%X{X-B3-SpanId:-}|%X{X-Span-Export:-}|%class.%method-%line|%msg%n"/>
<!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN_DETAIL}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- Log file debug output -->
<appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/${app_name:-}.info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/%d{yyyy-MM-dd}/${app_name:-}.%d{yyyy-MM-dd}.info.log</fileNamePattern>
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- Log file error output -->
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/${app_name:-}.error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>logs/%d{yyyy-MM-dd}/${app_name:-}.%d{yyyy-MM-dd}.error.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="INFO">
<appender-ref ref="console" />
<appender-ref ref="logFile" />
<appender-ref ref="error" />
</root>
</configuration>
\ No newline at end of file
... ...
import com.wondertek.ivod.cmr.commons.utils.FileUtils;
import com.wondertek.ivod.cmr.manage.CMRManageApplication;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.io.File;
// 第一种方式,推荐这种使用更方便
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = CMRManageApplication.class)
@Slf4j
public class MyTest {
@Test
public void testHello() {
File file = FileUtils.downLoadFromUrl("https://dev.aivideo.cn/preview/ay-file/upload/cloud-media-resources/10000000019/0/2021/9/26/18/a07483d8b1ef4856a11411fce5e0c5e8.mp4.figuredot/data.json","aa.json");
log.info(file.getName());
}
}
... ...
FROM 192.168.1.7/library/java8:centos7
ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
SPRING_PROFILE_ACTIVE=prod \
SPRING_OPTS="" \
JAVA_OPTS=""
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=${SPRING_PROFILE_ACTIVE} ${SPRING_OPTS}
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ADD target/*.jar /app.jar
\ No newline at end of file
... ...
FROM 192.168.1.7/library/java8:centos7
ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
SPRING_PROFILE_ACTIVE=preview \
SPRING_OPTS="" \
JAVA_OPTS=""
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=${SPRING_PROFILE_ACTIVE} ${SPRING_OPTS}
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ADD *.jar /app.jar
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud-media-resources</artifactId>
<groupId>com.wondertek.ivod.cmr</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.wondertek.ivod.cmr.search</groupId>
<artifactId>cmr-search</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.wondertek.ivod.cmr.commons</groupId>
<artifactId>cmr-commons</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.wondertek.ivod.cmr.core</groupId>
<artifactId>cmr-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>
<!--如果需要打docker镜像,把注释放开即可-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.1.0</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>192.168.1.69/ai_lib/${project.artifactId}:${project.version}</imageName>
<dockerHost>http://192.168.1.70:2375</dockerHost>
<dockerDirectory>${basedir}/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<profiles>
<profile>
<id>docker</id>
<properties>
<spring.profiles.active>preview</spring.profiles.active>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<imageName>192.168.1.7/ivod/${project.artifactId}:${project.version}</imageName>
<dockerHost>http://192.168.1.70:2375</dockerHost>
<serverId>wd-harbor</serverId>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
\ No newline at end of file
... ...
package com.wondertek.ivod.cmr.search;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableDiscoveryClient
public class CMRSearchApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(CMRSearchApplication.class, args);
SpringUtil springUtil = new SpringUtil();
springUtil.setApplicationContext(applicationContext);
}
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
... ...
package com.wondertek.ivod.cmr.search.config;
import cn.hutool.json.JSONUtil;
import com.wondertek.ivod.cmr.commons.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
/**
* 请求参数与响应结果封装
* @Author: CuiSiBo
* @Date: 2020/5/6 17:03
* @Version 1.0
*/
@Aspect
@Component
@Slf4j
public class LogAspect {
@Pointcut("execution(public * com.wondertek.ivod.cmr.search.controller.*Controller.*(..))")
public void webLog() {
}
@Around("webLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
//获取当前请求对象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//设置用户信息
UserUtils.setUser(request);
String uri = request.getRequestURI();
//记录入参
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
Object inParameter = getParameter(method, joinPoint.getArgs());
String paramStr = "{}";
if (ObjectUtils.isNotEmpty(inParameter)) {
paramStr = JSONUtil.parse(inParameter).toJSONString(0);
//paramStr = paramStr.length() > 1000 ? paramStr.substring(0, 1000) : paramStr;
}
log.info(">>>>>>>>>> {} begin ! parameter:{}", uri, paramStr);
//执行接口
Object result = joinPoint.proceed();
//记录出参
String resultStr = "{}";
if (ObjectUtils.isNotEmpty(result)){
resultStr = JSONUtil.parse(result).toJSONString(0);
//resultStr = resultStr.length() > 1000 ? resultStr.substring(0, 1000) : resultStr;
}
long endTime = System.currentTimeMillis();
log.info(">>>>>>>>>> {} end, time-consuming:{}ms ! result:{}", uri, endTime - startTime, resultStr);
return result;
}
/**
* 根据方法和传入的参数获取请求参数
*/
private List<Map> getParameter(Method method, Object[] args) {
List<Map> argList = new ArrayList<>();
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
Map<String, Object> map = new HashMap<>();
map.put(parameters[i].getName(), args[i]);
argList.add(map);
}
return argList;
}
}
... ...
package com.wondertek.ivod.cmr.search.controller;
import cn.hutool.core.util.ObjectUtil;
import com.wondertek.ivod.cmr.commons.utils.PageBean;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.search.service.MaterialService;
import com.wondertek.ivod.cmr.search.vo.MaterialPageReqVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.text.ParseException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @Author Hcg
* @Date 2021/8/13
* @desc
*/
@RestController
@RequestMapping("/material")
public class MaterialController {
@Autowired
private MaterialService materialService;
/**
* 列表查询
*
* @param vo
* @return
*/
@PostMapping("/list")
public ResultBean list(@RequestBody MaterialPageReqVo vo) {
return materialService.list(vo);
}
/**
* 人脸识别信息
*
* @param materialId
* @param keywords
* @param page
* @param rows
* @return
*/
@GetMapping("/get-figure")
public ResultBean getFigure(@RequestParam(value = "materialId") Long materialId, String keywords, Integer page, Integer rows) {
return materialService.getFigure(materialId, keywords, page, rows);
}
/**
* 媒资详情
*
* @param materialId
* @return
*/
@GetMapping("/get")
public ResultBean getFigure(@RequestParam(value = "materialId") Long materialId) {
return materialService.getInfo(materialId);
}
/**
* 批量查询详情
*
* @param map
* @return
* @throws ParseException
*/
@PostMapping("/getByIds")
public ResultBean getByIds(@RequestBody Map<String, List<Long>> map) throws ParseException {
List<Long> materialIds = map.get("materialIds");
materialIds.removeAll(Collections.singleton(null));
return materialService.getByIds(materialIds);
}
/**
* 文字识别信息
*
* @param materialId
* @param keywords
* @return
*/
@GetMapping("/getAiWords")
public ResultBean getAiWords(@RequestParam Long materialId, @RequestParam(required = false) String keywords) {
if (ObjectUtil.isEmpty(materialId)) {
return ResultBean.error("媒资id必传");
}
return ResultBean.ok(materialService.getAiWords(materialId, keywords));
}
}
... ...
package com.wondertek.ivod.cmr.search.controller;
import cn.hutool.core.util.ObjectUtil;
import com.wondertek.ivod.cmr.commons.enums.GlobalCodeEnum;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
import com.wondertek.ivod.cmr.core.entity.dto.MaterialDeleteDto;
import com.wondertek.ivod.cmr.search.service.IMaterialInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/6 15:29
* <p>
* 介质信息
*/
@RestController
@RequestMapping("es/materialInfo")
public class MaterialInfoController {
@Autowired
private IMaterialInfoService materialInfoService;
/**
* 新建
*
* @param materialInfo
* @return
*/
@PostMapping("/create")
public ResultBean create(@RequestBody MaterialInfo materialInfo) {
materialInfoService.create(materialInfo);
return ResultBean.ok();
}
/**
* 修改
*
* @param materialInfo
* @return
*/
@PutMapping("/update")
public ResultBean update(@RequestBody MaterialInfo materialInfo) {
materialInfoService.update(materialInfo);
return ResultBean.ok();
}
/**
* 批量删除
*
* @param materialDeleteDto
* @return
*/
@DeleteMapping("/deleteInfos")
public ResultBean deleteInfos(@RequestBody MaterialDeleteDto materialDeleteDto) {
if (ObjectUtil.isEmpty(materialDeleteDto.getMaterialIds())) {
return ResultBean.error("媒资ID不能为空");
}
materialInfoService.deleteByIds(materialDeleteDto.getMaterialIds());
return ResultBean.ok();
}
/**
* 通过ID查询
*
* @param materialId
* @return
*/
@GetMapping("/getById")
public ResultBean getById(@RequestParam Long materialId) {
if (ObjectUtil.isEmpty(materialId)){
return ResultBean.error("媒资ID不能为空");
}
return ResultBean.ok(materialInfoService.getById(materialId));
}
}
... ...
package com.wondertek.ivod.cmr.search.enums;
import java.util.Arrays;
/**
* 全局枚举属性
* @date: 2021/4/6
*/
public enum GlobalCodeEnum {
//错误枚举
UNKNOWN_ERROR("-1", "服务器异常"),
FAILURE("0", "failure"),
SUCCESS("1", "success"),
INVALID_PARAMS("2", "请求参数无效"),
UNSUPPORTED_URI("3", "未知URI"),
LACK_PARAMS("4", "请求参数缺失"),
PASS_URL_ERR("5", "组装pass层公共参数出现异常"),
DATE_ISNULL_ERR("6", "数据不存在!"),
REQUEST_PASS_ERROR("7", "请求pass层出现异常"),
AI_CLOUD_ERR("3001","Ai云调度服务响应异常"),
ACCESS_CLOUD_ERR("3001","接入云调度服务响应异常"),
DATA_CLOUD_ERR("3001","数据云服务响应异常"),
ICLOUD_ERR("3001","存储云调度服务响应异常"),
MAINTENANCE_ERR("3001","营维中台服务响应异常"),
;
private String code;
private String msg;
private GlobalCodeEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
/**
* 根据Key得到枚举的Value
* Lambda表达式,比较判断(JDK 1.8)
*
* @param key
* @return
*/
public static String getMsg(String key) {
return Arrays.stream(GlobalCodeEnum.values())
.filter(globalCodeEnum -> globalCodeEnum.getCode().equals(key))
.findFirst().orElse(GlobalCodeEnum.UNKNOWN_ERROR).getMsg();
}
}
... ...
package com.wondertek.ivod.cmr.search.exception;
import com.wondertek.ivod.cmr.search.enums.GlobalCodeEnum;
/**
* <p><b>BusinessException Description:</b> 业务类运行时异常, 所有业务类运行时异常继承于该异常</p>
* @author douzi
* <b>DATE</b> 2019年2月18日 上午10:27:00
*/
public class DefaultException extends RuntimeException {
private static final long serialVersionUID = 1L;
protected int errorCode;
public DefaultException(GlobalCodeEnum globalCodeEnum) {
super(globalCodeEnum.getMsg());
this.errorCode = Integer.parseInt(globalCodeEnum.getCode());
}
public DefaultException(GlobalCodeEnum globalCodeEnum, String message) {
super(message);
this.errorCode = Integer.parseInt(globalCodeEnum.getCode());
}
public DefaultException(Throwable cause) {
super(cause);
}
/**
* @param message
* @param cause
*/
public DefaultException(int errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
/**
* @param message
*/
public DefaultException(int errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public DefaultException(String message) {
super(message);
this.errorCode = Integer.parseInt(GlobalCodeEnum.FAILURE.getCode());
}
public DefaultException(String message,Throwable throwable) {
super(message + throwable.getMessage());
this.errorCode = Integer.parseInt(GlobalCodeEnum.FAILURE.getCode());
}
/**
* @param cause
*/
public DefaultException(int errorCode, Throwable cause) {
super(cause);
this.errorCode = errorCode;
}
public int getErrorCode() {
return this.errorCode;
}
}
... ...
package com.wondertek.ivod.cmr.search.exception;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.search.enums.GlobalCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import javax.servlet.http.HttpServletRequest;
/**
* @Title com.migu.editor.cloudeditor.advice
* @Author beckhamyht
* @Created 2019/5/23 19:01
*/
@RestControllerAdvice
@Slf4j
public class ExceptionHandlerAdvice {
@ExceptionHandler(Exception.class)
@ResponseBody
public ResultBean handlerException(HttpServletRequest req, Exception e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.UNKNOWN_ERROR.getCode(), GlobalCodeEnum.UNKNOWN_ERROR.getMsg());
}
@ExceptionHandler({BindException.class})
@ResponseBody
public ResultBean handlerBindException(BindException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
}
@ExceptionHandler({HttpMessageNotReadableException.class})
@ResponseBody
public ResultBean handlerParseException(HttpMessageNotReadableException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
}
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
@ResponseBody
public ResultBean handlerParseException(HttpRequestMethodNotSupportedException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.FAILURE.getCode(), e.getMessage());
}
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
@ResponseBody
public ResultBean handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
}
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseBody
public ResultBean missingServletRequestParameterException(MissingServletRequestParameterException e) {
log.error(e.getMessage(), e);
return ResultBean.error(GlobalCodeEnum.INVALID_PARAMS.getCode(), GlobalCodeEnum.INVALID_PARAMS.getMsg());
}
/**
* 自定义异常拦截
*
* @param ex
* @return
*/
@ExceptionHandler({DefaultException.class})
public ResultBean DefaultException(DefaultException ex) {
log.error("{},{}",ex.getErrorCode(),ex.getMessage());
return ResultBean.error(ex.getErrorCode() + "", ex.getMessage());
}
}
... ...
package com.wondertek.ivod.cmr.search.repository;
import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
/**
* @Author yubin
* @Date 2021/8/6 15:27
*/
public interface MaterialInfoRepository extends ElasticsearchRepository<MaterialInfo, Long> {
}
... ...
package com.wondertek.ivod.cmr.search.service;
import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
import java.util.List;
/**
* @Author yubin
* @Date 2021/8/6 15:28
*/
public interface IMaterialInfoService {
void create(MaterialInfo materialInfo);
void update(MaterialInfo materialInfo);
void deleteByIds(List<Long> materialIds);
MaterialInfo getById(Long materialId);
}
... ...
package com.wondertek.ivod.cmr.search.service;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.WordInfo;
import com.wondertek.ivod.cmr.search.vo.MaterialPageReqVo;
import java.text.ParseException;
import java.util.List;
/**
* @Author Hcg
* @Date 2021/8/13
* @desc
*/
public interface MaterialService {
/**
*人脸识别信息
* @param materialId 媒资id
* @param keywords 关键字
* @return ResultBean
*/
ResultBean getFigure(Long materialId, String keywords,Integer page,Integer rows);
/**
* 详情
* @param materialId 媒资id
* @return ResultBean
*/
ResultBean getInfo(Long materialId);
/**
* 列表分页查询
* @param vo 入参
* @return PageBean
*/
ResultBean list(MaterialPageReqVo vo);
/**
* 批量查询
* @param materialIds 媒资id数组
* @return ResultBean
*/
ResultBean getByIds(List<Long> materialIds) throws ParseException;
/**
* 文字识别信息
*
* @param materialId
* @param keywords
* @return
*/
List<WordInfo> getAiWords(Long materialId, String keywords);
}
... ...
package com.wondertek.ivod.cmr.search.service.impl;
import com.wondertek.ivod.cmr.core.entity.bean.MaterialInfo;
import com.wondertek.ivod.cmr.search.repository.MaterialInfoRepository;
import com.wondertek.ivod.cmr.search.service.IMaterialInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* @Author yubin
* @Date 2021/8/6 15:28
*/
@Service
@Slf4j
public class MaterialInfoServiceImpl implements IMaterialInfoService {
@Autowired
private MaterialInfoRepository materialInfoRepository;
@Override
public void create(MaterialInfo materialInfo) {
materialInfoRepository.save(materialInfo);
}
@Override
public void update(MaterialInfo materialInfo) {
materialInfoRepository.save(materialInfo);
}
@Override
public void deleteByIds(List<Long> materialIds) {
List<MaterialInfo> materialInfoList = new ArrayList<>();
materialIds.forEach(materialId -> {
MaterialInfo materialInfo = new MaterialInfo();
materialInfo.setMaterialId(materialId);
materialInfoList.add(materialInfo);
});
materialInfoRepository.deleteAll(materialInfoList);
}
@Override
public MaterialInfo getById(Long materialId) {
Optional<MaterialInfo> optional = materialInfoRepository.findById(materialId);
if (optional.isPresent()) {
return optional.get();
}
return null;
}
}
... ...
package com.wondertek.ivod.cmr.search.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.wondertek.ivod.cmr.commons.enums.CommonStatusEnum;
import com.wondertek.ivod.cmr.commons.enums.MaterialTypeEnum;
import com.wondertek.ivod.cmr.commons.exception.DefaultException;
import com.wondertek.ivod.cmr.commons.utils.PageBean;
import com.wondertek.ivod.cmr.commons.utils.ResultBean;
import com.wondertek.ivod.cmr.commons.utils.UserUtils;
import com.wondertek.ivod.cmr.core.entity.bean.*;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.PictureAnalysisResult;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.*;
import com.wondertek.ivod.cmr.search.repository.MaterialInfoRepository;
import com.wondertek.ivod.cmr.search.service.MaterialService;
import com.wondertek.ivod.cmr.search.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Author Hcg
* @Date 2021/8/13
* @desc
*/
@Slf4j
@Service
public class MaterialServiceImpl implements MaterialService {
@Autowired
private MaterialInfoRepository materialInfoRepository;
@Override
public ResultBean getFigure(Long materialId, String keywords, Integer page, Integer rows) {
log.info("【视频详情】人脸识别信息入参:materialId={},keywords={}", materialId, keywords);
if (materialId == null) {
return PageBean.error("媒资id不能为空");
}
MaterialInfo materialInfo = materialInfoRepository.findById(materialId).orElse(null);
if (materialInfo == null) {
return PageBean.error("媒资信息不存在或者数据库媒资信息错误");
}
if (null == page || page < 1) {
page = 1;
}
if (null == rows || rows < 1) {
rows = 20;
}
log.info(materialInfo.toString());
List<FaceInfo> faceInfos = materialInfo.getFaceInfo();
//根据出现次数排序
if (!CollectionUtils.isEmpty(faceInfos)) {
Collections.sort(faceInfos, Comparator.comparing((FaceInfo faceInfo) ->
Integer.valueOf(faceInfo.getAppearRate() == null ? "0" : faceInfo.getAppearRate().replace("%", ""))).reversed());
int total = faceInfos.size();
int pageSum = (total - 1) / rows + 1;
if (!StrUtil.isBlank(keywords)) {
ArrayList<FaceInfo> list = Lists.newArrayList();
faceInfos.forEach(faceInfo -> {
if (StrUtil.isNotBlank(faceInfo.getFigureName())) {
if (faceInfo.getFigureName().contains(keywords)) {
list.add(faceInfo);
}
}
});
int total1 = list.size();
int pageSum1 = (total1 - 1) / rows + 1;
List<FaceInfo> collect1 = list.stream().skip((page - 1) * rows).limit(rows).collect(Collectors.toList());
return PageBean.ok(pageSum1, (long) total1, collect1);
}
List<FaceInfo> collect = faceInfos.stream().skip((page - 1) * rows).limit(rows).
collect(Collectors.toList());
return PageBean.ok(pageSum, (long) total, collect);
}
return PageBean.ok();
}
@Override
public ResultBean getInfo(Long materialId) {
log.info("【视频详情】获取详情信息入参:materialId={}", materialId);
if (materialId == null) {
return ResultBean.error("媒资id不能为空");
}
MaterialInfo materialInfo = materialInfoRepository.findById(materialId).orElse(null);
if (materialInfo == null) {
return ResultBean.error("媒资信息不存在或者数据库媒资信息错误");
}
BasicInfo basicInfo = materialInfo.getBasicInfo();
MaterialInfoVo materialInfoVo = new MaterialInfoVo();
if (null != basicInfo) {
BeanUtils.copyProperties(basicInfo, materialInfoVo);
if (!CollectionUtils.isEmpty(basicInfo.getTagInfoSet())) {
materialInfoVo.setLabel(Joiner.on(",").join(basicInfo.getTagInfoSet()));
}
if (null != basicInfo.getImageAttr()) {
materialInfoVo.setArtist(basicInfo.getImageAttr().getArtist());
materialInfoVo.setShootingTime(basicInfo.getImageAttr().getShootingTime());
materialInfoVo.setLocation(basicInfo.getImageAttr().getLocation());
}
if (!CollectionUtils.isEmpty(basicInfo.getCustomLabelSet())) {
materialInfoVo.setCustomLabel(Joiner.on(",").join(basicInfo.getCustomLabelSet()));
}
}
MediaInfo mediaInfo = materialInfo.getMediaInfo();
if (null != mediaInfo) {
materialInfoVo.setDuration(mediaInfo.getDuration() + "");
}
materialInfoVo.setAiAnalysisStatus(materialInfo.getMaterialStatus().getAiAnalysisStatus());
return ResultBean.ok(materialInfoVo);
}
@Override
public ResultBean list(MaterialPageReqVo vo) {
Integer page = vo.getPage();
Integer rows = vo.getRows();
if (ObjectUtil.isEmpty(page) || ObjectUtil.isEmpty(rows) || page < 1 || rows < 1) {
return PageBean.error("分页参数不正确");
}
log.info("【视频列表查询】获取列表信息入参:{}", JSONUtil.toJsonStr(vo));
if (ObjectUtil.isNotEmpty(vo.getFaceId()) && ObjectUtil.isNotEmpty(vo.getKeywords())) {
return PageBean.error("图片同关键字只能有一个");
}
String tenantId = UserUtils.getUser().getTenantId();
if (StrUtil.isBlank(tenantId)) {
return PageBean.error("租户id不存在");
}
//检索条件
BoolQueryBuilder query = getQuery(vo, vo.getFaceId(), tenantId);
//排序条件
FieldSortBuilder fsb = SortBuilders.fieldSort("basicInfo." + vo.getSidx()).order("asc".equals(vo.getSord()) ? SortOrder.ASC : SortOrder.DESC);
FieldSortBuilder fsb1 = SortBuilders.fieldSort("basicInfo.materialType").order(SortOrder.DESC);
//分页条件
Pageable pageable = PageRequest.of(vo.getPage() - 1, vo.getRows());
//构建查询
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(query)
.withSort(fsb)
.withSort(fsb1)
.withPageable(pageable).withTrackScores(false)
.build();
Page<MaterialInfo> search = materialInfoRepository.search(searchQuery);
Long videoCount = 0L;
Long imgCount = 0L;
//添加条件,查询视频和图片数量
if (ObjectUtil.isNotEmpty(vo.getMaterialType())) {
if (MaterialTypeEnum.VIDEO.getCode().equals(vo.getMaterialType())) {
videoCount = search.getTotalElements();
}
if (MaterialTypeEnum.PICTURE.getCode().equals(vo.getMaterialType())) {
imgCount = search.getTotalElements();
}
} else {
query.must(QueryBuilders.termQuery("basicInfo.materialType", MaterialTypeEnum.VIDEO.getCode()));
NativeSearchQuery searchQuery1 = new NativeSearchQueryBuilder()
.withQuery(query)
.withSort(fsb)
.withPageable(pageable).withTrackScores(false)
.build();
Page<MaterialInfo> searchVideo = materialInfoRepository.search(searchQuery1);
videoCount = searchVideo.getTotalElements();
//查询图片数量
imgCount = search.getTotalElements() - videoCount;
}
ResultBean list = getVideoAndImageCount(search, vo.getFaceId(), vo.getKeywords(), videoCount, imgCount);
if (list != null) {
return list;
}
return PageBean.ok(search.getTotalPages(), search.getTotalElements(), search.getContent());
}
@Override
public ResultBean getByIds(List<Long> materialIds) throws ParseException {
log.info("【视频批量查询】获取批量信息入参:{}", materialIds);
if (CollectionUtils.isEmpty(materialIds)) {
return ResultBean.error("媒资id不能为空");
}
ArrayList<MaterialInfo> list = Lists.newArrayList();
for (Long materialId : materialIds) {
MaterialInfo materialInfo = materialInfoRepository.findById(materialId).orElse(null);
if (null != materialInfo) {
//如果修改时间一天后还是分析中或上传中的改成失败
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
BasicInfo basicInfo = materialInfo.getBasicInfo();
String updateTime = basicInfo.getUpdateTime();
Date parse = simpleDateFormat.parse(updateTime);
long time = parse.getTime();
MaterialStatus materialStatus = materialInfo.getMaterialStatus();
if (null != materialStatus) {
long currentTimeMillis = System.currentTimeMillis();
long l = (currentTimeMillis - time) / 1000;
if (l > (60 * 60 * 24)) {
if (CommonStatusEnum.WAIT.getCode().equals(materialStatus.getUploadStatus())) {
materialStatus.setUploadStatus(CommonStatusEnum.FAIL.getCode());
}
if (CommonStatusEnum.WAIT.getCode().equals(materialStatus.getAiAnalysisStatus())) {
materialStatus.setAiAnalysisStatus(CommonStatusEnum.FAIL.getCode());
}
materialInfo.setMaterialStatus(materialStatus);
materialInfoRepository.save(materialInfo);
}
}
list.add(materialInfo);
}
}
return ResultBean.ok(list);
}
/**
* 设置查询条件
*
* @param vo 入参
* @param faceId 分析器结果
*/
private BoolQueryBuilder getQuery(MaterialPageReqVo vo, String faceId, String tenantId) {
BoolQueryBuilder query = QueryBuilders.boolQuery();
query.must(QueryBuilders.termQuery("basicInfo.owner.tenantId", tenantId));
String keywords = vo.getKeywords();
if (StrUtil.isNotBlank(keywords)) {
query.should(QueryBuilders.wildcardQuery("basicInfo.name", "*" + keywords + "*"))
.should(QueryBuilders.wildcardQuery("basicInfo.tagInfoSet", keywords)).minimumShouldMatch(1);
}
if (ObjectUtil.isNotEmpty(faceId)) {
query.must(QueryBuilders.nestedQuery("faceInfo", QueryBuilders.termsQuery("faceInfo.figureId", faceId), ScoreMode.None));
}
if (ObjectUtil.isNotEmpty(vo.getMaterialType())) {
query.must(QueryBuilders.termQuery("basicInfo.materialType", vo.getMaterialType()));
}
if (ObjectUtil.isNotEmpty(vo.getSource())) {
query.must(QueryBuilders.termQuery("basicInfo.source", vo.getSource()));
}
if (ObjectUtil.isNotEmpty(vo.getStatus())) {
if (CommonStatusEnum.EXT.getCode().equals(vo.getStatus())) {
query.must(QueryBuilders.termQuery("materialStatus.embodyStatus", CommonStatusEnum.FAIL.getCode()));
} else {
query.must(QueryBuilders.termQuery("materialStatus.aiAnalysisStatus", vo.getStatus()));
}
}
return query;
}
/**
* 查询图片视频总数
*
* @param search 分页查询结果
* @param faceId 分析器结果
* @param keywords 关键字
* @param videoCount 视频数量
* @param imgCount 图片数量
* @return
*/
private ResultBean getVideoAndImageCount(Page<MaterialInfo> search, String faceId, String keywords, Long videoCount, Long imgCount) {
List<MaterialInfo> content = search.getContent();
if (!CollectionUtils.isEmpty(content)) {
ArrayList<MaterialListVo> list = Lists.newArrayList();
content.forEach(materialInfo -> {
MaterialListVo materialListVo = new MaterialListVo();
BeanUtils.copyProperties(materialInfo, materialListVo);
materialListVo.setImgCount(imgCount);
materialListVo.setVideoCount(videoCount);
List<FaceInfo> faceInfo = materialInfo.getFaceInfo();
getFirstFaceInfo(faceId, keywords, materialListVo, faceInfo);
list.add(materialListVo);
});
return PageBean.ok(search.getTotalPages(), search.getTotalElements(), list);
}
return null;
}
/**
* 获取列表页人物展示
*
* @param faceId
* @param keywords
* @param materialListVo
* @param faceInfo
*/
private void getFirstFaceInfo(String faceId, String keywords, MaterialListVo materialListVo, List<FaceInfo> faceInfo) {
FaceInfoVo faceInfoVo = new FaceInfoVo();
//当图片分析不为空时:
if (!CollectionUtils.isEmpty(faceInfo)) {
if (ObjectUtil.isNotEmpty(faceId)) {
//采用函数,当内循环结束满足条件时,结束外循环
lab:
for (FaceInfo info : faceInfo) {
if (StrUtil.isNotBlank(info.getFigureId())) {
if (info.getFigureId().equals(faceId)) {
BeanUtils.copyProperties(info, faceInfoVo);
if (!CollectionUtils.isEmpty(info.getFragments())) {
faceInfoVo.setAppearCount(info.getFragments().size());
}
break lab;
}
}
}
}
//当关键字不为空时:
if (StrUtil.isNotBlank(keywords)) {
for (FaceInfo info : faceInfo) {
if (StrUtil.isNotBlank(info.getFigureName())) {
if (info.getFigureName().contains(keywords)) {
BeanUtils.copyProperties(info, faceInfoVo);
if (!CollectionUtils.isEmpty(info.getFragments())) {
faceInfoVo.setAppearCount(info.getFragments().size());
}
break;
}
}
}
}
if (StrUtil.isBlank(faceInfoVo.getFigureName()) && StrUtil.isBlank(faceInfoVo.getFigureId())) {
Collections.sort(faceInfo, Comparator.comparing(FaceInfo::getAppearRate).reversed());
BeanUtils.copyProperties(faceInfo.get(0), faceInfoVo);
if (faceInfo.get(0).getFragments() != null && !CollectionUtils.isEmpty(faceInfo.get(0).getFragments())) {
faceInfoVo.setAppearCount(faceInfo.get(0).getFragments().size());
}
}
}
materialListVo.setFaceInfo(faceInfoVo);
}
/**
* 文字识别信息
*
* @param materialId
* @param keywords
* @return
*/
@Override
public List<WordInfo> getAiWords(Long materialId, String keywords) {
Optional<MaterialInfo> optional = materialInfoRepository.findById(materialId);
if (!optional.isPresent()) {
throw new DefaultException("该媒资不存在");
}
List<WordInfo> wordInfoList = optional.get().getWordInfo();
if (ObjectUtil.isNotEmpty(keywords)) {
wordInfoList = wordInfoList.stream().filter(wordInfo -> wordInfo.getWord().contains(keywords)).collect(Collectors.toList());
}
return wordInfoList;
}
}
... ...
package com.wondertek.ivod.cmr.search.vo;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.FaceInfo;
import lombok.Data;
/**
* @Author Hcg
* @Date 2021/8/23
* @desc
*/
@Data
public class FaceInfoVo extends FaceInfo {
private Integer appearCount;
}
... ...
package com.wondertek.ivod.cmr.search.vo;
import lombok.Data;
/**
* @Author Hcg
* @Date 2021/8/13
* @desc
*/
@Data
public class MaterialInfoVo {
private String duration;
/**
* 媒资类型
*/
private Integer materialType;
/**
* 名称
*/
private String name;
/**
* 来源
*/
private Integer source;
/**
* 标签
*/
private String label;
/**
* 封面图路径
*/
private String previewUrl;
/**
* 视频路径
*/
private String mediaUrl;
/**
* AI分析状态 0-未开启 1-成功 2-失败 3-进行中
*/
private Integer aiAnalysisStatus;
/**
* 自定义标签
*/
private String customLabel;
/**
* 图片拍摄时间
*/
private String shootingTime;
/**
* 地点
*/
private String location;
/**
* 作者
*/
private String artist;
}
... ...
package com.wondertek.ivod.cmr.search.vo;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.PictureAnalysisResult;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.BasicInfo;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.MaterialStatus;
import com.wondertek.ivod.cmr.core.entity.bean.materialInfoEs.MediaInfo;
import lombok.Data;
import java.util.List;
/**
* @Author Hcg
* @Date 2021/8/18
* @desc
*/
@Data
public class MaterialListVo {
/**
* 视频数量
*/
private Long videoCount;
/**
* 图片数量
*/
private Long imgCount;
/**
* 媒资ID
*/
private Long materialId;
/**
* 基本信息
*/
private BasicInfo basicInfo;
/**
* 介质信息
*/
private MediaInfo mediaInfo;
/**
* 人脸识别信息
*/
private FaceInfoVo faceInfo;
/**
* 状态信息
*/
private MaterialStatus materialStatus;
}
... ...
package com.wondertek.ivod.cmr.search.vo;
import com.wondertek.ivod.cmr.core.entity.bean.analyser.PictureAnalysisResult;
import lombok.Data;
import java.util.List;
/**
* @Author Hcg
* @Date 2021/8/13
* @desc
*/
@Data
public class MaterialPageReqVo {
/**
* 关键词
*/
private String keywords;
/**
* 类型 1-视频 2-音频 3-图片
*/
private Integer materialType;
/**
* 来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控
*/
private Integer source;
/**
* 人脸检索陌生人id
*/
private String faceId;
private Integer page;
private Integer rows;
private String sidx = "createTime";
private String sord = "desc";
/**
* 状态 -1-收录失败 0-未开启AI 1-AI识别成功 2-AI识别失败
*/
private Integer status;
}
... ...
package com.wondertek.ivod.cmr.search.vo;
import lombok.Data;
/**
* @Author Hcg
* @Date 2021/8/20
* @desc
*/
@Data
public class PictureAnalysis {
private String namespace;
private String faceImg;
private String userId;
}
\ No newline at end of file
... ...
spring:
# elasticsearch:
# rest:
# uris: 127.0.0.1:9300
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: localhost:9300
repositories:
enabled: true
\ No newline at end of file
... ...
spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 192.168.1.72:9300
repositories:
enabled: true
... ...
spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 192.168.0.25:9301
repositories:
enabled: true
#分析器上传接口
file:
pictureAnalysisUrl: http://figure-data-service/picture/person
#分析器侧命名空间
analyser:
namespace: cloud-media-resources
\ No newline at end of file
... ...
spring:
profiles:
active: preview #@spring.profiles.active@
logging:
level:
com.wondertek.ivod.*: info
springfox.documentation.*: error
org.springframework.*: error
\ No newline at end of file
... ...
common:
group: SAAS_GROUP
nacos:
username: nacos
password: nacos
server-addr: localhost:8848
... ...
common:
group: SAAS_GROUP
nacos:
username: nacos
password: nacos
server-addr: 192.168.1.84:8848
... ...
common:
group: SAAS_GROUP
nacos:
username: nacos
password: nacos
server-addr: 192.168.0.14:8848
... ...
spring:
servlet:
multipart:
max-file-size: 104857600
max-request-size: 104857600
application:
name: cmr-search
cloud:
nacos:
discovery:
server-addr: ${common.nacos.server-addr}
namespace: ${spring.profiles.active}
group: ${common.group}
username: ${common.nacos.username}
password: ${common.nacos.password}
# enabled: false
config:
server-addr: ${common.nacos.server-addr}
namespace: ${spring.profiles.active}
group: ${common.group}
username: ${common.nacos.username}
password: ${common.nacos.password}
file-extension: yml
shared-configs:
- data-id: ${spring.application.name}-base.yaml
group: ${common.group}
refresh: true
extension-configs:
- data-id: ${spring.application.name}-fallback-resp.yml
group: ${common.group}
refresh: true
enabled: true
server:
port: 18667
servlet:
context-path: /cmr-search
logging:
file:
path: ./logs
... ...
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false">
<springProperty scop="context" name="app_name" source="spring.application.name" defaultValue="cmr-search"/>
<property name="log.path" value="logs" />
<property name="CONSOLE_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%msg%n"/>
<property name="CONSOLE_LOG_PATTERN_DETAIL"
value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|${PID:-}|%thread|${app_name:-}|%X{X-B3-TraceId:-}|%X{X-B3-SpanId:-}|%X{X-Span-Export:-}|%class.%method-%line|%msg%n"/>
<!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN_DETAIL}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- Log file debug output -->
<appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/${app_name:-}.info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/%d{yyyy-MM-dd}/${app_name:-}.%d{yyyy-MM-dd}.info.log</fileNamePattern>
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- Log file error output -->
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/${app_name:-}.error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>logs/%d{yyyy-MM-dd}/${app_name:-}.%d{yyyy-MM-dd}.error.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="INFO">
<appender-ref ref="console" />
<appender-ref ref="logFile" />
<appender-ref ref="error" />
</root>
</configuration>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.wondertek.ivod.cmr</groupId>
<artifactId>cloud-media-resources</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>
<modules>
<module>cmr-manage</module>
<module>cmr-commons</module>
<module>cmr-search</module>
<module>cmr-core</module>
</modules>
<repositories>
<repository>
<id>wd-releases</id>
<name>wd-releases</name>
<url>http://180.167.180.242:7881/repository/3rd_part/</url>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<!--服务调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<!-- spring boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- search 基础依赖包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty3-client</artifactId>
<version>5.6.14</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<!-- 添加data jpa依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.8.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-core-asl -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
... ...
CREATE TABLE `cmr_ai_figure` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`material_Id` bigint(20) DEFAULT NULL COMMENT '媒资ID',
`figure_id` bigint(20) DEFAULT NULL COMMENT '分析器陌生人库ID',
`image_path` varchar(1024) DEFAULT NULL COMMENT '头像',
`begin_time` varchar(32) DEFAULT NULL COMMENT '露出开始时间',
`end_time` varchar(32) DEFAULT NULL COMMENT '露出结束时间',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_ai_ids` (`material_Id`,`figure_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='人物识别表 ';
CREATE TABLE `cmr_figure` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '人物ID',
`name` varchar(128) DEFAULT NULL COMMENT '人物名称',
`figure_define_id` varchar(128) DEFAULT NULL COMMENT '人物自定义ID',
`gender` int(1) DEFAULT NULL COMMENT '性别 0-女 1-男',
`remark` varchar(128) DEFAULT NULL COMMENT '备注',
`familiar_figure_id` varchar(128) DEFAULT NULL COMMENT '分析器熟人id',
`preview_url` varchar(1024) DEFAULT NULL COMMENT '预览路径',
`tenant_Id` varchar(32) DEFAULT NULL COMMENT '租户ID',
`create_by` varchar(128) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(128) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='人物表 ';
CREATE TABLE `cmr_figure_image` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`figure_id` varchar(32) DEFAULT NULL COMMENT '人物ID',
`name` datetime DEFAULT NULL COMMENT '名称',
`type` varchar(32) DEFAULT NULL COMMENT '图片类型',
`image_path` datetime DEFAULT NULL COMMENT '图片路径',
`resolution` varchar(32) DEFAULT NULL COMMENT '分辨率',
`width` varchar(32) DEFAULT NULL COMMENT '宽',
`high` varchar(32) DEFAULT NULL COMMENT '高',
`md5` varchar(32) DEFAULT NULL COMMENT 'MD5',
PRIMARY KEY (`id`),
KEY `idx_image_figureid` (`figure_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='人物图片表 ';
CREATE TABLE `cmr_logs` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '乐观锁',
`operation_BY` varchar(32) DEFAULT NULL COMMENT '操作人',
`operation_TIME` datetime DEFAULT NULL COMMENT '操作时间',
`object_id` varchar(32) DEFAULT NULL COMMENT '对象ID',
`object_type` varchar(32) DEFAULT NULL COMMENT '对象类型',
`operation__msg` varchar(512) DEFAULT NULL COMMENT '操作信息',
`operation__type` varchar(32) DEFAULT NULL COMMENT '操作类型',
`request_url` varchar(128) DEFAULT NULL COMMENT '请求URL',
PRIMARY KEY (`ID`),
KEY `idx_logs_objectid` (`object_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作记录表 ';
CREATE TABLE `cmr_material` (
`material_Id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '媒资ID',
`material_type` int(10) DEFAULT NULL COMMENT '媒资类型 1-视频 2-音频 3-图片',
`name` varchar(128) DEFAULT NULL COMMENT '名称',
`source` int(10) DEFAULT NULL COMMENT '来源 1-本地上传 2-视频搬迁 3-直播录制 4-云剪辑 5-视频监控 ',
`tenant_Id` varchar(32) DEFAULT NULL COMMENT '租户ID',
`media_url` varchar(1024) DEFAULT NULL COMMENT '介质预览路径',
`preview_url` varchar(1024) DEFAULT NULL COMMENT '封面图',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`updated_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`updated_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`material_Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频表 ';
CREATE TABLE `cmr_material_files` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '介质ID',
`material_Id` bigint(20) DEFAULT NULL COMMENT '媒资ID',
`width` varchar(32) DEFAULT NULL COMMENT '宽',
`height` varchar(32) DEFAULT NULL COMMENT '高',
`md5` varchar(1024) DEFAULT NULL COMMENT 'MD5',
`bit_rate` varchar(32) DEFAULT NULL COMMENT '码率',
`type` varchar(32) DEFAULT NULL COMMENT '文件类型 VIDEO-视频 AUDIO-音频 PICTURE-图片',
`path` varchar(128) DEFAULT NULL COMMENT '文件路径',
PRIMARY KEY (`id`),
KEY `idx_files_Materialid` (`material_Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频文件表 ';
\ No newline at end of file
... ...