Browse Source

Merge remote-tracking branch 'origin/dev_voice_scan' into dev

master
yinzuomei 5 years ago
parent
commit
3e4fe9463a
  1. 35
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/param/VideoScanParamDTO.java
  2. 32
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/param/VideoTaskDTO.java
  3. 2
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/result/AsyncScanResult.java
  4. 47
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/result/VideoAsyncScanResultDTO.java
  5. 56
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/result/VideoScanDetailDTO.java
  6. 88
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/ScanContentUtils.java
  7. 68
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/common/enu/CommonErrorCodeEnum.java
  8. 50
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/common/enu/VideoSceneEnum.java
  9. 32
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/controller/ScanController.java
  10. 18
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/service/impl/ScanService.java
  11. 235
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/service/impl/ScanServiceImpl.java
  12. 76
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/param/video/VideoAsyncScanParam.java
  13. 30
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/param/video/VideoAsyncScanTask.java
  14. 41
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoAsyncScanTaskDataDTO.java
  15. 45
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoAsyncScanTaskResultDTO.java
  16. 48
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoResultDTO.java
  17. 53
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoScanOriginDetail.java
  18. 51
      epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoScanOriginalResultDTO.java

35
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/param/VideoScanParamDTO.java

@ -0,0 +1,35 @@
package com.epmet.commons.tools.scan.param;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* 异步检测请求参数
*
* @author yinzuomei@elink-cn.com
* @date 2021/1/10 21:05
*/
@Data
public class VideoScanParamDTO implements Serializable {
private static final long serialVersionUID = -7261993744367287072L;
/**
* 是否开启回调
*/
@NotNull(message = "openCallBack必填,true开启;false不开启")
private Boolean openCallBack;
/**
* 异步检测结果回调地址,执行异步审查内容时 必填
* openCallBack=true时,callback必填
*/
private String callback;
@Valid
@NotEmpty(message = "任务列表不能为空")
private List<VideoTaskDTO> tasks;
}

32
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/param/VideoTaskDTO.java

@ -0,0 +1,32 @@
package com.epmet.commons.tools.scan.param;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 异步检测请求参数
*
* @author yinzuomei@elink-cn.com
* @date 2021/1/10 21:06
*/
@Data
public class VideoTaskDTO implements Serializable {
private static final long serialVersionUID = -5268462578193403270L;
/**
* 不必填
* 要检测的数据id 非必填
* 检测对象对应的数据ID
* 由大小写英文字母数字下划线_短划线-英文句号.组成不超过128个字符可以用于唯一标识您的业务数据
* */
@NotBlank(message = "dataId不能为空")
private String dataId;
/**
* 必填
* 待检测视频的URL该字段不能和frames同时为空也不能和frames同时有值
*/
@NotBlank(message = "音频URL不能为空")
private String url;
}

2
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/result/AsyncScanResult.java

@ -8,7 +8,7 @@ import java.util.List;
/**
* 语音异步检测 返参
*
* 视频异步检测 返参通用
* @author yinzuomei@elink-cn.com
* @date 2020/12/18 10:09
*/

47
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/result/VideoAsyncScanResultDTO.java

@ -0,0 +1,47 @@
package com.epmet.commons.tools.scan.result;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 视频异步检测结果查询接口返参
* 正在检测中的不返回,调用方继续轮询查询结果
* @author yinzuomei@elink-cn.com
* @date 2020/12/29 15:37
*/
@Data
public class VideoAsyncScanResultDTO implements Serializable {
private static final long serialVersionUID = -7302168989456734818L;
/**
* 执行成功的任务Id集合
* code=200,且所有语音+视频所有场景返回结果都为pass时则为成功
*/
private List<String> passDataIds = new ArrayList<>();
/**
* 执行失败的任务Id集合
*/
private List<String> noPassDataIds = new ArrayList<>();
private List<String> passTaskIds = new ArrayList<>();
private List<String> noPassTaskIds = new ArrayList<>();
/**
* desc:阿里内容审核API返回结果详情
*/
private List<VideoScanDetailDTO> details = new ArrayList<>();
/**
* 本地是否全部通过
*/
private Boolean isAllPass;
public boolean isAllPass() {
if (noPassTaskIds.isEmpty() && !passTaskIds.isEmpty()) {
return true;
}
return isAllPass;
}
}

56
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/scan/result/VideoScanDetailDTO.java

@ -0,0 +1,56 @@
package com.epmet.commons.tools.scan.result;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
*
* @author yinzuomei@elink-cn.com
* @date 2021/1/10 21:24
*/
@Data
public class VideoScanDetailDTO implements Serializable {
/**
* 错误码和HTTP状态码一致
* 更多信息请参见公共错误码
*/
private Integer code;
private String codeDesc;
/**
* 错误描述信息
*/
private String msg;
/**
* 检测对象对应的数据ID
*/
private String dataId;
/**
* 检测任务的ID
*/
private String taskId;
/**
* 返回结果调用成功时code=200返回结果中包含一个或多个元素每个元素是个结构体具体结构描述请参见result
* 说明 视频流检测场景中code返回280表示在检测中返回200表示检测完成在检测中状态时检测结果中包含从开始检测到当前时间的检测到结果
*/
private List<ResultDetail> results;
/**
* 视频语音检测结果具体结构描述请参见audioScanResult
*/
private List<ResultDetail> audioScanResults;
@Data
public static class ResultDetail {
private String scene;
private String label;
private String suggestion;
private Float rate;
}
}

