Browse Source

修复图片或视频任务并发时产生多条对话历史记录的问题

lh 1 tháng trước cách đây
mục cha
commit
620e3dcfab

+ 23 - 3
app/Console/Commands/CheckVideoGenerationTasksCommand.php

@@ -169,7 +169,7 @@ class CheckVideoGenerationTasksCommand extends Command
                     
                     
                     $successCount++;
                     $successCount++;
                     
                     
-                    // 更新分镜视频成功后新增对话记录
+                    // 更新分镜视频成功后新增对话记录(addVideoGenerationRecords 内部按 video_task_id 幂等)
                     $this->addVideoGenerationRecords($videoTask, $segmentId, $videoTask->result_url);
                     $this->addVideoGenerationRecords($videoTask, $segmentId, $videoTask->result_url);
                     
                     
                     dLog('command')->info('分镜视频生成成功', [
                     dLog('command')->info('分镜视频生成成功', [
@@ -280,7 +280,25 @@ class CheckVideoGenerationTasksCommand extends Command
                 $assistantContent = $segment->act_show_content ? $segment->act_show_content : $segment->act_content;
                 $assistantContent = $segment->act_show_content ? $segment->act_show_content : $segment->act_content;
                 if (!$assistantContent) $assistantContent = '';
                 if (!$assistantContent) $assistantContent = '';
             }
             }
-            
+
+            // 同一视频任务只写一次对话记录(仅在有任务ID时按任务幂等,允许多个任务对应同一 act)
+            $videoTaskId = getProp($task, 'id');
+            if (!empty($videoTaskId)) {
+                $exists = DB::table('mp_anime_records')
+                    ->where('video_task_id', $videoTaskId)
+                    ->where('role', 'assistant')
+                    ->exists();
+
+                if ($exists) {
+                    dLog('generate')->info('该视频任务的对话记录已存在,跳过重复写入', [
+                        'video_task_id' => $videoTaskId,
+                        'segment_id_or_act_id' => $segmentIdOrActId,
+                        'video_url' => $videoUrl
+                    ]);
+                    return;
+                }
+            }
+
             // 保存对话记录
             // 保存对话记录
             $records = [
             $records = [
                 [
                 [
@@ -289,6 +307,7 @@ class CheckVideoGenerationTasksCommand extends Command
                     'sequence'      => $segment->episode_number,
                     'sequence'      => $segment->episode_number,
                     'role'          => 'user',
                     'role'          => 'user',
                     'content'       => $userContent,
                     'content'       => $userContent,
+                    'video_task_id' => $videoTaskId,
                     $recordField    => $recordValue,
                     $recordField    => $recordValue,
                     'video_url'     => '',
                     'video_url'     => '',
                     'reference_images' => json_encode([], 256),
                     'reference_images' => json_encode([], 256),
@@ -301,6 +320,7 @@ class CheckVideoGenerationTasksCommand extends Command
                     'sequence'      => $segment->episode_number,
                     'sequence'      => $segment->episode_number,
                     'role'          => 'assistant',
                     'role'          => 'assistant',
                     'content'       => $assistantContent,
                     'content'       => $assistantContent,
+                    'video_task_id' => $videoTaskId,
                     $recordField    => $recordValue,
                     $recordField    => $recordValue,
                     'video_url'     => $videoUrl,
                     'video_url'     => $videoUrl,
                     'reference_images' => $reference_images,
                     'reference_images' => $reference_images,
@@ -326,4 +346,4 @@ class CheckVideoGenerationTasksCommand extends Command
             ]);
             ]);
         }
         }
     }
     }
-}
+}

+ 1 - 1
app/Console/Kernel.php

@@ -32,7 +32,7 @@ class Kernel extends ConsoleKernel
         $schedule->command('AIGeneration:checkImgTasks')->everyMinute();
         $schedule->command('AIGeneration:checkImgTasks')->everyMinute();
         
         
         // 检查视频生成任务状态
         // 检查视频生成任务状态
