Browse Source

完成AI生成接口重构

tsurumure 4 months ago
parent
commit
9db28d9ff4
44 changed files with 675 additions and 632 deletions
  1. 1 1
      db/ai_generate_video_task.sql
  2. 22 0
      db/ai_media_ttv.sql
  3. 0 1
      src/main/java/com/backendsys/modules/ai/chat/entity/Chat.java
  4. 13 5
      src/main/java/com/backendsys/modules/ai/media/controller/MediaController.java
  5. 0 17
      src/main/java/com/backendsys/modules/ai/media/dao/MediaDao.java
  6. 9 0
      src/main/java/com/backendsys/modules/ai/media/dao/MediaTtvDao.java
  7. 0 11
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Common/MediaSource.java
  8. 0 18
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/Config.java
  9. 0 11
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigBgMusic.java
  10. 0 14
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigCaption.java
  11. 0 11
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigVideoBegin.java
  12. 0 11
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigVideoEnd.java
  13. 0 7
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigVideoLogo.java
  14. 0 12
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Source/Source.java
  15. 0 10
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Source/StructsItem.java
  16. 1 2
      src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/__bak_MediaParams.java
  17. 47 0
      src/main/java/com/backendsys/modules/ai/media/entity/MediaTtv.java
  18. 11 0
      src/main/java/com/backendsys/modules/ai/media/entity/MediaTtvConfig.java
  19. 11 0
      src/main/java/com/backendsys/modules/ai/media/entity/MediaTtvSource.java
  20. 7 3
      src/main/java/com/backendsys/modules/ai/media/service/MediaService.java
  21. 130 36
      src/main/java/com/backendsys/modules/ai/media/service/impl/MediaServiceImpl.java
  22. 64 0
      src/main/java/com/backendsys/modules/common/utils/CommonUtil.java
  23. 0 9
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/AiGenerateVideoCustomDTO.java
  24. 0 8
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigBgMusicDTO.java
  25. 0 12
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigCaptionDTO.java
  26. 0 18
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigDTO.java
  27. 0 8
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigVideoBeginDTO.java
  28. 0 8
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigVideoEndDTO.java
  29. 0 11
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigVideoLogoDTO.java
  30. 0 9
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/MediaSourceVO.java
  31. 0 10
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/SourceDTO.java
  32. 0 10
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/SourceStructDTO.java
  33. 11 0
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/BaiduBceMediaJob.java
  34. 12 0
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/BaiduBceMediaJobResult.java
  35. 0 11
      src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/MediaMaterialResponse.java
  36. 7 14
      src/main/java/com/backendsys/modules/sdk/baidu/bce/service/BaiduBceMediaService.java
  37. 140 205
      src/main/java/com/backendsys/modules/sdk/baidu/bce/service/impl/BaiduBceMediaServiceImpl.java
  38. 4 0
      src/main/java/com/backendsys/modules/sdk/douyincloud/tos/service/DouyinTosService.java
  39. 14 0
      src/main/java/com/backendsys/modules/sdk/douyincloud/tos/service/impl/DouyinTosServiceImpl.java
  40. 7 2
      src/main/java/com/backendsys/modules/sdk/tencentcloud/cos/service/TencentCosService.java
  41. 58 1
      src/main/java/com/backendsys/modules/sdk/tencentcloud/cos/service/impl/TencentCosServiceImpl.java
  42. 1 1
      src/main/java/com/backendsys/service/SDKService/SDKBaidu/SDKBaiduAiGenerateVideoServiceImpl.java
  43. 0 125
      src/main/resources/mapper/ai/media/MediaMapper.xml
  44. 105 0
      src/main/resources/mapper/ai/media/MediaTtvMapper.xml

+ 1 - 1
db/ai_generate_video_task.sql