88
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/ScanContentUtils.java

@ -8,6 +8,7 @@ import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.scan.param.*;
import com.epmet.commons.tools.scan.result.AsyncScanResult;
import com.epmet.commons.tools.scan.result.SyncScanResult;
import com.epmet.commons.tools.scan.result.VideoAsyncScanResultDTO;
import com.epmet.commons.tools.scan.result.VoiceResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@ -136,6 +137,65 @@ public class ScanContentUtils {
}
}
/**
* @param url 视频地址
* @param param
* @author yinzuomei
* @description 异步检测-提交检测任务
**/
public static Result<AsyncScanResult> videoAsyncScan(String url, VideoScanParamDTO param){
log.debug("videoAsyncScan param:{}", JSON.toJSONString(param));
if (StringUtils.isBlank(url) || param == null) {
throw new RenException("参数错误");
}
if (param.getOpenCallBack() && StringUtils.isBlank(param.getCallback())) {
throw new RenException("参数错误,开启回调,callback必填");
}
try {
Result<String> result = HttpClientManager.getInstance().sendPostByJSON(url, JSON.toJSONString(param));
log.debug("videoAsyncScan result:{}", JSON.toJSONString(result));
if (result.success()) {
return JSON.parseObject(result.getData(),new TypeReference<Result<AsyncScanResult>>(){});
}
Result<AsyncScanResult> resultResult = new Result<>();
resultResult.error(result.getCode(),result.getMsg());
resultResult.setInternalMsg(result.getInternalMsg());
return resultResult;
} catch (Exception e) {
log.error("videoAsyncScan exception:", e);
throw new RenException(EpmetErrorCode.SERVER_ERROR.getCode(), e.getMessage());
}
}
/**
* @param url
* @param taskIds
* @author yinzuomei
* @description 查询视频检测结果
**/
public static Result<VideoAsyncScanResultDTO> videoResults(String url, List<String> taskIds) {
if (StringUtils.isBlank(url) || CollectionUtils.isEmpty(taskIds)) {
throw new RenException("参数错误");
}
if (taskIds.size() > NumConstant.ONE_HUNDRED) {
throw new RenException("参数错误,查询检测任务最大不能超过100");
}
try {
Result<String> result = HttpClientManager.getInstance().sendPostByJSON(url, JSON.toJSONString(taskIds));
log.debug("videoResults result:{}", JSON.toJSONString(result));
if (result.success()) {
return JSON.parseObject(result.getData(), new TypeReference<Result<VideoAsyncScanResultDTO>>() {
});
}
Result<VideoAsyncScanResultDTO> resultResult = new Result<>();
resultResult.error(result.getCode(), result.getMsg());
resultResult.setInternalMsg(result.getInternalMsg());
return resultResult;
} catch (Exception e) {
log.error("voiceResults exception:", e);
throw new RenException(EpmetErrorCode.SERVER_ERROR.getCode(), e.getMessage());
}
}
public static void main(String[] args) {
//测试文本检测
@ -143,7 +203,11 @@ public class ScanContentUtils {
//测试语音检测
// testVoiceAsyncScan();
//语音检测结果
testVoiceResults();
// testVoiceResults();
//视频检测任务提交
// testVideoAsyncScan();
//查询视频检测结果
testVideoResults();
}
public static void testTextSyncScan(){
@ -200,4 +264,26 @@ public class ScanContentUtils {
Result<List<VoiceResultDTO>> asyncScanResultResult = ScanContentUtils.voiceResults(url, taskIds);
System.out.println("================" + JSON.toJSONString(asyncScanResultResult));
}
public static void testVideoAsyncScan(){
String url = "http://localhost:8107/epmetscan/api/videoAsyncScan";
VideoTaskDTO p = new VideoTaskDTO();
p.setDataId("1");
p.setUrl("https://elink-esua-epdc.oss-cn-qingdao.aliyuncs.com/epmet/test/20210111/e996a68b9f0144a3843666c430f73086.mp4");
List<VideoTaskDTO> list = new ArrayList<>();
list.add(p);
VideoScanParamDTO param = new VideoScanParamDTO();
param.setTasks(list);
param.setOpenCallBack(false);
Result<AsyncScanResult> asyncScanResultResult = ScanContentUtils.videoAsyncScan(url, param);
System.out.println(JSON.toJSONString(asyncScanResultResult));
}
public static void testVideoResults(){
String url = "http://localhost:8107/epmetscan/api/videoResults";
List<String> taskIds=new ArrayList<>();
taskIds.add("vi6ZatqnJEkqf5m@FZ7Ka0AU-1tKYdk");
Result<VideoAsyncScanResultDTO> result = ScanContentUtils.videoResults(url, taskIds);
System.out.println("================" + JSON.toJSONString(result));
}
}

68
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/common/enu/CommonErrorCodeEnum.java

@ -0,0 +1,68 @@
package com.epmet.openapi.scan.common.enu;
import com.epmet.commons.tools.constant.StrConstant;
/**
* 公共错误码
*
* @author yinzuomei@elink-cn.com
* @date 2021/1/10 19:43
*/
public enum CommonErrorCodeEnum {
OK(200, "请求成功。"),
PROCESSING(280, "任务正在执行中,建议您等待一段时间(例如5s)后再查询结果。"),
BAD_REQUEST(400, "请求有误,通常由于请求参数不正确导致,请仔细检查请求参数。"),
NOT_ALLOWED(401, "请求失败,通常是由于使用了不安全的图片、视频、语音链接地址。"),
FORBIDDEN(403, "请求访问失败,通常由于您的图片、视频、语音链接无法访问导致,请确认公网是否可访问,并且无防盗链策略。"),
NOT_FOUND(404, "待检测内容未找到,通常是由于您的图片、视频、语音内容无法下载导致,请确认内容可通过公网访问到。"),
DOWNLOAD_FAILED(480, "下载失败,请确认待检测内容的大小、分辨率(如果有)在API的限制范围内。"),
GENERAL_ERROR(500, "一般是服务端临时出错。建议重试,若持续返回该错误码,请通过工单联系我们。"),
DB_FAILED(580, "数据库操作失败。建议重试,若持续返回该错误码,请通过工单联系我们。"),
TIMEOUT(581, "超时。建议重试,若持续返回该错误码,请通过工单联系我们。"),
CACHE_FAILED(585, "缓存出错。建议重试,若持续返回该错误码,请通过工单联系我们。"),
ALGO_FAILED(586, "算法出错。请通过工单联系我们。"),
MQ_FAILED(587, "中间件出错。请通过工单联系我们。"),
EXCEED_QUOTA(588, "请求频率超出配额。默认配额:图片检测50张/秒,视频检测20路/秒,语音检测20路/秒,文本检测100条/秒。如果需要调整配额,请通过工单联系我们。"),
TOO_LARGE(589, "待检测内容过大,请确保检测的内容在API的限制范围内。建议重试,若持续返回该错误码,请通过工单联系我们。"),
BAD_FORMAT(590, "待检测内容格式错误,请确保检测的内容在API的限制范围内。"),
CONNECTION_POOL_FULL(591, "连接池满。请通过工单联系我们。"),
DOWNLOAD_TIMEOUT(592, "下载超时,下载时间限制为3s,请确保检测的内容大小在API的限制范围内。"),
EXPIRED(594, "任务过期,如taskId过期。"),
CATCH_FRAME_FAILED(595, "截帧失败,请通过工单联系我们。"),
PERMISSION_DENY(596, "账号未授权、账号欠费、账号未开通、账号被禁等原因,具体可以参考返回的msg。");
private Integer code;
private String desc;
CommonErrorCodeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static String getErrorMsg(Integer value) {
CommonErrorCodeEnum[] codeEnums = values();
for (CommonErrorCodeEnum commonErrorCodeEnum : codeEnums) {
if (commonErrorCodeEnum.getCode().equals(value)) {
return commonErrorCodeEnum.getDesc();
}
}
return StrConstant.EPMETY_STR;
}
}

50
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/common/enu/VideoSceneEnum.java

@ -0,0 +1,50 @@
package com.epmet.openapi.scan.common.enu;
import java.util.ArrayList;
import java.util.List;
/**
* desc:视频检测场景
* @author yinzuomei@elink-cn.com
* @date 2020/12/29 13:47
**/
public enum VideoSceneEnum {
PORN("porn", "视频智能鉴黄"),
TERRORISM("terrorism", "视频暴恐涉政"),
LIVE("live","视频不良场景"),
LOGO("logo","视频logo"),
AD("ad","视频图文违规");
private String code;
private String desc;
VideoSceneEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static List<String> getVideoSceneList() {
List<String> result = new ArrayList<>();
VideoSceneEnum[] values = VideoSceneEnum.values();
for (VideoSceneEnum v : values) {
result.add(v.getCode());
}
return result;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}

32
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/controller/ScanController.java

@ -2,14 +2,20 @@ package com.epmet.openapi.scan.controller;
import com.epmet.commons.tools.utils.Result;
import com.epmet.commons.tools.validator.ValidatorUtils;
import com.epmet.openapi.scan.common.constant.SysConstant;
import com.epmet.openapi.scan.common.enu.SysResponseEnum;
import com.epmet.openapi.scan.service.impl.ScanService;
import com.epmet.openapi.scan.support.param.ImgScanParam;
import com.epmet.openapi.scan.support.param.TextScanParam;
import com.epmet.openapi.scan.support.param.VoiceAsyncScanParam;
import com.epmet.openapi.scan.support.param.video.VideoAsyncScanParam;
import com.epmet.openapi.scan.support.result.ImgAsyncScanResult;
import com.epmet.openapi.scan.support.result.SyncScanResult;
import com.epmet.openapi.scan.support.result.VoiceAsyncScanResult;
import com.epmet.openapi.scan.support.result.VoiceAsyncScanTaskResult;
import com.epmet.openapi.scan.support.result.video.VideoAsyncScanTaskResultDTO;
import com.epmet.openapi.scan.support.result.video.VideoResultDTO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -81,4 +87,30 @@ public class ScanController {
return scanService.voiceResults(taskIds);
}
/**
* @author yinzuomei
* @description 视频检测-异步检测
**/
@PostMapping("videoAsyncScan")
public Result<VideoAsyncScanTaskResultDTO> videoAsyncScan(@RequestBody VideoAsyncScanParam param) {
ValidatorUtils.validateEntity(param);
return scanService.videoAsyncScan(param);
}
/**
* @author yinzuomei
* @description 视频异步检测结果查询接口
**/
@PostMapping("videoResults")
public Result<VideoResultDTO> videoResults(@RequestBody List<String> taskIds) {
if (CollectionUtils.isEmpty(taskIds)) {
return new Result<>();
}
//检测对象不能为空,且最多支持100个元素
if (org.springframework.util.CollectionUtils.isEmpty(taskIds) || taskIds.size() > SysConstant.MAX_TASK_SIZE) {
return new Result<VideoResultDTO>().error(SysResponseEnum.SCAN_TASK_LIST_PARAM_ERROR.getCode(),
SysResponseEnum.SCAN_TASK_LIST_PARAM_ERROR.getMsg().concat(SysConstant.MAX_TASK_SIZE.toString()));
}
return scanService.videoResults(taskIds);
}
}

18
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/service/impl/ScanService.java

@ -4,9 +4,12 @@ import com.epmet.commons.tools.utils.Result;
import com.epmet.openapi.scan.support.param.ImgScanParam;
import com.epmet.openapi.scan.support.param.TextScanParam;
import com.epmet.openapi.scan.support.param.VoiceAsyncScanParam;
import com.epmet.openapi.scan.support.param.video.VideoAsyncScanParam;
import com.epmet.openapi.scan.support.result.SyncScanResult;
import com.epmet.openapi.scan.support.result.VoiceAsyncScanResult;
import com.epmet.openapi.scan.support.result.VoiceAsyncScanTaskResult;
import com.epmet.openapi.scan.support.result.video.VideoAsyncScanTaskResultDTO;
import com.epmet.openapi.scan.support.result.video.VideoResultDTO;
import java.util.List;
@ -48,4 +51,19 @@ public interface ScanService {
* @return com.epmet.openapi.scan.support.result.VoiceAsyncScanResult
*/
Result<List<VoiceAsyncScanResult>> voiceResults(List<String> taskIds);
/**
* desc:视频检测-异步检测
* @param videoAsyncScanParam
* @return 异步检测返回数据taskId<=>dataId
*/
Result<VideoAsyncScanTaskResultDTO> videoAsyncScan(VideoAsyncScanParam videoAsyncScanParam);
/**
* @param taskIds
* @author yinzuomei
* @description 视频异步检测结果查询接口
* @Date 2020/12/29 16:10
**/
Result<VideoResultDTO> videoResults(List<String> taskIds);
}

235
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/service/impl/ScanServiceImpl.java

@ -4,10 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.AcsRequest;
import com.aliyuncs.green.model.v20180509.ImageSyncScanRequest;
import com.aliyuncs.green.model.v20180509.TextScanRequest;
import com.aliyuncs.green.model.v20180509.VoiceAsyncScanRequest;
import com.aliyuncs.green.model.v20180509.VoiceAsyncScanResultsRequest;
import com.aliyuncs.green.model.v20180509.*;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.HttpResponse;
import com.epmet.commons.tools.constant.NumConstant;
@ -20,7 +17,10 @@ import com.epmet.openapi.scan.common.exception.ExecuteHttpException;
import com.epmet.openapi.scan.common.redis.RedisKeys;
import com.epmet.openapi.scan.common.util.IAcsClientUtil;
import com.epmet.openapi.scan.support.param.*;
import com.epmet.openapi.scan.support.param.video.VideoAsyncScanParam;
import com.epmet.openapi.scan.support.param.video.VideoAsyncScanTask;
import com.epmet.openapi.scan.support.result.*;
import com.epmet.openapi.scan.support.result.video.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
@ -504,4 +504,231 @@ public class ScanServiceImpl implements ScanService {
return getResultsRequest;
}
/**
* desc:视频检测-异步检测
*
* @param videoAsyncScanParam
* @return
*/
@Override
public Result<VideoAsyncScanTaskResultDTO> videoAsyncScan(VideoAsyncScanParam videoAsyncScanParam) {
//一次至多提交100个检测对象
List<VideoAsyncScanTask> videoTasks = videoAsyncScanParam.getTasks();
if (CollectionUtils.isEmpty(videoTasks) || videoTasks.size() > SysConstant.MAX_TASK_SIZE) {
return new Result<VideoAsyncScanTaskResultDTO>().error(SysResponseEnum.SCAN_TASK_LIST_PARAM_ERROR.getCode(), SysResponseEnum.SCAN_TASK_LIST_PARAM_ERROR.getMsg().concat(SysConstant.MAX_TASK_SIZE.toString()));
}
//默认参数赋值
videoAsyncScanParam.setScenes(VideoSceneEnum.getVideoSceneList());
videoAsyncScanParam.setBizType(bizType);
videoAsyncScanParam.setAudioScenes(VoiceSceneEnum.getVoiceSceneList());
videoAsyncScanParam.setSeed(UUID.randomUUID().toString().replace("-", ""));
//API文档没写限制多少最大多少,应该与图片一致
if (videoTasks.size() <= SysConstant.MAX_SCAN_IMG_TASK_SIZE) {
return doScanVideo(videoAsyncScanParam);
}
log.info("videoAsyncScan tasks size:{} over 10", videoTasks.size());
//分组调用,一次提交10个
List<List<VideoAsyncScanTask>> partition = ListUtils.partition(videoTasks, SysConstant.MAX_SCAN_IMG_TASK_SIZE);
VideoAsyncScanTaskResultDTO finalResult = new VideoAsyncScanTaskResultDTO();
for (List<VideoAsyncScanTask> tasks : partition) {
VideoAsyncScanParam videParam = new VideoAsyncScanParam();
videParam.setBizType(videoAsyncScanParam.getBizType());
videParam.setScenes(videoAsyncScanParam.getScenes());
videParam.setTasks(tasks);
videParam.setCallback(videoAsyncScanParam.getCallback());
videParam.setSeed(videoAsyncScanParam.getSeed());
videParam.setAudioScenes(videoAsyncScanParam.getAudioScenes());
Result<VideoAsyncScanTaskResultDTO> partResult = doScanVideo(videParam);
try {
Thread.sleep(5L);
} catch (InterruptedException e) {
log.error("videoAsyncScan InterruptedException");
}
if (partResult.success()) {
VideoAsyncScanTaskResultDTO data = partResult.getData();
finalResult.setSeed(data.getSeed());
finalResult.getSuccessTasks().addAll(data.getSuccessTasks());
finalResult.getFailTasks().addAll(data.getFailTasks());
} else {
return partResult;
}
}
return new Result<VideoAsyncScanTaskResultDTO>().ok(finalResult);
}
private Result<VideoAsyncScanTaskResultDTO> doScanVideo(VideoAsyncScanParam videoAsyncScanParam) {
VideoAsyncScanRequest videoAsyncScanRequest = getVideoAsyncScanRequest();
try {
videoAsyncScanRequest.setHttpContent(JSON.toJSONString(videoAsyncScanParam).getBytes(SysConstant.UTF8), SysConstant.UTF8, FormatType.JSON);
} catch (UnsupportedEncodingException e) {
log.error("doScanVideo parse param exception", e);
return new Result<VideoAsyncScanTaskResultDTO>().error(SysResponseEnum.SCAN_PARAM_ERROR.getCode(), SysResponseEnum.SCAN_PARAM_ERROR.getMsg());
}
try {
VideoAsyncScanTaskResultDTO scanResult = executeAsyncVideo(videoAsyncScanRequest);
scanResult.setSeed(videoAsyncScanParam.getSeed());
return new Result<VideoAsyncScanTaskResultDTO>().ok(scanResult);
} catch (ExecuteHttpException e) {
log.error("doScanVideo execute exception,param:{},fail msg:{}", JSON.toJSONString(videoAsyncScanParam), e.getMsg());
return new Result<VideoAsyncScanTaskResultDTO>().error(e.getCode(), e.getMsg());
}
}
private VideoAsyncScanRequest getVideoAsyncScanRequest() {
VideoAsyncScanRequest videoAsyncScanRequest = new VideoAsyncScanRequest();
videoAsyncScanRequest.setAcceptFormat(FormatType.JSON); // 指定API返回格式。
videoAsyncScanRequest.setMethod(com.aliyuncs.http.MethodType.POST); // 指定请求方法。
/**
* 请务必设置超时时间
*/
videoAsyncScanRequest.setConnectTimeout(3000);
videoAsyncScanRequest.setReadTimeout(6000);
return videoAsyncScanRequest;
}
private VideoAsyncScanTaskResultDTO executeAsyncVideo(VideoAsyncScanRequest videoAsyncScanRequest) {
try {
HttpResponse httpResponse = IAcsClientUtil.getIAcsClient().doAction(videoAsyncScanRequest);
if (httpResponse.isSuccess()) {
JSONObject scrResponse = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
if (HttpStatus.SC_OK == scrResponse.getInteger(SysConstant.CODE)) {
//获取data列表
JSONArray dataResults = scrResponse.getJSONArray(SysConstant.DATA);
List<VideoAsyncScanTaskDataDTO> dataList = dataResults.toJavaList(VideoAsyncScanTaskDataDTO.class);
VideoAsyncScanTaskResultDTO result=new VideoAsyncScanTaskResultDTO();
dataList.forEach(data->{
if (HttpStatus.SC_OK == data.getCode()) {
result.getSuccessTasks().add(data);
} else {
result.getFailTasks().add(data);
}
});
return result;
} else {
log.warn("executeAsyncVideo detect not success. code:{}", scrResponse.getInteger(SysConstant.CODE));
throw new ExecuteHttpException(SysResponseEnum.THIRD_PLATFORM_RESP_CODE_ERROR.getCode(),
SysResponseEnum.THIRD_PLATFORM_RESP_CODE_ERROR.getMsg() + ",status:" + httpResponse.getStatus());
}
} else {
log.warn("executeAsyncVideo response status is not success. httpResponse:{}", JSON.toJSONString(httpResponse));
throw new ExecuteHttpException(SysResponseEnum.THIRD_PLATFORM_RESP_STATUS_ERROR.getCode(),
SysResponseEnum.THIRD_PLATFORM_RESP_STATUS_ERROR.getMsg() + ",status:" + httpResponse.getStatus());
}
} catch (Exception e) {
log.error("executeAsyncVideo exception IAcsClientUtil do action exception", e);
throw new ExecuteHttpException(SysResponseEnum.THIRD_PLATFORM_SERVER_ERROR.getCode(), SysResponseEnum.THIRD_PLATFORM_SERVER_ERROR.getMsg());
}
}
/**
* @param taskIds
* @author yinzuomei
* @description 视频异步检测结果查询接口
* @Date 2020/12/29 16:10
**/
@Override
public Result<VideoResultDTO> videoResults(List<String> taskIds) {
VideoAsyncScanResultsRequest videoAsyncScanResultsRequest = new VideoAsyncScanResultsRequest();
videoAsyncScanResultsRequest.setAcceptFormat(FormatType.JSON);
videoAsyncScanResultsRequest.setMethod(com.aliyuncs.http.MethodType.POST);
videoAsyncScanResultsRequest.setConnectTimeout(3000);
videoAsyncScanResultsRequest.setReadTimeout(6000);
try {
videoAsyncScanResultsRequest.setHttpContent(JSON.toJSONString(taskIds).getBytes("UTF-8"), "UTF-8", FormatType.JSON);
} catch (UnsupportedEncodingException e) {
log.error("videoResults parse param exception", e);
return new Result<VideoResultDTO>().error(SysResponseEnum.SCAN_PARAM_ERROR.getCode(), SysResponseEnum.SCAN_PARAM_ERROR.getMsg());
}
try {
HttpResponse httpResponse = IAcsClientUtil.getIAcsClient().doAction(videoAsyncScanResultsRequest);
if (httpResponse.isSuccess()) {
JSONObject responseObject = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
log.info("查询视频检测结果返参"+JSON.toJSONString(responseObject));
if (HttpStatus.SC_OK == responseObject.getInteger(SysConstant.CODE)) {
//获取data列表
JSONArray dataResults = responseObject.getJSONArray(SysConstant.DATA);
List<VideoScanOriginalResultDTO> resultList = dataResults.toJavaList(VideoScanOriginalResultDTO.class);
//解析数据
VideoResultDTO resultDTO = processVideoResults(resultList);
//成功返回
return new Result<VideoResultDTO>().ok(resultDTO);
} else {
log.warn("查询视频检测结果,接口返回code=" + responseObject.getInteger(SysConstant.CODE));
throw new ExecuteHttpException(SysResponseEnum.THIRD_PLATFORM_RESP_CODE_ERROR.getCode(),
SysResponseEnum.THIRD_PLATFORM_RESP_CODE_ERROR.getMsg() + ",status:" + httpResponse.getStatus());
}
} else {
log.warn("查询视频检测结果,API返回失败");
throw new ExecuteHttpException(SysResponseEnum.THIRD_PLATFORM_RESP_STATUS_ERROR.getCode(),
SysResponseEnum.THIRD_PLATFORM_RESP_STATUS_ERROR.getMsg() + ",status:" + httpResponse.getStatus());
}
} catch (Exception e) {
log.error("videoResults exception ", e);
throw new ExecuteHttpException(SysResponseEnum.THIRD_PLATFORM_SERVER_ERROR.getCode(), SysResponseEnum.THIRD_PLATFORM_SERVER_ERROR.getMsg());
}
}
/**
* @author yinzuomei
* @description
**/
private VideoResultDTO processVideoResults(List<VideoScanOriginalResultDTO> resultList) {
VideoResultDTO videoResultDTO = new VideoResultDTO();
resultList.forEach(result -> {
result.setCodeDesc(CommonErrorCodeEnum.getErrorMsg(result.getCode()));
if (result.getCode().equals(CommonErrorCodeEnum.PROCESSING.getCode())) {
//任务正在检测中,继续轮询
} else if (result.getCode().equals(CommonErrorCodeEnum.OK.getCode())) {
//成功=>分析结果
boolean videoPassFlag = getVideoFlag(result.getResults());
boolean voicePassFlag = getVoiceFlag(result.getAudioScanResults());
if (videoPassFlag && voicePassFlag) {
videoResultDTO.getPassDataIds().add(result.getDataId());
videoResultDTO.getPassTaskIds().add(result.getTaskId());
} else {
videoResultDTO.getNoPassDataIds().add(result.getDataId());
videoResultDTO.getNoPassTaskIds().add(result.getTaskId());
}
} else {
//检测结果走丢了.... (*^▽^*) 默认失败
videoResultDTO.getNoPassDataIds().add(result.getDataId());
videoResultDTO.getNoPassTaskIds().add(result.getTaskId());
}
});
videoResultDTO.setDetails(resultList);
return videoResultDTO;
}
/**
* @return boolean
* @author yinzuomei
* @description 视频检测结果判断
**/
private boolean getVideoFlag(List<VideoScanOriginDetail> results) {
for(VideoScanOriginDetail videoRes:results){
if (!SuggestionEnum.PASS.getCode().equals(videoRes.getSuggestion())) {
return false;
}
}
return true;
}
/**
* @return boolean true:内容通过; 建议为内容违规或者需要人工审核的统一视为不通过,返回false
* @author yinzuomei
* @description 返回视频语音检测结果
**/
private boolean getVoiceFlag(List<VoiceAsyncScanResultDTO> audioScanResults) {
if (CollectionUtils.isEmpty(audioScanResults)) {
return true;
}
for(VoiceAsyncScanResultDTO m:audioScanResults){
//人工审核或者内容违规,统一视为不通过
if (!SuggestionEnum.PASS.getCode().equals(m.getSuggestion())) {
return false;
}
}
return true;
}
}

