|
|
@@ -0,0 +1,169 @@
|
|
|
+package com.tzld.videoVector.api;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.tzld.videoVector.model.entity.VideoDetail;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import okhttp3.*;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 视频 API 服务
|
|
|
+ * 调用长视频 API 获取视频详情信息
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class VideoApiService {
|
|
|
+
|
|
|
+ private OkHttpClient client;
|
|
|
+
|
|
|
+ private static final String POST_VIDEO_DETAIL_URL = "https://longvideoapi.piaoquantv.com/longvideoapi/openapi/video/batchSelectVideoInfo";
|
|
|
+
|
|
|
+ private static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每批次最大查询数量
|
|
|
+ */
|
|
|
+ private static final int BATCH_SIZE = 20;
|
|
|
+
|
|
|
+ @Value("${video.api.timeout:30}")
|
|
|
+ private int timeout;
|
|
|
+
|
|
|
+ @PostConstruct
|
|
|
+ public void init() {
|
|
|
+ client = new OkHttpClient.Builder()
|
|
|
+ .connectTimeout(timeout, TimeUnit.SECONDS)
|
|
|
+ .readTimeout(timeout, TimeUnit.SECONDS)
|
|
|
+ .writeTimeout(timeout, TimeUnit.SECONDS)
|
|
|
+ .build();
|
|
|
+ log.info("视频 API 服务初始化完成");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量获取视频详情信息
|
|
|
+ * 自动分批处理,每批次最多20个videoId
|
|
|
+ *
|
|
|
+ * @param videoIdList 视频ID列表
|
|
|
+ * @return videoId -> VideoDetail 映射
|
|
|
+ */
|
|
|
+ public Map<Long, VideoDetail> getVideoDetail(Set<Long> videoIdList) {
|
|
|
+ if (CollectionUtils.isEmpty(videoIdList)) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Long, VideoDetail> result = new HashMap<>();
|
|
|
+ List<Long> videoIds = new ArrayList<>(videoIdList);
|
|
|
+
|
|
|
+ // 分批处理,每批次最多20个
|
|
|
+ List<List<Long>> partitions = Lists.partition(videoIds, BATCH_SIZE);
|
|
|
+ for (List<Long> batch : partitions) {
|
|
|
+ try {
|
|
|
+ Map<Long, VideoDetail> batchResult = getVideoDetailBatch(new HashSet<>(batch));
|
|
|
+ result.putAll(batchResult);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("批量获取视频详情失败, batch={}, error={}", batch, e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 单批次获取视频详情信息
|
|
|
+ *
|
|
|
+ * @param videoIdList 视频ID列表(最多20个)
|
|
|
+ * @return videoId -> VideoDetail 映射
|
|
|
+ */
|
|
|
+ private Map<Long, VideoDetail> getVideoDetailBatch(Set<Long> videoIdList) {
|
|
|
+ try {
|
|
|
+ Map<Long, VideoDetail> map = new HashMap<>();
|
|
|
+ JSONObject params = new JSONObject();
|
|
|
+ params.put("videoIdList", videoIdList);
|
|
|
+
|
|
|
+ RequestBody body = RequestBody.create(JSON_MEDIA_TYPE, params.toJSONString());
|
|
|
+ Request request = new Request.Builder()
|
|
|
+ .url(POST_VIDEO_DETAIL_URL)
|
|
|
+ .post(body)
|
|
|
+ .addHeader("Content-Type", "application/json")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ try (Response response = client.newCall(request).execute()) {
|
|
|
+ if (!response.isSuccessful()) {
|
|
|
+ String errorBody = response.body() != null ? response.body().string() : "无";
|
|
|
+ log.error("获取视频详情 API 请求失败,HTTP状态码: {}, 错误信息: {}", response.code(), errorBody);
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ String post = response.body().string();
|
|
|
+ JSONObject res = JSONObject.parseObject(post);
|
|
|
+ JSONArray data = res.getJSONArray("data");
|
|
|
+
|
|
|
+ if (data == null || data.isEmpty()) {
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < data.size(); i++) {
|
|
|
+ JSONObject jsonObject = data.getJSONObject(i);
|
|
|
+ if (jsonObject == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ Long videoId = jsonObject.getLong("id");
|
|
|
+ if (videoId == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ VideoDetail videoDetail = new VideoDetail();
|
|
|
+ videoDetail.setCover(jsonObject.getString("shareImgPath"));
|
|
|
+ videoDetail.setTitle(jsonObject.getString("title"));
|
|
|
+ videoDetail.setVideoPath(jsonObject.getString("videoPath"));
|
|
|
+ videoDetail.setVideoCoverSnapshotPath(jsonObject.getString("videoCoverSnapshotPath"));
|
|
|
+ videoDetail.setAuditStatus(jsonObject.getInteger("auditStatus"));
|
|
|
+ videoDetail.setRecommendStatus(jsonObject.getInteger("recommendStatus"));
|
|
|
+
|
|
|
+ map.put(videoId, videoDetail);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return map;
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("VideoApiService getVideoDetail error", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return new HashMap<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取审核未通过的视频ID列表
|
|
|
+ *
|
|
|
+ * @param videoIdList 视频ID列表
|
|
|
+ * @return 审核未通过的视频ID集合
|
|
|
+ */
|
|
|
+ public Set<Long> getNotAuditPassedVideoIds(Set<Long> videoIdList) {
|
|
|
+ Map<Long, VideoDetail> videoDetails = getVideoDetail(videoIdList);
|
|
|
+ Set<Long> notPassedIds = new HashSet<>();
|
|
|
+
|
|
|
+ for (Map.Entry<Long, VideoDetail> entry : videoDetails.entrySet()) {
|
|
|
+ if (!entry.getValue().isAuditPassed()) {
|
|
|
+ notPassedIds.add(entry.getKey());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果查询结果中没有某些视频ID,说明这些视频可能已被删除,也视为审核不通过
|
|
|
+ for (Long videoId : videoIdList) {
|
|
|
+ if (!videoDetails.containsKey(videoId)) {
|
|
|
+ notPassedIds.add(videoId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return notPassedIds;
|
|
|
+ }
|
|
|
+}
|