-        $schedule->command('AIGeneration:checkVideoTasks')->everyMinute();
+        $schedule->command('AIGeneration:checkVideoTasks')->everyMinute()->withoutOverlapping(5);
 
 
         // 检查动漫对话图片生成状态
         // 检查动漫对话图片生成状态
         $schedule->command('Anime:checkImgUrl')->everyMinute();
         $schedule->command('Anime:checkImgUrl')->everyMinute();

+ 157 - 23
app/Services/AIGeneration/AIVideoGenerationService.php

@@ -370,8 +370,15 @@ class AIVideoGenerationService
                 try {
                 try {
                     DB::beginTransaction();
                     DB::beginTransaction();
                     
                     
-                    // 在事务中更新任务状态
-                    $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                    // 原子抢占:只有仍为 processing 的任务能更新为 success,避免并发重复处理
+                    if (!$this->markVideoTaskSuccess($task, $statusInfo)) {
+                        DB::rollBack();
+                        dLog('generate')->info('视频任务已被其他进程处理,跳过重复更新', [
+                            'id' => $task->id,
+                            'result_url' => $statusInfo['result_url'] ?? null
+                        ]);
+                        return;
+                    }
                     
                     
                     $now = date('Y-m-d H:i:s');
                     $now = date('Y-m-d H:i:s');
                     
                     
@@ -414,7 +421,7 @@ class AIVideoGenerationService
                 }
                 }
             } else {
             } else {
                 // 没有segment_id的情况下,直接更新任务状态
                 // 没有segment_id的情况下,直接更新任务状态
-                $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                $this->markVideoTaskSuccess($task, $statusInfo);
             }
             }
         } elseif ($statusInfo['status'] === 'failed') {
         } elseif ($statusInfo['status'] === 'failed') {
             logDB('generate', 'error', '即梦AI视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
             logDB('generate', 'error', '即梦AI视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
@@ -1127,8 +1134,15 @@ class AIVideoGenerationService
                 try {
                 try {
                     DB::beginTransaction();
                     DB::beginTransaction();
                     
                     
-                    // 在事务中更新任务状态
-                    $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                    // 原子抢占:只有仍为 processing 的任务能更新为 success,避免并发重复处理
+                    if (!$this->markVideoTaskSuccess($task, $statusInfo)) {
+                        DB::rollBack();
+                        dLog('generate')->info('视频任务已被其他进程处理,跳过重复更新', [
+                            'id' => $task->id,
+                            'result_url' => $statusInfo['result_url'] ?? null
+                        ]);
+                        return;
+                    }
                     
                     
                     $now = date('Y-m-d H:i:s');
                     $now = date('Y-m-d H:i:s');
                     
                     
@@ -1173,7 +1187,7 @@ class AIVideoGenerationService
                 }
                 }
             } else {
             } else {
                 // 没有segment_id的情况下,直接更新任务状态
                 // 没有segment_id的情况下,直接更新任务状态
-                $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                $this->markVideoTaskSuccess($task, $statusInfo);
             }
             }
         } elseif ($statusInfo['status'] === 'failed') {
         } elseif ($statusInfo['status'] === 'failed') {
             logDB('generate', 'error', 'Seedance视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
             logDB('generate', 'error', 'Seedance视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
@@ -1556,14 +1570,31 @@ class AIVideoGenerationService
                 }
                 }
             }
             }
             
             
