Просмотр исходного кода

1.新增百度模型并适配外部API请求参数2.批量生成视频增加对快快AI和百度API的兼容

lh 1 месяц назад
Родитель
Сommit
a8e18111c9

+ 35 - 4
app/Http/Controllers/Anime/AnimeController.php

@@ -907,7 +907,7 @@ class AnimeController extends BaseController
                 
                 
                 // 如果有首帧图片,添加到content中
                 // 如果有首帧图片,添加到content中
                 if ($hasImage) {
                 if ($hasImage) {
-                    if (in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128'])) {
+                    if (in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-260128', 'baidu-doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-mini-260615'])) {
                         $videoParams['content'][] = [
                         $videoParams['content'][] = [
                             'type' => 'image_url',
                             'type' => 'image_url',
                             'image_url' => [
                             'image_url' => [
@@ -995,10 +995,41 @@ class AnimeController extends BaseController
                     
                     
                     // 调用统一API创建任务
                     // 调用统一API创建任务
                     $task = $this->AIVideoGenerationService->createUnifiedApiTask($unifiedParams);
                     $task = $this->AIVideoGenerationService->createUnifiedApiTask($unifiedParams);
+                } elseif ($this->AnimeService->isSeedance20SeriesModel($model)) {
+                    // 豆包Seedance 2.0(百度AI网关)/ 快快AI Seedance 2.0/2.5:图片需要先上传为素材
+                    $isKuaikuai = $this->AnimeService->isKuaikuaiSeedanceModel($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);
+
+                        // 参考图上传为素材(百度网关/快快AI),上传失败时同步清理提示词中的<图片N>标记
+                        $reference_image_assets = $isKuaikuai
+                            ? $this->AIVideoGenerationService->processReferenceImagesToKuaikuaiAssets($reference_images, $videoParams['prompt'])
+                            : $this->AIVideoGenerationService->processReferenceImagesToSeedance20Assets($reference_images, $videoParams['prompt']);
+
+                        // 素材上传失败后提示词可能被清理,同步更新视频参数中的提示词
+                        $videoParams['prompt'] = trim($videoParams['prompt']);
+                        $videoParams['content'][0]['text'] = trim($videoParams['prompt']);
+                        $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 {
                 } else {
                     // Seedance模型(默认)
                     // Seedance模型(默认)
                     // 检查是否为 Seedance 2.0 模型,如果是则需要处理配音音频
                     // 检查是否为 Seedance 2.0 模型,如果是则需要处理配音音频
-                    if ($canUseAudio && in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128'])) {
+                    if ($canUseAudio && in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-260128', 'baidu-doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-mini-260615'])) {
                         // 添加配音音频到content中
                         // 添加配音音频到content中
                         $videoParams['content'][] = [
                         $videoParams['content'][] = [
                             'type' => 'audio_url',
                             'type' => 'audio_url',
@@ -3031,7 +3062,7 @@ class AnimeController extends BaseController
                 
                 
                 // 如果有首帧图片,添加到content中
                 // 如果有首帧图片,添加到content中
                 if ($hasImage) {
                 if ($hasImage) {
-                    if (in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128'])) {
+                    if (in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-260128', 'baidu-doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-mini-260615'])) {
                         $videoParams['content'][] = [
                         $videoParams['content'][] = [
                             'type' => 'image_url',
                             'type' => 'image_url',
                             'image_url' => [
                             'image_url' => [
@@ -3118,7 +3149,7 @@ class AnimeController extends BaseController
                 } else {
                 } else {
                     // Seedance模型(默认)
                     // Seedance模型(默认)
                     // 检查是否为 Seedance 2.0 模型,如果是则需要处理配音音频
                     // 检查是否为 Seedance 2.0 模型,如果是则需要处理配音音频
-                    if ($canUseAudio && in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128'])) {
+                    if ($canUseAudio && in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-260128', 'baidu-doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-mini-260615'])) {
                         // 添加配音音频到content中
                         // 添加配音音频到content中
                         $videoParams['content'][] = [
                         $videoParams['content'][] = [
                             'type' => 'audio_url',
                             'type' => 'audio_url',

+ 21 - 3
app/Services/AIGeneration/AIVideoGenerationService.php

@@ -760,9 +760,10 @@ class AIVideoGenerationService
                 }
                 }
             }
             }
             
             
-            // 构建火山引擎 Seedance API 请求参数
+            // 构建火山引擎 Seedance API 请求参数(百度模型先映射为网关原名)
+            $requestModel = $this->baiduModelAliasMap((string)($extraParams['model'] ?? ''));
             $apiParams = [
             $apiParams = [
-                'model' => isset(\App\Consts\BaseConst::MODELS_MAP[$extraParams['model']]) ? \App\Consts\BaseConst::MODELS_MAP[$extraParams['model']] : $extraParams['model'],
+                'model' => isset(\App\Consts\BaseConst::MODELS_MAP[$requestModel]) ? \App\Consts\BaseConst::MODELS_MAP[$requestModel] : $requestModel,
                 'content' => $content,
                 'content' => $content,
             ];
             ];
 
 
@@ -773,7 +774,7 @@ class AIVideoGenerationService
             if (isset($extraParams['return_last_frame'])) {
             if (isset($extraParams['return_last_frame'])) {
                 $apiParams['return_last_frame'] = $extraParams['return_last_frame'];
                 $apiParams['return_last_frame'] = $extraParams['return_last_frame'];
             }
             }
-            if (!empty($extraParams['service_tier']) && !in_array($extraParams['model'], ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'doubao-seedance-2.0'])) {
+            if (!empty($extraParams['service_tier']) && !in_array($requestModel, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'doubao-seedance-2.0'])) {
                 $apiParams['service_tier'] = $extraParams['service_tier'];
                 $apiParams['service_tier'] = $extraParams['service_tier'];
             }
             }
             if (!empty($extraParams['execution_expires_after'])) {
             if (!empty($extraParams['execution_expires_after'])) {
@@ -1140,6 +1141,23 @@ class AIVideoGenerationService
     }
     }
 
 
     /**
     /**
+     * 百度AI网关模型名映射:系统内使用 baidu- 前缀名,请求网关时映射为 doubao- 原名
+     *
+     * @param string $model
+     * @return string
+     */
+    private function baiduModelAliasMap(string $model): string
+    {
+        $map = [
+            'baidu-doubao-seedance-2-0-260128' => 'doubao-seedance-2-0-260128',
+            'baidu-doubao-seedance-2-0-fast-260128' => 'doubao-seedance-2-0-fast-260128',
+            'baidu-doubao-seedance-2-0-mini-260615' => 'doubao-seedance-2-0-mini-260615',
+        ];
+
+        return $map[$model] ?? $model;
+    }
+
+    /**
      * 将 Seedance 2.0 参考图上传为百度AI网关素材
      * 将 Seedance 2.0 参考图上传为百度AI网关素材
      * 失败处理与智帧AI的processReferenceImagesToAssets一致:删除参考图的同时清理提示词中的<图片N>标记
      * 失败处理与智帧AI的processReferenceImagesToAssets一致:删除参考图的同时清理提示词中的<图片N>标记
      *
      *

+ 35 - 6
app/Services/Anime/AnimeService.php

@@ -4671,7 +4671,7 @@ class AnimeService
         
         
         // 如果有首帧图片,添加到content中
         // 如果有首帧图片,添加到content中
         if ($hasImage) {
         if ($hasImage) {
-            if (in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128'])) {
+            if (in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-260128', 'baidu-doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-mini-260615'])) {
                 $videoParams['content'][] = [
                 $videoParams['content'][] = [
                     'type' => 'image_url',
                     'type' => 'image_url',
                     'image_url' => [
                     'image_url' => [
@@ -4811,7 +4811,7 @@ class AnimeService
                     $videoParams['video_duration'] = max(4, min(12, ceil($audioDuration)));
                     $videoParams['video_duration'] = max(4, min(12, ceil($audioDuration)));
                 }
                 }
                 $task = $this->aiVideoGenerationService->createKuaikuaiVideoTask($videoParams);
                 $task = $this->aiVideoGenerationService->createKuaikuaiVideoTask($videoParams);
-            } elseif ($canUseAudio && in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128'])) {
+            } elseif ($canUseAudio && in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-260128', 'baidu-doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-mini-260615'])) {
             // 检查是否为 Seedance 2.0 模型,如果是则需要处理配音音频
             // 检查是否为 Seedance 2.0 模型,如果是则需要处理配音音频
                 // 添加配音音频到content中
                 // 添加配音音频到content中
                 $videoParams['content'][] = [
                 $videoParams['content'][] = [
@@ -4857,11 +4857,40 @@ class AnimeService
      * @param string $model
      * @param string $model
      * @return bool
      * @return bool
      */
      */
-    private function isKuaikuaiSeedanceModel(string $model): bool
+    public function isKuaikuaiSeedanceModel(string $model): bool
     {
     {
         return in_array($model, ['seed-2-fast', 'seed-2-mini', 'seed-2.5', 'seed-2'], true);
         return in_array($model, ['seed-2-fast', 'seed-2-mini', 'seed-2.5', 'seed-2'], true);
     }
     }
 
 
+    /**
+     * 是否为百度AI网关Seedance 2.0系列模型(系统内使用 baidu- 前缀名,请求网关时映射为 doubao- 原名)
+     *
+     * @param string $model
+     * @return bool
+     */
+    public function isBaiduSeedanceModel(string $model): bool
+    {
+        return in_array($model, [
+            'baidu-doubao-seedance-2-0-260128',
+            'baidu-doubao-seedance-2-0-fast-260128',
+            'baidu-doubao-seedance-2-0-mini-260615',
+        ], true);
+    }
+
+    /**
+     * 是否为 Seedance 2.0 系列模型(百度 doubao-seedance-2.0 / baidu-* / 快快AI seed-2 系列)
+     * 供单条与批量生成入口统一判断,避免各入口各自维护模型白名单
+     *
+     * @param string $model
+     * @return bool
+     */
+    public function isSeedance20SeriesModel(string $model): bool
+    {
+        return strpos($model, 'doubao-seedance-2.0') !== false
+            || $this->isKuaikuaiSeedanceModel($model)
+            || $this->isBaiduSeedanceModel($model);
+    }
+
     public function createActVideoTask($data) {
     public function createActVideoTask($data) {
         $act_id = getProp($data, 'act_id');
         $act_id = getProp($data, 'act_id');
         $first_frame_url = getProp($data, 'first_frame_url');
         $first_frame_url = getProp($data, 'first_frame_url');
@@ -5038,7 +5067,7 @@ class AnimeService
         
         
         // 如果有首帧图片,添加到content中
         // 如果有首帧图片,添加到content中
         if ($hasImage) {
         if ($hasImage) {
-            if (in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'doubao-seedance-2.0'])) {
+            if (in_array($model, ['doubao-seedance-2-0-260128', 'doubao-seedance-2-0-fast-260128', 'doubao-seedance-2.0', 'baidu-doubao-seedance-2-0-260128', 'baidu-doubao-seedance-2-0-fast-260128', 'baidu-doubao-seedance-2-0-mini-260615'])) {
                 $videoParams['content'][] = [
                 $videoParams['content'][] = [
                     'type' => 'image_url',
                     'type' => 'image_url',
                     'image_url' => [
                     'image_url' => [
@@ -5143,7 +5172,7 @@ class AnimeService
             
             
             // 调用统一API创建任务
             // 调用统一API创建任务
             $task = $this->aiVideoGenerationService->createUnifiedApiTask($unifiedParams);
             $task = $this->aiVideoGenerationService->createUnifiedApiTask($unifiedParams);
-        } elseif (strpos($model, 'doubao-seedance-2.0') !== false || $this->isKuaikuaiSeedanceModel($model)) {
+        } elseif ($this->isSeedance20SeriesModel($model)) {
             // 豆包Seedance 2.0(百度AI网关)/ 快快AI Seedance 2.0/2.5:图片需要先上传为素材
             // 豆包Seedance 2.0(百度AI网关)/ 快快AI Seedance 2.0/2.5:图片需要先上传为素材
             $isKuaikuai = $this->isKuaikuaiSeedanceModel($model);
             $isKuaikuai = $this->isKuaikuaiSeedanceModel($model);
             // 保存原始参考图用于任务记录
             // 保存原始参考图用于任务记录
@@ -5358,7 +5387,7 @@ class AnimeService
 
 
             // 调用统一API创建任务
             // 调用统一API创建任务
             $task = $this->aiVideoGenerationService->createUnifiedApiTask($unifiedParams);
             $task = $this->aiVideoGenerationService->createUnifiedApiTask($unifiedParams);
-        } elseif (strpos($model, 'doubao-seedance-2.0') !== false || $this->isKuaikuaiSeedanceModel($model)) {
+        } elseif ($this->isSeedance20SeriesModel($model)) {
             // 豆包Seedance 2.0(百度AI网关)/ 快快AI Seedance 2.0/2.5:图片/视频/音频需要先上传为素材
             // 豆包Seedance 2.0(百度AI网关)/ 快快AI Seedance 2.0/2.5:图片/视频/音频需要先上传为素材
             $isKuaikuai = $this->isKuaikuaiSeedanceModel($model);
             $isKuaikuai = $this->isKuaikuaiSeedanceModel($model);
             $videoParams['reference_images'] = $reference_images;
             $videoParams['reference_images'] = $reference_images;