Przeglądaj źródła

定时任务脚本也新增对分镜表的更新和视频配音任务的创建

lh 4 dni temu
rodzic
commit
05e2225e6f

+ 1 - 1
app/Console/Commands/CheckImageGenerationTasksCommand.php

@@ -32,7 +32,7 @@ class CheckImageGenerationTasksCommand extends Command
     {
         dLog('generate')->info('开始检查图片生成任务状态...');
 
-        // 执行40s
+        // 执行50s
         $time_start = time();
         try {
             $count = DB::table('mp_generate_pic_tasks')->where('status', 'processing')->count('id');

+ 16 - 7
app/Console/Commands/CheckVideoGenerationTasksCommand.php

@@ -4,6 +4,7 @@ namespace App\Console\Commands;
 
 use App\Services\AIGeneration\AIVideoGenerationService;
 use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
 
 class CheckVideoGenerationTasksCommand extends Command
 {
@@ -24,19 +25,27 @@ class CheckVideoGenerationTasksCommand extends Command
     /**
      * Execute the console command.
      *
+     * @param AIVideoGenerationService $videoGenerationService
      * @return int
      */
     public function handle(AIVideoGenerationService $videoGenerationService)
     {
-        $this->info('开始检查视频生成任务状态...');
-        
+        dLog('generate')->info('开始检查视频生成任务状态...');
+
+        // 执行50s
+        $time_start = time();
         try {
-            // 更新所有待处理的视频生成任务状态
-            $videoGenerationService->updatePendingTasks();
-            
-            $this->info('视频生成任务状态检查完成');
+            $count = DB::table('mp_generate_video_tasks')->where('status', 'processing')->count('id');
+            while ($count > 0) {
+                $time_diff = time() - $time_start;
+                sleep(3);
+                if ($time_diff > 50) break;
+                $videoGenerationService->updatePendingTasks();
+                $count = DB::table('mp_generate_video_tasks')->where('status', 'processing')->count('id');
+            }
+            dLog('generate')->info('视频任务状态检查完成');
         } catch (\Exception $e) {
-            $this->error('视频生成任务状态检查失败: ' . $e->getMessage());
+            dLog('generate')->error('视频任务状态检查失败: ' . $e->getMessage());
             return 1;
         }
 

+ 79 - 28
app/Http/Controllers/Anime/AnimeController.php

@@ -355,16 +355,87 @@ class AnimeController extends BaseController
                                 ]) ? now() : null
                             ]);
                             