76
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/param/video/VideoAsyncScanParam.java

@ -0,0 +1,76 @@
package com.epmet.openapi.scan.support.param.video;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
import java.util.List;
/**
* 视频审核-异步检测入参DTO
*
* @author yinzuomei@elink-cn.com
*/
@Data
public class VideoAsyncScanParam implements Serializable {
private static final long serialVersionUID = -7635290200099445362L;
/**
* 是否开启回调
*/
private Boolean openCallBack;
/**
* 不必填
* 该字段用于标识您的业务场景您可以通过内容安全控制台创建业务场景具体操作请参见自定义机审标准或者提交工单联系我们帮助您创建业务场景
*/
private String bizType;
/**
* 不必填
* 是否为语音流例如直播流检测取值
* true表示语音流检测
* false默认表示音频文件检测
*/
private Boolean live;
/**
* 不必填
* 是否为近线检测模式 取值
* true表示近线检测模式近线检测模式下您提交的任务不保证能够实时处理但是可以排队并在24小时内开始检测
* false默认表示实时检测模式对于超过了并发路数限制的检测请求会直接拒绝
* 说明 该参数仅适用于音频文件检测不适用于语音流检测
*/
private Boolean offline;
/**
* 必填
* 指定视频检测场景取值
* porn视频智能鉴黄
* terrorism视频暴恐涉政
* live视频不良场景
* logo视频logo
* ad视频图文违规
*/
private List<String> scenes;
/**
* 不必填
* 指定视频语音检测场景唯一取值antispam表示语音反垃圾不传入该参数时仅检测视频图像内容如果传入该参数则在检测视频中图像的同时对视频中语音进行检测
* 说明 如果需要检测视频语音则不支持通过上传视频截帧序列的方式即在task中传入frames进行检测您必须传入视频或视频流的URL地址即在task中传入url进行检测
*/
private List<String> audioScenes;
/**
* 异步检测结果回调地址,执行异步审查内容时 必填
*/
private String callback;
/**
* 随机字符串该值用于回调通知请求中的签名使用callback时 必填
*/
private String seed;
@NotEmpty(message = "检测对象不能为空")
private List<VideoAsyncScanTask> tasks;
}

