Browse Source

修改接口参数

glx
glx 4 weeks ago
parent
commit
d138d40869
  1. 27
      src/main/java/com/youlai/boot/mini/controller/AiGenerationController.java
  2. 10
      src/main/java/com/youlai/boot/mini/model/form/AiCallbackImage.java
  3. 35
      src/main/java/com/youlai/boot/mini/model/form/AiFourPanelCallbackForm.java
  4. 12
      src/main/java/com/youlai/boot/mini/model/form/AiFourPanelGenerateForm.java
  5. 13
      src/main/java/com/youlai/boot/mini/model/form/AiSingleImageCallbackForm.java
  6. 12
      src/main/java/com/youlai/boot/mini/model/form/AiSingleImageGenerateForm.java
  7. 5
      src/main/java/com/youlai/boot/mini/model/form/AiVideoGenerateForm.java
  8. 19
      src/main/java/com/youlai/boot/mini/model/form/MediaUrl.java
  9. 34
      src/main/java/com/youlai/boot/mini/model/form/VideoContentItem.java
  10. 38
      src/main/java/com/youlai/boot/mini/model/vo/AiTaskCallbackResult.java
  11. 31
      src/main/java/com/youlai/boot/mini/model/vo/AiTaskCallbackUsage.java
  12. 7
      src/main/java/com/youlai/boot/mini/service/AiGenerationService.java
  13. 171
      src/main/java/com/youlai/boot/mini/service/impl/AiGenerationServiceImpl.java
  14. 14
      src/main/resources/application-dev.yml

27
src/main/java/com/youlai/boot/mini/controller/AiGenerationController.java

@ -7,15 +7,13 @@ import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.framework.security.util.SecurityUtils;
import com.youlai.boot.mini.model.form.AiFourPanelGenerateForm;
import com.youlai.boot.mini.model.form.AiSingleImageCallbackForm;
import com.youlai.boot.mini.model.form.AiSingleImageGenerateForm;
import com.youlai.boot.mini.model.form.AiVideoGenerateForm;
import com.youlai.boot.mini.model.vo.AiTaskCallbackVO;
import com.youlai.boot.mini.model.form.AiFourPanelCallbackForm;
import com.youlai.boot.mini.model.vo.AiVideoCallbackVO;
import com.youlai.boot.mini.service.AiGenerationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
@ -23,7 +21,6 @@ import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Collections;
import java.util.List;
@Tag(name = "AI生成图片视频相关接口")
@ -48,6 +45,10 @@ public class AiGenerationController {
return Result.success(urlList);
}
//TODO: 查询用户最近上传的图片视频接口
//TODO:用户删除上次的图片视频接口
@Operation(summary = "提交单图生成任务")
@PostMapping("/generate-single-image")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.INSERT)
@ -57,12 +58,11 @@ public class AiGenerationController {
return Result.success(taskUuid);
}
//TODO: 后续增加用户小程序订阅通知
@Operation(summary = "单图任务回调接口")
@PostMapping("/single-image/task/callback")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.UPDATE)
public Result<Boolean> taskCallback(@Valid @RequestBody AiTaskCallbackVO vo) {
boolean success = aiGenerationService.handleTaskCallback(vo);
public Result<Boolean> singleImageTaskCallback(@Valid @RequestBody AiSingleImageCallbackForm form) {
boolean success = aiGenerationService.handleTaskCallback(form);
return Result.success(success);
}
@ -75,6 +75,14 @@ public class AiGenerationController {
return Result.success(taskUuid);
}
@Operation(summary = "四宫格漫画任务回调接口")
@PostMapping("/four-panel/task/callback")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.UPDATE)
public Result<Boolean> fourPanelTaskCallback(@Valid @RequestBody AiFourPanelCallbackForm form) {
boolean success = aiGenerationService.handleFourPanelCallback(form);
return Result.success(success);
}
@Operation(summary = "提交视频生成任务")
@PostMapping("/generate-video")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.INSERT)
@ -84,7 +92,6 @@ public class AiGenerationController {
return Result.success(taskUuid);
}
//TODO: 后续增加用户小程序订阅通知
@Operation(summary = "视频任务回调接口")
@PostMapping("/video/task/callback")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.UPDATE)
@ -93,4 +100,6 @@ public class AiGenerationController {
return Result.success(success);
}
//TODO: 后续在回调中 增加用户小程序订阅通知
}

