Bläddra i källkod

片段转视频接口新增中文格式化报错

lh 1 vecka sedan
förälder
incheckning
01f2957e9d
1 ändrade filer med 117 tillägg och 96 borttagningar
  1. 117 96
      app/Services/Anime/AnimeService.php

+ 117 - 96
app/Services/Anime/AnimeService.php

@@ -4,6 +4,7 @@ namespace App\Services\Anime;
 
 use App\Consts\BaseConst;
 use App\Consts\ErrorConst;
+use App\Exceptions\ApiException;
 use App\Facade\Site;
 use App\Libs\Utils;
 use App\Models\MpGeneratePicTask;
@@ -5017,6 +5018,8 @@ class AnimeService
         // 音效同出(默认使用)
         $current_generate_audio = $generate_audio ? 1 : 0;
 
+        $actContent = '{程悠悠-校服黄发叛逆造型}赤裸着身体在浴室中洗澡,手轻轻抚摸着自己丰腴的乳房,口中发出呻吟声。';
+
         // 构建完整的提示词
         $processResult = $this->processActContentWithProducts($actContent, $products);
         $fullPrompt = $processResult['content'];
@@ -5141,106 +5144,117 @@ class AnimeService
         // dd($videoParams);
         
         // 根据模型选择不同的视频生成方法