-                            // 如果任务成功,更新分镜表
+                            // 如果任务成功,使用事务更新分镜表并创建配音任务
                             if ($statusResult['status'] === 'success' && isset($statusResult['result_url'])) {
-                                DB::table('mp_episode_segments')
-                                    ->where('video_task_id', $taskId)
-                                    ->update([
-                                        'video_url' => $statusResult['result_url'],
-                                        'video_task_status' => '已完成',
-                                        'last_frame_url' => $statusResult['last_frame_url'] ?? '',
-                                        'updated_at' => date('Y-m-d H:i:s')
+                                try {
+                                    DB::beginTransaction();
+                                    
+                                    $now = date('Y-m-d H:i:s');
+                                    
+                                    // 获取分镜ID
+                                    $segment = DB::table('mp_episode_segments')
+                                        ->where('video_task_id', $taskId)
+                                        ->first();
+                                    
+                                    if (!$segment) {
+                                        throw new \Exception('未找到对应的分镜记录');
+                                    }
+                                    
+                                    $segmentId = $segment->segment_id;
+                                    
+                                    // 更新分镜表
+                                    $updateResult = DB::table('mp_episode_segments')
+                                        ->where('segment_id', $segmentId)
+                                        ->update([
+                                            'video_url' => $statusResult['result_url'],
+                                            'video_task_status' => '已完成',
+                                            'last_frame_url' => $statusResult['last_frame_url'] ?? '',
+                                            'updated_at' => $now
+                                        ]);
+                                    
+                                    if (!$updateResult) {
+                                        Utils::throwError('20003:更新分镜表失败');
+                                    }
+                                    
+                                    // 获取分镜信息用于创建配音任务
+                                    $segmentInfo = DB::table('mp_episode_segments')
+                                        ->where('segment_id', $segmentId)
+                                        ->select('voice_actor', 'dialogue', 'voice_type', 'voice_name', 'emotion', 'emotion_type', 'gender', 'speed_ratio', 'loudness_ratio', 'emotion_scale', 'pitch')
+                                        ->first();
+                                    
+                                    // 如果分镜有对话内容,创建视频配音合成任务
+                                    $dubTaskId = null;
+                                    if ($segmentInfo && !empty($segmentInfo->dialogue)) {
+                                        $generate_json = [
+                                            'text' => $segmentInfo->dialogue,
+                                            'role' => $segmentInfo->voice_actor,
+                                            'voice_type' => $segmentInfo->voice_type,
+                                            'voice_name' => $segmentInfo->voice_name,
+                                            'emotion' => $segmentInfo->emotion,
+                                            'emotion_type' => $segmentInfo->emotion_type,
+                                            'gender' => $segmentInfo->gender,
+                                            'speed_ratio' => $segmentInfo->speed_ratio ?? 0,
+                                            'loudness_ratio' => $segmentInfo->loudness_ratio ?? 0,
+                                            'emotion_scale' => $segmentInfo->emotion_scale ?? 0,
+                                            'pitch' => $segmentInfo->pitch ?? 0,
+                                        ];
+                                        
+                                        // 插入视频配音合成任务
+                                        $dubTaskId = DB::table('mp_dub_video_tasks')->insertGetId([
+                                            'alias_segment_id' => $segmentId,
+                                            'video_url' => $statusResult['result_url'],
+                                            'generate_status' => '执行中',
+                                            'dub_video_url' => '',
+                                            'generate_json' => json_encode($generate_json, 256),
+                                            'created_at' => $now,
+                                            'updated_at' => $now,
+                                        ]);
+                                        
+                                        if (!$dubTaskId) {
+                                            Utils::throwError('20003:创建配音任务失败');
+                                        }
+                                    }
+                                    
+                                    DB::commit();
+                                    
+                                } catch (\Exception $e) {
+                                    DB::rollBack();
+                                    
+                                    dLog('anime')->error('视频任务处理失败', [
+                                        'task_id' => $taskId,
+                                        'error' => $e->getMessage()
                                     ]);
+                                }
                             } elseif ($statusResult['status'] === 'failed') {
                                 DB::table('mp_episode_segments')
                                     ->where('video_task_id', $taskId)
@@ -384,7 +455,6 @@ class AnimeController extends BaseController
                             'status' => $task->status,
                             'result_url' => $task->result_url,
                             'error_message' => $task->error_message,
-                            'progress' => $this->getTaskProgress($task->status),
                             'elapsed_time' => time() - $startTime
                         ]
                     ]) . "\n\n";
@@ -444,24 +514,6 @@ class AnimeController extends BaseController
             'X-Accel-Buffering' => 'no', // 禁用 Nginx 缓冲
         ]);
     }