10
src/main/java/com/youlai/boot/mini/model/vo/AiTaskCallbackImage.java → src/main/java/com/youlai/boot/mini/model/form/AiCallbackImage.java

@ -1,17 +1,17 @@
package com.youlai.boot.mini.model.vo;
package com.youlai.boot.mini.model.form;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* AI生成图片信息
* AI回调图片通用结构
*
* @author youlai
*/
@Data
@Schema(description = "AI生成图片信息")
public class AiTaskCallbackImage {
@Schema(description = "AI回调图片通用结构")
public class AiCallbackImage {
@Schema(description = "图片URL地址")
private String url;
@ -20,6 +20,6 @@ public class AiTaskCallbackImage {
@Schema(description = "Base64编码的图片JSON")
private String b64Json;
@Schema(description = "图片尺寸,格式如 1664x2496")
@Schema(description = "图片尺寸,格式如 2048x2048")
private String size;
}

35
src/main/java/com/youlai/boot/mini/model/form/AiFourPanelCallbackForm.java

@ -0,0 +1,35 @@
package com.youlai.boot.mini.model.form;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.util.List;
/**
* 四宫格漫画任务回调请求表单
*
* @author youlai
*/
@Data
@Schema(description = "四宫格漫画任务回调请求表单")
public class AiFourPanelCallbackForm {
@NotBlank(message = "任务UUID不能为空")
@Schema(description = "任务唯一标识UUID", requiredMode = Schema.RequiredMode.REQUIRED)
private String uuid;
@Schema(description = "任务状态:succeeded=成功,failed=失败")
private String status;
@Schema(description = "生成的图片列表")
private List<AiCallbackImage> result;
@JsonProperty("created_at")
@Schema(description = "创建时间戳")
private Long createdAt;
@JsonProperty("updated_at")
@Schema(description = "更新时间戳")
private Long updatedAt;
}

12
src/main/java/com/youlai/boot/mini/model/form/AiFourPanelGenerateForm.java

@ -20,16 +20,16 @@ public class AiFourPanelGenerateForm {
private String model;
@Schema(description = "画风:1=治愈系水彩,2=Q版卡通,3=日式漫画,4=吉卜力风,5=3D毛绒,6=搞笑夸张", defaultValue = "1")
private Integer style = 1;
private Integer style;
@Schema(description = "比例:1=1:1,2=2:3,3=3:4,4=4:3,5=5:4", defaultValue = "1")
private Integer ratio = 1;
private Integer ratio;
@Schema(description = "图片尺寸:1=2K,2=4K,3=8K", defaultValue = "1")
private Integer imgSize = 1;
private Integer imgSize;
@Schema(description = "图片格式:1=png,2=jpeg", defaultValue = "1")
private Integer imgType = 1;
private Integer imgType;
@Schema(description = "宠物物种:如cat、dog")
private String species;
@ -47,8 +47,8 @@ public class AiFourPanelGenerateForm {
private String bodyType;
@Schema(description = "特殊特征:如flat face、thick coat", defaultValue = "")
private String distinctiveFeatures = "";
private String distinctiveFeatures;
@Schema(description = "故事梗概:AI会据此生成四格漫画脚本")
private String storyOutline;
private String description;
}

13
src/main/java/com/youlai/boot/mini/model/vo/AiTaskCallbackVO.java → src/main/java/com/youlai/boot/mini/model/form/AiSingleImageCallbackForm.java

@ -1,18 +1,19 @@
package com.youlai.boot.mini.model.vo;
package com.youlai.boot.mini.model.form;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.util.List;
/**
* AI生成任务回调请求VO
* 单图生成任务回调请求表单
*
* @author youlai
*/
@Data
@Schema(description = "AI生成任务回调请求")
public class AiTaskCallbackVO {
@Schema(description = "单图生成任务回调请求表单")
public class AiSingleImageCallbackForm {
@NotBlank(message = "任务UUID不能为空")
@Schema(description = "任务唯一标识UUID", requiredMode = Schema.RequiredMode.REQUIRED)
@ -21,8 +22,8 @@ public class AiTaskCallbackVO {
@Schema(description = "任务状态:succeeded=成功,failed=失败")
private String status;
@Schema(description = "生成结果")
private AiTaskCallbackResult result;
@Schema(description = "生成的图片列表")
private List<AiCallbackImage> result;
@JsonProperty("created_at")
@Schema(description = "创建时间戳")

12
src/main/java/com/youlai/boot/mini/model/form/AiSingleImageGenerateForm.java

@ -20,16 +20,16 @@ public class AiSingleImageGenerateForm {
private String model;
@Schema(description = "画风:1=治愈系水彩,2=Q版卡通,3=日式漫画,4=吉卜力风,5=3D毛绒,6=搞笑夸张", defaultValue = "1")
private Integer style = 1;
private Integer style;
@Schema(description = "比例:1=1:1,2=2:3,3=3:4,4=4:3,5=5:4", defaultValue = "1")
private Integer ratio = 1;
private Integer ratio;
@Schema(description = "图片尺寸:1=2K,2=4K,3=8K", defaultValue = "1")
private Integer imgSize = 1;
private Integer imgSize;
@Schema(description = "图片格式:1=png,2=jpeg", defaultValue = "1")
private Integer imgType = 1;
private Integer imgType;
@Schema(description = "宠物物种:如cat、dog")
private String species;
@ -47,8 +47,8 @@ public class AiSingleImageGenerateForm {
private String bodyType;
@Schema(description = "特殊特征:如flat face、thick coat", defaultValue = "")
private String distinctiveFeatures = "";
private String distinctiveFeatures;
@Schema(description = "场景描述:用户自定义生成场景")
private String sceneDescription;
private String description;
}

5
src/main/java/com/youlai/boot/mini/model/form/AiVideoGenerateForm.java

@ -3,7 +3,6 @@ package com.youlai.boot.mini.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* AI视频生成请求表单
@ -17,8 +16,8 @@ public class AiVideoGenerateForm {
@Schema(description = "使用的模型ID", defaultValue = "doubao-seedance-2-0-260128")
private String model;
@Schema(description = "内容数组,包含text、image_url类型")
private List<Map<String, Object>> content;
@Schema(description = "内容数组,包含text、image_url、video_url、audio_url类型")
private List<VideoContentItem> content;
@Schema(description = "分辨率: 480p, 720p, 1080p, 2K", defaultValue = "720p")
private String resolution = "720p";

19
src/main/java/com/youlai/boot/mini/model/form/MediaUrl.java

@ -0,0 +1,19 @@
package com.youlai.boot.mini.model.form;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 媒体URL通用结构
*
* @author youlai
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(description = "媒体URL通用结构")
public class MediaUrl {
@Schema(description = "资源URL地址")
private String url;
}

34
src/main/java/com/youlai/boot/mini/model/form/VideoContentItem.java

@ -0,0 +1,34 @@
package com.youlai.boot.mini.model.form;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 视频生成内容项
*
* @author youlai
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(description = "视频生成内容项")
public class VideoContentItem {
@Schema(description = "内容类型:text/image_url/video_url/audio_url", allowableValues = {"text", "image_url", "video_url", "audio_url"})
private String type;
@Schema(description = "文本内容,type=text时必填")
private String text;
@Schema(description = "图片URL结构,type=image_url时必填")
private MediaUrl image_url;
@Schema(description = "视频URL结构,type=video_url时必填")
private MediaUrl video_url;
@Schema(description = "音频URL结构,type=audio_url时必填")
private MediaUrl audio_url;
@Schema(description = "内容角色标识,比如reference_image/reference_video/reference_audio")
private String role;
}

38
src/main/java/com/youlai/boot/mini/model/vo/AiTaskCallbackResult.java

@ -1,38 +0,0 @@
package com.youlai.boot.mini.model.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* AI任务生成结果
*
* @author youlai
*/
@Data
@Schema(description = "AI任务生成结果")
public class AiTaskCallbackResult {
@Schema(description = "使用的模型ID")
private String model;
@Schema(description = "生成的图片列表")
private List<AiTaskCallbackImage> data;
@Schema(description = "错误信息,无错误则为null")
private Object error;
@Schema(description = "Token使用统计")
private AiTaskCallbackUsage usage;
@JsonProperty("created_at")
@Schema(description = "创建时间戳")
private Long createdAt;
@Schema(description = "使用的工具")
private String tool;
@Schema(description = "创建时间戳")
private Long created;
}

31
src/main/java/com/youlai/boot/mini/model/vo/AiTaskCallbackUsage.java

@ -1,31 +0,0 @@
package com.youlai.boot.mini.model.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* AI生成资源消耗统计
*
* @author youlai
*/
@Data
@Schema(description = "AI生成资源消耗统计")
public class AiTaskCallbackUsage {
@JsonProperty("generated_images")
@Schema(description = "生成的图片数量")
private Integer generatedImages;
@JsonProperty("output_tokens")
@Schema(description = "输出token数")
private Integer outputTokens;
@JsonProperty("total_tokens")
@Schema(description = "总token数")
private Integer totalTokens;
@JsonProperty("tool_usage")
@Schema(description = "工具使用信息")
private Object toolUsage;
}

7
src/main/java/com/youlai/boot/mini/service/AiGenerationService.java

@ -1,10 +1,11 @@
package com.youlai.boot.mini.service;
import com.youlai.boot.mini.model.form.AiFourPanelGenerateForm;
import com.youlai.boot.mini.model.form.AiSingleImageCallbackForm;
import com.youlai.boot.mini.model.form.AiSingleImageGenerateForm;
import com.youlai.boot.mini.model.form.AiVideoGenerateForm;
import com.youlai.boot.mini.model.entity.MiniAiGenerationTask;
import com.youlai.boot.mini.model.vo.AiTaskCallbackVO;
import com.youlai.boot.mini.model.form.AiFourPanelCallbackForm;
import com.youlai.boot.mini.model.vo.AiVideoCallbackVO;
import org.springframework.web.multipart.MultipartFile;
@ -18,12 +19,14 @@ public interface AiGenerationService {
String createAndGenerateFourPanel(AiFourPanelGenerateForm form, Long userId);
boolean handleTaskCallback(AiTaskCallbackVO vo);
boolean handleTaskCallback(AiSingleImageCallbackForm form);
String createAndGenerateVideo(AiVideoGenerateForm form, Long userId);
boolean handleVideoTaskCallback(AiVideoCallbackVO vo);
boolean handleFourPanelCallback(AiFourPanelCallbackForm form);
MiniAiGenerationTask getTaskByUuid(String uuid);
}

171
src/main/java/com/youlai/boot/mini/service/impl/AiGenerationServiceImpl.java

@ -25,11 +25,13 @@ import com.youlai.boot.mini.mapper.MiniAiTaskMediaMapper;
import com.youlai.boot.mini.model.entity.MiniAiGenerationTask;
import com.youlai.boot.mini.model.entity.MiniAiTaskMedia;
import com.youlai.boot.mini.model.form.AiFourPanelGenerateForm;
import com.youlai.boot.mini.model.form.AiSingleImageCallbackForm;
import com.youlai.boot.mini.model.form.AiSingleImageGenerateForm;
import com.youlai.boot.mini.model.form.AiVideoGenerateForm;
import com.youlai.boot.mini.model.form.MiniDeductPointForm;
import com.youlai.boot.mini.model.vo.AiTaskCallbackVO;
import com.youlai.boot.mini.model.vo.AiVideoCallbackVO;
import com.youlai.boot.mini.model.form.AiCallbackImage;
import com.youlai.boot.mini.model.form.AiFourPanelCallbackForm;
import com.youlai.boot.mini.model.vo.VideoCallbackData;
import com.youlai.boot.common.exception.BusinessException;
import com.youlai.boot.mini.service.AiGenerationService;
@ -76,6 +78,9 @@ public class AiGenerationServiceImpl implements AiGenerationService {
//AI单图/四宫格图片生成任务回调地址
@Value("${ai.callback.single-image-callback-url:http://127.0.0.1:30101/backend/api/v1/mini/ai/generation/task/callback}")
private String aiSingleImageCallbackUrl;
//四宫格图片生成任务回调地址
@Value("${ai.callback.four-panel-callback-url:http://192.168.31.197:30101/backend/api/v1/mini/ai/generation/four-panel/task/callback}")
private String aiFourPanelCallbackUrl;
//视频生成服务地址
@Value("${ai.generate.video-server-url:http://127.0.0.1:8001/api/v1/video/submit}")
private String aiVideoServerUrl;
@ -129,23 +134,24 @@ public class AiGenerationServiceImpl implements AiGenerationService {
String objectName = OSS_IMAGE_DIR + fileName + "." + ext;
String url = aliyunFileService.uploadFile(objectName, image.getInputStream());
// 获取图片信息
BufferedImage imageInfo = ImageIO.read(image.getInputStream());
// 保存媒体记录
MiniAiTaskMedia media = new MiniAiTaskMedia();
String uuid = UUID.randomUUID().toString().replace("-", "");
media.setUuid(uuid)
.setFileSource("user_upload")//TODO 待整理成枚举,参考项目已有内容
.setMiniUserId(userId)
.setFileSource("user_upload")
.setMediaType("image")
.setSourceUrl(url)
.setStorageKey(objectName)
.setWidth(imageInfo.getWidth())
.setHeight(imageInfo.getHeight())
.setCreateBy(userId)
.setCreateTimestamp(timestamp)
.setCreateTime(new Date(timestamp));
// 获取图片信息
BufferedImage imageInfo = ImageIO.read(image.getInputStream());
media.setWidth(imageInfo.getWidth())
.setHeight(imageInfo.getHeight());
int result = aiTaskMediaMapper.insert(media);
if (result > 0) {
urlList.add(url);
@ -178,6 +184,7 @@ public class AiGenerationServiceImpl implements AiGenerationService {
String uuid = UUID.randomUUID().toString().replace("-", "");
media.setUuid(uuid)
.setMiniUserId(userId)
.setFileSource("user_upload")
.setMediaType("video")
.setSourceUrl(url)
@ -262,7 +269,7 @@ public class AiGenerationServiceImpl implements AiGenerationService {
aiRequest.put("eye_color", form.getEyeColor());
aiRequest.put("body_type", form.getBodyType());
aiRequest.put("distinctive_features", form.getDistinctiveFeatures());
aiRequest.put("scene_description", form.getSceneDescription());
aiRequest.put("description", form.getDescription());
// 传递任务UUID和回调地址
aiRequest.put("uuid", taskUuid);
aiRequest.put("callback_url", aiSingleImageCallbackUrl);
@ -347,10 +354,10 @@ public class AiGenerationServiceImpl implements AiGenerationService {
aiRequest.put("eye_color", form.getEyeColor());
aiRequest.put("body_type", form.getBodyType());
aiRequest.put("distinctive_features", form.getDistinctiveFeatures());
aiRequest.put("story_outline", form.getStoryOutline());
aiRequest.put("description", form.getDescription());
// 传递任务UUID和回调地址
aiRequest.put("uuid", taskUuid);
aiRequest.put("callback_url", aiSingleImageCallbackUrl);
aiRequest.put("callback_url", aiFourPanelCallbackUrl);
try {
log.info("提交四宫格漫画生成任务,任务UUID:{},请求参数:{}", taskUuid, JSONUtil.toJsonStr(aiRequest));
@ -425,14 +432,14 @@ public class AiGenerationServiceImpl implements AiGenerationService {
aiRequest.put("resolution", form.getResolution());
aiRequest.put("duration", form.getDuration());
aiRequest.put("uuid", taskUuid);
aiRequest.put("callback_url", aiVideoCallbackUrl); //TODO 后续独立回调地址
aiRequest.put("callback_url", aiVideoCallbackUrl);
try {
log.info("提交视频生成任务,任务UUID:{},请求参数:{}", taskUuid, JSONUtil.toJsonStr(aiRequest));
HttpResponse response = HttpRequest.post(aiVideoServerUrl)
.header("Content-Type", "application/json")
.body(JSONUtil.toJsonStr(aiRequest))
.timeout(1000)
.timeout(30000) //超时30秒
.execute();
if (!response.isOk()) {
@ -525,6 +532,7 @@ public class AiGenerationServiceImpl implements AiGenerationService {
String mediaUuid = UUID.randomUUID().toString().replace("-", "");
media.setUuid(mediaUuid)
.setTaskId(task.getId())
.setMiniUserId(task.getMiniUserId())
.setFileSource("ai_generate")
.setMediaType("video")
.setSourceUrl(ossUrl)
@ -544,37 +552,140 @@ public class AiGenerationServiceImpl implements AiGenerationService {
}
@Override
public boolean handleTaskCallback(AiTaskCallbackVO vo) {
log.info("处理AI生成任务回调,任务UUID:{}", vo.getUuid());
@Transactional(rollbackFor = Exception.class)
public boolean handleFourPanelCallback(AiFourPanelCallbackForm form) {
try {
String taskUuid = vo.getUuid();
log.info("处理四宫格漫画生成任务回调,任务UUID:{}", form.getUuid());
String taskUuid = form.getUuid();
// 查询任务是否存在
MiniAiGenerationTask task = getTaskByUuid(taskUuid);
if (task == null) {
log.error("回调任务不存在,UUID:{}", taskUuid);
log.error("四宫格回调任务不存在,UUID:{}", taskUuid);
return false;
}
// 转换任务状态
Integer status;
if ("succeeded".equals(vo.getStatus())) {
if ("succeeded".equals(form.getStatus())) {
status = 1; // 成功
} else if ("failed".equals(vo.getStatus())) {
} else if ("failed".equals(form.getStatus())) {
status = 2; // 失败
} else {
log.error("回调任务状态非法,UUID:{},status:{}", taskUuid, vo.getStatus());
log.info("四宫格任务{}处于中间状态:{},不处理", taskUuid, form.getStatus());
return true; // 中间状态直接返回成功,不更新任务
}
// 更新任务状态
task.setStatus(status);
task.setUpdateTime(new Date());
task.setUpdateTimestamp(System.currentTimeMillis());
aiGenerationTaskMapper.updateById(task);
// 如果生成成功,下载外部URL到OSS
if (status == 1 && form.getResult() != null && !form.getResult().isEmpty()) {
String externalImageUrl = form.getResult().get(0).getUrl();
// 调用下载方法,存储到图片目录
String ossUrl = downloadExternalUrlToOss(externalImageUrl);
task.setResultResourceUrl(ossUrl);
aiGenerationTaskMapper.updateById(task);
// 保存生成的媒体记录
MiniAiTaskMedia media = new MiniAiTaskMedia();
String mediaUuid = UUID.randomUUID().toString().replace("-", "");
AiCallbackImage image = form.getResult().get(0);
// 解析尺寸
Integer width = null;
Integer height = null;
if (image.getSize() != null && image.getSize().contains("x")) {
String[] sizeArr = image.getSize().split("x");
try {
width = Integer.parseInt(sizeArr[0]);
height = Integer.parseInt(sizeArr[1]);
} catch (Exception e) {
log.warn("解析四宫格图片尺寸失败,size:{}", image.getSize(), e);
}
}
media.setUuid(mediaUuid)
.setTaskId(task.getId())
.setMiniUserId(task.getMiniUserId())
.setFileSource("ai_generate")
.setMediaType("image")
.setSourceUrl(ossUrl)
.setWidth(width)
.setHeight(height)
.setCreateBy(task.getCreateBy())
.setCreateTimestamp(System.currentTimeMillis())
.setCreateTime(new Date());
aiTaskMediaMapper.insert(media);
// 更新用户上传的参考文件:关联当前任务ID并软删除
LambdaUpdateWrapper<MiniAiTaskMedia> updateMediaWrapper = new LambdaUpdateWrapper<>();
updateMediaWrapper.eq(MiniAiTaskMedia::getMiniUserId, task.getMiniUserId())
.isNull(MiniAiTaskMedia::getTaskId)
.eq(MiniAiTaskMedia::getFileSource, "user_upload")
.eq(MiniAiTaskMedia::getDeleted, false)
.set(MiniAiTaskMedia::getTaskId, task.getId())
.set(MiniAiTaskMedia::getDeleted, true)
.set(MiniAiTaskMedia::getUpdateTime, new Date())
.set(MiniAiTaskMedia::getUpdateTimestamp, System.currentTimeMillis());
aiTaskMediaMapper.update(null, updateMediaWrapper);
}
log.info("四宫格任务{}回调处理完成,状态:{}", taskUuid, status);
return true;
} catch (Exception e) {
log.error("四宫格任务回调处理异常,任务UUID:{},异常信息:{}", form.getUuid(), e.getMessage(), e);
return false;
}
}
@Override
public boolean handleTaskCallback(AiSingleImageCallbackForm form) {
log.info("处理单图生成任务回调,任务UUID:{}", form.getUuid());
try {
String taskUuid = form.getUuid();
// 查询任务是否存在
MiniAiGenerationTask task = getTaskByUuid(taskUuid);
if (task == null) {
log.error("单图回调任务不存在,UUID:{}", taskUuid);
return false;
}
// 转换任务状态
Integer status;
if ("succeeded".equals(form.getStatus())) {
status = 1; // 成功
} else if ("failed".equals(form.getStatus())) {
status = 2; // 失败
} else {
log.error("单图回调任务状态非法,UUID:{},status:{}", taskUuid, form.getStatus());
return false;
}
// 如果生成成功,下载外部URL到OSS
String ossUrl = null;
if (status == 1 && vo.getResult() != null && !vo.getResult().getData().isEmpty()) {
String externalResultUrl = vo.getResult().getData().get(0).getUrl();
if (status == 1 && form.getResult() != null && !form.getResult().isEmpty()) {
String externalResultUrl = form.getResult().get(0).getUrl();
ossUrl = downloadExternalUrlToOss(externalResultUrl);
// 保存生成的媒体记录
MiniAiTaskMedia media = new MiniAiTaskMedia();
String mediaUuid = UUID.randomUUID().toString().replace("-", "");
AiCallbackImage image = form.getResult().get(0);
// 解析尺寸
Integer width = null;
Integer height = null;
if (image.getSize() != null && image.getSize().contains("x")) {
String[] sizeArr = image.getSize().split("x");
try {
width = Integer.parseInt(sizeArr[0]);
height = Integer.parseInt(sizeArr[1]);
} catch (Exception e) {
log.warn("解析单图图片尺寸失败,size:{}", image.getSize(), e);
}
}
media.setUuid(mediaUuid)
.setMiniUserId(task.getMiniUserId())
@ -582,6 +693,8 @@ public class AiGenerationServiceImpl implements AiGenerationService {
.setFileSource("ai_generated")
.setMediaType("image")
.setSourceUrl(ossUrl)
.setWidth(width)
.setHeight(height)
.setCreateBy(task.getCreateBy())
.setCreateTime(new Date())
.setCreateTimestamp(System.currentTimeMillis())
@ -590,13 +703,25 @@ public class AiGenerationServiceImpl implements AiGenerationService {
.setDeleted(false);
aiTaskMediaMapper.insert(media);
// 更新用户上传的参考文件:关联当前任务ID并软删除
LambdaUpdateWrapper<MiniAiTaskMedia> updateMediaWrapper = new LambdaUpdateWrapper<>();
updateMediaWrapper.eq(MiniAiTaskMedia::getMiniUserId, task.getMiniUserId())
.isNull(MiniAiTaskMedia::getTaskId)
.eq(MiniAiTaskMedia::getFileSource, "user_upload")
.eq(MiniAiTaskMedia::getDeleted, false)
.set(MiniAiTaskMedia::getTaskId, task.getId())
.set(MiniAiTaskMedia::getDeleted, true)
.set(MiniAiTaskMedia::getUpdateTime, new Date())
.set(MiniAiTaskMedia::getUpdateTimestamp, System.currentTimeMillis());
aiTaskMediaMapper.update(null, updateMediaWrapper);
}
// 更新任务状态
return updateTaskStatus(taskUuid, status, ossUrl);
} catch (Exception e) {
log.error("处理AI任务回调异常,UUID:{},异常信息:{}", vo.getUuid(), e.getMessage(), e);
log.error("处理AI任务回调异常,UUID:{},异常信息:{}", form.getUuid(), e.getMessage(), e);
return false;
}
}
@ -655,7 +780,7 @@ public class AiGenerationServiceImpl implements AiGenerationService {
if (lastDotIndex > 0 && lastDotIndex < path.length() - 1) {
ext = path.substring(lastDotIndex + 1);
}
if (ext == null){
if (ext == null) {
log.error("无法从URL中提取文件后缀,URL:{}", externalUrl);
ext = "jpg";
}

14
src/main/resources/application-dev.yml

@ -92,7 +92,8 @@ security:
- /api/v1/mini/homePage/listByBounds
- /healthcheck
- /api/v1/mini/ai/generation/single-image/task/callback # AIGeneration 单图任务回调
- /api/v1/mini/ai/generation/video/task/callback # AIGeneration 单图任务回调
- /api/v1/mini/ai/generation/video/task/callback # AIGeneration 视频任务回调
- /api/v1/mini/ai/generation/four-panel/task/callback # AIGeneration 四宫格任务回调
# 非安全端点路径,完全绕过 Spring Security 的过滤器
unsecured-urls:
- ${springdoc.swagger-ui.path}
@ -231,12 +232,15 @@ wx:
# AIGeneration 配置
ai:
generate:
single-image-server-url: http://192.168.31.91:8001/api/v1/photo-to-comic
four-panel-server-url: http://192.168.31.91:8001/api/v1/four-panel-comic
video-server-url: http://192.168.31.91:8001/api/v1/video/submit
single-image-server-url: http://192.168.31.93:8001/api/v1/photo-to-comic
four-panel-server-url: http://192.168.31.93:8001/api/v1/four-panel-comic
video-server-url: http://192.168.31.93:8001/api/v1/video/submit
callback:
single-image-callback-url: http://192.168.31.197:30101/backend/api/v1/mini/ai/generation/task/callback
single-image-callback-url: http://192.168.31.197:30101/backend/api/v1/mini/ai/generation/single-image/task/callback
four-panel-callback-url: http://192.168.31.197:30101/backend/api/v1/mini/ai/generation/four-panel/task/callback
#需要内网穿透工具 由火山方舟 api 回调,ngrok http 30101 替换为内网穿透工具地址
video-url: http://192.168.31.197:30101/backend/api/v1/mini/ai/generation/video/task/callback
default:
image-model: doubao-seedream-5-0-260128
video-model: doubao-seedance-2-0-260128

Loading…
Cancel
Save