30
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/param/video/VideoAsyncScanTask.java

@ -0,0 +1,30 @@
package com.epmet.openapi.scan.support.param.video;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 视频审核-异步检测入参-检测对象
*
* @author yinzuomei@elink-cn.com
*/
@Data
public class VideoAsyncScanTask implements Serializable {
/**
* 建议必填
* 要检测的数据id 非必填
* 检测对象对应的数据ID
* 由大小写英文字母数字下划线_短划线-英文句号.组成不超过128个字符可以用于唯一标识您的业务数据
* */
@NotBlank(message = "dataId不能为空")
private String dataId;
/**
* 必填
* 待检测视频的URL该字段不能和frames同时为空也不能和frames同时有值
*/
@NotBlank(message = "音频URL不能为空")
private String url;
}

41
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoAsyncScanTaskDataDTO.java

@ -0,0 +1,41 @@
package com.epmet.openapi.scan.support.result.video;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.io.Serializable;
/**
* 视频审核-异步检测任务提交返参详情
*
* @author yinzuomei@elink-cn.com
* @date 2020/12/29 13:42
*/
@Data
public class VideoAsyncScanTaskDataDTO implements Serializable {
private static final long serialVersionUID = 8430710131685814181L;
/**
* 错误码和HTTP状态码一致
* 更多信息请参见公共错误码
*/
private Integer code;
/**
* 错误描述信息
*/
private String msg;
/**
* 检测对象对应的数据ID
*/
private String dataId;
/**
* 检测任务的ID
*/
private String taskId;
/**
* 暂时没用所以返回忽略
*/
@JsonIgnore
private String url;
}