-            // 更新任务记录
-            $task->update($updateData);
+            // 成功任务的状态更新放到下方事务中做原子抢占,其他状态直接更新
+            if (!($taskStatus === MpGenerateVideoTask::STATUS_SUCCESS && isset($updateData['result_url']))) {
+                $task->update($updateData);
+            }
             
             
             // 如果任务成功,更新分镜表
             // 如果任务成功,更新分镜表
             if ($taskStatus === MpGenerateVideoTask::STATUS_SUCCESS && isset($updateData['result_url'])) {
             if ($taskStatus === MpGenerateVideoTask::STATUS_SUCCESS && isset($updateData['result_url'])) {
                 try {
                 try {
                     DB::beginTransaction();
                     DB::beginTransaction();
                     
                     
+                    // 原子抢占:只有仍为 processing 的任务能更新为 success,避免回调与轮询重复处理
+                    if (!$this->markVideoTaskSuccess($task, $updateData)) {
+                        DB::rollBack();
+                        dLog('generate')->info('Seedance 任务已被其他进程处理,跳过重复更新', [
+                            'id' => $task->id,
+                            'result_url' => $updateData['result_url'] ?? null
+                        ]);
+                        return [
+                            'success' => true,
+                            'message' => '任务已被其他进程处理',
+                            'task_id' => $taskId,
+                            'status' => $taskStatus
+                        ];
+                    }
+                    
                     $now = date('Y-m-d H:i:s');
                     $now = date('Y-m-d H:i:s');
                     
                     
                     // 获取分镜ID(兼容分镜模式和全能模式)
                     // 获取分镜ID(兼容分镜模式和全能模式)
@@ -1616,6 +1647,7 @@ class AIVideoGenerationService
                                 'role'          => 'user',
                                 'role'          => 'user',
                                 'content'       => '图片转视频',
                                 'content'       => '图片转视频',
                                 'segment_id'    => $segmentId,
                                 'segment_id'    => $segmentId,
+                                'video_task_id' => getProp($task, 'id'),
                                 'video_url'     => '',
                                 'video_url'     => '',
                                 'created_at'    => $now,
                                 'created_at'    => $now,
                                 'updated_at'    => $now
                                 'updated_at'    => $now
@@ -1627,6 +1659,7 @@ class AIVideoGenerationService
                                 'role'          => 'assistant',
                                 'role'          => 'assistant',
                                 'content'       => $tail_frame,
                                 'content'       => $tail_frame,
                                 'segment_id'    => $segmentId,
                                 'segment_id'    => $segmentId,
+                                'video_task_id' => getProp($task, 'id'),
                                 'video_url'     => $updateData['result_url'],
                                 'video_url'     => $updateData['result_url'],
                                 'created_at'    => $now,
                                 'created_at'    => $now,
                                 'updated_at'    => $now
                                 'updated_at'    => $now
@@ -2132,8 +2165,15 @@ class AIVideoGenerationService
                 try {
                 try {
                     DB::beginTransaction();
                     DB::beginTransaction();
                     
                     
-                    // 在事务中更新任务状态
-                    $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                    // 原子抢占:只有仍为 processing 的任务能更新为 success,避免并发重复处理
+                    if (!$this->markVideoTaskSuccess($task, $statusInfo)) {
+                        DB::rollBack();
+                        dLog('generate')->info('视频任务已被其他进程处理,跳过重复更新', [
+                            'id' => $task->id,
+                            'result_url' => $statusInfo['result_url'] ?? null
+                        ]);
+                        return;
+                    }
                     
                     
                     $now = date('Y-m-d H:i:s');
                     $now = date('Y-m-d H:i:s');
                     
                     
@@ -2178,7 +2218,7 @@ class AIVideoGenerationService
                 }
                 }
             } else {
             } else {
                 // 没有segment_id的情况下,直接更新任务状态
                 // 没有segment_id的情况下,直接更新任务状态
-                $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                $this->markVideoTaskSuccess($task, $statusInfo);
             }
             }
         } elseif ($statusInfo['status'] === 'failed') {
         } elseif ($statusInfo['status'] === 'failed') {
             $task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
             $task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, [
@@ -2813,7 +2853,25 @@ class AIVideoGenerationService
                 $assistantContent = $segment->act_show_content ? $segment->act_show_content : $segment->act_content;
                 $assistantContent = $segment->act_show_content ? $segment->act_show_content : $segment->act_content;
                 if (!$assistantContent) $assistantContent = '';
                 if (!$assistantContent) $assistantContent = '';
             }
             }
-            
+
+            // 同一视频任务只写一次对话记录(仅在有任务ID时按任务幂等,允许多个任务对应同一 act)
+            $videoTaskId = getProp($task, 'id');
+            if (!empty($videoTaskId)) {
+                $exists = DB::table('mp_anime_records')
+                    ->where('video_task_id', $videoTaskId)
+                    ->where('role', 'assistant')
+                    ->exists();
+
+                if ($exists) {
+                    dLog('generate')->info('该视频任务的对话记录已存在,跳过重复写入', [
+                        'video_task_id' => $videoTaskId,
+                        'segment_id_or_act_id' => $segmentIdOrActId,
+                        'video_url' => $videoUrl
+                    ]);
+                    return;
+                }
+            }
+
             // 保存对话记录
             // 保存对话记录
             $records = [
             $records = [
                 [
                 [
@@ -2822,6 +2880,7 @@ class AIVideoGenerationService
                     'sequence'      => $segment->episode_number,
                     'sequence'      => $segment->episode_number,
                     'role'          => 'user',
                     'role'          => 'user',
                     'content'       => $userContent,
                     'content'       => $userContent,
+                    'video_task_id' => $videoTaskId,
                     $recordField    => $recordValue,
                     $recordField    => $recordValue,
                     'video_url'     => '',
                     'video_url'     => '',
                     'reference_images' => json_encode([], 256),
                     'reference_images' => json_encode([], 256),
@@ -2834,6 +2893,7 @@ class AIVideoGenerationService
                     'sequence'      => $segment->episode_number,
                     'sequence'      => $segment->episode_number,
                     'role'          => 'assistant',
                     'role'          => 'assistant',
                     'content'       => $assistantContent,
                     'content'       => $assistantContent,
+                    'video_task_id' => $videoTaskId,
                     $recordField    => $recordValue,
                     $recordField    => $recordValue,
                     'video_url'     => $videoUrl,
                     'video_url'     => $videoUrl,
                     'reference_images' => $reference_images,
                     'reference_images' => $reference_images,
@@ -3265,8 +3325,15 @@ class AIVideoGenerationService
                 try {
                 try {
                     DB::beginTransaction();
                     DB::beginTransaction();
                     
                     
-                    // 在事务中更新任务状态
-                    $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                    // 原子抢占:只有仍为 processing 的任务才能更新成功,避免多个进程重复处理同一任务
+                    if (!$this->markVideoTaskSuccess($task, $statusInfo)) {
+                        DB::rollBack();
+                        dLog('generate')->info('视频任务已被其他进程处理,跳过重复更新', [
+                            'id' => $task->id,
+                            'result_url' => $statusInfo['result_url'] ?? null
+                        ]);
+                        return;
+                    }
                     
                     
                     $now = date('Y-m-d H:i:s');
                     $now = date('Y-m-d H:i:s');
                     
                     
@@ -3338,7 +3405,7 @@ class AIVideoGenerationService
                 }
                 }
             } else {
             } else {
                 // 没有segment_id的情况下,直接更新任务状态
                 // 没有segment_id的情况下,直接更新任务状态
-                $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                $this->markVideoTaskSuccess($task, $statusInfo);
             }
             }
         } elseif ($statusInfo['status'] === 'failed') {
         } elseif ($statusInfo['status'] === 'failed') {
             logDB('generate', 'error', '统一API视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
             logDB('generate', 'error', '统一API视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
@@ -3378,6 +3445,61 @@ class AIVideoGenerationService
     }
     }
 
 
     /**
     /**
+     * 将任务从 processing 原子更新为 success,返回是否更新成功
+     *
+     * 防止多个定时任务进程同时查询到同一 processing 任务后重复处理,
+     * 导致对话记录重复写入、任务表 result_url 被后写入的结果覆盖。
+     *
+     * @param MpGenerateVideoTask $task
+     * @param array $statusInfo
+     * @return bool
+     */
+    private function markVideoTaskSuccess(MpGenerateVideoTask $task, array $statusInfo): bool
+    {
+        $updateData = [
+            'status' => MpGenerateVideoTask::STATUS_SUCCESS,
+            'updated_at' => now(),
+        ];
+
+        if (isset($statusInfo['result_json'])) {
+            $updateData['result_json'] = is_array($statusInfo['result_json'])
+                ? json_encode($statusInfo['result_json'], JSON_UNESCAPED_UNICODE)
+                : $statusInfo['result_json'];
+        }
+        if (isset($statusInfo['result_url'])) {
+            $updateData['result_url'] = $statusInfo['result_url'];
+        }
+        if (isset($statusInfo['compressed_url'])) {
+            $updateData['compressed_url'] = $statusInfo['compressed_url'];
+        }
+        if (isset($statusInfo['last_frame_url'])) {
+            $updateData['last_frame_url'] = $statusInfo['last_frame_url'];
+        }
+        if (isset($statusInfo['error_message'])) {
+            $updateData['error_message'] = $statusInfo['error_message'];
+        }
+        if (isset($statusInfo['extra_params'])) {
+            $updateData['extra_params'] = is_array($statusInfo['extra_params'])
+                ? json_encode($statusInfo['extra_params'], JSON_UNESCAPED_UNICODE)
+                : $statusInfo['extra_params'];
+        }
+        if (!$task->completed_at) {
+            $updateData['completed_at'] = now();
+        }
+
+        $updated = DB::table('mp_generate_video_tasks')
+            ->where('id', $task->id)
+            ->where('status', MpGenerateVideoTask::STATUS_PROCESSING)
+            ->update($updateData);
+
+        if ($updated) {
+            $task->status = MpGenerateVideoTask::STATUS_SUCCESS;
+        }
+
+        return (bool)$updated;
+    }
+
+    /**
      * 确保视频为标准分辨率(720p -> 1280*720 / 720*1280,1080p -> 1920*1080 / 1080*1920)
      * 确保视频为标准分辨率(720p -> 1280*720 / 720*1280,1080p -> 1920*1080 / 1080*1920)
      *
      *
      * 下载视频并探测实际分辨率,若属于目标档位但不是标准尺寸,则强制转码为标准分辨率
      * 下载视频并探测实际分辨率,若属于目标档位但不是标准尺寸,则强制转码为标准分辨率
@@ -3915,7 +4037,7 @@ class AIVideoGenerationService
             
             
             if (!$originalTaskId) {
             if (!$originalTaskId) {
                 // 如果没有原始任务ID,只更新超分任务本身
                 // 如果没有原始任务ID,只更新超分任务本身
-                $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                $this->markVideoTaskSuccess($task, $statusInfo);
                 return;
                 return;
             }
             }
 
 
@@ -3925,7 +4047,7 @@ class AIVideoGenerationService
                     'enhance_task_id' => $task->id,
                     'enhance_task_id' => $task->id,
                     'original_task_id' => $originalTaskId
                     'original_task_id' => $originalTaskId
                 ]);
                 ]);
-                $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                $this->markVideoTaskSuccess($task, $statusInfo);
                 return;
                 return;
             }
             }
 
 
@@ -3935,11 +4057,17 @@ class AIVideoGenerationService
                 try {
                 try {
                     DB::beginTransaction();
                     DB::beginTransaction();
                     
                     
-                    // 更新超分任务状态
-                    $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                    // 原子抢占:只有仍为 processing 的超分任务能更新为 success,避免并发重复处理
+                    if (!$this->markVideoTaskSuccess($task, $statusInfo)) {
+                        DB::rollBack();
+                        dLog('video_enhance')->info('视频超分任务已被其他进程处理,跳过重复更新', [
+                            'enhance_task_id' => $task->id
+                        ]);
+                        return;
+                    }
                     
                     
-                    // 更新原始480p任务状态
-                    $originalTask->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                    // 原始480p任务可能已被主流程处理为 success,这里仅尽力同步状态
+                    $this->markVideoTaskSuccess($originalTask, $statusInfo);
                     
                     
                     $now = date('Y-m-d H:i:s');
                     $now = date('Y-m-d H:i:s');
                     
                     
@@ -4015,8 +4143,14 @@ class AIVideoGenerationService
                 try {
                 try {
                     DB::beginTransaction();
                     DB::beginTransaction();
                     
                     
-                    $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
-                    $originalTask->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
+                    if (!$this->markVideoTaskSuccess($task, $statusInfo)) {
+                        DB::rollBack();
+                        dLog('video_enhance')->info('视频超分任务已被其他进程处理,跳过重复更新', [
+                            'enhance_task_id' => $task->id
+                        ]);
+                        return;
+                    }
+                    $this->markVideoTaskSuccess($originalTask, $statusInfo);
                     
                     
                     DB::commit();
                     DB::commit();
                 } catch (\Exception $e) {
                 } catch (\Exception $e) {

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

@@ -966,6 +966,7 @@ class AnimeService
                     'role'          => 'user',
                     'role'          => 'user',
                     'content'       => $prompt,
                     'content'       => $prompt,
                     'segment_id'    => $segment_id,
                     'segment_id'    => $segment_id,
+                    'pic_task_id'   => $task_id,
                     'image_url'     => '',
                     'image_url'     => '',
                     'created_at'    => $now,
                     'created_at'    => $now,
                     'updated_at'    => $now
                     'updated_at'    => $now
@@ -977,6 +978,7 @@ class AnimeService
                     'role'          => 'assistant',
                     'role'          => 'assistant',
                     'content'       => $pic_prompt,
                     'content'       => $pic_prompt,
                     'segment_id'    => $segment_id,
                     'segment_id'    => $segment_id,
+                    'pic_task_id'   => $task_id,
                     'image_url'     => $img_url,
                     'image_url'     => $img_url,
                     'created_at'    => $now,
                     'created_at'    => $now,
                     'updated_at'    => $now
                     'updated_at'    => $now
@@ -1006,7 +1008,7 @@ class AnimeService
 
 
         if (!$segment_id) Utils::throwError('20003:请选择分镜!');
         if (!$segment_id) Utils::throwError('20003:请选择分镜!');
 
 
-        $query = DB::table('mp_anime_records')->where('segment_id', $segment_id)->select('role', 'content', 'segment_id', 'image_url', 'video_url', 'created_at');
+        $query = DB::table('mp_anime_records')->where('segment_id', $segment_id)->select('role', 'content', 'segment_id', 'image_url', 'video_url', 'video_task_id', 'pic_task_id', 'created_at');
         
         
         $chat = $query->orderBy('id')->get()->map(function ($value) {
         $chat = $query->orderBy('id')->get()->map(function ($value) {
             $value = (array)$value;
             $value = (array)$value;
@@ -2376,6 +2378,7 @@ class AnimeService
                     'role'          => 'user',
                     'role'          => 'user',
                     'content'       => '重新生成',
                     'content'       => '重新生成',
                     'segment_id'    => $segment_id,
                     'segment_id'    => $segment_id,
+                    'pic_task_id'   => $task_id,
                     'image_url'     => '',
                     'image_url'     => '',
                     'created_at'    => $now,
                     'created_at'    => $now,
                     'updated_at'    => $now
                     'updated_at'    => $now
@@ -2387,6 +2390,7 @@ class AnimeService
                     'role'          => 'assistant',
                     'role'          => 'assistant',
                     'content'       => $pic_prompt,
                     'content'       => $pic_prompt,
                     'segment_id'    => $segment_id,
                     'segment_id'    => $segment_id,
+                    'pic_task_id'   => $task_id,
                     'image_url'     => $img_url,
                     'image_url'     => $img_url,
                     'created_at'    => $now,
                     'created_at'    => $now,
                     'updated_at'    => $now
                     'updated_at'    => $now
@@ -3331,7 +3335,7 @@ class AnimeService
 
 
         if (!$act_id) Utils::throwError('20003:请选择片段!');
         if (!$act_id) Utils::throwError('20003:请选择片段!');
 
 
-        $query = DB::table('mp_anime_records')->where('act_id', $act_id)->select('role', 'content', 'act_id', 'image_url', 'video_url', 'reference_images', 'created_at');
+        $query = DB::table('mp_anime_records')->where('act_id', $act_id)->select('role', 'content', 'act_id', 'image_url', 'video_url', 'video_task_id', 'pic_task_id', 'reference_images', 'created_at');
         
         
         $chat = $query->orderBy('id')->get()->map(function ($value) {
         $chat = $query->orderBy('id')->get()->map(function ($value) {
             $value = (array)$value;
             $value = (array)$value;