@@ -14,7 +14,7 @@ CREATE TABLE `ai_generate_video_task` (
     `source` TEXT NOT NULL COMMENT '内容',
     `resolution` VARCHAR(255) COMMENT '分辨率,横屏支持[1920,1080]、[1280,720]、[1024,576]、竖屏支持[1080,1920]、[720,1280]、[576,1024]',
     `product_type` VARCHAR(255) NOT NULL COMMENT '视频输出形式,可选项为 video、timeline (video: 产出结果为mp4视频;timeline: 产出结果为json时间轴信息;)',
-    `tts_per` VARCHAR(10) DEFAULT '4100' COMMENT '音库,支持基础音库、精品音库、臻品音库,默认 4100:度小雯-女',
+    `tts_per` VARCHAR(10) DEFAULT '4144' COMMENT '音库,支持基础音库、精品音库、臻品音库,默认 4100:度小雯-女',
     `bg_music_url` VARCHAR(1000) COMMENT '背景音乐URL',
     `video_begin_url` VARCHAR(1000) COMMENT '片头',
     `video_end_url` VARCHAR(1000) COMMENT '片尾',

+ 22 - 0
db/ai_media_ttv.sql

@@ -0,0 +1,22 @@
+/**
+Source Server Version: 8.0.31
+Source Database: backendsys
+Date: 2025/04/23 10:21:01
+*/
+
+DROP TABLE IF EXISTS `ai_media_ttv`;
+CREATE TABLE `ai_media_ttv` (
+    PRIMARY KEY (`id`),
+    `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
+    `user_id` BIGINT COMMENT '用户ID',
+    `job_id` VARCHAR(255) NOT NULL COMMENT '任务ID',
+    `job_status` int DEFAULT '0' COMMENT '任务状态 (0任务排队中,1任务完成,3任务执行中)',
+    `title` VARCHAR(255) NOT NULL COMMENT '标题',
+    `request_params` TEXT COMMENT '入参',
+    `response_params` TEXT COMMENT '出参',
+    `video_origin_url` TEXT COMMENT '视频原地址',
+    `video_url` TEXT COMMENT '视频转存地址',
+    `object_key` TEXT COMMENT 'Object_key',
+    `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+    `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
+) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='AI生成图文语音视频表 (百度)';

+ 0 - 1
src/main/java/com/backendsys/modules/ai/chat/entity/Chat.java

@@ -1,6 +1,5 @@
 package com.backendsys.modules.ai.chat.entity;
 
-import com.backendsys.entity.validator.RangeStringArray;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;

+ 13 - 5
src/main/java/com/backendsys/modules/ai/media/controller/MediaController.java

@@ -1,6 +1,6 @@
 package com.backendsys.modules.ai.media.controller;
 
-import com.backendsys.modules.ai.media.entity.MediaParams.MediaParams;
+import com.backendsys.modules.ai.media.entity.MediaTtv;
 import com.backendsys.modules.ai.media.service.MediaService;
 import com.backendsys.modules.common.config.security.utils.SecurityUtil;
 import com.backendsys.modules.common.utils.Result;
@@ -9,6 +9,7 @@ import io.swagger.v3.oas.annotations.Operation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
@@ -20,12 +21,19 @@ public class MediaController {
     @Autowired
     private MediaService mediaService;
 
-    @Operation(summary = "定制成片")
+    @Operation(summary = "生成图文语音视频")
     @PreAuthorize("@sr.hasPermission('34')")
     @PostMapping("/api/ai/media/ttv/generate")
-    public Result generateMediaTtv(@Validated(MediaParams.Create.class) @RequestBody MediaParams mediaParams) throws JsonProcessingException {
-        mediaParams.setUser_id(SecurityUtil.getUserId());
-        return Result.success().put("data", mediaService.makeGenerateVideoAndInsert(mediaParams));
+    public Result generateMediaTtv(@Validated(MediaTtv.Generate.class) @RequestBody MediaTtv mediaTtv) {
+        mediaTtv.setUser_id(SecurityUtil.getUserId());
+        return Result.success().put("data", mediaService.generateMediaTtv(mediaTtv));
+    }
+
+    @Operation(summary = "查询图文语音视频")
+    @PreAuthorize("@sr.hasPermission('34')")
+    @GetMapping("/api/ai/media/ttv/query")
+    public Result queryMediaTtv(@Validated(MediaTtv.Query.class) MediaTtv mediaTtv) {
+        return Result.success().put("data", mediaService.queryMediaTtv(mediaTtv));
     }
 
 }

+ 0 - 17
src/main/java/com/backendsys/modules/ai/media/dao/MediaDao.java

@@ -1,17 +0,0 @@
-package com.backendsys.modules.ai.media.dao;
-
-import com.backendsys.modules.ai.media.entity.AiGenerateVideoDTO;
-import com.backendsys.modules.ai.media.entity.MediaParams.MediaParams;
-import org.apache.ibatis.annotations.Mapper;
-
-import java.util.List;
-import java.util.Map;
-
-@Mapper
-public interface MediaDao {
-    List<Map<String, Object>> queryAiGenerateVideoList(AiGenerateVideoDTO aiGenerateVideoDTO);
-    Map<String, Object> queryAiGenerateVideoDetail(AiGenerateVideoDTO aiGenerateVideoDTO);
-    long insertAiGenerateVideo(MediaParams mediaParams);
-    long updateAiGenerateVideo(AiGenerateVideoDTO aiGenerateVideoDTO);
-    long deleteAiGenerateVideo(AiGenerateVideoDTO aiGenerateVideoDTO);
-}

+ 9 - 0
src/main/java/com/backendsys/modules/ai/media/dao/MediaTtvDao.java

@@ -0,0 +1,9 @@
+package com.backendsys.modules.ai.media.dao;
+
+import com.backendsys.modules.ai.media.entity.MediaTtv;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MediaTtvDao extends BaseMapper<MediaTtv> {
+}

+ 0 - 11
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Common/MediaSource.java

@@ -1,11 +0,0 @@
-package com.backendsys.modules.ai.media.entity.MediaParams.Common;
-
-import lombok.Data;
-
-@Data
-public class MediaSource {
-
-    private Integer type = 3;
-    private String url;
-
-}

+ 0 - 18
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/Config.java

@@ -1,18 +0,0 @@
-package com.backendsys.modules.ai.media.entity.MediaParams.Config;
-
-import lombok.Data;
-
-@Data
-public class Config {
-
-    private String productType = "video";
-    private Integer ttsPer = 0;
-    private Integer[] resolution = {1024,576};
-    private String templateId;
-    private ConfigBgMusic bgMusic;
-    private ConfigVideoBegin videoBegin;
-    private ConfigVideoEnd videoEnd;
-    private ConfigCaption caption;
-    private ConfigVideoLogo videoLogo;
-
-}

+ 0 - 11
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigBgMusic.java

@@ -1,11 +0,0 @@
-package com.backendsys.modules.ai.media.entity.MediaParams.Config;
-
-import com.backendsys.modules.ai.media.entity.MediaParams.Common.MediaSource;
-import lombok.Data;
-
-@Data
-public class ConfigBgMusic {
-
-    private MediaSource mediaSource;
-
-}

+ 0 - 14
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigCaption.java

@@ -1,14 +0,0 @@
-package com.backendsys.modules.ai.media.entity.MediaParams.Config;
-
-import lombok.Data;
-
-@Data
-public class ConfigCaption {
-
-    private String marginBottom;
-    private String fontColor;
-    private Integer fontAlpha;
-    private String bgColor;
-    private Integer bgAlpha;
-
-}

+ 0 - 11
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigVideoBegin.java

@@ -1,11 +0,0 @@
-package com.backendsys.modules.ai.media.entity.MediaParams.Config;
-
-import com.backendsys.modules.ai.media.entity.MediaParams.Common.MediaSource;
-import lombok.Data;
-
-@Data
-public class ConfigVideoBegin {
-
-    private MediaSource mediaSource;
-
-}

+ 0 - 11
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigVideoEnd.java

@@ -1,11 +0,0 @@
-package com.backendsys.modules.ai.media.entity.MediaParams.Config;
-
-import com.backendsys.modules.ai.media.entity.MediaParams.Common.MediaSource;
-import lombok.Data;
-
-@Data
-public class ConfigVideoEnd {
-
-    private MediaSource mediaSource;
-
-}

+ 0 - 7
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Config/ConfigVideoLogo.java

@@ -1,7 +0,0 @@
-package com.backendsys.modules.ai.media.entity.MediaParams.Config;
-
-import lombok.Data;
-
-@Data
-public class ConfigVideoLogo {
-}

+ 0 - 12
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Source/Source.java

@@ -1,12 +0,0 @@
-package com.backendsys.modules.ai.media.entity.MediaParams.Source;
-
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-public class Source {
-
-    private List<StructsItem> structs;
-
-}

+ 0 - 10
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/Source/StructsItem.java

@@ -1,10 +0,0 @@
-package com.backendsys.modules.ai.media.entity.MediaParams.Source;
-
-import com.backendsys.modules.ai.media.entity.MediaParams.Common.MediaSource;
-import lombok.Data;
-
-@Data
-public class StructsItem {
-    private String type;                // type: text、image
-    private MediaSource mediaSource;    // mediaSource: { type, url }
-}

+ 1 - 2
src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/MediaParams.java → src/main/java/com/backendsys/modules/ai/media/entity/MediaParams/__bak_MediaParams.java

@@ -2,7 +2,6 @@ package com.backendsys.modules.ai.media.entity.MediaParams;
 
 import com.backendsys.entity.validator.RangeStringArray;
 import com.backendsys.modules.ai.media.entity.AiGenerateVideoDTO;
-import com.backendsys.modules.ai.media.entity.MediaParams.Source.Source;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Size;
 import lombok.Data;
@@ -10,7 +9,7 @@ import lombok.ToString;
 
 @Data
 @ToString
-public class MediaParams {
+public class __bak_MediaParams {
 
     public static interface Detail{}
     public static interface Create{}

+ 47 - 0
src/main/java/com/backendsys/modules/ai/media/entity/MediaTtv.java

@@ -0,0 +1,47 @@
+package com.backendsys.modules.ai.media.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@TableName("ai_media_ttv")
+public class MediaTtv {
+
+    public static interface Query{}
+    public static interface Generate{}
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long user_id;
+    @NotEmpty(message = "标题不能为空", groups = { Generate.class })
+    private String title;
+    @NotEmpty(message = "job_id 不能为空", groups = { Query.class })
+    private String job_id;
+    private Integer job_status;     // 任务状态 (0任务排队中,1任务完成,3任务执行中)
+    @TableField(exist = false)
+    private Float job_progress = 0f;     // 任务进度 (1=100%)
+
+    private String video_origin_url;
+    private String video_url;
+    private String object_key;
+
+    @TableField(exist = false)
+    @NotEmpty(message = "source 不能为空", groups = { Generate.class })
+    private List<MediaTtvSource> source;
+    @TableField(exist = false)
+    @NotNull(message = "config 不能为空", groups = { Generate.class })
+    private MediaTtvConfig config;
+
+    private String request_params;
+    private String response_params;
+    private String create_time;
+    private String update_time;
+
+}

+ 11 - 0
src/main/java/com/backendsys/modules/ai/media/entity/MediaTtvConfig.java

@@ -0,0 +1,11 @@
+package com.backendsys.modules.ai.media.entity;
+
+import lombok.Data;
+import lombok.ToString;
+
+@Data
+@ToString
+public class MediaTtvConfig {
+    private Integer tts_voice_type;
+    private Integer[] resolution;
+}

+ 11 - 0
src/main/java/com/backendsys/modules/ai/media/entity/MediaTtvSource.java

@@ -0,0 +1,11 @@
+package com.backendsys.modules.ai.media.entity;
+
+import lombok.Data;
+import lombok.ToString;
+
+@Data
+@ToString
+public class MediaTtvSource {
+    private String type;
+    private String content;
+}

+ 7 - 3
src/main/java/com/backendsys/modules/ai/media/service/MediaService.java

@@ -1,14 +1,18 @@
 package com.backendsys.modules.ai.media.service;
 
 
-import com.backendsys.modules.ai.media.entity.MediaParams.MediaParams;
+import com.backendsys.modules.ai.media.entity.MediaTtv;
+import com.backendsys.modules.sdk.baidu.bce.entity.BaiduBceMediaJob;
+import com.backendsys.modules.sdk.baidu.bce.entity.BaiduBceMediaJobResult;
 import com.fasterxml.jackson.core.JsonProcessingException;
 
 import java.util.Map;
 
 public interface MediaService {
 
-    // 定制成片任务
-    Map<String, Object> makeGenerateVideoAndInsert(MediaParams mediaParams) throws JsonProcessingException;
+    // 生成图文语音视频
+    BaiduBceMediaJob generateMediaTtv(MediaTtv mediaTtv);
+    // 查询图文语音视频
+    MediaTtv queryMediaTtv(MediaTtv mediaTtv);
 
 }

+ 130 - 36
src/main/java/com/backendsys/modules/ai/media/service/impl/MediaServiceImpl.java

@@ -1,60 +1,154 @@
 package com.backendsys.modules.ai.media.service.impl;
 
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
-import com.backendsys.modules.ai.media.dao.MediaDao;
-import com.backendsys.modules.ai.media.entity.MediaParams.MediaParams;
+import cn.hutool.json.JSONUtil;
+import com.backendsys.exception.CustException;
+import com.backendsys.modules.ai.media.dao.MediaTtvDao;
+import com.backendsys.modules.ai.media.entity.MediaTtv;
+import com.backendsys.modules.ai.media.entity.MediaTtvConfig;
+import com.backendsys.modules.ai.media.entity.MediaTtvSource;
 import com.backendsys.modules.ai.media.service.MediaService;
+import com.backendsys.modules.sdk.baidu.bce.entity.BaiduBceMediaJob;
+import com.backendsys.modules.sdk.baidu.bce.entity.BaiduBceMediaJobResult;
 import com.backendsys.modules.sdk.baidu.bce.service.BaiduBceMediaService;
-import com.fasterxml.jackson.core.JsonProcessingException;
+import com.backendsys.modules.sdk.douyincloud.tos.service.DouyinTosService;
+import com.backendsys.modules.sdk.tencentcloud.cos.service.TencentCosService;
+import com.backendsys.modules.system.service.SysCommonService;
+import com.backendsys.modules.upload.entity.SysFileResult;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 @Service
 public class MediaServiceImpl implements MediaService {
 
     @Autowired
-    private MediaDao mediaDao;
+    private MediaTtvDao mediaTtvDao;
+
+    @Autowired
+    private SysCommonService sysCommonService;
+    @Autowired
+    private TencentCosService tencentCosService;
+    @Autowired
+    private DouyinTosService douyinTosService;
 
     @Autowired
     private BaiduBceMediaService baiduBceMediaService;
 
     /**
-     * 定制成片任务
+     * 生成图文语音视频
      */
     @Override
-    public Map<String, Object> makeGenerateVideoAndInsert(MediaParams mediaParams) throws JsonProcessingException {
-
-        // [远程] 发起定制
-        JSONObject resp = baiduBceMediaService.makeGenerateVideo(mediaParams);
-
-        System.out.println("makeGenerateVideoAndInsert resp:");
-        System.out.println(resp);
-        return null;
-
-//        // 提交定制成功后,将数据插入表;失败则抛出错误
-//
-////        Integer error_code = (Integer) MapUtil.get(resp, "error_code");
-//        Integer error_code = Convert.toInt(MapUtil.get(resp, "error_code"));
-//        if (error_code == null || error_code == 0) {
-//
-//            System.out.println("setJob_id: " + MapUtil.get(resp, "data.jobId"));
-//
-//            mediaParams.setJob_id(Convert.toLong(MapUtil.get(resp, "data.jobId")));
-//            // 数组 转 字符串
-//            String resolutionString = CustomArrayUtil.convertToString(mediaParams.getResolution());
-//            mediaParams.setResolutionString(resolutionString);
-//
-//            System.out.println("insertAiGenerateVideo mediaParams");
-//            System.out.println(mediaParams);
-//            mediaDao.insertAiGenerateVideo(mediaParams);
-//
-////            aiGenerateVideoMapper.insertAiGenerateVideo(mediaParams);
-//        } else {
-//            String error_message = Convert.toStr(MapUtil.get(resp, "error_msg"));
-//            throw new CustException("(" + error_code + ") " + error_message);
-//        }
+    public BaiduBceMediaJob generateMediaTtv(MediaTtv mediaTtv) {
+
+        // 发起任务
+        BaiduBceMediaJob response = baiduBceMediaService.generateMediaTtv(mediaTtv);
+        String job_id = response.getJob_id();
+        if (StrUtil.isNotEmpty(job_id)) {
+            // 记录任务
+            mediaTtv.setJob_id(job_id);
+            mediaTtv.setRequest_params(response.getRequest_params());
+            mediaTtv.setResponse_params(response.getResponse_params());
+            mediaTtvDao.insert(mediaTtv);
+        }
+        return response;
+
+    }
+
+
+    /**
+     * 查询图文语音视频
+     */
+    @Override
+    public MediaTtv queryMediaTtv(MediaTtv mediaTtv) {
+
+        // [Get] 查询是否存在生成记录
+        MediaTtv detail = mediaTtvDao.selectOne(new LambdaQueryWrapper<MediaTtv>().eq(MediaTtv::getJob_id, mediaTtv.getJob_id()));
+        if (detail == null) throw new CustException("任务记录不存在,请重新生成");
+
+        // -- 静态赋值 -------------------------------
+        String request_params_str = detail.getRequest_params();
+        JSONObject request_params = JSONUtil.parseObj(request_params_str);
+
+        // source
+        List<MediaTtvSource> source = new ArrayList<>();
+        JSONObject request_params_source = JSONUtil.parseObj(request_params.get("source"));
+        JSONArray request_params_source_structs = JSONUtil.parseArray(request_params_source.get("structs"));
+        for(Object obj : request_params_source_structs) {
+            System.out.println("obj = " + obj);
+            JSONObject jsonObject = JSONUtil.parseObj(obj);
+            String type = Convert.toStr(jsonObject.get("type"));
+            String content = "";
+            if ("text".equals(type)) content = Convert.toStr(jsonObject.get("text"));
+            if ("image".equals(type)) {
+                JSONObject mediaSource = JSONUtil.parseObj(jsonObject.get("mediaSource"));
+                content = Convert.toStr(mediaSource.get("url"));
+            }
+            MediaTtvSource sourceItem = new MediaTtvSource();
+            sourceItem.setType(type);
+            sourceItem.setContent(content);
+            source.add(sourceItem);
+        }
+        detail.setSource(source);
+
+        // config
+        MediaTtvConfig config = new MediaTtvConfig();
+        JSONObject request_params_config = JSONUtil.parseObj(request_params.get("config"));
+        config.setTts_voice_type(Convert.toInt(request_params_config.get("ttsPer")));
+        config.setResolution(Convert.toIntArray(request_params_config.get("resolution")));
+        detail.setConfig(config);
+        // ---------------------------------------
+
+
+        // 任务状态 (0任务排队中,1任务完成,3任务执行中)
+        Integer job_status = detail.getJob_status();
+        if (job_status != 1) {
+
+            // [百度AI] AI成片-查询结果
+            BaiduBceMediaJobResult response = baiduBceMediaService.queryMediaTtv(mediaTtv.getJob_id());
+
+            // -- 静态赋值 ------------------------
+            // progress: 查询进度
+            // System.out.println("(queryMediaTtv) user_id: " + detail.getUser_id() + ", job_id: " + mediaTtv.getJob_id() + ", progress: " + response.getProgress());
+            detail.setJob_progress(response.getProgress());
+            // ----------------------------------
+
+            if (StrUtil.isNotEmpty(response.getVideo_origin_url())) {
+                String video_url = "";
+                String object_key = "";
+
+                // -- [转存] 将查询结果转存 --------------------------------------
+                Integer UPLOAD_TARGET = Convert.toInt(sysCommonService.getCommonByTag("UPLOAD_TARGET"));
+                // target: 上传目标 (-1:本地, 1:腾讯云, 2:阿里云, 3.抖音云)
+                if (UPLOAD_TARGET == 1) {
+                    SysFileResult sysFileResult = tencentCosService.uploadFileFromUrlToCOS(response.getVideo_origin_url());
+                    object_key = sysFileResult.getKey();
+                    video_url = sysFileResult.getDomain() + "/" + sysFileResult.getKey();
+                }
+                // 3: 抖音云
+                if (UPLOAD_TARGET == 3) {
+
+                }
+                // ------------------------------------------------------------
+
+                // [db] 更新表记录
+                detail.setVideo_origin_url(response.getVideo_origin_url());
+                detail.setVideo_url(video_url);
+                detail.setObject_key(object_key);
+                detail.setJob_status(1);
+                mediaTtvDao.updateById(detail);
+            }
+
+        }
+        return detail;
 
     }
+
 }

+ 64 - 0
src/main/java/com/backendsys/modules/common/utils/CommonUtil.java

@@ -1,9 +1,22 @@
 package com.backendsys.modules.common.utils;
 
 import cn.hutool.core.convert.Convert;
+import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.lang.UUID;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
+import org.springframework.util.StringUtils;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
 public class CommonUtil {
 
     // [文件名] 获得文件后缀名
@@ -22,6 +35,57 @@ public class CommonUtil {
     public static String generateUUIDFilename(MultipartFile multipartFile) {
         return Convert.toStr(UUID.randomUUID()) + getFilenameSuffix(multipartFile, true);
     }
+    public static String generateUUIDFilename(String suffix) {
+        return Convert.toStr(UUID.randomUUID()) + "." + suffix;
+    }
+
+//    // 获取远程文件大小(有问题,暂不可用)
+//    public static long getFileSize(String fileUrl) throws IOException {
+//        HttpResponse response = HttpRequest.head(fileUrl).execute();
+//        if (response.isOk()) {
+//            String contentLength = response.header("Content-Length");
+//            if (StrUtil.isNotEmpty(contentLength)) {
+//                return Long.parseLong(contentLength);
+//            } else {
+//                throw new IOException("无法获取文件大小,响应头中缺少 Content-Length 字段。");
+//            }
+//        } else {
+//            throw new IOException("无法获取文件大小,HTTP 响应码: " + response.getStatus());
+//        }
+//    }
+
+    // 获得URL文件后缀名
+    public static String getFileSuffixFromUrl(String url) {
+        try {
+            // 获得远程 url
+            URL urlObject = new URL(url);
+            // 获得文件名
+            String filename = Paths.get(urlObject.getPath()).getFileName().toString();
+            // 获取文件后缀名
+            String fileSuffix = FileUtil.extName(filename);
+            return fileSuffix;
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    // 下载URL文件到本地
+    public static File downloadLocalFromUrl(String url) {
+        try {
+            // 获取系统默认的临时目录
+            Path tempDirPath = Paths.get(System.getProperty("java.io.tmpdir"));
+            // 下载文件到本地 (可能会有性能问题)
+            HttpUtil.downloadFile(url, tempDirPath.toFile());
+            // 获得远程 url
+            URL urlObject = new URL(url);
+            // 获得文件名
+            String filename = Paths.get(urlObject.getPath()).getFileName().toString();
+            // 获得下载到本地的路径
+            File downloadFile = new File(tempDirPath + File.separator + filename);
+            return downloadFile;
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+    }
 
     // [文件名] 插入 '-thumb' 文件名后缀
     public static String insertThumbSuffix(String filePath) {

+ 0 - 9
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/AiGenerateVideoCustomDTO.java

@@ -1,9 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-@Data
-public class AiGenerateVideoCustomDTO {
-    private SourceDTO source;
-    private ConfigDTO config;
-}

+ 0 - 8
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigBgMusicDTO.java

@@ -1,8 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-@Data
-public class ConfigBgMusicDTO {
-    private MediaSourceVO mediaSource;
-}

+ 0 - 12
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigCaptionDTO.java

@@ -1,12 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-@Data
-public class ConfigCaptionDTO {
-    private Integer marginBottom;
-    private String fontColor;
-    private Integer fontAlpha;
-    private String bgColor;
-    private Integer bgAlpha;
-}

+ 0 - 18
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigDTO.java

@@ -1,18 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-@Data
-public class ConfigDTO {
-    private Integer[] resolution;
-    private String productType;
-    private Integer ttsPer;
-    private String digitalHumanId;
-    private String mediaLibs;
-
-    private ConfigBgMusicDTO bgMusic;
-    private ConfigVideoBeginDTO videoBegin;
-    private ConfigVideoEndDTO videoEnd;
-    private ConfigVideoLogoDTO videoLogo;
-
-}

+ 0 - 8
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigVideoBeginDTO.java

@@ -1,8 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-@Data
-public class ConfigVideoBeginDTO {
-    private MediaSourceVO mediaSource;
-}

+ 0 - 8
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigVideoEndDTO.java

@@ -1,8 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-@Data
-public class ConfigVideoEndDTO {
-    private MediaSourceVO mediaSource;
-}

+ 0 - 11
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/ConfigVideoLogoDTO.java

@@ -1,11 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-@Data
-public class ConfigVideoLogoDTO {
-    private MediaSourceVO mediaSource;
-
-    private String location;
-    private Integer margin;
-}

+ 0 - 9
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/MediaSourceVO.java

@@ -1,9 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-@Data
-public class MediaSourceVO {
-    private Integer type;
-    private String url;
-}

+ 0 - 10
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/SourceDTO.java

@@ -1,10 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-public class SourceDTO {
-    private List<SourceStructDTO> structs;
-}

+ 0 - 10
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/AiGenerateVideoCustom/SourceStructDTO.java

@@ -1,10 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom;
-
-import lombok.Data;
-
-@Data
-public class SourceStructDTO {
-    private String type;
-    private String text;
-    private MediaSourceVO mediaSource;
-}

+ 11 - 0
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/BaiduBceMediaJob.java

@@ -0,0 +1,11 @@
+package com.backendsys.modules.sdk.baidu.bce.entity;
+
+import lombok.Data;
+
+@Data
+public class BaiduBceMediaJob {
+    private String job_id;
+    private String log_id;
+    private String request_params;
+    private String response_params;
+}

+ 12 - 0
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/BaiduBceMediaJobResult.java

@@ -0,0 +1,12 @@
+package com.backendsys.modules.sdk.baidu.bce.entity;
+
+import lombok.Data;
+
+@Data
+public class BaiduBceMediaJobResult {
+    private String job_id;
+    private Float progress;
+    private String video_origin_url;
+    private String video_url;
+    private String response_params;
+}

+ 0 - 11
src/main/java/com/backendsys/modules/sdk/baidu/bce/entity/MediaMaterialResponse.java

@@ -1,11 +0,0 @@
-package com.backendsys.modules.sdk.baidu.bce.entity;
-
-import com.backendsys.entity.Ai.AiGenerateVideoCustom.ConfigDTO;
-import com.backendsys.entity.Ai.AiGenerateVideoCustom.SourceDTO;
-import lombok.Data;
-
-@Data
-public class MediaMaterialResponse {
-    private SourceDTO source;
-    private ConfigDTO config;
-}

+ 7 - 14
src/main/java/com/backendsys/modules/sdk/baidu/bce/service/BaiduBceMediaService.java

@@ -1,19 +1,12 @@
 package com.backendsys.modules.sdk.baidu.bce.service;
 
-import cn.hutool.json.JSONObject;
-import com.backendsys.modules.ai.media.entity.MediaParams.MediaParams;
-import com.fasterxml.jackson.core.JsonProcessingException;
-
-import java.util.Map;
+import com.backendsys.modules.ai.media.entity.MediaTtv;
+import com.backendsys.modules.sdk.baidu.bce.entity.BaiduBceMediaJob;
+import com.backendsys.modules.sdk.baidu.bce.entity.BaiduBceMediaJobResult;
 
 public interface BaiduBceMediaService {
-
-    // [百度-AI成片] 定制成片任务
-    JSONObject makeGenerateVideo(MediaParams mediaParams) throws JsonProcessingException;
-    // [百度-AI成片] 查询成片任务进度
-    Map<String, Object> getGenerateVideoProgress(Long jobId);
-
-
-
-
+    // [百度AI] AI成片-图文转视频
+    BaiduBceMediaJob generateMediaTtv(MediaTtv mediaTtv);
+    // [百度AI] AI成片-查询结果
+    BaiduBceMediaJobResult queryMediaTtv(String job_id);
 }

+ 140 - 205
src/main/java/com/backendsys/modules/sdk/baidu/bce/service/impl/BaiduBceMediaServiceImpl.java

@@ -1,28 +1,22 @@
 package com.backendsys.modules.sdk.baidu.bce.service.impl;
 
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.convert.Convert;
 import cn.hutool.http.HttpUtil;
-import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
-import com.backendsys.modules.ai.media.entity.AiGenerateVideoDTO;
-import com.backendsys.modules.ai.media.entity.MediaParams.MediaParams;
-import com.backendsys.modules.sdk.baidu.bce.entity.AiGenerateVideoCustom.*;
+import com.backendsys.exception.CustException;
+import com.backendsys.modules.ai.media.entity.MediaTtv;
+import com.backendsys.modules.ai.media.entity.MediaTtvConfig;
+import com.backendsys.modules.ai.media.entity.MediaTtvSource;
+import com.backendsys.modules.sdk.baidu.bce.entity.BaiduBceMediaJob;
+import com.backendsys.modules.sdk.baidu.bce.entity.BaiduBceMediaJobResult;
 import com.backendsys.modules.sdk.baidu.bce.service.BaiduBceMediaService;
 import com.backendsys.modules.sdk.baidu.bce.utils.BaiduBceUtil;
-import com.backendsys.utils.CustomArrayUtil;
-import com.fasterxml.jackson.core.JsonProcessingException;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.ParameterizedTypeReference;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.MediaType;
 import org.springframework.stereotype.Service;
-import org.springframework.web.reactive.function.client.WebClient;
 
-import java.net.URI;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
 
 
 /**
@@ -35,138 +29,50 @@ public class BaiduBceMediaServiceImpl implements BaiduBceMediaService {
     @Autowired
     private BaiduBceUtil baiduBceUtil;
 
-
-    // [百度-AI成片] 封装拼接授权过的 AccessToken URL
-    private URI getUriWithParams(String url) {
-        return null;
-    }
-
-    /**
-     * [方法] 将接口入参 (AiGenerateVideoDTO) 转换为 符合SDK接口的格式 (AiGenerateVideoDTOResponse)
-     */
-    private AiGenerateVideoCustomDTO formatCustom(AiGenerateVideoDTO aiGenerateVideoDTO) {
-
-        System.out.println("----------------------------------");
-        System.out.println(aiGenerateVideoDTO);
-
-        AiGenerateVideoCustomDTO customDTO = new AiGenerateVideoCustomDTO();
-        SourceDTO sourceDTO = new SourceDTO();
-        ConfigDTO configDTO = new ConfigDTO();
-
-        // -- source ------------------------------------------------------------
-        String source = aiGenerateVideoDTO.getSource();
-        // \"structs\":[{\"type\":\"text\",\"text\":\"夕阳如红色绸带轻轻拂过天际,悄然间,大地沐浴在金色的温柔中。\"},{\"type\":\"image\",\"mediaSource\":{\"type\":3,\"url\":\"http://dev.manage.daoguyujia.com/assets/p1.jpg\"}}]
-        JSONObject sourceJSON = JSONUtil.parseObj(source);
-        JSONArray structs = (JSONArray) sourceJSON.get("structs");
-
-        List<SourceStructDTO> StructList = new ArrayList<>();
-        for (int i=0; i < structs.size(); i++) {
-            SourceStructDTO sourceStructDTO = new SourceStructDTO();
-            //
-            JSONObject obj = structs.getJSONObject(i);
-            String type = (String) obj.get("type");
-            sourceStructDTO.setType(type);
-            if (type.equals("text")) {
-                String text = (String) obj.get("text");
-                sourceStructDTO.setText(text);
+    /*
+        数据格式转化:
+        {\"type\":\"image\",\"mediaSource\":{\"type\":3,\"url\":\"" + imageUrl + "\"}},
+        {"\"type\":\"text\",\"text\":\"" + text + "\"}
+    */
+    private String sourceToParams(List<MediaTtvSource> sourceList) {
+        AtomicReference<String> sourceStr = new AtomicReference<>("[");
+        for (int i = 0; i < sourceList.size(); i++) {
+            String item = "";
+            if ("text".equals(sourceList.get(i).getType())) {
+                item = "{\"type\":\"text\",\"text\":\"" + sourceList.get(i).getContent() + "\"}";
             }
-            if (type.equals("image")) {
-                MediaSourceVO mediaSourceVO = new MediaSourceVO();
-                JSONObject mediaSourceObj = (JSONObject) obj.get("mediaSource");
-                mediaSourceVO.setType(3);
-                mediaSourceVO.setUrl((String) mediaSourceObj.get("url"));
-
-                sourceStructDTO.setMediaSource(mediaSourceVO);
+            if ("image".equals(sourceList.get(i).getType())) {
+                item = "{\"type\":\"image\",\"mediaSource\":{\"type\":3,\"url\":\"" + sourceList.get(i).getContent() + "\"}}";
             }
-            //
-            StructList.add(sourceStructDTO);
-        }
-        // -------------------------------------------------------------------------
-        sourceDTO.setStructs(StructList);
-        // -------------------------------------------------------------------------
-        customDTO.setSource(sourceDTO);
-        // -------------------------------------------------------------------------
-
-        // -- config ---------------------------------------------------------------
-        configDTO.setResolution(aiGenerateVideoDTO.getResolution());
-        configDTO.setProductType(aiGenerateVideoDTO.getProduct_type());
-        configDTO.setTtsPer(aiGenerateVideoDTO.getTts_per());
-        // -------------------------------------------------------------------------
-        // -- config.bgMusic.mediaSource (背景图) -----------------------------------
-        String bg_music_url = aiGenerateVideoDTO.getBg_music_url();
-        if (StrUtil.isNotBlank(bg_music_url)) {
-            ConfigBgMusicDTO bgMusicDTO = new ConfigBgMusicDTO();
-
-            MediaSourceVO mediaSourceVO = new MediaSourceVO();
-            mediaSourceVO.setType(3);
-            mediaSourceVO.setUrl(bg_music_url);
-            bgMusicDTO.setMediaSource(mediaSourceVO);
-
-            configDTO.setBgMusic(bgMusicDTO);
-        }
-        // -------------------------------------------------------------------------
-        // -- config.videoBegin.mediaSource (片头) ----------------------------------
-        String video_begin_url = aiGenerateVideoDTO.getVideo_begin_url();
-        if (StrUtil.isNotBlank(video_begin_url)) {
-            ConfigVideoBeginDTO videoBeginDTO = new ConfigVideoBeginDTO();
-
-            MediaSourceVO mediaSourceVO = new MediaSourceVO();
-            mediaSourceVO.setType(3);
-            mediaSourceVO.setUrl(video_begin_url);
-            videoBeginDTO.setMediaSource(mediaSourceVO);
-
-            configDTO.setVideoBegin(videoBeginDTO);
-        }
-        // -------------------------------------------------------------------------
-        // -- config.videoEnd.mediaSource (片尾) ------------------------------------
-        String video_end_url = aiGenerateVideoDTO.getVideo_end_url();
-        if (StrUtil.isNotBlank(video_end_url)) {
-            ConfigVideoEndDTO videoEndDTO = new ConfigVideoEndDTO();
-
-            MediaSourceVO mediaSourceVO = new MediaSourceVO();
-            mediaSourceVO.setType(3);
-            mediaSourceVO.setUrl(video_end_url);
-            videoEndDTO.setMediaSource(mediaSourceVO);
-
-            configDTO.setVideoEnd(videoEndDTO);
+            if (i < sourceList.size() - 1) item += ",";
+            sourceStr.set(sourceStr.get() + item);
         }
-        // -------------------------------------------------------------------------
-        // -- config.videoLogo (LOGO) ----------------------------------------------
-        String video_logo_url = aiGenerateVideoDTO.getVideo_logo_url();
-        if (StrUtil.isNotBlank(video_logo_url)) {
-            ConfigVideoLogoDTO videoLogoDTO = new ConfigVideoLogoDTO();
-
-            MediaSourceVO mediaSourceVO = new MediaSourceVO();
-            mediaSourceVO.setType(3);
-            mediaSourceVO.setUrl(video_logo_url);
-            videoLogoDTO.setMediaSource(mediaSourceVO);
-
-            String video_logo_location = aiGenerateVideoDTO.getVideo_logo_location();
-            Integer video_logo_margin = aiGenerateVideoDTO.getVideo_logo_margin();
-            if (StrUtil.isNotBlank(video_logo_location)) {
-                videoLogoDTO.setLocation(video_logo_location);
-            }
-            if (video_logo_margin != null) {
-                videoLogoDTO.setMargin(video_logo_margin);
-            }
-            configDTO.setVideoLogo(videoLogoDTO);
-        }
-        // -------------------------------------------------------------------------
-        System.out.println("configDTO:");
-        System.out.println(configDTO);
-
-        customDTO.setConfig(configDTO);
-        // -------------------------------------------------------------------------
-
-        return customDTO;
+        sourceStr.set(sourceStr.get() + "]");
+        return sourceStr.get();
     }
 
     /**
-     * [百度-AI成片] 定制成片任务
+     * [百度AI] AI成片-图文转视频
      * https://ai.baidu.com/ai-doc/NLP/Zk7ylspjv
      */
     @Override
-    public JSONObject makeGenerateVideo(MediaParams mediaParams) throws JsonProcessingException {
+    public BaiduBceMediaJob generateMediaTtv(MediaTtv mediaTtv) {
+
+        /*
+            入参模板:
+            mediaTtv: {
+                "title": "测试百度AI成片 (图片+文生语音配音)",
+                "source": [
+                    { "type": "text", "content": "云渺修仙历经千年,实力超凡,却因身世之谜未解,毅然成为摆渡人。" },
+                    { "type": "image", "content": "http://43.138.151.228:3001/2cut_compress.png" }
+                ],
+                "config": {
+                    "tts_voice_type": 4144,
+                    "resolution": [1024, 576]
+                }
+            }
+        */
+
 
 //        // structs: 文本、图片素材内容,文字内容必填,structs中文本总长度在20-800字符之间
 //        // mediaSource: 若内容类型type=image,该字段描述图片内容,支持jpg/jpeg/png格式的图片
@@ -175,58 +81,65 @@ public class BaiduBceMediaServiceImpl implements BaiduBceMediaService {
 //        // 传入图片、视频的url地址,图片、视频总数量不得超过20个,视频总大小不超过1G
 //        String text = "夕阳如红色绸带轻轻拂过天际,悄然间,大地沐浴在金色的温柔中。";      // 若内容类型type=text,该字段描述文本内容
 
-        String source = mediaParams.getSource();
-
-        // config: 视频生产配置
-        String productType = mediaParams.getProduct_type();
-        Integer ttsPer = mediaParams.getTts_per();
-        String resolution = CustomArrayUtil.convertToString(mediaParams.getResolution());
+//        String source = mediaTtv.getSource();
 
-//        String productType = "video";       // 视频产出结果形式,支持产出为mp4和json格式。可选项为video、timeline。video: 产出结果为mp4视频;timeline: 产出结果为json时间轴信息;
+//        // config: 视频生产配置
 //        Integer ttsPer = 4144;                // 支持基础音库、甄选音库,默认4144:度姗姗-女;【基础音库】0:度小美-女、1:度小宇-男、3:度小云-男、4:度小丫-女童、5:度小娇-女、103:度小朵-女童、106:度小博-男、110:度小童-男童、111:度小萌-女、5003:度小遥-男、5118:度小婷-女、4003:度小耀-男、4100:度小雯-女、4103:度小米-男童、4105:度小灵-女、4106:度小文-男、4115:度小贤-男、4117:度小乔-女、4119:度小鹿-女;【甄选音库】4144:度姗姗-女、4140:度小新-女、4143:度清风-男、4129:度小彦-男、4278:度小贝-女、4254:度小清-女、4149:度星河-男
-//        String resolution = "[1024,576]";   // 分辨率,横屏支持[1920,1080]、[1280,720]、[1024,576]、竖屏支持[1080,1920]、[720,1280]、[576,1024]
+//        String resolution = "[1024,576]";     // 分辨率,横屏支持[1920,1080]、[1280,720]、[1024,576]、竖屏支持[1080,1920]、[720,1280]、[576,1024]
 
-        String templateId = "";             // 视频模板id,不传则智能匹配,横屏模板支持:"30","41","42","43","44","45","46","47","48","49",竖屏模板支持:"40","28","29","31","32","33","34","35","36","37","38","39","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70","71"
 
-        // bgMusic: 背景音乐,支持使用mp3格式,文件大小不超过10M
-        String bgMusicUrl = "";
-        // videoBegin: 视频片头,大小限制50M,格式为mp4或mov
-        String videoBeginUrl = "";
-        String videoEndUrl = "";
 
-        // caption: 字幕显示设置
-        String marginBottom = "170px";  // 字幕距离视频底部的位置,单位px,支持选择0-500。横屏默认值为70px;竖屏[1080,1920]默认为270px、[720,1280]默认为180px、[576,1024]默认为170px
-        String fontColor = "ffffff";    // 字体颜色,支持传入颜色的十六进制,默认:ffffff
-        Integer fontAlpha = 100;        // 字体透明度,范围:0-100,从透明到不透明,默认:100
-        String bgColor = "927070";      // 字幕背景颜色,支持传入颜色的十六进制,默认:927070
-        Integer bgAlpha = 32;           // 字幕背景透明度,范围:0-100,从透明到不透明,默认32
+//        String templateId = "";         // 视频模板id,不传则智能匹配,横屏模板支持:"30","41","42","43","44","45","46","47","48","49",竖屏模板支持:"40","28","29","31","32","33","34","35","36","37","38","39","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70","71"
+//
+//        // bgMusic: 背景音乐,支持使用mp3格式,文件大小不超过10M
+//        String bgMusicUrl = "";
+//        String videoBeginUrl = "";  // videoBegin: 视频片头,大小限制50M,格式为mp4或mov
+//        String videoEndUrl = "";
+//
+//        // caption: 字幕显示设置
+//        String marginBottom = "170px";  // 字幕距离视频底部的位置,单位px,支持选择0-500。横屏默认值为70px;竖屏[1080,1920]默认为270px、[720,1280]默认为180px、[576,1024]默认为170px
+//        String fontColor = "ffffff";    // 字体颜色,支持传入颜色的十六进制,默认:ffffff
+//        Integer fontAlpha = 100;        // 字体透明度,范围:0-100,从透明到不透明,默认:100
+//        String bgColor = "927070";      // 字幕背景颜色,支持传入颜色的十六进制,默认:927070
+//        Integer bgAlpha = 32;           // 字幕背景透明度,范围:0-100,从透明到不透明,默认32
+//
+//        String location = "";           // 角标位置,支持:top-left(左上)、top-right(右上),默认为 top-left
+//        Integer margin = 20;            // 角标边缘距离,单位px,支持0-100,默认为 20
+
+
+
+        String structs = sourceToParams(mediaTtv.getSource());
+        MediaTtvConfig config = mediaTtv.getConfig();
+
+        Integer ttsPer = config.getTts_voice_type();
+        if (ttsPer == null) throw new CustException("音色参数不能为空");
+
+
+
+        Integer[] resolution = config.getResolution();
+        if (resolution == null) throw new CustException("分辨率参数不能为空");
+        if (resolution.length != 2) throw new CustException("分辨率参数格式不正确,必须是:[数值,数值]");
+        // 定义支持的分辨率列表
+        List<Integer[]> supportedResolutions = Arrays.asList(
+            new Integer[]{1920, 1080}, new Integer[]{1280, 720}, new Integer[]{1024, 576},
+            new Integer[]{1080, 1920}, new Integer[]{720, 1280}, new Integer[]{576, 1024}
+        );
+        Boolean resolutionValid = false;
+        for (Integer[] supportedResolution : supportedResolutions) {
+            if (Arrays.equals(resolution, supportedResolution)) {
+                resolutionValid = true;
+            }
+        }
+        if (!resolutionValid) throw new CustException("分辨率参数格式不支持,必须是:横屏[1920,1080]、[1280,720]、[1024,576],竖屏[1080,1920]、[720,1280]、[576,1024]");
+
 
-        String location = "";           // 角标位置,支持:top-left(左上)、top-right(右上),默认为 top-left
-        Integer margin = 20;            // 角标边缘距离,单位px,支持0-100,默认为 20
 
         String params = "{" +
-            "\"source\":" + source + "," +
-//            "\"source\":{" +
-//                "\"structs\":[" +
-//                    "{" +
-//                        "\"type\":\"image\"," +
-//                        "\"mediaSource\":{" +
-//                            "\"type\":3," +
-//                            "\"url\":\"" + imageUrl + "\"" +
-//                        "}" +
-//                    "}," +
-//                    "{" +
-//                        "\"type\":\"text\"," +
-//                        "\"text\":\"" + text + "\"" +
-//                    "}" +
-//                "]" +
-//            "}," +
+            "\"source\":{\"structs\":" + structs + "}," +
             "\"config\":{" +
-                "\"productType\":\"" + productType + "\"," +
+                "\"productType\":\"video\"," +
                 "\"ttsPer\":" + ttsPer + "," +
-                "\"resolution\":" + resolution + "" +
-
-//                "\"resolution\":" + resolution + "," +
+                "\"resolution\":[" + resolution[0] + "," + resolution[1] + "]" +
 //                "\"templateId\":\"" + templateId + "\"" +
 //                "\"bgMusic\":{" +
 //                    "\"mediaSource\":{" +
@@ -264,39 +177,61 @@ public class BaiduBceMediaServiceImpl implements BaiduBceMediaService {
             "}" +
         "}";
 
-        System.out.println("-------------------------------------------");
+        System.out.println("-- [百度AI] AI成片-图文转视频 (Params) -----");
         System.out.println(params);
-        System.out.println("-------------------------------------------");
+        System.out.println("-----------------------------------------");
 
         String access_token = baiduBceUtil.getAccessToken();
-        String result = HttpUtil.post("https://aip.baidubce.com/rpc/2.0/brain/creative/ttv/material?access_token=" + access_token, params);
-        JSONObject resultJSON = JSONUtil.parseObj(result);
-        return resultJSON;
+        String response = HttpUtil.post("https://aip.baidubce.com/rpc/2.0/brain/creative/ttv/material?access_token=" + access_token, params);
+        JSONObject responseJSON = JSONUtil.parseObj(response);
+        if (responseJSON.get("error_code") != null) throw new CustException(Convert.toStr(responseJSON.get("error_msg")));
+
+        JSONObject data = JSONUtil.parseObj(responseJSON.get("data"));
+        /*
+            {
+                "data": {
+                    "jobId": 1914625923861756991,
+                    "id": "1914625923861756991"
+                },
+                "log_id": 1914625923861756991
+            }
+         */
+        BaiduBceMediaJob job = new BaiduBceMediaJob();
+        job.setJob_id(Convert.toStr(data.get("jobId")));
+        job.setLog_id(Convert.toStr(responseJSON.get("log_id")));
+        job.setRequest_params(params);
+        job.setResponse_params(response);
+        return job;
     }
 
+
     /**
-     * [百度-AI成片] 查询成片任务进度
+     * [百度AI] AI成片-查询结果
      */
     @Override
-    public Map<String, Object> getGenerateVideoProgress(Long jobId) {
-        // Body 参数
-        Map<String, Object> resultMap = new LinkedHashMap<>();
-        resultMap.put("jobId", jobId);
-        String bodyData = JSONUtil.toJsonStr(resultMap);
-
-        // Http 远程调用
-        URI uriWithParams = getUriWithParams("https://aip.baidubce.com/rpc/2.0/brain/creative/ttv/query");
-        Map<String, Object> resp = WebClient.create()
-                .method(HttpMethod.POST)
-                .uri(uriWithParams)
-                .bodyValue(bodyData.toString())
-                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
-                })
-                .block();
-
-        System.out.println("getGenerateVideoProgress resp:");
-        System.out.println(resp);
-        return resp;
+    public BaiduBceMediaJobResult queryMediaTtv(String job_id) {
+
+        String params = "{\"jobId\":\"" +  job_id + "\"}";
+
+        // [Post] 查询结果
+        String access_token = baiduBceUtil.getAccessToken();
+        String response = HttpUtil.post("https://aip.baidubce.com/rpc/2.0/brain/creative/ttv/query?access_token=" + access_token, params);
+        JSONObject responseJSON = JSONUtil.parseObj(response);
+
+        // 检查返回值状态
+        Integer error_code = Convert.toInt(responseJSON.get("error_code"));
+        if (error_code != 0) throw new CustException(Convert.toStr(responseJSON.get("error_msg")));
+
+        // 出参
+        JSONObject data = JSONUtil.parseObj(responseJSON.get("data"));
+        BaiduBceMediaJobResult result = new BaiduBceMediaJobResult();
+        result.setJob_id(job_id);
+        Float progress = (data.get("progress") != null) ? Convert.toFloat(data.get("progress")) : 1;
+        result.setProgress(progress);
+        result.setVideo_origin_url(Convert.toStr(data.get("videoAddr")));
+        result.setVideo_url("");
+        result.setResponse_params(response);
+        return result;
     }
+
 }

+ 4 - 0
src/main/java/com/backendsys/modules/sdk/douyincloud/tos/service/DouyinTosService.java

@@ -33,4 +33,8 @@ public interface DouyinTosService {
 
     // [抖音云TOS] 查询已上传的分块
     List<ListPartsOutput> listParts(String upload_id, String object_key);
+
+
+    // [抖音云TOS] URL 转存
+    SysFileResult uploadFileFromUrlToCOS(String url);
 }

+ 14 - 0
src/main/java/com/backendsys/modules/sdk/douyincloud/tos/service/impl/DouyinTosServiceImpl.java

@@ -354,4 +354,18 @@ public class DouyinTosServiceImpl implements DouyinTosService {
 
     }
 
+
+    /**
+     * [抖音云TOS] URL 转存
+     */
+    public SysFileResult uploadFileFromUrlToCOS(String url) {
+//        try {
+
+            if (StrUtil.isEmpty(url)) throw new CustException("url 不能为空");
+
+//        } catch (IOException e) {
+//            throw new CustException(e.getMessage());
+//        }
+        return null;
+    }
 }

+ 7 - 2
src/main/java/com/backendsys/modules/sdk/tencentcloud/cos/service/TencentCosService.java

@@ -7,6 +7,7 @@ import org.springframework.web.multipart.MultipartFile;
 import java.io.IOException;
 import java.net.URL;
 import java.util.List;
+import java.util.Map;
 
 public interface TencentCosService {
 
@@ -15,12 +16,12 @@ public interface TencentCosService {
     // [腾讯云COS] 删除对象
     void deleteObject(String object_key);
 
-
 //    // [腾讯云COS] 批量删除对象
 //    void deleteObjects(String object_keys);
+
     // [腾讯云COS] 查询对象是否存在
     boolean doesObjectExist(String object_key);
-    // [腾讯云COS] 获得临时图片地址
+    // [腾讯云COS] 生成临时图片地址
     URL generateUrl(String object_key, Integer minutes);
 
 
@@ -33,4 +34,8 @@ public interface TencentCosService {
 
     // [腾讯云COS] 查询已上传的分块
     PartListing listParts(String upload_id, String object_key);
+
+
+    // [腾讯云COS] URL 转存
+    SysFileResult uploadFileFromUrlToCOS(String url);
 }

+ 58 - 1
src/main/java/com/backendsys/modules/sdk/tencentcloud/cos/service/impl/TencentCosServiceImpl.java

@@ -3,6 +3,7 @@ package com.backendsys.modules.sdk.tencentcloud.cos.service.impl;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
 import com.backendsys.exception.CustException;
 import com.backendsys.modules.common.config.security.utils.SecurityUtil;
 import com.backendsys.modules.common.utils.CommonUtil;
@@ -30,14 +31,18 @@ import org.joda.time.DateTime;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.*;
 import java.math.BigDecimal;
 import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 // 图片处理概述
 // https://cloud.tencent.com/document/product/436/42215
@@ -226,7 +231,7 @@ public class TencentCosServiceImpl implements TencentCosService {
 //    }
 
 
-    // [腾讯云COS] 获得临时图片地址
+    // [腾讯云COS] 生成临时图片地址
     @Override
     public URL generateUrl(String object_key, Integer minutes) {
         // 生成临时访问的URL (15分钟)
@@ -356,5 +361,57 @@ public class TencentCosServiceImpl implements TencentCosService {
     }
 
 
+    // [腾讯云COS] URL 转存
+    @Override
+    public SysFileResult uploadFileFromUrlToCOS(String url) {
+
+        if (StrUtil.isEmpty(url)) throw new CustException("url 不能为空");
+
+        // 下载URL文件到本地
+        File downloadFile = CommonUtil.downloadLocalFromUrl(url);
+        // 获得URL文件后缀名
+        String suffix = CommonUtil.getFileSuffixFromUrl(url);
+
+
+        // 使用临时文件夹 (/temp) + UUID文件名.后缀名
+        String object_filename = CommonUtil.generateUUIDFilename(suffix);
+        String object_key = "temp/" + object_filename;
+        System.out.println("initiateMultipartUpload object: " + object_key);
+
+        InputStream inputStream = null;
+        COSClient cosClient = getClient();
+        try{
+
+            PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, object_key, downloadFile);
+            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
+            System.out.println("putObjectResult: " + putObjectResult.toString());
+
+            // 高级上传
+            TransferManager transferManager = TencentCosUtil.createTransferManager(cosClient);
+            Upload upload = transferManager.upload(putObjectRequest);   // 返回一个异步结果Upload
+            showTransferProgress(object_filename, upload);                     // 查询上传进度,直到上传结束
+            UploadResult uploadResult = upload.waitForUploadResult();   // 捕获可能出现的异常
+
+            SysFileResult result = new SysFileResult();
+            result.setDomain(ACCESSIBLE_DOMAIN);
+            result.setKey(object_key);
+            result.setRequest_id(uploadResult.getRequestId());
+            result.setE_tag(uploadResult.getETag());
+            return result;
 
+        } catch (CosClientException e) {
+            throw new CustException(e.getMessage());
+        } catch (InterruptedException e) {
+            throw new CustException(e.getMessage());
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    // 忽略关闭流时的异常
+                }
+            }
+            if (cosClient != null) cosClient.shutdown();
+        }
+    }
 }

+ 1 - 1
src/main/java/com/backendsys/service/SDKService/SDKBaidu/SDKBaiduAiGenerateVideoServiceImpl.java

@@ -77,7 +77,7 @@ public class SDKBaiduAiGenerateVideoServiceImpl implements SDKBaiduAiGenerateVid
 
 
     /**
-     * [方法] 将接口入参 (MediaParams) 转换为 符合SDK接口的格式 (MediaMaterialResponse)
+     * [方法] 将接口入参 (MediaTtv) 转换为 符合SDK接口的格式 (BaiduBceMediaJob)
      */
     private AiGenerateVideoCustomDTO formatCustom(AiGenerateVideoDTO aiGenerateVideoDTO) {
 

+ 0 - 125
src/main/resources/mapper/ai/media/MediaMapper.xml

@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
-<mapper namespace="com.backendsys.modules.ai.media.dao.MediaDao">
-
-    <sql id="includeAiGenerateVideo">
-        id,
-        user_id,
-        job_id,
-        title,
-        source,
-        resolution,
-        product_type,
-        COALESCE(tts_per, '') tts_per,
-        COALESCE(bg_music_url, '') bg_music_url,
-        COALESCE(video_begin_url, '') video_begin_url,
-        COALESCE(video_end_url, '') video_end_url,
-        COALESCE(video_logo_url, '') video_logo_url,
-        COALESCE(video_logo_location, '') video_logo_location,
-        COALESCE(video_logo_margin, '') video_logo_margin,
-        COALESCE(job_status, '') job_status,
-        COALESCE(result_video_url, '') result_video_url,
-        COALESCE(result_points, '') result_points,
-        COALESCE(result_basic_duration, '') result_basic_duration,
-        COALESCE(result_fail_reason, '') result_fail_reason,
-        create_time,
-        update_time
-    </sql>
-
-    <resultMap id="resultMapAiGenerateVideo" type="java.util.LinkedHashMap">
-        <id property="id" column="id" jdbcType="BIGINT" />
-        <result property="user_id" column="user_id" javaType="java.lang.Long" />
-        <result property="job_id" column="job_id" />
-        <result property="title" column="title" />
-        <result property="source" column="source" />
-        <result property="resolution" column="resolution" />
-        <result property="product_type" column="product_type" />
-        <result property="tts_per" column="tts_per" />
-        <result property="bg_music_url" column="bg_music_url" />
-        <result property="video_begin_url" column="video_begin_url" />
-        <result property="video_end_url" column="video_end_url" />
-        <result property="video_logo_url" column="video_logo_url" />
-        <result property="video_logo_location" column="video_logo_location" />
-        <result property="video_logo_margin" column="video_logo_margin" />
-        <result property="job_status" column="job_status" javaType="java.lang.Integer" />
-        <result property="result_video_url" column="result_video_url" />
-        <result property="result_points" column="result_points" />
-        <result property="result_basic_duration" column="result_basic_duration" />
-        <result property="result_fail_reason" column="result_fail_reason" />
-        <result property="create_time" column="create_time" />
-        <result property="update_time" column="update_time" />
-    </resultMap>
-
-    <!-- 列表 -->
-    <select id="queryAiGenerateVideoList" resultMap="resultMapAiGenerateVideo">
-        SELECT <include refid="includeAiGenerateVideo" />
-        FROM ai_generate_video_task
-        <where>
-            user_id = #{user_id}
-            <if test="job_id != null and job_id != ''">
-                AND job_id = #{job_id}
-            </if>
-            <if test="title != null and title != ''">
-                AND title LIKE CONCAT('%', #{title}, '%')
-            </if>
-            <if test="product_type != null and product_type != ''">
-                AND product_type = #{product_type}
-            </if>
-            <if test="job_status != null and job_status != ''">
-                AND job_status = #{job_status}
-            </if>
-        </where>
-        ORDER BY create_time DESC
-    </select>
-
-    <!-- 详情 -->
-    <select id="queryAiGenerateVideoDetail" resultMap="resultMapAiGenerateVideo">
-        SELECT <include refid="includeAiGenerateVideo" />
-        FROM ai_generate_video_task
-        WHERE job_id = #{job_id} AND user_id = #{user_id}
-    </select>
-
-    <!-- 插入 -->
-    <insert id="insertAiGenerateVideo" parameterType="com.backendsys.entity.Ai.AiGenerateVideoDTO"
-        useGeneratedKeys="true" keyProperty="job_id">
-        INSERT INTO ai_generate_video_task (
-            user_id, job_id, title, source, product_type, resolution
-            <if test="tts_per != null and tts_per != ''">, tts_per</if>
-            <if test="bg_music_url != null and bg_music_url != ''">, bg_music_url</if>
-            <if test="video_begin_url != null and video_begin_url != ''">, video_begin_url</if>
-            <if test="video_end_url != null and video_end_url != ''">, video_end_url</if>
-            <if test="video_logo_url != null and video_logo_url != ''">, video_logo_url</if>
-            <if test="video_logo_location != null and video_logo_location != ''">, video_logo_location</if>
-            <if test="video_logo_margin != null and video_logo_margin != ''">, video_logo_margin</if>
-            <if test="job_status != null and job_status != ''">, job_status</if>
-        )
-        VALUES (
-            #{user_id}, #{job_id}, #{title}, #{source}, #{product_type}, #{resolutionString}
-            <if test="tts_per != null and tts_per != ''">, #{tts_per}</if>
-            <if test="bg_music_url != null and bg_music_url != ''">, #{bg_music_url}</if>
-            <if test="video_begin_url != null and video_begin_url != ''">, #{video_begin_url}</if>
-            <if test="video_end_url != null and video_end_url != ''">, #{video_end_url}</if>
-            <if test="video_logo_url != null and video_logo_url != ''">, #{video_logo_url}</if>
-            <if test="video_logo_location != null and video_logo_location != ''">, #{video_logo_location}</if>
-            <if test="video_logo_margin != null and video_logo_margin != ''">, #{video_logo_margin}</if>
-            <if test="job_status != null and job_status != ''">, #{job_status}</if>
-        )
-    </insert>
-
-    <!-- 更新 -->
-    <update id="updateAiGenerateVideo" parameterType="com.backendsys.entity.Ai.AiGenerateVideoDTO"
-        useGeneratedKeys="true" keyProperty="job_id">
-        UPDATE ai_generate_video_task
-        SET job_status = #{job_status}
-            <if test="result_video_url != null and result_video_url != ''">, result_video_url = #{result_video_url}</if>
-            <if test="result_points != null and result_points != ''">, result_points = #{result_points}</if>
-            <if test="result_basic_duration != null and result_basic_duration != ''">, result_basic_duration = #{result_basic_duration}</if>
-            <if test="result_fail_reason != null and result_fail_reason != ''">, result_fail_reason = #{result_fail_reason}</if>
-        WHERE job_id = #{job_id} AND user_id = #{user_id}
-    </update>
-
-    <delete id="deleteAiGenerateVideo">
-        DELETE FROM ai_generate_video_task WHERE job_id = #{job_id} AND user_id = #{user_id}
-    </delete>
-
-</mapper>

+ 105 - 0
src/main/resources/mapper/ai/media/MediaTtvMapper.xml

@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.backendsys.modules.ai.media.dao.MediaTtvDao">
+
+<!--    <sql id="includeAiGenerateVideo">-->
+<!--        id,-->
+<!--        user_id,-->
+<!--        job_id,-->
+<!--        job_status,-->
+<!--        title,-->
+<!--        COALESCE(request_params, '') request_params,-->
+<!--        COALESCE(response_params, '') response_params,-->
+<!--        COALESCE(video_origin_url, '') video_origin_url,-->
+<!--        COALESCE(video_url, '') video_url,-->
+<!--        create_time,-->
+<!--        update_time-->
+<!--    </sql>-->
+
+<!--    <resultMap id="resultMapAiGenerateVideo" type="java.util.LinkedHashMap">-->
+<!--        <id property="id" column="id" jdbcType="BIGINT" />-->
+<!--        <result property="user_id" column="user_id" javaType="java.lang.Long" />-->
+<!--        <result property="job_id" column="job_id" />-->
+<!--        <result property="job_status" column="job_status" javaType="java.lang.Integer" />-->
+<!--        <result property="title" column="title" />-->
+<!--        <result property="request_params" column="request_params" />-->
+<!--        <result property="response_params" column="response_params" />-->
+<!--        <result property="video_origin_url" column="video_origin_url" />-->
+<!--        <result property="video_url" column="video_url" />-->
+<!--        <result property="create_time" column="create_time" />-->
+<!--        <result property="update_time" column="update_time" />-->
+<!--    </resultMap>-->
+
+    <!-- 列表 -->
+<!--    <select id="queryAiGenerateVideoList" resultMap="resultMapAiGenerateVideo">-->
+<!--        SELECT <include refid="includeAiGenerateVideo" />-->
+<!--        FROM ai_generate_video_task-->
+<!--        <where>-->
+<!--            user_id = #{user_id}-->
+<!--            <if test="job_id != null and job_id != ''">-->
+<!--                AND job_id = #{job_id}-->
+<!--            </if>-->
+<!--            <if test="title != null and title != ''">-->
+<!--                AND title LIKE CONCAT('%', #{title}, '%')-->
+<!--            </if>-->
+<!--            <if test="product_type != null and product_type != ''">-->
+<!--                AND product_type = #{product_type}-->
+<!--            </if>-->
+<!--            <if test="job_status != null and job_status != ''">-->
+<!--                AND job_status = #{job_status}-->
+<!--            </if>-->
+<!--        </where>-->
+<!--        ORDER BY create_time DESC-->
+<!--    </select>-->
+
+    <!-- 详情 -->
+<!--    <select id="queryAiGenerateVideoDetail" resultMap="resultMapAiGenerateVideo">-->
+<!--        SELECT <include refid="includeAiGenerateVideo" />-->
+<!--        FROM ai_generate_video_task-->
+<!--        WHERE job_id = #{job_id} AND user_id = #{user_id}-->
+<!--    </select>-->
+
+    <!-- 插入 -->
+<!--    <insert id="insertAiGenerateVideo" parameterType="com.backendsys.entity.Ai.AiGenerateVideoDTO"-->
+<!--        useGeneratedKeys="true" keyProperty="job_id">-->
+<!--        INSERT INTO ai_generate_video_task (-->
+<!--            user_id, job_id, title, source, product_type, resolution-->
+<!--            <if test="tts_per != null and tts_per != ''">, tts_per</if>-->
+<!--            <if test="bg_music_url != null and bg_music_url != ''">, bg_music_url</if>-->
+<!--            <if test="video_begin_url != null and video_begin_url != ''">, video_begin_url</if>-->
+<!--            <if test="video_end_url != null and video_end_url != ''">, video_end_url</if>-->
+<!--            <if test="video_logo_url != null and video_logo_url != ''">, video_logo_url</if>-->
+<!--            <if test="video_logo_location != null and video_logo_location != ''">, video_logo_location</if>-->
+<!--            <if test="video_logo_margin != null and video_logo_margin != ''">, video_logo_margin</if>-->
+<!--            <if test="job_status != null and job_status != ''">, job_status</if>-->
+<!--        )-->
+<!--        VALUES (-->
+<!--            #{user_id}, #{job_id}, #{title}, #{source}, #{product_type}, #{resolutionString}-->
+<!--            <if test="tts_per != null and tts_per != ''">, #{tts_per}</if>-->
+<!--            <if test="bg_music_url != null and bg_music_url != ''">, #{bg_music_url}</if>-->
+<!--            <if test="video_begin_url != null and video_begin_url != ''">, #{video_begin_url}</if>-->
+<!--            <if test="video_end_url != null and video_end_url != ''">, #{video_end_url}</if>-->
+<!--            <if test="video_logo_url != null and video_logo_url != ''">, #{video_logo_url}</if>-->
+<!--            <if test="video_logo_location != null and video_logo_location != ''">, #{video_logo_location}</if>-->
+<!--            <if test="video_logo_margin != null and video_logo_margin != ''">, #{video_logo_margin}</if>-->
+<!--            <if test="job_status != null and job_status != ''">, #{job_status}</if>-->
+<!--        )-->
+<!--    </insert>-->
+
+    <!-- 更新 -->
+<!--    <update id="updateAiGenerateVideo" parameterType="com.backendsys.entity.Ai.AiGenerateVideoDTO"-->
+<!--        useGeneratedKeys="true" keyProperty="job_id">-->
+<!--        UPDATE ai_generate_video_task-->
+<!--        SET job_status = #{job_status}-->
+<!--            <if test="result_video_url != null and result_video_url != ''">, result_video_url = #{result_video_url}</if>-->
+<!--            <if test="result_points != null and result_points != ''">, result_points = #{result_points}</if>-->
+<!--            <if test="result_basic_duration != null and result_basic_duration != ''">, result_basic_duration = #{result_basic_duration}</if>-->
+<!--            <if test="result_fail_reason != null and result_fail_reason != ''">, result_fail_reason = #{result_fail_reason}</if>-->
+<!--        WHERE job_id = #{job_id} AND user_id = #{user_id}-->
+<!--    </update>-->
+
+<!--    <delete id="deleteAiGenerateVideo">-->
+<!--        DELETE FROM ai_generate_video_task WHERE job_id = #{job_id} AND user_id = #{user_id}-->
+<!--    </delete>-->
+
+</mapper>