45
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoAsyncScanTaskResultDTO.java

@ -0,0 +1,45 @@
package com.epmet.openapi.scan.support.result.video;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 视频审核-异步检测任务提交返参
*
* @author yinzuomei@elink-cn.com
* @date 2020/12/29 13:38
*/
@Data
public class VideoAsyncScanTaskResultDTO implements Serializable {
private static final long serialVersionUID = -467990806428860191L;
/**
* 随机字符串该值用于回调通知请求中的签名
*/
private String seed;
/**
* 提交成功的失败对象
*/
private List<VideoAsyncScanTaskDataDTO> successTasks=new ArrayList<>();
/**
* 提交失败的检测对象
*/
private List<VideoAsyncScanTaskDataDTO> failTasks=new ArrayList<>();
/**
* 是否全部提交成功
*/
private Boolean isAllSuccess;
public boolean isAllSuccess() {
if (failTasks.isEmpty() && !successTasks.isEmpty()) {
return true;
}
return isAllSuccess;
}
}

48
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoResultDTO.java

@ -0,0 +1,48 @@
package com.epmet.openapi.scan.support.result.video;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 视频异步检测结果查询接口返参
* 正在检测中的不返回,调用方继续轮询查询结果
* @author yinzuomei@elink-cn.com
* @date 2020/12/29 15:37
*/
@Data
public class VideoResultDTO implements Serializable {
private static final long serialVersionUID = -3451342817149956488L;
/**
* 执行成功的任务Id集合
* code=200,且所有语音+视频所有场景返回结果都为pass时则为成功
*/
private List<String> passDataIds = new ArrayList<>();
/**
* 执行失败的任务Id集合
*/
private List<String> noPassDataIds = new ArrayList<>();
private List<String> passTaskIds = new ArrayList<>();
private List<String> noPassTaskIds = new ArrayList<>();
/**
* desc:阿里内容审核API返回结果详情
*/
private List<VideoScanOriginalResultDTO> details = new ArrayList<>();
/**
* 本地是否全部通过
*/
private Boolean isAllPass;
public boolean isAllPass() {
if (noPassTaskIds.isEmpty() && !passTaskIds.isEmpty()) {
return true;
}
return isAllPass;
}
}