-        if (strpos($model, 'jimeng') !== false) {
-            // 即梦模型参数调整
-            unset($videoParams['content']); // 即梦不使用content格式
-            $task = $this->aiVideoGenerationService->createJimengTask($videoParams);
-        } elseif (strpos($model, 'kling') !== false) {
-            // Keling模型参数调整
-            $videoParams['aspect_ratio'] = $videoParams['ratio']; // Keling使用aspect_ratio
-            unset($videoParams['ratio']);
-            unset($videoParams['content']); // Keling不使用content格式
-            $task = $this->aiVideoGenerationService->createKelingOmniTask($videoParams);
-        } elseif (strpos($model, 'zhizhen') !== false) {
-            // 智帧20等新模型使用统一API
-            // 构建统一API参数
-            $unifiedParams = [
-                'model_code' => $model,
-                'alias_act_id' => $act_id,
-                'prompt' => trim($fullPrompt),
-                'video_duration' => $videoDuration,
-                'video_resolution' => strtolower($videoParams['video_resolution']),
-                'video_ratio' => $ratio,
-                'seed' => -1,
-            ];
-            
-            // 构建parameters参数
-            $parameters = [
-                'seconds' => $unifiedParams['video_duration'],
-                'resolution' => $unifiedParams['video_resolution'],
-                'ratio' => $ratio,
-                // 'video_mode' => 'multi_image',
-                // 'mode' => 'multi_image',
-                'generate_audio' => (int)$current_generate_audio === 1 ? true : false,
-            ];
-            
-            $hasImage = false;
-            // 处理首帧和尾帧(智帧20模型必须要有首帧图片)
-            if ($hasImage) {
-                $parameters['first_frame_url'] = $videoParams['first_frame_url'];
-                if (isset($videoParams['tail_frame_url'])) {
-                    $parameters['last_frame_url'] = $videoParams['tail_frame_url'];
+        try {
+            if (strpos($model, 'jimeng') !== false) {
+                // 即梦模型参数调整
+                unset($videoParams['content']); // 即梦不使用content格式
+                $task = $this->aiVideoGenerationService->createJimengTask($videoParams);
+            } elseif (strpos($model, 'kling') !== false) {
+                // Keling模型参数调整
+                $videoParams['aspect_ratio'] = $videoParams['ratio']; // Keling使用aspect_ratio
+                unset($videoParams['ratio']);
+                unset($videoParams['content']); // Keling不使用content格式
+                $task = $this->aiVideoGenerationService->createKelingOmniTask($videoParams);
+            } elseif (strpos($model, 'zhizhen') !== false) {
+                // 智帧20等新模型使用统一API
+                // 构建统一API参数
+                $unifiedParams = [
+                    'model_code' => $model,
+                    'alias_act_id' => $act_id,
+                    'prompt' => trim($fullPrompt),
+                    'video_duration' => $videoDuration,
+                    'video_resolution' => strtolower($videoParams['video_resolution']),
+                    'video_ratio' => $ratio,
+                    'seed' => -1,
+                ];
+                
+                // 构建parameters参数
+                $parameters = [
+                    'seconds' => $unifiedParams['video_duration'],
+                    'resolution' => $unifiedParams['video_resolution'],
+                    'ratio' => $ratio,
+                    // 'video_mode' => 'multi_image',
+                    // 'mode' => 'multi_image',
+                    'generate_audio' => (int)$current_generate_audio === 1 ? true : false,
+                ];
+                
+                $hasImage = false;
+                // 处理首帧和尾帧(智帧20模型必须要有首帧图片)
+                if ($hasImage) {
+                    $parameters['first_frame_url'] = $videoParams['first_frame_url'];
+                    if (isset($videoParams['tail_frame_url'])) {
+                        $parameters['last_frame_url'] = $videoParams['tail_frame_url'];
+                    }
+                } else {
+                    // 没有图片时,记录错误日志
+                    logDB('anime', 'error', '智帧20模型缺少首帧图片', [
+                        'act_id' => $act_id,
+                        'model' => $model
+                    ]);
                 }
-            } else {
-                // 没有图片时,记录错误日志
-                logDB('anime', 'error', '智帧20模型缺少首帧图片', [
-                    'act_id' => $act_id,
-                    'model' => $model
-                ]);
-            }
 
-            if ($reference_images) {
-                // 限制只传入9张参考图
-                $reference_images = array_slice($reference_images, 0, 9);
+                if ($reference_images) {
+                    // 限制只传入9张参考图
+                    $reference_images = array_slice($reference_images, 0, 9);
 
-                // 在处理之前先保存原始reference_images到任务参数中
-                $unifiedParams['ref_image_url'] = json_encode($reference_images, 256);
-                $reference_images = $this->aiImageGenerationService->processReferenceImagesToAssets($reference_images, $unifiedParams['prompt']);
-                $parameters['reference_images'] = $reference_images;
-                $parameters['video_mode'] = 'multi_image';
-                $parameters['mode'] = 'multi_image';
-            }
-            
-            $unifiedParams['parameters'] = $parameters;
-            
-            // 调用统一API创建任务
-            $task = $this->aiVideoGenerationService->createUnifiedApiTask($unifiedParams);
-        } elseif ($this->isSeedance20SeriesModel($model)) {
-            // 豆包Seedance 2.0(百度AI网关)/ 快快AI Seedance 2.0/2.5:图片需要先上传为素材
-            $isKuaikuai = $this->isKuaikuaiSeedanceModel($model);
-            $isDreamina = $this->isOverseasBaiduSeedanceModel($model);
-            // 保存原始参考图用于任务记录
-            $videoParams['reference_images'] = $reference_images;
-
-            if ($reference_images) {
-                // 限制只传入9张参考图
-                $reference_images = array_slice($reference_images, 0, 9);
-
-                // 维护ref_image_url字段(参考图URL,JSON数组,与智帧分支保持一致)
-                $videoParams['ref_image_url'] = json_encode($reference_images, 256);
-
-                // 参考图上传为素材(国内百度/海外百度dreamina/快快AI),上传失败时同步清理提示词中的<图片N>标记
-                $reference_image_assets = $isKuaikuai
-                    ? $this->aiVideoGenerationService->processReferenceImagesToKuaikuaiAssets($reference_images, $fullPrompt)
-                    : ($isDreamina
-                        ? $this->aiVideoGenerationService->processReferenceImagesToBaiduDreaminaAssets($reference_images, $fullPrompt)
-                        : $this->aiVideoGenerationService->processReferenceImagesToSeedance20Assets($reference_images, $fullPrompt));
-
-                // 素材上传失败后提示词可能被清理,同步更新视频参数中的提示词
-                $videoParams['prompt'] = trim($fullPrompt);
-                $videoParams['content'][0]['text'] = trim($fullPrompt);
-                $videoParams['reference_image_assets'] = $reference_image_assets;
-            }
-
-            // 快快AI走聚合网关 /v1/video/generations(火山豆包格式)
-            if ($isKuaikuai) {
-                $videoParams['gateway_base_url'] = env('KUAIKUAI_AI_BASE_URL', 'https://ai-api.kkidc.com');
-                $task = $this->aiVideoGenerationService->createKuaikuaiVideoTask($videoParams);
+                    // 在处理之前先保存原始reference_images到任务参数中
+                    $unifiedParams['ref_image_url'] = json_encode($reference_images, 256);
+                    $reference_images = $this->aiImageGenerationService->processReferenceImagesToAssets($reference_images, $unifiedParams['prompt']);
+                    $parameters['reference_images'] = $reference_images;
+                    $parameters['video_mode'] = 'multi_image';
+                    $parameters['mode'] = 'multi_image';
+                }
+                
+                $unifiedParams['parameters'] = $parameters;
+                
+                // 调用统一API创建任务
+                $task = $this->aiVideoGenerationService->createUnifiedApiTask($unifiedParams);
+            } elseif ($this->isSeedance20SeriesModel($model)) {
+                // 豆包Seedance 2.0(百度AI网关)/ 快快AI Seedance 2.0/2.5:图片需要先上传为素材
+                $isKuaikuai = $this->isKuaikuaiSeedanceModel($model);
+                $isDreamina = $this->isOverseasBaiduSeedanceModel($model);
+                // 保存原始参考图用于任务记录
+                $videoParams['reference_images'] = $reference_images;
+
+                if ($reference_images) {
+                    // 限制只传入9张参考图
+                    $reference_images = array_slice($reference_images, 0, 9);
+
+                    // 维护ref_image_url字段(参考图URL,JSON数组,与智帧分支保持一致)
+                    $videoParams['ref_image_url'] = json_encode($reference_images, 256);
+
+                    // 参考图上传为素材(国内百度/海外百度dreamina/快快AI),上传失败时同步清理提示词中的<图片N>标记
+                    $reference_image_assets = $isKuaikuai
+                        ? $this->aiVideoGenerationService->processReferenceImagesToKuaikuaiAssets($reference_images, $fullPrompt)
+                        : ($isDreamina
+                            ? $this->aiVideoGenerationService->processReferenceImagesToBaiduDreaminaAssets($reference_images, $fullPrompt)
+                            : $this->aiVideoGenerationService->processReferenceImagesToSeedance20Assets($reference_images, $fullPrompt));
+
+                    // 素材上传失败后提示词可能被清理,同步更新视频参数中的提示词
+                    $videoParams['prompt'] = trim($fullPrompt);
+                    $videoParams['content'][0]['text'] = trim($fullPrompt);
+                    $videoParams['reference_image_assets'] = $reference_image_assets;
+                }
+
+                // 快快AI走聚合网关 /v1/video/generations(火山豆包格式)
+                if ($isKuaikuai) {
+                    $videoParams['gateway_base_url'] = env('KUAIKUAI_AI_BASE_URL', 'https://ai-api.kkidc.com');
+                    $task = $this->aiVideoGenerationService->createKuaikuaiVideoTask($videoParams);
+                } else {
+                    $task = $this->aiVideoGenerationService->createSeedance20Task($videoParams);
+                }
             } else {
-                $task = $this->aiVideoGenerationService->createSeedance20Task($videoParams);
+                $task = $this->aiVideoGenerationService->createSeedanceTask($videoParams);
             }
-        } else {
-            $task = $this->aiVideoGenerationService->createSeedanceTask($videoParams);
+        } catch (ApiException $e) {
+            // 上游调用抛出的网关异常统一做友好化处理;本地业务错误(非1001)保持原提示不变
+            if ($e->getCode() === 1001) {
+                Utils::throwError('1001:' . mapErrorMessage($e->getMessage()));
+            }
+            throw $e;
+        } catch (\Exception $e) {
+            // 其他未包装的异常,同样只对报错信息做格式化,便于前端展示友好提示
+            Utils::throwError('20003:' . mapErrorMessage($e->getMessage()));
         }
         
         // 更新分镜表的视频任务信息
@@ -5258,12 +5272,19 @@ class AnimeService
             Redis::sadd('anime_act_first_frame_urls', $act_id);
         }
         
-        return [
+        $result = [
             'task_id' => $task->id,
             'status' => $task->status,
             'act_id' => $act_id,
             'video_duration' => $videoDuration
         ];
+
+        // 仅当任务提交阶段就已失败时,附带格式化后的错误信息;正常返回结构不受影响
+        if ($task->status === 'failed' && !empty($task->error_message)) {
+            $result['error_message'] = mapErrorMessage($task->error_message);
+        }
+
+        return $result;
     }
 
     /**