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

1.新增超分1080p分辨率模式2.新增超分720p到1080p公共方法3.视频生成任务和积分统计等兼容超分1080p模式

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

+ 9 - 3
app/Http/Controllers/Anime/AnimeController.php

@@ -2874,6 +2874,8 @@ class AnimeController extends BaseController
         }
         $episodeNumber = $episode->episode_number;        
         $ratio = !empty($episode->ratio) ? $episode->ratio : '9:16';
+        // 使用剧集保存的视频参数(saveActVideoGenerateParams 保存的 video_resolution / video_model)
+        $videoResolution = !empty($episode->video_resolution) ? $episode->video_resolution : '720p';
         $generate_audio = getProp($data, 'generate_audio', 1);
 
         // 合并角色、场景和道具作为products,统一字段名为product_name
@@ -2928,7 +2930,11 @@ class AnimeController extends BaseController
         //         $model = 'zhizhen-20';
         //     }
         // }
-        $model = 'seed-2'; // 使用默认值
+        // 使用剧集保存的视频模型,未保存时使用默认值
+        $model = getProp($episode, 'video_model');
+        if (!$model) {
+            $model = 'seed-2'; // 使用默认值
+        }
         // 验证模型是否在可用模型表中
         if (!DB::table('mp_video_models')->where('model', $model)->where('is_enabled', 1)->exists()) {
             $model = 'seed-2';
@@ -2988,7 +2994,7 @@ class AnimeController extends BaseController
             }
             $needPoints += $this->pointsService->getVideoChargePoints([
                 'model' => $model,
-                'video_resolution' => '720p',
+                'video_resolution' => $videoResolution,
                 'video_duration' => $duration,
                 'ratio' => $ratio,
                 'generate_audio' => (int)$generate_audio,
@@ -3034,7 +3040,7 @@ class AnimeController extends BaseController
                     'alias_act_id' => $act->id,
                     'prompt' => $fullPrompt,
                     'video_duration' => $videoDuration,
-                    'video_resolution' => '720P',
+                    'video_resolution' => $videoResolution,
                     'seed' => -1,
                     'ratio' => $ratio,
                     'generate_audio' => (int)$generate_audio === 0 ? false : true,

+ 61 - 32
app/Libs/Helpers.php

@@ -5277,14 +5277,17 @@ function mapErrorMessage($errorMessage)
 }
 
 /**
- * 将480p视频升级到720p(使用FFmpeg本地超分,强制输出720*1280或1280*720分辨率)
- * 
+ * 视频超分:480p档升级到720p,720p档升级到1080p(使用FFmpeg本地超分)
+ * 目标分辨率按源视频方向强制为标准档位(横屏 16:9 / 竖屏 9:16)
+ * 可通过 $targetResolution 显式指定目标档位(720p/1080p),显式指定优先;未指定时按源档位自动识别
+ *
  * @param string|resource $videoSource 视频URL地址或视频内容(字符串)
  * @param string $prefix 上传文件夹前缀(如:'video')
  * @param bool $isContent 是否为视频内容而非URL(默认false)
- * @return string 返回升级后的视频URL,失败返回原视频URL或空字符串
+ * @param string $targetResolution 显式目标档位:'720p' 或 '1080p',空字符串表示自动识别
+ * @return string 返回超分后的视频URL,失败返回原视频URL或空字符串
  */
-function upgrade480pTo720p($videoSource, $prefix = 'video', $isContent = false)
+function upgrade480pTo720p($videoSource, $prefix = 'video', $isContent = false, $targetResolution = '')
 {
     if (env('APP_ENV') == 'local') {
         return $isContent ? '' : $videoSource;
@@ -5342,13 +5345,13 @@ function upgrade480pTo720p($videoSource, $prefix = 'video', $isContent = false)
         }
 
         $inputFileSize = filesize($inputFile);
-        dLog('video_upgrade')->info('视频准备完成,开始升级到720p', [
+        dLog('video_upgrade')->info('视频准备完成,开始超分', [
             'source' => $videoUrl,
             'size' => $inputFileSize,
             'size_mb' => round($inputFileSize / 1024 / 1024, 2) . 'MB'
         ]);
 
-        // 获取视频分辨率,确保短边为720
+        // 获取视频分辨率,根据源档位选择目标档位
         // 使用 ffprobe 的 JSON 输出,这是最可靠的方式
         $ffprobePath = env('FFPROBE_PATH', 'ffprobe');
         $ffmpegPath = env('FFMPEG_PATH', 'ffmpeg');
@@ -5378,43 +5381,69 @@ function upgrade480pTo720p($videoSource, $prefix = 'video', $isContent = false)
             'json_parsed' => !empty($videoInfo)
         ]);
         
-        // 根据视频方向决定目标标准分辨率,强制720*1280(竖屏)或1280*720(横屏),不再按比例计算
+        // 根据视频方向决定目标标准分辨率
+        // 480p档 -> 720p(720*1280 竖屏 / 1280*720 横屏)
+        // 720p档 -> 1080p(1080*1920 竖屏 / 1920*1080 横屏)
+        $shortSide = min($width, $height);
+        $targetShortSide = 0;
+        $targetResolution = strtolower(trim($targetResolution));
+        if (in_array($targetResolution, ['720p', '1080p'], true)) {
+            // 显式指定档位优先(不允许降级:源短边超过目标档位则跳过)
+            $targetShortSide = $targetResolution === '720p' ? 720 : 1080;
+            if ($shortSide > $targetShortSide + 40) {
+                dLog('video_upgrade')->info('视频分辨率高于目标档位,跳过超分', [
+                    'width' => $width,
+                    'height' => $height,
+                    'target' => $targetResolution
+                ]);
+                @unlink($inputFile);
+                return $isContent ? '' : $videoSource;
+            }
+        } elseif ($shortSide > 0 && abs($shortSide - 480) <= 40) {
+            $targetShortSide = 720;
+        } elseif ($shortSide > 0 && abs($shortSide - 720) <= 40) {
+            $targetShortSide = 1080;
+        } else {
+            // 自动识别且非480p/720p档,无需超分,直接返回原视频
+            dLog('video_upgrade')->info('视频不属于480p/720p档位,跳过超分', [
+                'width' => $width,
+                'height' => $height,
+                'short_side' => $shortSide
+            ]);
+            @unlink($inputFile);
+            return $isContent ? '' : $videoSource;
+        }
+
+        $isPortrait = $width > 0 && $height > 0 && $width < $height;
+        $targetWidth = $isPortrait ? $targetShortSide : (int)round($targetShortSide * 16 / 9);
+        $targetHeight = $isPortrait ? (int)round($targetShortSide * 16 / 9) : $targetShortSide;
+        $scaleFilter = "scale={$targetWidth}:{$targetHeight}:flags=lanczos:force_original_aspect_ratio=decrease,pad={$targetWidth}:{$targetHeight}:(ow-iw)/2:(oh-ih)/2";
+
         if ($width > 0 && $height > 0) {
             dLog('video_upgrade')->info('缩放计算详情', [
                 'original' => "{$width}x{$height}",
-                'target' => $width < $height ? '720x1280' : '1280x720',
+                'target' => "{$targetWidth}x{$targetHeight}",
                 'is_portrait' => $width < $height ? 'yes' : 'no'
             ]);
-            
-            if ($width < $height) {
-                // 竖屏:强制720*1280(scale保持宽高比 + pad补边)
-                $scaleFilter = "scale=720:1280:flags=lanczos:force_original_aspect_ratio=decrease,pad=720:1280:(ow-iw)/2:(oh-ih)/2";
-                dLog('video_upgrade')->info('检测到竖屏视频,强制720*1280', [
-                    'original_size' => "{$width}x{$height}",
-                    'target_size' => '720x1280',
-                    'scale_filter' => $scaleFilter
-                ]);
-            } else {
-                // 横屏:强制1280*720(scale保持宽高比 + pad补边)
-                $scaleFilter = "scale=1280:720:flags=lanczos:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2";
-                dLog('video_upgrade')->info('检测到横屏视频,强制1280*720', [
-                    'original_size' => "{$width}x{$height}",
-                    'target_size' => '1280x720',
-                    'scale_filter' => $scaleFilter
-                ]);
-            }
+            dLog('video_upgrade')->info(($isPortrait ? '竖屏' : '横屏') . '视频超分', [
+                'original_size' => "{$width}x{$height}",
+                'target_size' => "{$targetWidth}x{$targetHeight}",
+                'scale_filter' => $scaleFilter
+            ]);
         } else {
-            // 无法获取分辨率,默认按横屏1280*720处理
-            $scaleFilter = "scale=1280:720:flags=lanczos:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2";
-            dLog('video_upgrade')->warning('无法获取视频分辨率,默认按1280*720处理');
+            // 无法获取分辨率,默认按横屏处理
+            $targetWidth = (int)round($targetShortSide * 16 / 9);
+            $targetHeight = $targetShortSide;
+            $scaleFilter = "scale={$targetWidth}:{$targetHeight}:flags=lanczos:force_original_aspect_ratio=decrease,pad={$targetWidth}:{$targetHeight}:(ow-iw)/2:(oh-ih)/2";
+            dLog('video_upgrade')->warning('无法获取视频分辨率,默认按横屏处理');
         }
 
         // 输出文件路径
         $outputFile = $tempDir . '/' . $uniqueId . '_output.mp4';
 
-        // 使用FFmpeg将视频升级到720p,使用高质量的Lanczos算法和锐化滤镜
+        // 使用FFmpeg超分视频,使用高质量的Lanczos算法和锐化滤镜
         // 滤镜说明:
-        // 1. scale: 使用Lanczos算法缩放并保持宽高比,pad补边到720*1280或1280*720标准分辨率
+        // 1. scale: 使用Lanczos算法缩放并保持宽高比,pad补边到标准分辨率(720p或1080p档)
         // 2. unsharp=5:5:1.0:5:5:0.5: 锐化滤镜,增强细节
         //    - 5:5:1.0 表示亮度锐化(luma_msize_x:luma_msize_y:luma_amount)
         //    - 5:5:0.5 表示色度锐化(chroma_msize_x:chroma_msize_y:chroma_amount)
@@ -5449,7 +5478,7 @@ function upgrade480pTo720p($videoSource, $prefix = 'video', $isContent = false)
         
         $ffmpegCmd = "$ffmpegPath -i \"$inputFile\" -vf \"$scaleFilter,unsharp=$unsharp,hqdn3d=1.5:1.5:6:6\" -c:v libx264 -preset $preset -crf $crf -tune film -profile:v high -level 4.1 -pix_fmt yuv420p -c:a aac -b:a $audioBitrate -movflags +faststart -y \"$outputFile\" 2>&1";
         
-        dLog('video_upgrade')->info('开始FFmpeg升级视频到720p', ['command' => $ffmpegCmd]);
+        dLog('video_upgrade')->info('开始FFmpeg超分视频', ['command' => $ffmpegCmd]);
         $output = shell_exec($ffmpegCmd);
 
         if (!file_exists($outputFile)) {

+ 96 - 34
app/Services/AIGeneration/AIVideoGenerationService.php

@@ -137,12 +137,14 @@ class AIVideoGenerationService
             }
 
             // 根据任务类型选择对应的req_key
+            // sr_1080p(超分1080p)按720p生成,本地再超分到1080p
+            $is720Like = in_array(strtolower((string)$task->video_resolution), ['720p', 'sr_1080p'], true);
             if ($task->first_frame_url && $task->tail_frame_url) {
-                $req_key = $task->video_resolution == '720P' ? 'jimeng_i2v_first_tail_v30' : 'jimeng_i2v_first_tail_v30_1080';
+                $req_key = $is720Like ? 'jimeng_i2v_first_tail_v30' : 'jimeng_i2v_first_tail_v30_1080';
             }else if($task->first_frame_url){
-                $req_key = $task->video_resolution == '720P' ? 'jimeng_i2v_first_v30' : 'jimeng_i2v_first_v30_1080';
+                $req_key = $is720Like ? 'jimeng_i2v_first_v30' : 'jimeng_i2v_first_v30_1080';
             }else{
-                $req_key = $task->video_resolution == '720P' ? 'jimeng_t2v_v30' : 'jimeng_t2v_v30_1080p';
+                $req_key = $is720Like ? 'jimeng_t2v_v30' : 'jimeng_t2v_v30_1080p';
             }
                 
             // 构建即梦AI 3.0 视频生成API请求参数
@@ -235,12 +237,14 @@ class AIVideoGenerationService
             }
 
             // 根据任务类型选择对应的req_key
+            // sr_1080p(超分1080p)按720p生成,本地再超分到1080p
+            $is720Like = in_array(strtolower((string)$task->video_resolution), ['720p', 'sr_1080p'], true);
             if ($task->first_frame_url && $task->tail_frame_url) {
-                $req_key = $task->video_resolution == '720P' ? 'jimeng_i2v_first_tail_v30' : 'jimeng_i2v_first_tail_v30_1080';
+                $req_key = $is720Like ? 'jimeng_i2v_first_tail_v30' : 'jimeng_i2v_first_tail_v30_1080';
             }else if($task->first_frame_url){
-                $req_key = $task->video_resolution == '720P' ? 'jimeng_i2v_first_v30' : 'jimeng_i2v_first_v30_1080';
+                $req_key = $is720Like ? 'jimeng_i2v_first_v30' : 'jimeng_i2v_first_v30_1080';
             }else{
-                $req_key = $task->video_resolution == '720P' ? 'jimeng_t2v_v30' : 'jimeng_t2v_v30_1080p';
+                $req_key = $is720Like ? 'jimeng_t2v_v30' : 'jimeng_t2v_v30_1080p';
             }
     
             // 构建查询参数
@@ -299,14 +303,14 @@ class AIVideoGenerationService
                     $videoContent = file_get_contents($result['video_url']);
 
                     // 从任务中获取视频分辨率,仅480p视频执行480p->720p超分
-                    if (strpos(strtoupper((string)$task->video_resolution), '480') !== false) {
+                    if ($this->shouldUpgradeVideoResolution($task)) {
                         dLog('generate')->info('即梦检测到480p视频,开始480p->720p超分', [
                             'original_url' => $result['video_url'],
                             'video_resolution' => $task->video_resolution,
                             'size' => round(strlen($videoContent) / 1024 / 1024, 2) . 'MB'
                         ]);
 
-                        $url = upgrade480pTo720p($videoContent, 'video', true);
+                        $url = upgrade480pTo720p($videoContent, 'video', true, $this->getVideoUpgradeTarget($task));
                         if (!$url) {
                             // 超分失败,上传原视频
                             dLog('generate')->warning('即梦视频超分失败,使用原视频');
@@ -787,7 +791,7 @@ class AIVideoGenerationService
                 $apiParams['draft'] = $extraParams['draft'];
             }
             if (!empty($extraParams['video_resolution'])) {
-                $apiParams['resolution'] = strtolower($task->video_resolution);
+                $apiParams['resolution'] = $this->apiRequestResolution($task->video_resolution);
             }
             if (!empty($extraParams['ratio'])) {
                 $apiParams['ratio'] = $extraParams['ratio'];
@@ -1017,8 +1021,8 @@ class AIVideoGenerationService
         $watermark = !empty($params['watermark']);
         $generateAudio = isset($params['generate_audio']) ? (bool)$params['generate_audio'] : true;
 
-        // 分辨率归一化:480p / 720p / 1080p / 4k
-        $resolution = strtolower((string)($params['resolution'] ?? $params['video_resolution'] ?? '720p'));
+        // 分辨率归一化:480p / 720p / 1080p / 4k(sr_1080p 请求时按 720p 生成,本地再超分)
+        $resolution = $this->apiRequestResolution((string)($params['resolution'] ?? $params['video_resolution'] ?? '720p'));
         if (in_array($resolution, ['4k', '2160p', '2160'], true)) {
             $resolution = '4k';
         } else {
@@ -1104,9 +1108,9 @@ class AIVideoGenerationService
     /**
      * 快快AI请求接口模型名适配(仅外部接口调用传参,系统记录保持原模型名)
      * 规则:
-     * - seed-2:480p/720p -> seed-2;1080p -> seed-2-1080;4k -> seed-2-4k
-     *           带参考视频时分别对应 seed-2-vision / seed-2-vision-1080 / seed-2-vision-4k
-     * - seed-2-fast / seed-2-mini / seed-2.5:仅支持 -vision(不带分辨率变体)
+     * - seed-2 / seed-2.5:480p/720p -> 原模型;1080p -> -1080;4k -> -4k
+     *           带参考视频时分别对应 -vision / -vision-1080 / -vision-4k
+     * - seed-2-fast / seed-2-mini:仅支持 -vision(不带分辨率变体)
      *
      * @param string $model 系统内模型名
      * @param string $resolution 归一化分辨率(480p/720p/1080p/4k)
@@ -1115,9 +1119,9 @@ class AIVideoGenerationService
      */
     private function kuaikuaiRequestModel(string $model, string $resolution, bool $hasReferenceVideo): string
     {
-        // seed-2 支持 1080p / 4k 分辨率变体
-        if ($model === 'seed-2') {
-            $base = 'seed-2' . ($hasReferenceVideo ? '-vision' : '');
+        // seed-2 / seed-2.5 支持 1080p / 4k 分辨率变体(与参考视频组合 -vision)
+        if (in_array($model, ['seed-2', 'seed-2.5'], true)) {
+            $base = $model . ($hasReferenceVideo ? '-vision' : '');
             if ($resolution === '1080p') {
                 return $base . '-1080';
             }
@@ -1127,12 +1131,11 @@ class AIVideoGenerationService
             return $base;
         }
 
-        // seed-2-fast / seed-2-mini / seed-2.5 仅适配 -vision,不带分辨率
+        // seed-2-fast / seed-2-mini 仅适配 -vision,不带分辨率
         if ($hasReferenceVideo) {
             $map = [
                 'seed-2-fast' => 'seed-2-fast-vision',
                 'seed-2-mini' => 'seed-2-mini-vision',
-                'seed-2.5' => 'seed-2.5-vision',
             ];
             return $map[$model] ?? $model;
         }
@@ -1158,6 +1161,54 @@ class AIVideoGenerationService
     }
 
     /**
+     * 请求外部API时的分辨率映射
+     * sr_1080p(超分1080p)模式:外部按720p生成,本地再超分到1080p,因此请求分辨率统一改为720p
+     *
+     * @param string $resolution
+     * @return string
+     */
+    private function apiRequestResolution(string $resolution): string
+    {
+        $resolution = strtolower(trim($resolution));
+        if (in_array($resolution, ['sr_1080p', 'sr1080p'], true)) {
+            return '720p';
+        }
+        return $resolution;
+    }
+
+    /**
+     * 判断任务是否需要本地超分(480p -> 720p;sr_1080p -> 1080p)
+     * 超分统一走 upgrade480pTo720p(内部按源档位自动选择目标分辨率)
+     *
+     * @param object $task
+     * @return bool
+     */
+    private function shouldUpgradeVideoResolution($task): bool
+    {
+        $resolution = strtoupper((string)getProp($task, 'video_resolution', ''));
+        return strpos($resolution, '480') !== false || strpos($resolution, 'SR_1080') !== false;
+    }
+
+    /**
+     * 获取任务本地超分目标档位(显式传给 upgrade480pTo720p)
+     * 480p -> 720p;sr_1080p -> 1080p
+     *
+     * @param object $task
+     * @return string '720p'|'1080p'|''(空表示由超分函数自动识别)
+     */
+    private function getVideoUpgradeTarget($task): string
+    {
+        $resolution = strtoupper((string)getProp($task, 'video_resolution', ''));
+        if (strpos($resolution, 'SR_1080') !== false) {
+            return '1080p';
+        }
+        if (strpos($resolution, '480') !== false) {
+            return '720p';
+        }
+        return '';
+    }
+
+    /**
      * 将 Seedance 2.0 参考图上传为百度AI网关素材
      * 失败处理与智帧AI的processReferenceImagesToAssets一致:删除参考图的同时清理提示词中的<图片N>标记
      *
@@ -2610,14 +2661,14 @@ class AIVideoGenerationService
                     $videoContent = file_get_contents($video_url);
 
                     // 从任务中获取视频分辨率,仅480p视频执行480p->720p超分
-                    if (strpos(strtoupper((string)$task->video_resolution), '480') !== false) {
+                    if ($this->shouldUpgradeVideoResolution($task)) {
                         dLog('generate')->info('Seedance检测到480p视频,开始480p->720p超分', [
                             'original_url' => $video_url,
                             'video_resolution' => $task->video_resolution,
                             'size' => round(strlen($videoContent) / 1024 / 1024, 2) . 'MB'
                         ]);
 
-                        $url = upgrade480pTo720p($videoContent, 'video', true);
+                        $url = upgrade480pTo720p($videoContent, 'video', true, $this->getVideoUpgradeTarget($task));
                         if (!$url) {
                             // 超分失败,上传原视频
                             dLog('generate')->warning('Seedance视频超分失败,使用原视频');
@@ -2879,14 +2930,14 @@ class AIVideoGenerationService
             $videoContent = file_get_contents($video_url);
 
             // 从任务中获取视频分辨率,仅480p视频执行480p->720p超分
-            if (strpos(strtoupper((string)$task->video_resolution), '480') !== false) {
+            if ($this->shouldUpgradeVideoResolution($task)) {
                 dLog('generate')->info('Seedance检测到480p视频,开始480p->720p超分', [
                     'original_url' => $video_url,
                     'video_resolution' => $task->video_resolution,
                     'size' => round(strlen($videoContent) / 1024 / 1024, 2) . 'MB'
                 ]);
 
-                $url = upgrade480pTo720p($videoContent, 'video', true);
+                $url = upgrade480pTo720p($videoContent, 'video', true, $this->getVideoUpgradeTarget($task));
                 if (!$url) {
                     // 超分失败,上传原视频
                     dLog('generate')->warning('Seedance视频超分失败,使用原视频');
@@ -3034,14 +3085,14 @@ class AIVideoGenerationService
                         $videoContent = file_get_contents($video_url);
 
                         // 从任务中获取视频分辨率,仅480p视频执行480p->720p超分
-                        if (strpos(strtoupper((string)$task->video_resolution), '480') !== false) {
+                        if ($this->shouldUpgradeVideoResolution($task)) {
                             dLog('generate')->info('Seedance回调检测到480p视频,开始480p->720p超分', [
                                 'original_url' => $video_url,
                                 'video_resolution' => $task->video_resolution,
                                 'size' => round(strlen($videoContent) / 1024 / 1024, 2) . 'MB'
                             ]);
 
-                            $url = upgrade480pTo720p($videoContent, 'video', true);
+                            $url = upgrade480pTo720p($videoContent, 'video', true, $this->getVideoUpgradeTarget($task));
                             if (!$url) {
                                 // 超分失败,上传原视频
                                 dLog('generate')->warning('Seedance回调视频超分失败,使用原视频');
@@ -3592,14 +3643,14 @@ class AIVideoGenerationService
                     $videoContent = file_get_contents($video_url);
 
                     // 从任务中获取视频分辨率,仅480p视频执行480p->720p超分
-                    if (strpos(strtoupper((string)$task->video_resolution), '480') !== false) {
+                    if ($this->shouldUpgradeVideoResolution($task)) {
                         dLog('generate')->info('可灵检测到480p视频,开始480p->720p超分', [
                             'original_url' => $video_url,
                             'video_resolution' => $task->video_resolution,
                             'size' => round(strlen($videoContent) / 1024 / 1024, 2) . 'MB'
                         ]);
 
-                        $url = upgrade480pTo720p($videoContent, 'video', true);
+                        $url = upgrade480pTo720p($videoContent, 'video', true, $this->getVideoUpgradeTarget($task));
                         if (!$url) {
                             // 超分失败,上传原视频
                             dLog('generate')->warning('可灵视频超分失败,使用原视频');
@@ -4698,7 +4749,7 @@ class AIVideoGenerationService
                 'model_code' => $extraParams['model_code'] ?? 'zhizhen-20',
                 'prompt' => $task->prompt,
                 'video_duration' => $extraParams['video_duration'] ?? 5,
-                'video_resolution' => $task->video_resolution,
+                'video_resolution' => $this->apiRequestResolution((string)$task->video_resolution),
                 'video_ratio' => $extraParams['video_ratio'] ?? '9:16',
             ];
 
@@ -4709,7 +4760,12 @@ class AIVideoGenerationService
 
             // 添加parameters参数
             if (!empty($extraParams['parameters'])) {
-                $apiParams['parameters'] = $extraParams['parameters'];
+                $parameters = $extraParams['parameters'];
+                // sr_1080p 请求时按 720p 生成,本地再超分
+                if (isset($parameters['resolution'])) {
+                    $parameters['resolution'] = $this->apiRequestResolution((string)$parameters['resolution']);
+                }
+                $apiParams['parameters'] = $parameters;
             }
             
             dLog('generate')->info('统一API视频生成参数: ', $apiParams);
@@ -4880,14 +4936,14 @@ class AIVideoGenerationService
                         $videoContent = file_get_contents($videoUrl);
 
                         // 从任务中获取视频分辨率,仅480p视频执行480p->720p超分
-                        if (strpos(strtoupper((string)$task->video_resolution), '480') !== false) {
+                        if ($this->shouldUpgradeVideoResolution($task)) {
                             dLog('generate')->info('检测到480p视频,开始480p->720p超分', [
                                 'original_url' => $videoUrl,
                                 'video_resolution' => $task->video_resolution,
                                 'size' => round(strlen($videoContent) / 1024 / 1024, 2) . 'MB'
                             ]);
 
-                            $enhancedUrl = upgrade480pTo720p($videoContent, 'video', true);
+                            $enhancedUrl = upgrade480pTo720p($videoContent, 'video', true, $this->getVideoUpgradeTarget($task));
                             if ($enhancedUrl) {
                                 dLog('generate')->info('视频超分成功', ['enhanced_url' => $enhancedUrl]);
                                 $url = $enhancedUrl;
@@ -5274,7 +5330,7 @@ class AIVideoGenerationService
      */
     private function ensureStandardVideoResolution($videoUrl, $targetResolution = '720p')
     {
-        if (empty($videoUrl) || !in_array($targetResolution, ['720p', '1080p'])) {
+        if (empty($videoUrl) || !in_array($targetResolution, ['720p', '1080p', 'sr_1080p'])) {
             return $videoUrl;
         }
 
@@ -5330,10 +5386,12 @@ class AIVideoGenerationService
                 return $videoUrl;
             }
 
-            // 3. 档位校验:仅处理实际属于720p/1080p档位的视频(短边接近目标值),其他分辨率不处理
+            // 3. 档位校验:仅处理实际属于目标档位的视频(短边接近目标值),其他分辨率不处理
             $shortSide = min($width, $height);
+            // 兜底标准化:仅处理已属于目标档位的视频(超分由 upgrade480pTo720p 负责,这里不做放大)
             $targetShortSide = $targetResolution === '720p' ? 720 : 1080;
-            if (abs($shortSide - $targetShortSide) > 40) {
+            $isMatch = abs($shortSide - $targetShortSide) <= 40;
+            if (!$isMatch) {
                 dLog('video_standard')->info('视频不属于目标分辨率档位,跳过处理', [
                     'url' => $videoUrl,
                     'source' => $width . 'x' . $height,
@@ -5348,6 +5406,7 @@ class AIVideoGenerationService
                 $targetWidth = $isPortrait ? 720 : 1280;
                 $targetHeight = $isPortrait ? 1280 : 720;
             } else {
+                // 1080p / sr_1080p 统一目标:16:9 -> 1920x1080,9:16 -> 1080x1920
                 $targetWidth = $isPortrait ? 1080 : 1920;
                 $targetHeight = $isPortrait ? 1920 : 1080;
             }
@@ -5419,6 +5478,9 @@ class AIVideoGenerationService
     private function getTaskTargetResolution($task)
     {
         $resolution = strtoupper((string)getProp($task, 'video_resolution', ''));
+        if (strpos($resolution, 'SR_1080') !== false) {
+            return 'sr_1080p';
+        }
         if (strpos($resolution, '480') !== false) {
             return '720p';
         }

+ 6 - 1
app/Services/PointsService.php

@@ -103,7 +103,12 @@ class PointsService
             return self::DEFAULT_VIDEO_CHARGE_POINTS;
         }
 
-        $pricePerSecond = $prices[$this->normalizeResolutionKey($resolution)] ?? null;
+        $resKey = $this->normalizeResolutionKey($resolution);
+        $pricePerSecond = $prices[$resKey] ?? null;
+        // sr_1080p 无单独定价时回退 720p 档
+        if ($pricePerSecond === null && $resKey === 'sr_1080p') {
+            $pricePerSecond = $prices['720p'] ?? null;
+        }
         if ($pricePerSecond === null || (float)$pricePerSecond <= 0) {
             return self::DEFAULT_VIDEO_CHARGE_POINTS;
         }