53
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoScanOriginDetail.java

@ -0,0 +1,53 @@
package com.epmet.openapi.scan.support.result.video;
import lombok.Data;
import java.io.Serializable;
/**
* 视频异步检测结果查询接口原生返参-视频检测结果
*
* @author yinzuomei@elink-cn.com
* @date 2020/12/29 16:39
*/
@Data
public class VideoScanOriginDetail implements Serializable {
private static final long serialVersionUID = 5547706236158849091L;
/**
* 视频检测场景和调用请求中的场景对应取值
* porn视频智能鉴黄
* terrorism视频暴恐涉政
* live视频不良场景
* logo视频logo
* ad视频图文违规
*/
private String scene;
/**
* 视频检测结果的分类不同检测场景的结果分类不同具体如下
* 视频智能鉴黄porn结果分类
* normal正常
* porn色情
* 视频暴恐涉政terrorism结果分类
* normal正常
* terrorism暴恐涉政
* 视频不良场景live结果分类
* normal正常
* live包含不良场景
* 视频logologo结果分类
* normal正常
* logo包含logo
* 视频图文违规ad结果分类
* normal正常
* ad包含广告或文字违规信息
*/
private String label;
/**
* 建议您执行的后续操作取值
* pass结果正常无需进行其余操作
* review结果不确定需要进行人工审核
* block结果违规建议直接删除或者限制公开
*/
private String suggestion;
}

