Quellcode durchsuchen

阿里视频审核工具V2

wxd vor 4 Monaten
Ursprung
Commit
11910a2c5a

+ 2 - 2
alien-entity/src/main/java/shop/alien/entity/VideoModerationTask.java → alien-entity/src/main/java/shop/alien/entity/SecondVideoTask.java

@@ -12,8 +12,8 @@ import java.util.Date;
  * 视频审核任务实体类
  */
 @Data
-@TableName("video_moderation_task")
-public class VideoModerationTask implements Serializable {
+@TableName("second_video_task")
+public class SecondVideoTask implements Serializable {
     
     private static final long serialVersionUID = 1L;
     

+ 9 - 9
alien-entity/src/main/java/shop/alien/mapper/system/VideoModerationTaskMapper.java → alien-entity/src/main/java/shop/alien/mapper/system/SecondVideoTaskMapper.java

@@ -6,7 +6,7 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 import org.springframework.stereotype.Repository;
-import shop.alien.entity.VideoModerationTask;
+import shop.alien.entity.SecondVideoTask;
 
 import java.util.List;
 
@@ -15,22 +15,22 @@ import java.util.List;
  */
 @Mapper
 @Repository
-public interface VideoModerationTaskMapper extends BaseMapper<VideoModerationTask> {
+public interface SecondVideoTaskMapper extends BaseMapper<SecondVideoTask> {
 
     /**
      * 查询待处理的审核任务
      * @return 审核任务列表
      */
-    @Select("SELECT * FROM video_moderation_task WHERE status IN ('SUBMITTED', 'PROCESSING') ORDER BY create_time ASC LIMIT 100")
-    List<VideoModerationTask> selectPendingTasks();
+    @Select("SELECT * FROM second_video_task WHERE status IN ('SUBMITTED', 'PROCESSING') ORDER BY create_time ASC LIMIT 100")
+    List<SecondVideoTask> selectPendingTasks();
 
     /**
      * 根据任务ID查询任务详情
      * @param taskId 任务ID
      * @return 任务详情
      */
-    @Select("SELECT * FROM video_moderation_task WHERE task_id = #{taskId}")
-    VideoModerationTask selectByTaskId(@Param("taskId") String taskId);
+    @Select("SELECT * FROM second_video_task WHERE task_id = #{taskId}")
+    SecondVideoTask selectByTaskId(@Param("taskId") String taskId);
 
     /**
      * 更新任务状态
@@ -38,7 +38,7 @@ public interface VideoModerationTaskMapper extends BaseMapper<VideoModerationTas
      * @param status 状态
      * @return 更新记录数
      */
-    @Update("UPDATE video_moderation_task SET status = #{status}, update_time = NOW() WHERE task_id = #{taskId}")
+    @Update("UPDATE second_video_task SET status = #{status}, update_time = NOW() WHERE task_id = #{taskId}")
     int updateTaskStatus(@Param("taskId") String taskId, @Param("status") String status);
 
     /**
@@ -49,7 +49,7 @@ public interface VideoModerationTaskMapper extends BaseMapper<VideoModerationTas
      * @param result 审核结果
      * @return 更新记录数
      */
-    @Update("UPDATE video_moderation_task SET status = #{status}, risk_level = #{riskLevel}, result = #{result}, update_time = NOW() WHERE task_id = #{taskId}")
+    @Update("UPDATE second_video_task SET status = #{status}, risk_level = #{riskLevel}, result = #{result}, update_time = NOW() WHERE task_id = #{taskId}")
     int updateTaskResult(@Param("taskId") String taskId, @Param("status") String status,
                          @Param("riskLevel") String riskLevel, @Param("result") String result);
 
@@ -58,6 +58,6 @@ public interface VideoModerationTaskMapper extends BaseMapper<VideoModerationTas
      * @param id 任务ID
      * @return 更新记录数
      */
-    @Update("UPDATE video_moderation_task SET retry_count = retry_count + 1, update_time = NOW() WHERE id = #{id}")
+    @Update("UPDATE second_video_task SET retry_count = retry_count + 1, update_time = NOW() WHERE id = #{id}")
     int incrementRetryCount(@Param("id") Long id);
 }

+ 1 - 1
alien-job/src/main/java/shop/alien/job/feign/SecondGoodsFeign.java

@@ -4,7 +4,7 @@ import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 
-@FeignClient(name = "alien-second", url = "http://localhost:8888")
+@FeignClient(name = "alien-second", url = "http://localhost:9999")
 public interface SecondGoodsFeign {
     
     /**

+ 5 - 5
alien-job/src/main/java/shop/alien/job/jobhandler/VideoModerationJobHandler.java

@@ -5,9 +5,9 @@ import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
-import shop.alien.entity.VideoModerationTask;
+import shop.alien.entity.SecondVideoTask;
 import shop.alien.job.feign.SecondGoodsFeign;
-import shop.alien.mapper.system.VideoModerationTaskMapper;
+import shop.alien.mapper.system.SecondVideoTaskMapper;
 
 import java.util.List;
 
@@ -22,7 +22,7 @@ public class VideoModerationJobHandler {
     /**
      * 视频审核任务Mapper
      */
-    private final VideoModerationTaskMapper videoModerationTaskMapper;
+    private final SecondVideoTaskMapper videoModerationTaskMapper;
 
     /**
      * 二级商品服务Feign客户端
@@ -39,7 +39,7 @@ public class VideoModerationJobHandler {
             log.info("开始执行视频审核结果拉取任务");
             
             // 查询待处理的审核任务(状态为SUBMITTED或PROCESSING)
-            List<VideoModerationTask> pendingTasks = videoModerationTaskMapper.selectPendingTasks();
+            List<SecondVideoTask> pendingTasks = videoModerationTaskMapper.selectPendingTasks();
             
             if (pendingTasks.isEmpty()) {
                 log.info("没有待处理的视频审核任务");
@@ -50,7 +50,7 @@ public class VideoModerationJobHandler {
             
             // 处理每个任务
             int successCount = 0;
-            for (VideoModerationTask task : pendingTasks) {
+            for (SecondVideoTask task : pendingTasks) {
                 try {
                     boolean success = secondGoodsFeign.processTask(task.getTaskId());
                     if (success) {

+ 6 - 10
alien-second/src/main/java/shop/alien/second/controller/SecondGoodsController.java

@@ -2,17 +2,14 @@ package shop.alien.second.controller;
 
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.Lists;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
-import shop.alien.entity.VideoModerationTask;
+import shop.alien.entity.SecondVideoTask;
 import shop.alien.entity.result.R;
 import shop.alien.entity.second.SecondGoods;
-import shop.alien.entity.second.SecondGoodsAudit;
 import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.mapper.second.SecondGoodsAuditMapper;
 import shop.alien.second.service.SecondGoodsService;
@@ -25,7 +22,6 @@ import shop.alien.util.common.safe.TextModerationUtil;
 import shop.alien.util.common.safe.TextReviewServiceEnum;
 import shop.alien.util.common.safe.*;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -261,17 +257,17 @@ public class SecondGoodsController {
      */
     @ApiOperation("处理视频审核结果")
     @GetMapping("/processVideoResult")
-    public R processVideoResult(String taskId) {
+    public boolean processVideoResult(String taskId) {
         try {
-            VideoModerationTask task = videoModerationService.getTaskByTaskId(taskId);
+            SecondVideoTask task = videoModerationService.getTaskByTaskId(taskId);
             if (task == null) {
-                return R.fail("未找到视频审核任务 ");
+                return false;
             }
             secondGoodsService.processVideoModerationResult(task);
-            return R.data(task, "审核成功");
+            return true;
         } catch (Exception e) {
             log.error("处理视频审核结果时发生异常,任务ID: {}", taskId, e);
-            return R.fail("处理失败: " + e.getMessage());
+            return false;
         }
     }
 }

+ 2 - 2
alien-second/src/main/java/shop/alien/second/controller/VideoModerationController.java

@@ -3,7 +3,7 @@ package shop.alien.second.controller;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
-import shop.alien.entity.VideoModerationTask;
+import shop.alien.entity.SecondVideoTask;
 import shop.alien.second.service.VideoModerationService;
 
 /**
@@ -61,7 +61,7 @@ public class VideoModerationController {
     public boolean processTask(@RequestParam("taskId") String taskId) {
         try {
             // 根据任务ID查询任务详情
-            VideoModerationTask task = videoModerationService.getTaskByTaskId(taskId);
+            SecondVideoTask task = videoModerationService.getTaskByTaskId(taskId);
             if (task == null) {
                 log.error("未找到任务ID为 {} 的视频审核任务", taskId);
                 return false;

+ 2 - 4
alien-second/src/main/java/shop/alien/second/service/SecondGoodsService.java

@@ -2,10 +2,8 @@ package shop.alien.second.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.models.auth.In;
 import org.springframework.transaction.annotation.Transactional;
-import shop.alien.entity.VideoModerationTask;
+import shop.alien.entity.SecondVideoTask;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.entity.second.vo.SellGoodsVo;
@@ -156,5 +154,5 @@ public interface SecondGoodsService extends IService<SecondGoods> {
      * 处理视频审核结果
      * @param task 视频审核任务
      */
-    void processVideoModerationResult(VideoModerationTask task);
+    void processVideoModerationResult(SecondVideoTask task);
 }

+ 5 - 5
alien-second/src/main/java/shop/alien/second/service/VideoModerationService.java

@@ -1,9 +1,9 @@
 package shop.alien.second.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import shop.alien.entity.VideoModerationTask;
+import shop.alien.entity.SecondVideoTask;
 
-public interface VideoModerationService  extends IService<VideoModerationTask> {
+public interface VideoModerationService  extends IService<SecondVideoTask> {
     /**
      * 提交视频审核任务
      *
@@ -17,19 +17,19 @@ public interface VideoModerationService  extends IService<VideoModerationTask> {
      * @param taskId 任务ID
      * @return 审核结果
      */
-    VideoModerationTask queryVideoModerationResult(String taskId);
+    SecondVideoTask queryVideoModerationResult(String taskId);
     /**
      * 处理视频审核结果
      *
      * @param task 视频审核任务
      * @return 是否处理成功
      */
-    boolean processTask(VideoModerationTask task);
+    boolean processTask(SecondVideoTask task);
     /**
      * 根据任务ID获取视频审核任务
      *
      * @param taskId 任务ID
      * @return 视频审核任务
      */
-    VideoModerationTask getTaskByTaskId(String taskId);
+    SecondVideoTask getTaskByTaskId(String taskId);
 }

+ 116 - 5
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java

@@ -1,7 +1,10 @@
 package shop.alien.second.service.impl;
 
 import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.nacos.api.config.annotation.NacosValue;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -13,9 +16,10 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
-import shop.alien.entity.VideoModerationTask;
+import shop.alien.entity.SecondVideoTask;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.SecondGoodsAudit;
 import shop.alien.entity.second.enums.SecondGoodsStatusEnum;
@@ -50,10 +54,10 @@ import java.util.stream.Collectors;
 public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, SecondGoods> implements SecondGoodsService {
 
 
-    @Value("${video.moderation.enabled:false}")
+    @Value("${video.moderation.enabled}")
     private boolean videoModerationEnabled;
     
-    @Value("${video.moderation.block-on-failure:true}")
+    @Value("${video.moderation.block-on-failure}")
     private boolean videoModerationBlockOnFailure;
 
     /**
@@ -230,6 +234,7 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
                 // TODO 后续配置到数据库 中
                 imgServicesList.add(ImageReviewServiceEnum.TONALITY_IMPROVE.getService());
                 imgServicesList.add(ImageReviewServiceEnum.AIGC_CHECK.getService());
+//                imgServicesList.add(ImageReviewServiceEnum.IMG_QUERY_SECURITY_CHECK.getService());
                 ImageModerationResultVO response = imageModerationUtil.productPublishCheck(imageUrl,imgServicesList);
                 if ("high".equals(response.getRiskLevel())) {
                     // 图片审核不通过或存在高风险
@@ -824,8 +829,114 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
      * @param task 视频审核任务
      */
     @Override
-    public void processVideoModerationResult(VideoModerationTask task) {
-
+    public void processVideoModerationResult(SecondVideoTask task) {
+        try {
+            // 查找关联的商品
+            QueryWrapper<SecondGoods> queryWrapper = new QueryWrapper<>();
+            queryWrapper.eq("video_task_id", task.getTaskId());
+            SecondGoods goods = getOne(queryWrapper);
+            
+            if (goods == null) {
+                log.warn("未找到关联的商品,任务ID: {}", task.getTaskId());
+                return;
+            }
+            
+            // 根据审核结果更新商品状态
+            if ("none".equals(task.getRiskLevel())) {
+                // 审核通过
+                goods.setGoodsStatus(SecondGoodsStatusEnum.LISTED.getCode());
+                goods.setFailedReason("");
+                goods.setReleaseTime(new Date());
+                updateById(goods);
+                
+                // 更新审核记录
+                createGoodsAudit(goods, "", Constants.AuditStatus.PASSED);
+                
+                // 发送审核成功消息
+                sendMessage(goods);
+            } else {
+                // 审核不通过
+                goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode());
+                
+                // 解析审核结果,生成具体的失败原因
+                String failedReason = parseVideoModerationFailureReason(task);
+                goods.setFailedReason(failedReason);
+                updateById(goods);
+                
+                // 更新审核记录
+                createGoodsAudit(goods, failedReason, Constants.AuditStatus.FAILED);
+                
+                // 发送审核失败消息
+                sendFailedMsg(goods);
+            }
+        } catch (Exception e) {
+            log.error("处理视频审核结果时发生异常,任务ID: {}", task.getTaskId(), e);
+        }
+    }
+    
+    /**
+     * 解析视频审核失败原因
+     * @param task 视频审核任务
+     * @return 失败原因
+     */
+    private String parseVideoModerationFailureReason(SecondVideoTask task) {
+        StringBuilder reasonBuilder = new StringBuilder("视频审核不通过,风险等级: " + task.getRiskLevel());
+        
+        try {
+            // 解析审核结果JSON
+            JSONObject resultJson = JSON.parseObject(task.getResult());
+            if (resultJson != null && resultJson.containsKey("data")) {
+                JSONObject data = resultJson.getJSONObject("data");
+                
+                // 处理帧结果(视频画面)
+                if (data.containsKey("FrameResult")) {
+                    JSONObject frameResult = data.getJSONObject("FrameResult");
+                    if (frameResult != null && frameResult.containsKey("FrameSummarys")) {
+                        JSONArray frameSummarys = frameResult.getJSONArray("FrameSummarys");
+                        if (frameSummarys != null && !frameSummarys.isEmpty()) {
+                            reasonBuilder.append("。检测到违规内容:");
+                            for (int i = 0; i < frameSummarys.size(); i++) {
+                                JSONObject summary = frameSummarys.getJSONObject(i);
+                                String label = summary.getString("Label");
+                                String description = summary.getString("Description");
+                                Integer labelSum = summary.getInteger("LabelSum");
+                                
+                                if (label != null && !label.isEmpty()) {
+                                    reasonBuilder.append("[").append(description != null ? description : label)
+                                            .append("]出现").append(labelSum != null ? labelSum : 1).append("次;");
+                                }
+                            }
+                        }
+                    }
+                }
+                
+                // 处理音频结果
+                if (data.containsKey("AudioResult")) {
+                    JSONObject audioResult = data.getJSONObject("AudioResult");
+                    if (audioResult != null && audioResult.containsKey("AudioSummarys")) {
+                        JSONArray audioSummarys = audioResult.getJSONArray("AudioSummarys");
+                        if (audioSummarys != null && !audioSummarys.isEmpty()) {
+                            reasonBuilder.append("。检测到违规音频:");
+                            for (int i = 0; i < audioSummarys.size(); i++) {
+                                JSONObject summary = audioSummarys.getJSONObject(i);
+                                String label = summary.getString("Label");
+                                String description = summary.getString("Description");
+                                Integer labelSum = summary.getInteger("LabelSum");
+                                
+                                if (label != null && !label.isEmpty()) {
+                                    reasonBuilder.append("[").append(description != null ? description : label)
+                                            .append("]出现").append(labelSum != null ? labelSum : 1).append("次;");
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.warn("解析视频审核结果失败,使用默认原因,任务ID: {}", task.getTaskId(), e);
+        }
+        
+        return reasonBuilder.toString();
     }
 
     /**

+ 10 - 14
alien-second/src/main/java/shop/alien/second/service/impl/VideoModerationServiceImpl.java

@@ -7,14 +7,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
-import shop.alien.entity.VideoModerationTask;
-import shop.alien.entity.second.vo.SecondGoodsRecommendVo;
-import shop.alien.mapper.second.SecondRecommendMapper;
-import shop.alien.mapper.system.VideoModerationTaskMapper;
-import shop.alien.second.service.SecondRecommendService;
+import shop.alien.entity.SecondVideoTask;
+import shop.alien.mapper.system.SecondVideoTaskMapper;
 import shop.alien.second.service.VideoModerationService;
 import shop.alien.util.common.safe.video.VideoModerationUtil;
-import shop.alien.entity.second.SecondGoods;
 
 import java.util.Date;
 import java.util.UUID;
@@ -25,7 +21,7 @@ import java.util.UUID;
 @Slf4j
 @Service
 @RequiredArgsConstructor
-public class VideoModerationServiceImpl extends ServiceImpl<VideoModerationTaskMapper, VideoModerationTask> implements VideoModerationService {
+public class VideoModerationServiceImpl extends ServiceImpl<SecondVideoTaskMapper, SecondVideoTask> implements VideoModerationService {
 
     /**
      * 视频审核工具类
@@ -35,7 +31,7 @@ public class VideoModerationServiceImpl extends ServiceImpl<VideoModerationTaskM
     /**
      * 视频审核任务Mapper
      */
-    private final VideoModerationTaskMapper videoModerationTaskMapper;
+    private final SecondVideoTaskMapper videoModerationTaskMapper;
 
     /**
      * 提交视频审核任务
@@ -55,7 +51,7 @@ public class VideoModerationServiceImpl extends ServiceImpl<VideoModerationTaskM
                     response.getBody().getCode() != null && response.getBody().getCode() == 200) {
 
                 // 保存任务信息到数据库
-                VideoModerationTask task = new VideoModerationTask();
+                SecondVideoTask task = new SecondVideoTask();
                 task.setDataId(dataId);
                 task.setVideoUrl(videoUrl);
                 task.setTaskId(response.getBody().getData().getTaskId());
@@ -83,7 +79,7 @@ public class VideoModerationServiceImpl extends ServiceImpl<VideoModerationTaskM
      * @param taskId 任务ID
      * @return 任务详情
      */
-    public VideoModerationTask getTaskByTaskId(String taskId) {
+    public SecondVideoTask getTaskByTaskId(String taskId) {
         try {
             return videoModerationTaskMapper.selectByTaskId(taskId);
         } catch (Exception e) {
@@ -98,7 +94,7 @@ public class VideoModerationServiceImpl extends ServiceImpl<VideoModerationTaskM
      * @param taskId 任务ID
      * @return 任务详情
      */
-    public VideoModerationTask getTaskById(String taskId) {
+    public SecondVideoTask getTaskById(String taskId) {
         try {
             return videoModerationTaskMapper.selectByTaskId(taskId);
         } catch (Exception e) {
@@ -113,10 +109,10 @@ public class VideoModerationServiceImpl extends ServiceImpl<VideoModerationTaskM
      * @param taskId 任务ID
      * @return 审核结果
      */
-    public VideoModerationTask queryVideoModerationResult(String taskId) {
+    public SecondVideoTask queryVideoModerationResult(String taskId) {
         try {
             // 查询数据库中的任务
-            VideoModerationTask task = videoModerationTaskMapper.selectByTaskId(taskId);
+            SecondVideoTask task = videoModerationTaskMapper.selectByTaskId(taskId);
             if (task == null) {
                 throw new RuntimeException("未找到任务ID为 " + taskId + " 的审核任务");
             }
@@ -158,7 +154,7 @@ public class VideoModerationServiceImpl extends ServiceImpl<VideoModerationTaskM
      * @param task 审核任务
      * @return 是否处理成功
      */
-    public boolean processTask(VideoModerationTask task) {
+    public boolean processTask(SecondVideoTask task) {
         try {
             // 调用阿里云接口获取审核结果
             VideoModerationResultResponse response = videoModerationUtil.getVideoModerationResult(task.getTaskId());

+ 4 - 4
alien-util/src/main/java/shop/alien/util/common/safe/video/VideoModerationUtil.java

@@ -21,10 +21,10 @@ public class VideoModerationUtil {
     @Value("${ali.yundun.secret}")
     private String accessKeySecret;
 
-    @Value("${ali.yundun.imgEndpoint}")
+    @Value("${ali.yundun.videoEndpoint}")
     private String imgEndpoint;
 
-    @Value("${ali.yundun.regionId:cn-shanghai}")
+    @Value("${ali.yundun.videoRegionId:cn-shanghai}")
     private String regionId;
 
     private Client client;
@@ -70,8 +70,8 @@ public class VideoModerationUtil {
         }
 
         VideoModerationRequest videoModerationRequest = new VideoModerationRequest();
-        // 检测类型:videoDetection
-        videoModerationRequest.setService("videoDetection");
+        // 检测类型:videoDetectionByVL
+        videoModerationRequest.setService("videoDetectionByVL");
         videoModerationRequest.setServiceParameters(serviceParameters.toJSONString());
 
         try {