-    
-    /**
-     * 获取任务进度百分比
-     */
-    private function getTaskProgress($status) {
-        switch ($status) {
-            case \App\Models\MpGenerateVideoTask::STATUS_PENDING:
-                return 10;
-            case \App\Models\MpGenerateVideoTask::STATUS_PROCESSING:
-                return 50;
-            case \App\Models\MpGenerateVideoTask::STATUS_SUCCESS:
-                return 100;
-            case \App\Models\MpGenerateVideoTask::STATUS_FAILED:
-                return 0;
-            default:
-                return 0;
-        }
-    }
 
     /**
      * 批量生成分镜视频
@@ -809,7 +861,6 @@ class AnimeController extends BaseController
                             'task_id' => $taskId,
                             'segment_number' => $segmentTask['segment_number'],
                             'status' => $task->status,
-                            'progress' => $this->getTaskProgress($task->status),
                             'video_url' => $task->result_url,
                             'error_message' => $task->error_message
                         ];

+ 241 - 1
app/Services/AIGeneration/AIVideoGenerationService.php

@@ -286,8 +286,79 @@ class AIVideoGenerationService
 
         if ($statusInfo['status'] === 'success') {
             $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+            
+            // 同步调整分镜视频状态和结果
+            $segment_id = getProp($task, 'alias_segment_id');
+            if ($segment_id && isset($statusInfo['result_url'])) {
+                try {
+                    DB::beginTransaction();
+                    
+                    $now = date('Y-m-d H:i:s');
+                    
+                    // 更新分镜表
+                    DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update([
+                        'video_url' => $statusInfo['result_url'],
+                        'video_task_status' => '已完成',
+                        'last_frame_url' => $statusInfo['last_frame_url'] ?? '',
+                        'updated_at' => $now
+                    ]);
+                    
+                    // 获取分镜信息用于创建配音任务
+                    $segment = DB::table('mp_episode_segments')
+                        ->where('segment_id', $segment_id)
+                        ->select('voice_actor', 'dialogue', 'voice_type', 'voice_name', 'emotion', 'emotion_type', 'gender', 'speed_ratio', 'loudness_ratio', 'emotion_scale', 'pitch')
+                        ->first();
+                    
+                    // 如果分镜有对话内容,创建视频配音合成任务
+                    if ($segment && !empty($segment->dialogue)) {
+                        $generate_json = [
+                            'text' => $segment->dialogue,
+                            'role' => $segment->voice_actor,
+                            'voice_type' => $segment->voice_type,
+                            'voice_name' => $segment->voice_name,
+                            'emotion' => $segment->emotion,
+                            'emotion_type' => $segment->emotion_type,
+                            'gender' => $segment->gender,
+                            'speed_ratio' => $segment->speed_ratio ?? 0,
+                            'loudness_ratio' => $segment->loudness_ratio ?? 0,
+                            'emotion_scale' => $segment->emotion_scale ?? 0,
+                            'pitch' => $segment->pitch ?? 0,
+                        ];
+                        
+                        // 插入视频配音合成任务
+                        DB::table('mp_dub_video_tasks')->insert([
+                            'alias_segment_id' => $segment_id,
+                            'video_url' => $statusInfo['result_url'],
+                            'generate_status' => '执行中',
+                            'dub_video_url' => '',
+                            'generate_json' => json_encode($generate_json, 256),
+                            'created_at' => $now,
+                            'updated_at' => $now,
+                        ]);
+                    }
+                    
+                    DB::commit();
+                    
+                } catch (\Exception $e) {
+                    DB::rollBack();
+                    dLog('generate')->error('即梦视频任务处理失败', [
+                        'segment_id' => $segment_id,
+                        'task_id' => $task->id,
+                        'error' => $e->getMessage()
+                    ]);
+                }
+            }
         } elseif ($statusInfo['status'] === 'failed') {
             $task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, $statusInfo);
+            
+            // 同步更新分镜表状态为失败
+            $segment_id = getProp($task, 'alias_segment_id');
+            if ($segment_id) {
+                DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update([
+                    'video_task_status' => '失败',
+                    'updated_at' => date('Y-m-d H:i:s')
+                ]);
+            }
         }
         // 如果仍然是处理中状态,不做任何操作
         
@@ -297,6 +368,15 @@ class AIVideoGenerationService
             $task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
                 'error_message' => '任务处理超时(超过12小时)'
             ]);
+            
+            // 同步更新分镜表状态为失败
+            $segment_id = getProp($task, 'alias_segment_id');
+            if ($segment_id) {
+                DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update([
+                    'video_task_status' => '失败',
+                    'updated_at' => date('Y-m-d H:i:s')
+                ]);
+            }
         }
     }
     
@@ -480,20 +560,100 @@ class AIVideoGenerationService
 
         if ($statusInfo['status'] === 'success') {
             $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+            
+            // 同步调整分镜视频状态和结果
+            $segment_id = getProp($task, 'alias_segment_id');
+            if ($segment_id && isset($statusInfo['result_url'])) {
+                try {
+                    DB::beginTransaction();
+                    
+                    $now = date('Y-m-d H:i:s');
+                    
+                    // 更新分镜表
+                    DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update([
+                        'video_url' => $statusInfo['result_url'],
+                        'video_task_status' => '已完成',
+                        'last_frame_url' => $statusInfo['last_frame_url'] ?? '',
+                        'updated_at' => $now
+                    ]);
+                    
+                    // 获取分镜信息用于创建配音任务
+                    $segment = DB::table('mp_episode_segments')
+                        ->where('segment_id', $segment_id)
+                        ->select('voice_actor', 'dialogue', 'voice_type', 'voice_name', 'emotion', 'emotion_type', 'gender', 'speed_ratio', 'loudness_ratio', 'emotion_scale', 'pitch')
+                        ->first();
+                    
+                    // 如果分镜有对话内容,创建视频配音合成任务
+                    if ($segment && !empty($segment->dialogue)) {
+                        $generate_json = [
+                            'text' => $segment->dialogue,
+                            'role' => $segment->voice_actor,
+                            'voice_type' => $segment->voice_type,
+                            'voice_name' => $segment->voice_name,
+                            'emotion' => $segment->emotion,
+                            'emotion_type' => $segment->emotion_type,
+                            'gender' => $segment->gender,
+                            'speed_ratio' => $segment->speed_ratio ?? 0,
+                            'loudness_ratio' => $segment->loudness_ratio ?? 0,
+                            'emotion_scale' => $segment->emotion_scale ?? 0,
+                            'pitch' => $segment->pitch ?? 0,
+                        ];
+                        
+                        // 插入视频配音合成任务
+                        DB::table('mp_dub_video_tasks')->insert([
+                            'alias_segment_id' => $segment_id,
+                            'video_url' => $statusInfo['result_url'],
+                            'generate_status' => '执行中',
+                            'dub_video_url' => '',
+                            'generate_json' => json_encode($generate_json, 256),
+                            'created_at' => $now,
+                            'updated_at' => $now,
+                        ]);
+                    }
+                    
+                    DB::commit();
+                    
+                } catch (\Exception $e) {
+                    DB::rollBack();
+                    dLog('generate')->error('Seedance视频任务处理失败', [
+                        'segment_id' => $segment_id,
+                        'task_id' => $task->id,
+                        'error' => $e->getMessage()
+                    ]);
+                }
+            }
         } elseif ($statusInfo['status'] === 'failed') {
             $task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
                 'error_message' => $statusInfo['error_message'],
                 'result_json'   => $statusInfo['result_json'] ?? []
             ]);
+            
+            // 同步更新分镜表状态为失败
+            $segment_id = getProp($task, 'alias_segment_id');
+            if ($segment_id) {
+                DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update([
+                    'video_task_status' => '失败',
+                    'updated_at' => date('Y-m-d H:i:s')
+                ]);
+            }
         }
         // 如果仍然是处理中状态,不做任何操作
         
-        // 处理:如果任务处理超过12小时,标记为失败
+        // 处理:如果任务处理超过48小时,标记为失败
         $processingTime = now()->diffInHours($task->created_at);
         if ($processingTime > 48) {
             $task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
                 'error_message' => '任务处理超时(超过48小时)'
             ]);
+            
+            // 同步更新分镜表状态为失败
+            $segment_id = getProp($task, 'alias_segment_id');
+            if ($segment_id) {
+                DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update([
+                    'video_task_status' => '失败',
+                    'updated_at' => date('Y-m-d H:i:s')
+                ]);
+            }
         }
     }
 
@@ -1122,11 +1282,82 @@ class AIVideoGenerationService
 
         if ($statusInfo['status'] === 'success') {
             $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+            
+            // 同步调整分镜视频状态和结果
+            $segment_id = getProp($task, 'alias_segment_id');
+            if ($segment_id && isset($statusInfo['result_url'])) {
+                try {
+                    DB::beginTransaction();
+                    
+                    $now = date('Y-m-d H:i:s');
+                    
+                    // 更新分镜表
+                    DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update([
+                        'video_url' => $statusInfo['result_url'],
+                        'video_task_status' => '已完成',
+                        'last_frame_url' => $statusInfo['last_frame_url'] ?? '',
+                        'updated_at' => $now
+                    ]);
+                    
+                    // 获取分镜信息用于创建配音任务
+                    $segment = DB::table('mp_episode_segments')
+                        ->where('segment_id', $segment_id)
+                        ->select('voice_actor', 'dialogue', 'voice_type', 'voice_name', 'emotion', 'emotion_type', 'gender', 'speed_ratio', 'loudness_ratio', 'emotion_scale', 'pitch')
+                        ->first();
+                    
+                    // 如果分镜有对话内容,创建视频配音合成任务
+                    if ($segment && !empty($segment->dialogue)) {
+                        $generate_json = [
+                            'text' => $segment->dialogue,
+                            'role' => $segment->voice_actor,
+                            'voice_type' => $segment->voice_type,
+                            'voice_name' => $segment->voice_name,
+                            'emotion' => $segment->emotion,
+                            'emotion_type' => $segment->emotion_type,
+                            'gender' => $segment->gender,
+                            'speed_ratio' => $segment->speed_ratio ?? 0,
+                            'loudness_ratio' => $segment->loudness_ratio ?? 0,
+                            'emotion_scale' => $segment->emotion_scale ?? 0,
+                            'pitch' => $segment->pitch ?? 0,
+                        ];
+                        
+                        // 插入视频配音合成任务
+                        DB::table('mp_dub_video_tasks')->insert([
+                            'alias_segment_id' => $segment_id,
+                            'video_url' => $statusInfo['result_url'],
+                            'generate_status' => '执行中',
+                            'dub_video_url' => '',
+                            'generate_json' => json_encode($generate_json, 256),
+                            'created_at' => $now,
+                            'updated_at' => $now,
+                        ]);
+                    }
+                    
+                    DB::commit();
+                    
+                } catch (\Exception $e) {
+                    DB::rollBack();
+                    dLog('generate')->error('可灵视频任务处理失败', [
+                        'segment_id' => $segment_id,
+                        'task_id' => $task->id,
+                        'error' => $e->getMessage()
+                    ]);
+                }
+            }
         } elseif ($statusInfo['status'] === 'failed') {
             $task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
                 'error_message' => $statusInfo['error_message'],
                 'result_json' => $statusInfo['result_json'] ?? []
             ]);
+            
+            // 同步更新分镜表状态为失败
+            $segment_id = getProp($task, 'alias_segment_id');
+            if ($segment_id) {
+                DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update([
+                    'video_task_status' => '失败',
+                    'updated_at' => date('Y-m-d H:i:s')
+                ]);
+            }
         }
         // 如果仍然是处理中状态,不做任何操作
         
@@ -1136,6 +1367,15 @@ class AIVideoGenerationService
             $task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
                 'error_message' => '任务处理超时(超过24小时)'
             ]);
+            
+            // 同步更新分镜表状态为失败
+            $segment_id = getProp($task, 'alias_segment_id');
+            if ($segment_id) {
+                DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update([
+                    'video_task_status' => '失败',
+                    'updated_at' => date('Y-m-d H:i:s')
+                ]);
+            }
         }
     }