Explorar el Código

Merge branch 'wyp/1230-videoCoverAudit' of Server/long-article-recommend into master

wangyunpeng hace 5 meses
padre
commit
8e9ee301ae

+ 32 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/VideoAuditTypeEnum.java

@@ -0,0 +1,32 @@
+package com.tzld.longarticle.recommend.server.common.enums;
+
+import lombok.Getter;
+
+import java.util.Objects;
+
+@Getter
+public enum VideoAuditTypeEnum {
+    PQ(1, "票圈审核"),
+    COVER(2, "封面检查"),
+
+    other(999, "其他"),
+    ;
+
+    // 审核类型 1-票圈审核 2-封面检查
+    private final Integer type;
+    private final String description;
+
+    VideoAuditTypeEnum(Integer type, String description) {
+        this.type = type;
+        this.description = description;
+    }
+
+    public static VideoAuditTypeEnum from(Integer type) {
+        for (VideoAuditTypeEnum typeEnum : VideoAuditTypeEnum.values()) {
+            if (Objects.equals(typeEnum.type, type)) {
+                return typeEnum;
+            }
+        }
+        return other;
+    }
+}

+ 31 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/cgi/FindFaceStatusEnum.java

@@ -0,0 +1,31 @@
+package com.tzld.longarticle.recommend.server.common.enums.cgi;
+
+import lombok.Getter;
+
+import java.util.Objects;
+
+@Getter
+public enum FindFaceStatusEnum {
+    EXIST(1, "有违规脸"),
+    NOT_EXIST(2, "没有违规脸"),
+
+    other(999, "其他"),
+    ;
+
+    private final Integer status;
+    private final String description;
+
+    FindFaceStatusEnum(Integer status, String description) {
+        this.status = status;
+        this.description = description;
+    }
+
+    public static FindFaceStatusEnum from(Integer status) {
+        for (FindFaceStatusEnum statusEnum : FindFaceStatusEnum.values()) {
+            if (Objects.equals(statusEnum.status, status)) {
+                return statusEnum;
+            }
+        }
+        return other;
+    }
+}

+ 1 - 1
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/mapper/longArticle/LongArticleBaseMapper.java

