|
|
|
@ -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"; |
|
|
|
} |
|
|
|
|