|
@@ -5520,12 +5520,68 @@ class AnimeService
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据 inner_prompt_type 附加内置提示词
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $prompt 用户提示词
|
|
|
|
|
+ * @param int $innerPromptType 内置提示词类型(1=三视图, 2=九宫格)
|
|
|
|
|
+ * @return string 合并后的提示词
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function appendInnerPrompt($prompt, $innerPromptType = 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ $innerPromptMap = [
|
|
|
|
|
+ 1 => '基于参考图生成主体的标准正面、侧面、后面三视图,主体完整。在最左侧添加主体正视图的特写,主体清晰完整。背景修改成纯白色,整体保持与参考图一致的美术风格和色彩搭配。画面无说明文字',
|
|
|
|
|
+ 2 => '基于参考图及提示词内容,生成9张连贯的系列图片:9张图片围绕同一主体展开,保持角色形象、美术风格和色彩搭配完全一致,画面内容依次衔接、情节连贯,整体构成一组完整的系列图。每张图片主体完整清晰,构图合理,画面干净,无文字、无水印、无字幕。',
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ if (!isset($innerPromptMap[$innerPromptType])) {
|
|
|
|
|
+ return $prompt;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return trim((string)$prompt) . "\n" . $innerPromptMap[$innerPromptType];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据 inner_prompt_type 获取生成图片数量
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $innerPromptType 内置提示词类型
|
|
|
|
|
+ * @return int 图片数量
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function getInnerImageNum($innerPromptType = 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return (int)$innerPromptType === 2 ? 9 : 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 提取图片生成结果URL
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param mixed $resultUrl 任务结果URL(数组、JSON字符串或普通字符串)
|
|
|
|
|
+ * @param int $innerPromptType 内置提示词类型
|
|
|
|
|
+ * @return mixed 类型2返回全部URL数组,其它类型返回首个URL
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function extractResultUrls($resultUrl, $innerPromptType = 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ $resultUrls = is_array($resultUrl) ? $resultUrl : json_decode((string)$resultUrl, true);
|
|
|
|
|
+
|
|
|
|
|
+ if (is_array($resultUrls) && !empty($resultUrls)) {
|
|
|
|
|
+ $resultUrls = array_values($resultUrls);
|
|
|
|
|
+ return (int)$innerPromptType === 2 ? $resultUrls : $resultUrls[0];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!empty($resultUrl)) {
|
|
|
|
|
+ return (int)$innerPromptType === 2 ? [$resultUrl] : $resultUrl;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (int)$innerPromptType === 2 ? [] : '';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public function generateImg($data) {
|
|
public function generateImg($data) {
|
|
|
$prompt = getProp($data, 'prompt');
|
|
$prompt = getProp($data, 'prompt');
|
|
|
$episode_id = getProp($data, 'episode_id');
|
|
$episode_id = getProp($data, 'episode_id');
|
|
|
$ref_img_urls = getProp($data, 'ref_img_urls');
|
|
$ref_img_urls = getProp($data, 'ref_img_urls');
|
|
|
$ratio = getProp($data, 'ratio', '9:16');
|
|
$ratio = getProp($data, 'ratio', '9:16');
|
|
|
$resolution = getProp($data, 'resolution', '2k');
|
|
$resolution = getProp($data, 'resolution', '2k');
|
|
|
|
|
+ $inner_prompt_type = getProp($data, 'inner_prompt_type', 0);
|
|
|
|
|
|
|
|
// 定义分辨率和宽高比对应的尺寸映射表
|
|
// 定义分辨率和宽高比对应的尺寸映射表
|
|
|
$sizeMap = [
|
|
$sizeMap = [
|
|
@@ -5612,6 +5668,10 @@ class AnimeService
|
|
|
// 参数验证
|
|
// 参数验证
|
|
|
if (!$prompt) Utils::throwError('20003:请提供提示词');
|
|
if (!$prompt) Utils::throwError('20003:请提供提示词');
|
|
|
|
|
|
|
|
|
|
+ // 根据 inner_prompt_type 附加内置提示词并确定生成图片数量
|
|
|
|
|
+ $prompt = self::appendInnerPrompt($prompt, $inner_prompt_type);
|
|
|
|
|
+ $imageNum = self::getInnerImageNum($inner_prompt_type);
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
// 创建图片生成任务
|
|
// 创建图片生成任务
|
|
|
$params = [
|
|
$params = [
|
|
@@ -5619,7 +5679,8 @@ class AnimeService
|
|
|
'model' => $model,
|
|
'model' => $model,
|
|
|
'ref_img_urls' => '',
|
|
'ref_img_urls' => '',
|
|
|
'width' => $width,
|
|
'width' => $width,
|
|
|
- 'height' => $height
|
|
|
|
|
|
|
+ 'height' => $height,
|
|
|
|
|
+ 'image_num' => $imageNum
|
|
|
];
|
|
];
|
|
|
if ($ref_img_urls) $params['ref_img_urls'] = is_array($ref_img_urls) ? $ref_img_urls : [$ref_img_urls];
|
|
if ($ref_img_urls) $params['ref_img_urls'] = is_array($ref_img_urls) ? $ref_img_urls : [$ref_img_urls];
|
|
|
|
|
|
|
@@ -5650,8 +5711,7 @@ class AnimeService
|
|
|
$task = MpGeneratePicTask::where('id', $task_id)->first();
|
|
$task = MpGeneratePicTask::where('id', $task_id)->first();
|
|
|
|
|
|
|
|
if ($task->status === 'success' && $task->result_url) {
|
|
if ($task->status === 'success' && $task->result_url) {
|
|
|
- $result_urls = is_array($task->result_url) ? $task->result_url : json_decode($task->result_url, true);
|
|
|
|
|
- $img_url = is_array($result_urls) ? $result_urls[0] : $task->result_url;
|
|
|
|
|
|
|
+ $img_url = self::extractResultUrls($task->result_url, $inner_prompt_type);
|
|
|
break;
|
|
break;
|
|
|
} elseif ($task->status === 'failed') {
|
|
} elseif ($task->status === 'failed') {
|
|
|
$errorMsg = mapErrorMessage($task->error_message ?? '');
|
|
$errorMsg = mapErrorMessage($task->error_message ?? '');
|
|
@@ -5670,7 +5730,7 @@ class AnimeService
|
|
|
'result_json' => $statusInfo['result_json'] ?? []
|
|
'result_json' => $statusInfo['result_json'] ?? []
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
- $img_url = $statusInfo['result_url'][0];
|
|
|
|
|
|
|
+ $img_url = self::extractResultUrls($statusInfo['result_url'], $inner_prompt_type);
|
|
|
break;
|
|
break;
|
|
|
} elseif ($statusInfo['status'] === 'failed') {
|
|
} elseif ($statusInfo['status'] === 'failed') {
|
|
|
$task->updateStatus('failed', [
|
|
$task->updateStatus('failed', [
|