Переглянути джерело

生图新增画面比例参数; StoryboardList 新增生图结果列表;

tsurumure 1 місяць тому
батько
коміт
54539be000

+ 3 - 1
db/crt_drama_project_storyboard.sql

@@ -37,7 +37,9 @@ CREATE TABLE `crt_drama_project_storyboard` (
 
     `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-    INDEX `idx_user_id` (`user_id`)
+    INDEX `idx_user_id` (`user_id`),
+    INDEX `idx_drama_project_id` (`drama_project_id`),
+    INDEX `idx_episode_num` (`episode_num`)
 ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短剧创作-分镜表';
 
 INSERT INTO crt_drama_project_storyboard(user_id, drama_project_id, episode_num, sort, story_prompt, story_framing, story_scene, story_weather_time,

+ 2 - 1
db/crt_generate_image.sql

@@ -18,5 +18,6 @@ CREATE TABLE `crt_generate_image` (
     `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
     INDEX `idx_user_id` (`user_id`),
-    INDEX `idx_prompt_id` (`prompt_id`)
+    INDEX `idx_prompt_id` (`prompt_id`),
+    INDEX `idx_drama_project_storyboard_id` (`drama_project_storyboard_id`)
 ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短剧创作-生成图片记录表';

+ 3 - 3
src/main/java/com/backendsys/modules/cms/article/service/impl/ArticleServiceImpl.java

@@ -43,8 +43,8 @@ public class ArticleServiceImpl implements ArticleService {
 //        List<Article> list = articleDao.selectList(new LambdaQueryWrapper<>());
         List<Map<String, Object>> list = articleDao.selectArticleList(article);
 
-//        // 1) 完成分页实体渲染
-//        PageEntity pageEntity = new PageInfoResult(list).toEntity();
+        // 1) 完成分页实体渲染
+        PageEntity pageEntity = new PageInfoResult(list).toEntity();
 //
 //        // 2) 分页列表格式化
 //        list = list.stream().map(item -> {
@@ -56,7 +56,7 @@ public class ArticleServiceImpl implements ArticleService {
 //        List<Object> objectList = list.stream().map(item -> (Object) item).collect(Collectors.toList());
 //        pageEntity.setList(objectList);
 
-        return new PageInfoResult(list).toEntity();
+        return pageEntity;
     }
 
     /**

+ 5 - 0
src/main/java/com/backendsys/modules/crt/dao/CrtDramaProjectStoryboardDao.java

@@ -4,9 +4,14 @@ import com.backendsys.modules.crt.entity.CrtDramaProjectStoryboard;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+import java.util.Map;
+
 @Mapper
 public interface CrtDramaProjectStoryboardDao extends BaseMapper<CrtDramaProjectStoryboard> {
 
+    List<CrtDramaProjectStoryboard> selectStoryboardList(CrtDramaProjectStoryboard crtDramaProjectStoryboard);
+
     // 编辑分镜
     int updateStoryboard(CrtDramaProjectStoryboard crtDramaProjectStoryboard);
 

+ 5 - 0
src/main/java/com/backendsys/modules/crt/entity/CrtDramaProjectStoryboard.java

@@ -16,6 +16,8 @@ import lombok.Data;
 import org.hibernate.validator.constraints.Range;
 
 import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
 
 @Data
 @TableName("crt_drama_project_storyboard")
@@ -103,6 +105,9 @@ public class CrtDramaProjectStoryboard {
     // 生图状态 (-1:未生图, 1:生成中, 2:已生图)
     private Integer generate_image_status;
 
+    @TableField(exist = false)
+    private List<CrtGenerateImage> generate_images;
+
     // 生视频状态 (-1:未生视频, 1:生成中, 2:已生视频)
     private Integer generate_video_status;
 

+ 40 - 8
src/main/java/com/backendsys/modules/crt/enums/AspectRatioEnums.java

@@ -2,24 +2,56 @@ package com.backendsys.modules.crt.enums;
 
 public enum AspectRatioEnums {
 
-    RATIO_16_9("16:9", "1280*720"),
-    RATIO_9_16("9:16", "720*1280"),
-    RATIO_1_1("1:1", "1024*1024")
+    RATIO_16_9("16:9", 1280, 720),
+    RATIO_9_16("9:16", 720, 1280),
+    RATIO_1_1("1:1", 1024, 1024)
     ;
 
     private final String key;
-    private final String value;
+    private final Integer width;
+    private final Integer height;
 
-    AspectRatioEnums(String key, String value) {
+    AspectRatioEnums(String key, Integer width, Integer height) {
         this.key = key;
-        this.value = value;
+        this.width = width;
+        this.height = height;
     }
 
-    public String getValue() {
-        return this.value;
+    public Integer getWidth() {
+        return this.width;
+    }
+    public Integer getHeight() {
+        return this.height;
     }
     public String getKey() {
         return this.key;
     }
 
+    /* 根据 key 返回枚举,找不到返回 null */
+    public static AspectRatioEnums of(String key) {
+        for (AspectRatioEnums e : values()) {
+            if (e.key.equals(key)) {
+                return e;
+            }
+        }
+        return null;
+    }
+
+    /*
+         int[] size = AspectRatioEnums.getAspectRatio("16:9");
+         // [1280, 720]
+     */
+    public static int[] getAspectRatio(String key) {
+        AspectRatioEnums e = of(key);
+        return e == null ? null : new int[]{e.width, e.height};
+    }
+    /*
+        String sizeStr = AspectRatioEnums.getAspectRatioString("16:9");
+        // "1280*720"
+    */
+    public static String getAspectRatioString(String key) {
+        AspectRatioEnums e = of(key);
+        return e == null ? null : e.width + "*" + e.height;
+    }
+
 }

+ 22 - 18
src/main/java/com/backendsys/modules/crt/service/impl/CrtDramaProjectStoryboardServiceImpl.java

@@ -1,5 +1,6 @@
 package com.backendsys.modules.crt.service.impl;
 
+import cn.hutool.core.convert.Convert;
 import com.backendsys.exception.CustException;
 import com.backendsys.modules.common.config.security.enums.SecurityEnum;
 import com.backendsys.modules.common.config.security.utils.SecurityUtil;
@@ -7,11 +8,10 @@ import com.backendsys.modules.common.enums.MatchType;
 import com.backendsys.modules.crt.dao.CrtDramaProjectDao;
 import com.backendsys.modules.crt.dao.CrtDramaProjectSettingsDao;
 import com.backendsys.modules.crt.dao.CrtDramaProjectStoryboardDao;
-import com.backendsys.modules.crt.entity.CrtDramaProject;
-import com.backendsys.modules.crt.entity.CrtDramaProjectSettings;
-import com.backendsys.modules.crt.entity.CrtDramaProjectStoryboard;
-import com.backendsys.modules.crt.entity.StoryboardResponse;
+import com.backendsys.modules.crt.entity.*;
 import com.backendsys.modules.crt.service.CrtDramaProjectStoryboardService;
+import com.backendsys.modules.upload.enums.StyleEnums;
+import com.backendsys.modules.upload.utils.UploadUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -41,19 +41,29 @@ public class CrtDramaProjectStoryboardServiceImpl implements CrtDramaProjectStor
     @Override
     public StoryboardResponse selectCrtDramaProjectStoryboardDetail(CrtDramaProjectStoryboard crtDramaProjectStoryboard) {
 
-        Integer episode_num = crtDramaProjectStoryboard.getEpisode_num();
         Long project_id = crtDramaProjectStoryboard.getDrama_project_id();
 
         CrtDramaProject crtDramaProject = crtDramaProjectDao.selectById(project_id);
         if (crtDramaProject == null) throw new CustException("项目不存在");
 
-        LambdaQueryWrapper<CrtDramaProjectStoryboard> wrapperStoryboard = new LambdaQueryWrapper<>();
-        wrapperStoryboard.eq(CrtDramaProjectStoryboard::getDrama_project_id, project_id);
-        wrapperStoryboard.eq(CrtDramaProjectStoryboard::getEpisode_num, episode_num);
-
-        List<CrtDramaProjectStoryboard> storyboardList = crtDramaProjectStoryboardDao.selectList(wrapperStoryboard);
+        List<CrtDramaProjectStoryboard> storyboardList = crtDramaProjectStoryboardDao.selectStoryboardList(crtDramaProjectStoryboard);
         if (storyboardList.isEmpty()) throw new CustException("分镜不存在");
 
+        // 获取分镜列表
+        storyboardList.stream().forEach(storyboard -> {
+            // 获取分镜生图结果
+            if (!storyboard.getGenerate_images().isEmpty()) {
+                // 设置生图结果缩略略
+                List<CrtGenerateImage> generate_image_list = storyboard.getGenerate_images().stream().map(item -> {
+                    String url = item.getUrl();
+                    Integer target = item.getTarget();
+                    String url_thumb = UploadUtil.getImageThumbUrl(url, target, 100, null, StyleEnums.THUMB_BACKGROUND.getValue());
+                    item.setUrl_thumb(url_thumb);
+                    return item;
+                }).collect(Collectors.toList());
+                storyboard.setGenerate_images(generate_image_list);
+            }
+        });
 
         // 查询项目设置
         LambdaQueryWrapper<CrtDramaProjectSettings> wrapperSettings = new LambdaQueryWrapper<>();
@@ -64,12 +74,6 @@ public class CrtDramaProjectStoryboardServiceImpl implements CrtDramaProjectStor
         StoryboardResponse storyboardResponse = new StoryboardResponse();
         storyboardResponse.setDrama_project_id(project_id);
         storyboardResponse.setProject_name(crtDramaProject.getProject_name());
-
-        // 字段格式化
-        storyboardList = storyboardList.stream().map(storyboard -> {
-            storyboard.setDrama_project_storyboard_id(storyboard.getId());
-            return storyboard;
-        }).collect(Collectors.toList());
         storyboardResponse.setStoryboard_list(storyboardList);
 
         if (settingsList.size() > 0) {
@@ -106,11 +110,11 @@ public class CrtDramaProjectStoryboardServiceImpl implements CrtDramaProjectStor
         wrapperStoryboard.eq(CrtDramaProjectStoryboard::getEpisode_num, episode_num);
         if (sort == null) {
             Boolean is_exist_storyboard = crtDramaProjectStoryboardDao.exists(wrapperStoryboard);
-            if (is_exist_storyboard) throw new CustException("该项目集数已存在,请勿重复创建");
+            if (is_exist_storyboard) throw new CustException("集数或分镜已存在,请勿重复创建");
         } else {
             wrapperStoryboard.eq(CrtDramaProjectStoryboard::getSort, sort);
             Boolean is_exist_storyboard = crtDramaProjectStoryboardDao.exists(wrapperStoryboard);
-            if (is_exist_storyboard) throw new CustException("该项目集数已存在,请勿重复创建");
+            if (is_exist_storyboard) throw new CustException("集数或分镜已存在,请勿重复创建");
         }
 
         // [DB] 创建分镜

+ 17 - 10
src/main/java/com/backendsys/modules/crt/service/impl/CrtGenerateServiceImpl.java

@@ -11,6 +11,7 @@ import com.backendsys.modules.crt.entity.CrtDramaProjectSettings;
 import com.backendsys.modules.crt.entity.CrtDramaProjectStoryboard;
 import com.backendsys.modules.crt.entity.CrtGenerateImage;
 import com.backendsys.modules.crt.entity.CrtModel;
+import com.backendsys.modules.crt.enums.AspectRatioEnums;
 import com.backendsys.modules.crt.enums.SamplerEnums;
 import com.backendsys.modules.crt.service.CrtGenerateService;
 import com.backendsys.modules.sdk.comfyui.entity.ComfyuiResponse;
@@ -96,18 +97,15 @@ public class CrtGenerateServiceImpl implements CrtGenerateService {
 
         // 项目配置类型 (1:生图配置, 2:生视频配置)
         CrtDramaProjectSettings settings_image = settingsDetail.stream().filter(item -> item.getDrama_project_setting_type() == 1).findFirst().orElse(null);
-        CrtDramaProjectSettings settings_video = settingsDetail.stream().filter(item -> item.getDrama_project_setting_type() == 2).findFirst().orElse(null);
         // System.out.println("- 生图配置: " + JSONUtil.toJsonStr(settings_image));
-        // System.out.println("- 生视频配置: " + JSONUtil.toJsonStr(settings_video));
-
-
 
+        // CrtDramaProjectSettings settings_video = settingsDetail.stream().filter(item -> item.getDrama_project_setting_type() == 2).findFirst().orElse(null);
+        // System.out.println("- 生视频配置: " + JSONUtil.toJsonStr(settings_video));
 
 
         // 文生图提示词
         String prompt_text = crtDramaProjectStoryboard.getText_to_image_prompt();
 
-
         // == 从 storboard detail 获取参数 =============================================================================
         Integer param_batch_size = storyboardDetail.getParam_batch_size();                        // 生成图片数量
         Float param_prompt_flux_guidance = storyboardDetail.getParam_prompt_flux_guidance();      // 提示词引导系数
@@ -130,8 +128,13 @@ public class CrtGenerateServiceImpl implements CrtGenerateService {
         wrapper.eq(CrtDramaProjectStoryboard::getId, drama_project_storyboard_id);
         crtDramaProjectStoryboardDao.update(entity, wrapper);
 
-        Integer width = 1280;
-        Integer height = 720;
+        // [db] 获取画面比例 (从项目配置)
+        String aspect_ratio = settings_image.getAspect_ratio();
+        AspectRatioEnums aspect_ratio_option = AspectRatioEnums.of(aspect_ratio);
+        Integer width = aspect_ratio_option.getWidth();
+        Integer height = aspect_ratio_option.getHeight();
+//        Integer width = 1280;
+//        Integer height = 720;
 
         // [db] 获取基础模型 (从项目配置)
         Long model_id = settings_image.getModel_id();
@@ -164,6 +167,8 @@ public class CrtGenerateServiceImpl implements CrtGenerateService {
 //        comfyuiText2Image.setWidth(400);
 //        comfyuiText2Image.setHeight(200);
 
+        // aspect_ratio 画面比例 (枚举)(16:9 - 1280*720, 9:16 - 720*1280, 1:1 - 1024*1024)
+
         comfyuiText2Image.setModel_name(model_name);
         comfyuiText2Image.setPrompt_text(prompt_text);
         comfyuiText2Image.setSeed(param_seed);
@@ -191,21 +196,23 @@ public class CrtGenerateServiceImpl implements CrtGenerateService {
         wrapper.orderByDesc(CrtGenerateImage::getCreate_time);
         List<CrtGenerateImage> list = crtGenerateImageDao.selectList(wrapper);
 
+        // 1) 完成分页实体渲染
+        PageEntity pageEntity = new PageInfoResult(list).toEntity();
+
         // 加入缩略图
         if (!list.isEmpty()) {
-            // 1) 完成分页实体渲染
-            PageEntity pageEntity = new PageInfoResult(list).toEntity();
             // 2) 分页列表格式化
             list = list.stream().map(item -> {
                 item.setUrl_thumb(UploadUtil.getImageThumbUrl(item.getUrl(), item.getTarget(), 100, null, StyleEnums.THUMB_BACKGROUND.getValue()));
                 return item;
             }).collect(Collectors.toList());
+
             // 3) 分页实体重新赋值
             List<Object> objectList = list.stream().map(item -> (Object) item).collect(Collectors.toList());
             pageEntity.setList(objectList);
         }
 
-        return new PageInfoResult(list).toEntity();
+        return pageEntity;
     }
 
 }

+ 5 - 2
src/main/java/com/backendsys/modules/sdk/comfyui/service/impl/ComfyuiSocketServiceImpl.java

@@ -145,14 +145,17 @@ public class ComfyuiSocketServiceImpl implements ComfyuiSocketService {
                             System.out.println("(doOnNext) Received from " + client_id + ": " + message);
 
                             JSONObject data = JSONUtil.parseObj(message);
+                            JSONObject dataChildren = JSONUtil.parseObj(data.get("data"));
 
+                            Long drama_project_storyboard_id = Convert.toLong(params.get("drama_project_storyboard_id"));
+                            dataChildren.put("drama_project_storyboard_id", drama_project_storyboard_id);
+                            data.put("data", dataChildren);
 
                             // == [任务执行完成] =======================================================
                             // { "type": "executed", .. }
                             String type = Convert.toStr(data.get("type"));
                             if (TaskStatusEnums.EXECUTED.getValue().equals(type)) {
 
-                                JSONObject dataChildren = JSONUtil.parseObj(data.get("data"));
                                 JSONObject output = JSONUtil.parseObj(dataChildren.get("output"));
 
                                 // -- [生成图片 -> 转存图片 -> 新增记录] ------------------------------------------------------
@@ -162,7 +165,7 @@ public class ComfyuiSocketServiceImpl implements ComfyuiSocketService {
                                 Object imagesObj = output.get("images");
                                 if (imagesObj != null) {
                                     String prompt_id = Convert.toStr(dataChildren.get("prompt_id"));
-                                    Long drama_project_storyboard_id = Convert.toLong(params.get("drama_project_storyboard_id"));
+
 
                                     // 临时图片相对路径
                                     JSONArray images = JSONUtil.parseArray(imagesObj);

+ 1 - 1
src/main/resources/application-dev.yml

@@ -199,4 +199,4 @@ klingai:
 comfyui:
   host: 127.0.0.1
   token: $2b$12$.MR4qGaFetN1FPQzbfyIrehsyjnPJ12xAZhR/l7KZpLkUPQTCG4gy
-  is-save: false
+  is-save: true

+ 1 - 1
src/main/resources/application-local.yml

@@ -212,4 +212,4 @@ klingai:
 comfyui:
   host: 43.128.1.201
   token: $2b$12$.MR4qGaFetN1FPQzbfyIrehsyjnPJ12xAZhR/l7KZpLkUPQTCG4gy
-  is-save: false
+  is-save: true

+ 1 - 1
src/main/resources/application-prod.yml

@@ -200,4 +200,4 @@ klingai:
 comfyui:
   host: 127.0.0.1
   token: $2b$12$.MR4qGaFetN1FPQzbfyIrehsyjnPJ12xAZhR/l7KZpLkUPQTCG4gy
-  is-save: false
+  is-save: true

+ 111 - 0
src/main/resources/mapper/crt/drama/CrtDramaProjectStoryboardDao.xml

@@ -2,6 +2,117 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
 <mapper namespace="com.backendsys.modules.crt.dao.CrtDramaProjectStoryboardDao">
 
+    <sql id="includeStoryboard">
+        id,
+        id drama_project_storyboard_id,
+        user_id,
+        drama_project_id,
+        episode_num,
+        sort,
+        COALESCE(story_prompt, '') story_prompt,
+        COALESCE(story_framing, '') story_framing,
+        COALESCE(story_scene, '') story_scene,
+        COALESCE(story_weather_time, '') story_weather_time,
+        COALESCE(lora_figure_ids, '') lora_figure_ids,
+
+        param_batch_size,
+        param_prompt_flux_guidance,
+        param_sampler,
+        param_step,
+        param_seed_type,
+        COALESCE(param_seed, 0) param_seed,
+        COALESCE(text_to_image_prompt, '') text_to_image_prompt,
+
+        param_video_reference_type,
+        COALESCE(param_video_reference_images, '') param_video_reference_images,
+        COALESCE(image_to_video_prompt, '') image_to_video_prompt,
+
+        generate_image_status,
+        generate_video_status,
+        create_time,
+        update_time
+    </sql>
+
+    <resultMap id="resultMapStoryboard" type="com.backendsys.modules.crt.entity.CrtDramaProjectStoryboard">
+        <id property="id" column="id" jdbcType="BIGINT" />
+        <result property="user_id" column="user_id" javaType="java.lang.Long" />
+        <result property="drama_project_id" column="drama_project_id" javaType="java.lang.Long" />
+        <result property="episode_num" column="episode_num" javaType="java.lang.Integer" />
+        <result property="sort" column="sort" javaType="java.lang.Integer" />
+        <result property="story_prompt" column="story_prompt" />
+        <result property="story_framing" column="story_framing" />
+        <result property="story_scene" column="story_scene" />
+        <result property="story_weather_time" column="story_weather_time" />
+        <result property="lora_figure_ids" column="lora_figure_ids" />
+        <result property="param_batch_size" column="param_batch_size" javaType="java.lang.Integer" />
+        <result property="param_prompt_flux_guidance" column="param_prompt_flux_guidance" javaType="java.lang.Float" />
+        <result property="param_sampler" column="param_sampler" />
+        <result property="param_step" column="param_step" javaType="java.lang.Integer" />
+        <result property="param_seed_type" column="param_seed_type" javaType="java.lang.Integer" />
+        <result property="param_seed" column="param_seed" />
+        <result property="text_to_image_prompt" column="text_to_image_prompt" />
+        <result property="param_video_reference_type" column="param_video_reference_type" javaType="java.lang.Integer" />
+        <result property="param_video_reference_images" column="param_video_reference_images" />
+        <result property="image_to_video_prompt" column="image_to_video_prompt" />
+        <result property="generate_image_status" column="generate_image_status" javaType="java.lang.Integer" />
+        <result property="generate_video_status" column="generate_video_status" javaType="java.lang.Integer" />
+        <result property="create_time" column="create_time" />
+        <result property="update_time" column="update_time" />
+        <collection property="generate_images" javaType="java.util.List"
+            select="queryGenerateImageById" column="id">
+            <id property="id" column="id" jdbcType="BIGINT" />
+            <result property="user_id" column="user_id" javaType="java.lang.Long" />
+            <result property="drama_project_storyboard_id" column="drama_project_storyboard_id" javaType="java.lang.Long" />
+            <result property="prompt_id" column="prompt_id" />
+            <result property="url_origin" column="url_origin" />
+            <result property="url" column="url" />
+            <result property="url_thumb" column="url_thumb" />
+            <result property="object_key" column="object_key" />
+            <result property="target" column="target" javaType="java.lang.Integer" />
+            <result property="create_time" column="create_time" />
+            <result property="update_time" column="update_time" />
+        </collection>
+    </resultMap>
+
+    <!-- 子查询 (生图结果) -->
+    <sql id="includeGenerateImage">
+        id,
+        user_id,
+        drama_project_storyboard_id,
+        COALESCE(prompt_id, "") prompt_id,
+        COALESCE(url_origin, "") url_origin,
+        COALESCE(url, "") url,
+        COALESCE(object_key, "") object_key,
+        COALESCE(target, -1) target,
+        create_time,
+        update_time
+    </sql>
+    <select id="queryGenerateImageById" resultType="com.backendsys.modules.crt.entity.CrtGenerateImage">
+        SELECT <include refid="includeGenerateImage" />
+        FROM crt_generate_image
+        WHERE drama_project_storyboard_id = #{id}
+        ORDER BY create_time DESC
+        LIMIT 8
+    </select>
+    <!--  -->
+
+    <select id="selectStoryboardList" resultMap="resultMapStoryboard">
+        SELECT <include refid="includeStoryboard" />
+        FROM crt_drama_project_storyboard
+        <where>
+            <if test="user_id != null and user_id != ''">
+                AND user_id = #{user_id}
+            </if>
+            <if test="drama_project_id != null and drama_project_id != ''">
+                AND drama_project_id = #{drama_project_id}
+            </if>
+            <if test="episode_num != null and episode_num != ''">
+                AND episode_num = #{episode_num}
+            </if>
+        </where>
+        ORDER BY sort ASC
+    </select>
+
     <!-- 编辑分镜 -->
     <!-- { user_id } 用户ID不能改 -->
     <!-- { drama_project_id, episode_num } 项目ID、集数 不能改 -->