51
epmet-openapi/epmet-openapi-scan/src/main/java/com/epmet/openapi/scan/support/result/video/VideoScanOriginalResultDTO.java

@ -0,0 +1,51 @@
package com.epmet.openapi.scan.support.result.video;
import com.epmet.openapi.scan.support.result.VoiceAsyncScanResultDTO;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 视频异步检测结果查询接口原生返参
*
* @author yinzuomei@elink-cn.com
* @date 2020/12/29 15:48
*/
@Data
public class VideoScanOriginalResultDTO implements Serializable {
private static final long serialVersionUID = -1565008507757551616L;
/**
* 错误码和HTTP状态码一致
* 更多信息请参见公共错误码
*/
private Integer code;
private String codeDesc;
/**
* 错误描述信息
*/
private String msg;
/**
* 检测对象对应的数据ID
*/
private String dataId;
/**
* 检测任务的ID
*/
private String taskId;
/**
* 返回结果调用成功时code=200返回结果中包含一个或多个元素每个元素是个结构体具体结构描述请参见result
* 说明 视频流检测场景中code返回280表示在检测中返回200表示检测完成在检测中状态时检测结果中包含从开始检测到当前时间的检测到结果
*/
private List<VideoScanOriginDetail> results;
/**
* 视频语音检测结果具体结构描述请参见audioScanResult
*/
private List<VoiceAsyncScanResultDTO> audioScanResults;
}
Loading…
Cancel
Save