@@ -65,7 +65,7 @@ public interface LongArticleBaseMapper {
 
     List<String> getFilterColdLongArticleTitle();
 
-    List<String> getExistsOssPath();
+    List<String> getExistsOssPath(Integer type);
 
     void updateVideoPoolContentBad(String contentTraceId);
 

+ 8 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/cgi/AlgFaceRecognizeResult.java

@@ -0,0 +1,8 @@
+package com.tzld.longarticle.recommend.server.model.cgi;
+
+import lombok.Data;
+
+@Data
+public class AlgFaceRecognizeResult {
+    private Integer find_face_status;
+}

+ 18 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/entity/longArticle/LongArticleVideoAudit.java

@@ -5,17 +5,22 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 
 import javax.persistence.*;
+import java.io.Serializable;
 
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
 @Entity
 @Table(name = "long_articles_video_audit")
+@IdClass(LongArticleVideoAudit.PK.class)
 public class LongArticleVideoAudit {
 
     @Id
     @Column(name = "video_id")
     private Long videoId;
+    @Id
+    @Column(name = "type")
+    private Integer type;
 
     @Column(name = "content_id")
     private String contentId;
@@ -40,4 +45,17 @@ public class LongArticleVideoAudit {
 
     @Column(name = "finish_timestamp")
     private Long finishTimestamp;
+
+    @Data
+    public static class PK implements Serializable {
+
+        @Column(name = "video_id")
+        private Long videoId;
+        @Column(name = "type")
+        private Integer type;
+
+        public PK() {
+        }
+
+    }
 }

+ 74 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/alg/DangerFaceRecognizeService.java

@@ -0,0 +1,74 @@
+package com.tzld.longarticle.recommend.server.remote.alg;
+
+import com.alibaba.fastjson.JSONObject;
+import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+import com.tzld.longarticle.recommend.server.model.cgi.AlgFaceRecognizeResult;
+import com.tzld.longarticle.recommend.server.model.param.PQResponse;
+import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.StatusLine;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+
+@Service
+@Slf4j
+public class DangerFaceRecognizeService {
+
+    @Autowired
+    ArticleRepository articleRepository;
+
+    private final CloseableHttpClient client = HttpPoolFactory.aigcPool();
+    private static final String url = "http://172.16.232.206:5000/recognize/url";
+
+    public AlgFaceRecognizeResult getResult(String imageUrl) {
+        int retryTimes = 3;
+        while (retryTimes > 0) {
+            AlgFaceRecognizeResult result = post(imageUrl);
+            if (Objects.nonNull(result)) {
+                return result;
+            }
+            retryTimes--;
+        }
+        return null;
+    }
+
+    public AlgFaceRecognizeResult post(String imageUrl) {
+        JSONObject params = new JSONObject();
+        params.put("url", imageUrl);
+        try {
+            HttpPost httpPost = new HttpPost(url);
+            StringEntity stringEntity = new StringEntity(params.toJSONString(), StandardCharsets.UTF_8);
+            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
+            httpPost.setEntity(stringEntity);
+            CloseableHttpResponse response = client.execute(httpPost);
+            StatusLine statusLine = response.getStatusLine();
+            if (statusLine.getStatusCode() == 200) {
+                HttpEntity responseEntity = response.getEntity();
+                if (Objects.nonNull(responseEntity)) {
+                    String responseBody = EntityUtils.toString(responseEntity, "UTF-8");
+                    PQResponse pqResponse = JSONObject.parseObject(responseBody, PQResponse.class);
+                    if (pqResponse.getCode() == 0 && Objects.nonNull(pqResponse.getData())) {
+                        return JSONObject.parseObject(JSONObject.toJSONString(pqResponse.getData()), AlgFaceRecognizeResult.class);
+                    } else {
+                        return null;
+                    }
+                }
+            }
+        } catch (IOException e) {
+            log.error("DangerFaceRecognizeService error", e);
+        }
+        return null;
+    }
+
+
+}

+ 4 - 4
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/repository/longArticle/LongArticleVideoAuditRepository.java

@@ -7,10 +7,10 @@ import org.springframework.stereotype.Repository;
 import java.util.List;
 
 @Repository
-public interface LongArticleVideoAuditRepository extends JpaRepository<LongArticleVideoAudit, Long> {
-    LongArticleVideoAudit getByVideoId(Long videoId);
+public interface LongArticleVideoAuditRepository extends JpaRepository<LongArticleVideoAudit, LongArticleVideoAudit.PK> {
+    LongArticleVideoAudit getByVideoIdAndType(Long videoId, Integer type);
 
-    List<LongArticleVideoAudit> getByVideoIdIn(List<Long> videoIds);
+    List<LongArticleVideoAudit> getByVideoIdInAndType(List<Long> videoIds, Integer type);
 
-    List<LongArticleVideoAudit> getByStatusAndTaskIdIsNotNull(Integer status);
+    List<LongArticleVideoAudit> getByStatusAndTypeAndTaskIdIsNotNull(Integer status, Integer type);
 }

+ 92 - 4
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/ArticleAuditService.java

@@ -6,9 +6,11 @@ import com.alibaba.fastjson.JSONObject;
 import com.google.common.collect.Lists;
 import com.tzld.longarticle.recommend.server.common.enums.FieshuTableColumnDataTypeEnum;
 import com.tzld.longarticle.recommend.server.common.enums.StatusEnum;
+import com.tzld.longarticle.recommend.server.common.enums.VideoAuditTypeEnum;
 import com.tzld.longarticle.recommend.server.common.enums.aigc.PublishContentStatusEnum;
 import com.tzld.longarticle.recommend.server.common.enums.aigc.PublishPlanInputSourceTypesEnum;
 import com.tzld.longarticle.recommend.server.common.enums.aigc.PushTypeEnum;
+import com.tzld.longarticle.recommend.server.common.enums.cgi.FindFaceStatusEnum;
 import com.tzld.longarticle.recommend.server.common.enums.cgi.PQVideoAuditResultEnum;
 import com.tzld.longarticle.recommend.server.common.enums.cgi.PQVideoSensitiveLevelEnum;
 import com.tzld.longarticle.recommend.server.common.enums.recommend.ArticleDeleteStatusEnum;
@@ -17,6 +19,7 @@ import com.tzld.longarticle.recommend.server.common.enums.recommend.FeishuRobotI
 import com.tzld.longarticle.recommend.server.mapper.aigc.AigcBaseMapper;
 import com.tzld.longarticle.recommend.server.mapper.crawler.ArticleMapper;
 import com.tzld.longarticle.recommend.server.mapper.longArticle.LongArticleBaseMapper;
+import com.tzld.longarticle.recommend.server.model.cgi.AlgFaceRecognizeResult;
 import com.tzld.longarticle.recommend.server.model.cgi.PQVideoAuditResult;
 import com.tzld.longarticle.recommend.server.model.dto.*;
 import com.tzld.longarticle.recommend.server.model.entity.aigc.PublishAccount;
@@ -30,11 +33,11 @@ import com.tzld.longarticle.recommend.server.model.vo.ArticleDeleteListVO;
 import com.tzld.longarticle.recommend.server.model.vo.FeishuTableDTO;
 import com.tzld.longarticle.recommend.server.remote.WxAccessTokenRemoteService;
 import com.tzld.longarticle.recommend.server.remote.WxArticleDeleteService;
+import com.tzld.longarticle.recommend.server.remote.alg.DangerFaceRecognizeService;
 import com.tzld.longarticle.recommend.server.remote.pq.PQVideoAuditResultService;
 import com.tzld.longarticle.recommend.server.remote.pq.PQVideoAuditStartProcessService;
 import com.tzld.longarticle.recommend.server.repository.aigc.PublishAccountRepository;
 import com.tzld.longarticle.recommend.server.repository.aigc.PublishContentRepository;
-import com.tzld.longarticle.recommend.server.repository.aigc.PublishPlanRepository;
 import com.tzld.longarticle.recommend.server.repository.crawler.ArticleRepository;
 import com.tzld.longarticle.recommend.server.repository.longArticle.*;
 import com.tzld.longarticle.recommend.server.util.DateUtils;
@@ -91,7 +94,7 @@ public class ArticleAuditService {
     @Autowired
     private ArticleMapper articleMapper;
     @Autowired
-    private PublishPlanRepository publishPlanRepository;
+    private DangerFaceRecognizeService dangerFaceRecognizeService;
 
 
     @XxlJob("articleVideoAudit")
@@ -110,7 +113,7 @@ public class ArticleAuditService {
         List<LongArticlesMatchVideo> longArticlesMatchVideoList = longArticlesMatchVideoRepository.getByTraceIdIn(traceIds);
         Map<String, LongArticlesMatchVideo> longarticlesMatchVideoMap = longArticlesMatchVideoList.stream()
                 .collect(Collectors.toMap(LongArticlesMatchVideo::getTraceId, Function.identity()));
-        List<String> existsOssPath = longArticleBaseMapper.getExistsOssPath();
+        List<String> existsOssPath = longArticleBaseMapper.getExistsOssPath(VideoAuditTypeEnum.PQ.getType());
         for (String traceId : traceIds) {
             try {
                 LongArticlesMatchVideo longArticlesMatchVideo = longarticlesMatchVideoMap.get(traceId);
@@ -127,6 +130,7 @@ public class ArticleAuditService {
                     LongArticleVideoAudit videoAudit = new LongArticleVideoAudit();
                     videoAudit.setVideoId(response.getVideoID());
                     videoAudit.setTraceId(traceId);
+                    videoAudit.setType(VideoAuditTypeEnum.PQ.getType());
                     videoAudit.setContentId(longArticlesMatchVideo.getContentId());
                     videoAudit.setOssPath(ossPath);
                     videoAudit.setStatus(StatusEnum.ZERO.getCode());
@@ -153,6 +157,89 @@ public class ArticleAuditService {
         return ReturnT.SUCCESS;
     }
 
+    @XxlJob("articleVideoAuditCover")
+    public ReturnT<String> articleVideoAuditCover(String param) {
+        long publishTime = DateUtils.getTodayStart() / 1000;
+        if (StringUtils.hasText(param)) {
+            publishTime = DateUtils.getStartOfDay(param, "yyyyMMdd");
+        }
+        List<GetOffVideoArticle> getOffVideoArticleList = getOffVideoArticleRepository.getByPublishTimeGreaterThanEqual(publishTime);
+        List<String> traceIds = getOffVideoArticleList.stream()
+                .filter(o -> !o.getTraceId().startsWith("direct"))
+                .map(GetOffVideoArticle::getTraceId).distinct().collect(Collectors.toList());
+        if (CollectionUtil.isEmpty(traceIds)) {
+            return ReturnT.SUCCESS;
+        }
+        List<LongArticlesMatchVideo> longArticlesMatchVideoList = longArticlesMatchVideoRepository.getByTraceIdIn(traceIds);
+        Map<String, LongArticlesMatchVideo> longarticlesMatchVideoMap = longArticlesMatchVideoList.stream()
+                .collect(Collectors.toMap(LongArticlesMatchVideo::getTraceId, Function.identity()));
+        List<String> existsOssPath = longArticleBaseMapper.getExistsOssPath(VideoAuditTypeEnum.COVER.getType());
+        for (String traceId : traceIds) {
+            try {
+                Long now = System.currentTimeMillis();
+                LongArticlesMatchVideo longArticlesMatchVideo = longarticlesMatchVideoMap.get(traceId);
+                List<LongArticlesMatchVideoResponse> responseList = JSONArray.parseArray(longArticlesMatchVideo.getResponse()
+                        , LongArticlesMatchVideoResponse.class);
+                for (LongArticlesMatchVideoResponse response : responseList) {
+                    String ossPath = response.getVideoOSS();
+                    if (StringUtils.hasText(ossPath)) {
+                        if (existsOssPath.contains(ossPath)) {
+                            continue;
+                        }
+                        existsOssPath.add(ossPath);
+                    }
+                    LongArticleVideoAudit videoAudit = new LongArticleVideoAudit();
+                    videoAudit.setVideoId(response.getVideoID());
+                    videoAudit.setTraceId(traceId);
+                    videoAudit.setType(VideoAuditTypeEnum.COVER.getType());
+                    videoAudit.setContentId(longArticlesMatchVideo.getContentId());
+                    videoAudit.setOssPath(ossPath);
+                    videoAudit.setStatus(StatusEnum.ZERO.getCode());
+                    videoAudit.setCreateTimestamp(now);
+                    longArticleVideoAuditRepository.save(videoAudit);
+                    try {
+                        // 调用封面检测
+                        AlgFaceRecognizeResult result = dangerFaceRecognizeService.getResult(response.getVideoCover());
+
+                        if (Objects.equals(result.getFind_face_status(), FindFaceStatusEnum.NOT_EXIST.getStatus())) {
+                            // 审核通过,更新文章状态
+                            videoAudit.setStatus(PQVideoAuditResultEnum.PASS.getStatus());
+                            videoAudit.setFinishTimestamp(now);
+                            longArticleVideoAuditRepository.save(videoAudit);
+                        } else if (Objects.equals(result.getFind_face_status(), FindFaceStatusEnum.EXIST.getStatus())) {
+                            // 审核不通过,删除文章
+                            videoAudit.setStatus(PQVideoAuditResultEnum.REJECT.getStatus());
+                            videoAudit.setFailReason("封面存在敏感");
+                            videoAudit.setFinishTimestamp(now);
+                            longArticleVideoAuditRepository.save(videoAudit);
+                            // 构建删除文章记录 并保存
+                            // saveDeleteRecord(longArticleVideoAudit.getOssPath());
+                            // 暂时不做删除 先发送通知
+                            if (videoAudit.getStatus().equals(PQVideoAuditResultEnum.REJECT.getStatus())) {
+                                log.info("视频封面识别不通过【存在敏感】 traceId:{} videoId:{} time:{}",
+                                        videoAudit.getTraceId(), videoAudit.getVideoId(),
+                                        DateUtils.getDateString(now, "yyyy-MM-dd HH:mm:ss"));
+                                FeishuMessageSender.sendWebHookMessage(FeishuRobotIdEnum.ARTICLE_DELETE.getRobotId(),
+                                        "视频封面识别不通过【存在敏感】\n" +
+                                                "traceId:" + videoAudit.getTraceId() + "\n" +
+                                                "视频id:" + videoAudit.getVideoId() + "\n" +
+                                                "管理后台地址:https://admin.piaoquantv.com/cms/post-detail/" + videoAudit.getVideoId() + "/detail\n" +
+                                                "操作删除视频及文章(慎点):" +
+                                                "http://192.168.203.83:30081/articleAudit/saveDeleteRecord?videoId=" + videoAudit.getVideoId());
+                            }
+                        }
+                    } catch (Exception e) {
+                        log.error("PQVideoAuditStartProcess start process videoId:{} error:{}", response.getVideoID(), e.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("articleVideoAudit traceId:{} error:{}", traceId, e.getMessage());
+            }
+        }
+
+        return ReturnT.SUCCESS;
+    }
+
     private String getOssPath(String ossUrl) {
         String result = "";
         if (ossUrl == null || ossUrl.isEmpty()) {
@@ -177,7 +264,8 @@ public class ArticleAuditService {
 
     @XxlJob("articleVideoAuditResult")
     public ReturnT<String> articleVideoAuditResult(String param) {
-        List<LongArticleVideoAudit> list = longArticleVideoAuditRepository.getByStatusAndTaskIdIsNotNull(StatusEnum.ZERO.getCode());
+        List<LongArticleVideoAudit> list = longArticleVideoAuditRepository.getByStatusAndTypeAndTaskIdIsNotNull(
+                StatusEnum.ZERO.getCode(), VideoAuditTypeEnum.PQ.getType());
         for (List<LongArticleVideoAudit> partition : Lists.partition(list, 10)) {
             List<Long> taskIds = partition.stream().map(LongArticleVideoAudit::getTaskId).collect(Collectors.toList());
             Map<Long, LongArticleVideoAudit> map = partition.stream().collect(Collectors.toMap(LongArticleVideoAudit::getTaskId, Function.identity()));

+ 5 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/recommend/ArticleAuditController.java

@@ -24,6 +24,11 @@ public class ArticleAuditController {
         service.articleVideoAudit(dateStr);
     }
 
+    @GetMapping("/articleVideoAuditCover")
+    public void articleVideoAuditCover(String dateStr) {
+        service.articleVideoAuditCover(dateStr);
+    }
+
     @GetMapping("/articleVideoAuditResult")
     public CommonResponse<Void> articleVideoAuditResult(String param) {
         service.articleVideoAuditResult(param);

+ 1 - 1
long-article-recommend-service/src/main/resources/mapper/longArticle/LongArticleBaseMapper.xml

@@ -246,7 +246,7 @@
     </insert>
 
     <select id="getExistsOssPath" resultType="java.lang.String">
-        select distinct oss_path from long_articles_video_audit
+        select distinct oss_path from long_articles_video_audit where type = #{type}
     </select>
 
     <update id="updateVideoPoolContentBad">