Pārlūkot izejas kodu

1.完成批量生成角色图片的功能2.即梦AI4.0图片生成任务增加并发为1的兼容性代码

lh 4 mēneši atpakaļ
vecāks
revīzija
faab05f10e

+ 80 - 26
app/Console/Anime/AnimeCheckImgUrlCommand.php

@@ -31,36 +31,90 @@ class AnimeCheckImgUrlCommand extends Command
         $time_start = microtime(true);
 
         // 获取待执行的动漫对话数据
-        $data = DB::table('mp_animes')->where('status', '执行中')->select('roles', 'scenes')->get();
+        $data = DB::table('mp_animes')->where('generate_status', '执行中')->select('id', 'roles', 'scenes')->get();
         
-        // foreach ($data as $val) {
-        //     $roles = json_decode($val->roles, true);
-        //     $scenes = json_decode($val->scenes, true);
-        //     $role_count = count($roles);
-        //     $scene_count = count($scenes);
-        //     $role_success_count = 0;
-        //     $scene_success_count = 0;
-        //     for ($i=0; $i < $role_count; $i++) { 
-        //         if (isset($roles[$i]['url']) && !empty($roles[$i]['url'])) {
-        //             $role_success_count++;
-        //         }
-        //     }
-        //     for ($i=0; $i < $scene_count; $i++) { 
-        //         if (isset($scenes[$i]['url']) && !empty($scenes[$i]['url'])) {
-        //             $scene_success_count++;
-        //         }
-        //     }
-
-        //     if ($role_success_count == $role_count && $scene_success_count == $scene_count) {
-        //         // 更新状态为已完成
-        //         DB::table('mp_animes')->where('status', '执行中')->update(['status' => '已完成']);
-        //         dLog('generate')->info('动漫对话图片已生成完成');
-        //     }
-        // }
-        // $this->info('检查完成');
+        foreach ($data as $item) {
+            $id = getProp($item, 'id');
+            $roles = json_decode(getProp($item, 'roles'), true);
+            $scenes = json_decode(getProp($item, 'scenes'), true);
+            $role_count = count($roles);
+            $scene_count = count($scenes);
+            $role_success_count = 0;
+            $scene_success_count = 0;
+
+            // 处理角色图片状态
+            $role_success_count = $this->checkRoles($id, $roles);
+
+            // 处理场景图片状态
+            $scene_success_count = $this->checkScenes($id, $scenes);
+
+            if ($role_success_count == $role_count && $scene_success_count == $scene_count) {
+                // 更新状态为已完成
+                DB::table('mp_animes')->where('id', $id)->update(['generate_status' => '已完成', 'updated_at'=>date('Y-m-d H:i:s')]);
+                dLog('generate')->info('动漫对话图片已生成完成');
+            }
+        }
 
         $time_end = microtime(true);
         dLog('generate')->info('脚本执行时间: '.round($time_end-$time_start, 2).'秒');
         dLog('generate')->info('====================结束检查动漫对话角色和场景图片生成状态====================');
     }
+
+    private function checkRoles($id, $roles) {
+        $role_success_count = 0;
+        foreach ($roles as &$role) {
+            $task_id = getProp($role, 'task_id');
+            $task_status = getProp($role, 'task_status');
+            if (!$task_id || $task_status == 'success') {
+                $role_success_count++;
+                continue;
+            }
+            $task = DB::table('mp_generate_pic_tasks')->where('id', $task_id)->select('result_url', 'status')->first();
+            if (in_array(getProp($task, 'status'), ['success', 'failed'])) {
+                $role['task_status'] = 'success';
+                $role['url'] = '';
+                $result_url = getProp($task, 'result_url');
+                if ($result_url && is_json($result_url)) {
+                    $role['url'] = json_decode($result_url, true)[0];
+                }
+
+                $role_success_count++;
+            }
+        }
+
+        if ($role_success_count > 0) {
+            DB::table('mp_animes')->where('id', $id)->update(['roles' => json_encode($roles, 256)]);
+        }
+
+        return $role_success_count;
+    }
+
+    private function checkScenes($id, $scenes) {
+        $scene_success_count = 0;
+        foreach ($scenes as &$scene) {
+            $task_id = getProp($scene, 'task_id');
+            $task_status = getProp($scene, 'task_status');
+            if (!$task_id || $task_status == 'success') {
+                $scene_success_count++;
+                continue;
+            }
+            $task = DB::table('mp_generate_pic_tasks')->where('id', $task_id)->select('result_url', 'status')->first();
+            if (in_array(getProp($task, 'status'), ['success', 'failed'])) {
+                $scene['task_status'] = 'success';
+                $scene['url'] = '';
+                $result_url = getProp($task, 'result_url');
+                if ($result_url && is_json($result_url)) {
+                    $scene['url'] = json_decode($result_url, true)[0];
+                }
+
+                $scene_success_count++;
+            }
+        }
+
+        if ($scene_success_count > 0) {
+            DB::table('mp_animes')->where('id', $id)->update(['scenes' => json_encode($scenes, 256)]);
+        }
+
+        return $scene_success_count;
+    }
 }

+ 14 - 4
app/Console/Commands/CheckImageGenerationTasksCommand.php

@@ -4,6 +4,7 @@ namespace App\Console\Commands;
 
 use App\Services\AIGeneration\AIImageGenerationService;
 use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
 
 class CheckImageGenerationTasksCommand extends Command
 {
@@ -29,13 +30,22 @@ class CheckImageGenerationTasksCommand extends Command
      */
     public function handle(AIImageGenerationService $aiImageGenerationService)
     {
-        $this->info('开始检查图片生成任务状态...');
+        dLog('generate')->info('开始检查图片生成任务状态...');
 
+        // 执行40s
+        $time_start = time();
         try {
-            $aiImageGenerationService->updatePendingTasks();
-            $this->info('任务状态检查完成');
+            $count = DB::table('mp_generate_pic_tasks')->where('status', 'processing')->count('id');
+            while ($count > 0) {
+                $time_diff = time() - $time_start;
+                sleep(3);
+                if ($time_diff > 50) break;
+                $aiImageGenerationService->updatePendingTasks();
+                $count = DB::table('mp_generate_pic_tasks')->where('status', 'processing')->count('id');
+            }
+            dLog('generate')->info('任务状态检查完成');
         } catch (\Exception $e) {
-            $this->error('任务状态检查失败: ' . $e->getMessage());
+            dLog('generate')->error('任务状态检查失败: ' . $e->getMessage());
             return 1;
         }
 

+ 67 - 0
app/Console/Commands/ProcessImageGenerationQueueCommand.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\AIGeneration\AIImageGenerationService;
+use Illuminate\Console\Command;
+
+class ProcessImageGenerationQueueCommand extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'image-generation:process-queue';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '处理图片生成任务队列,检查任务状态并处理下一个排队任务';
+
+    private $imageGenerationService;
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct(AIImageGenerationService $imageGenerationService)
+    {
+        parent::__construct();
+        $this->imageGenerationService = $imageGenerationService;
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $this->info('开始处理图片生成任务队列...');
+
+        try {
+            // 更新所有待处理任务的状态
+            $this->imageGenerationService->updatePendingTasks();
+            
+            // 获取队列状态
+            $queueStatus = $this->imageGenerationService->getQueueStatus();
+            
+            $this->info("队列状态: 处理中任务数: {$queueStatus['processing_count']}, 排队任务数: {$queueStatus['pending_count']}");
+            
+            if ($queueStatus['can_submit_new_task'] && $queueStatus['pending_count'] > 0) {
+                $this->info('开始处理下一个排队任务...');
+                $this->imageGenerationService->processNextQueuedTask();
+            }
+            
+            $this->info('任务队列处理完成');
+            return 0;
+        } catch (\Exception $e) {
+            $this->error('处理任务队列时发生错误: ' . $e->getMessage());
+            return 1;
+        }
+    }
+}

+ 4 - 0
app/Console/Kernel.php

@@ -13,6 +13,7 @@ class Kernel extends ConsoleKernel
         Test\TestCommand::class,
         RegisterUserCommand::class,
         AnimeCheckImgUrlCommand::class,
+        Commands\ProcessImageGenerationQueueCommand::class,
     ];
 
 
@@ -32,6 +33,9 @@ class Kernel extends ConsoleKernel
 
         // 没分钟检查一次动漫对话图片生成状态
         $schedule->command('Anime:checkImgUrl')->everyMinute();
+        
+        // 每30秒处理一次图片生成任务队列
+        $schedule->command('image-generation:process-queue')->everyMinute();
     }
 
     /**

+ 3 - 3
app/Http/Controllers/AIGeneration/ImageGenerationController.php

@@ -164,7 +164,7 @@ class ImageGenerationController extends BaseController
         try {
             $task = $this->aiImageGenerationService->createImageGenerationTask($data);
 
-            return $this->success(['task_id' => $task->task_id, 'status' => $task->status]);
+            return $this->success(['task_id' => $task->id, 'status' => $task->status]);
         } catch (\Exception $e) {
             Utils::throwError('1001:'.$e->getMessage());
         }
@@ -207,7 +207,7 @@ class ImageGenerationController extends BaseController
      */
     public function taskStatus(string $taskId): JsonResponse
     {
-        $task = \App\Models\MpGeneratePicTask::where('task_id', $taskId)->first();
+        $task = \App\Models\MpGeneratePicTask::where('id', $taskId)->first();
 
         if (!$task) {
             return response()->json([
@@ -219,7 +219,7 @@ class ImageGenerationController extends BaseController
         return response()->json([
             'success' => true,
             'data' => [
-                'task_id' => $task->task_id,
+                'task_id' => $task->id,
                 'status' => $task->status,
                 'result_url' => $task->result_url,
                 'error_message' => $task->error_message,

+ 11 - 12
app/Http/Controllers/AIGeneration/VideoGenerationController.php

@@ -154,7 +154,7 @@ class VideoGenerationController extends BaseController
         }
 
         $task = $this->aiVideoGenerationService->createJimengTask($data);
-        return $this->success(['task_id' => $task->task_id, 'status' => $task->status]);
+        return $this->success(['task_id' => $task->id, 'status' => $task->status]);
     }
 
     /**
@@ -165,7 +165,7 @@ class VideoGenerationController extends BaseController
      */
     public function taskStatus(string $taskId): JsonResponse
     {
-        $task = \App\Models\MpGenerateVideoTask::where('task_id', $taskId)->first();
+        $task = \App\Models\MpGenerateVideoTask::where('id', $taskId)->first();
 
         if (!$task) {
             return response()->json([
@@ -177,7 +177,7 @@ class VideoGenerationController extends BaseController
         return response()->json([
             'success' => true,
             'data' => [
-                'task_id' => $task->task_id,
+                'task_id' => $task->id,
                 'status' => $task->status,
                 'result_url' => $task->result_url,
                 'error_message' => $task->error_message,
@@ -458,7 +458,7 @@ class VideoGenerationController extends BaseController
         $this->validateSeedanceContent($data['content']);
     
         $task = $this->aiVideoGenerationService->createSeedanceTask($data);
-        return $this->success(['task_id' => $task->task_id, 'status' => $task->status]);
+        return $this->success(['task_id' => $task->id, 'status' => $task->status]);
     }
 
     /**
@@ -470,7 +470,7 @@ class VideoGenerationController extends BaseController
     public function getSeedanceTaskStatus(string $taskId): JsonResponse
     {
         try {
-            $task = \App\Models\MpGenerateVideoTask::where('task_id', $taskId)->first();
+            $task = \App\Models\MpGenerateVideoTask::where('id', $taskId)->first();
 
             if (!$task) {
                 return response()->json([
@@ -715,7 +715,7 @@ class VideoGenerationController extends BaseController
         }
 
         $task = $this->aiVideoGenerationService->createKelingOmniTask($data);
-        return $this->success(['task_id' => $task->task_id, 'status' => $task->status]);
+        return $this->success(['task_id' => $task->id, 'status' => $task->status]);
     }
 
     /**
@@ -727,7 +727,7 @@ class VideoGenerationController extends BaseController
     public function getKelingTaskStatus(string $taskId): JsonResponse
     {
         try {
-            $task = \App\Models\MpGenerateVideoTask::where('task_id', $taskId)->first();
+            $task = \App\Models\MpGenerateVideoTask::where('id', $taskId)->first();
 
             if (!$task) {
                 return response()->json([
@@ -795,7 +795,7 @@ class VideoGenerationController extends BaseController
                 'message' => '主体创建任务已提交',
                 'request_id' => uniqid(),
                 'data' => [
-                    'task_id' => $element->task_id,
+                    'task_id' => $element->id,
                     'task_info' => [
                         'external_task_id' => $element->external_task_id,
                     ],
@@ -835,7 +835,7 @@ class VideoGenerationController extends BaseController
             $externalTaskId = $request->get('external_task_id');
             
             // 先查询本地数据库
-            $query = AIElement::where('task_id', $taskId);
+            $query = AIElement::where('id', $taskId);
             if ($externalTaskId) {
                 $query->orWhere('external_task_id', $externalTaskId);
             }
@@ -860,7 +860,7 @@ class VideoGenerationController extends BaseController
 
             // 构建响应数据
             $responseData = [
-                'task_id' => $localElement->task_id,
+                'task_id' => $localElement->id,
                 'task_status' => $localElement->task_status,
                 'task_status_msg' => $localElement->task_status_msg,
                 'task_info' => [
@@ -1061,8 +1061,7 @@ class VideoGenerationController extends BaseController
             // 转换数据格式
             $data = $elements->map(function ($element) {
                 return [
-                    'id' => $element->id,
-                    'task_id' => $element->task_id,
+                    'task_id' => $element->id,
                     'external_task_id' => $element->external_task_id,
                     'task_status' => $element->task_status,
                     'task_status_msg' => $element->task_status_msg,

+ 1 - 0
app/Models/AIElement.php

@@ -12,6 +12,7 @@ class AIElement extends Model
     protected $table = 'mp_ai_elements';
 
     protected $fillable = [
+        'id',
         'task_id',
         'external_task_id',
         'task_status',

+ 1 - 0
app/Models/MpGeneratePicTask.php

@@ -59,6 +59,7 @@ class MpGeneratePicTask extends Model
         }
         $updateData['updated_at'] = now();
         if (isset($data['extra_params'])) $updateData['extra_params'] = $data['extra_params'];
+        if (isset($data['result_json'])) $updateData['result_json'] = $data['result_json'];
 
         if ($status === self::STATUS_PROCESSING) {
             if (isset($data['task_id'])) $updateData['task_id'] = $data['task_id'];

+ 1 - 0
app/Models/MpGenerateVideoTask.php

@@ -14,6 +14,7 @@ class MpGenerateVideoTask extends Model
     const STATUS_FAILED = 'failed';
 
     protected $fillable = [
+        'id',
         'task_id',
         'prompt',
         'first_frame_url',

+ 90 - 3
app/Services/AIGeneration/AIImageGenerationService.php

@@ -30,6 +30,12 @@ class AIImageGenerationService
      */
     public function createImageGenerationTask(array $params): MpGeneratePicTask
     {
+        // 检查是否有正在处理的任务
+        if ($this->hasProcessingTask()) {
+            // 如果有正在处理的任务,创建排队任务
+            return $this->createQueuedTask($params);
+        }
+
         // 生成唯一的任务ID
         $taskId = 'img_gen_' . time() . '_' . uniqid();
 
@@ -54,6 +60,43 @@ class AIImageGenerationService
     }
 
     /**
+     * 检查是否有正在处理的任务
+     *
+     * @return bool
+     */
+    private function hasProcessingTask(): bool
+    {
+        return MpGeneratePicTask::where('status', MpGeneratePicTask::STATUS_PROCESSING)
+            ->exists();
+    }
+
+    /**
+     * 创建排队任务
+     *
+     * @param array $params
+     * @return MpGeneratePicTask
+     */
+    private function createQueuedTask(array $params): MpGeneratePicTask
+    {
+        // 生成唯一的任务ID
+        $taskId = 'img_gen_' . time() . '_' . uniqid();
+
+        // 创建排队状态的任务记录
+        return MpGeneratePicTask::create([
+            'task_id' => $taskId,
+            'prompt' => $params['prompt'] ?? '',
+            'width' => $params['width'] ?? 2048,
+            'height' => $params['height'] ?? 2048,
+            'image_num' => $params['image_num'] ?? 1,
+            'scale' => $params['scale'] ?? 50,
+            'ref_img_url' => $params['ref_img_urls'] ?? null,
+            'mask_img_url' => $params['mask_img_url'] ?? null,
+            'extra_params' => $params['extra_params'] ?? null,
+            'status' => MpGeneratePicTask::STATUS_PENDING, // 保持PENDING状态,等待处理
+        ]);
+    }
+
+    /**
      * 提交任务到即梦AI API
      *
      * @param MpGeneratePicTask $task
@@ -155,7 +198,7 @@ class AIImageGenerationService
 
         $query = MpGeneratePicTask::select('*');
         if ($task_id) {
-            $query->where('task_id', $task_id);
+            $query->where('id', $task_id);
         }
         if ($status) {
             $query->where('status', $status);
@@ -277,11 +320,12 @@ class AIImageGenerationService
      */
     public function updatePendingTasks(): void
     {
+        dLog('generate')->info('更新图片状态ing');
         // 获取所有处理中的任务
-        $tasks = MpGeneratePicTask::where('status', MpGeneratePicTask::STATUS_PROCESSING)
+        $processingTasks = MpGeneratePicTask::where('status', MpGeneratePicTask::STATUS_PROCESSING)
             ->get();
 
-        foreach ($tasks as $task) {
+        foreach ($processingTasks as $task) {
             $statusInfo = $this->queryTaskStatus($task);
 
             if ($statusInfo['status'] === 'success') {
@@ -305,5 +349,48 @@ class AIImageGenerationService
                 ]);
             }
         }
+
+        // 检查是否有任务完成,如果有则处理下一个排队任务
+        $this->processNextQueuedTask();
+    }
+
+    /**
+     * 处理下一个排队的任务
+     *
+     * @return void
+     */
+    public function processNextQueuedTask(): void
+    {
+        // 检查是否还有正在处理的任务
+        if ($this->hasProcessingTask()) {
+            return; // 如果还有处理中的任务,不处理新任务
+        }
+
+        // 获取最早的待处理任务
+        $nextTask = MpGeneratePicTask::where('status', MpGeneratePicTask::STATUS_PENDING)
+            ->orderBy('created_at', 'asc')
+            ->first();
+
+        if ($nextTask) {
+            dLog('generate')->info('开始处理排队任务: ' . $nextTask->task_id);
+            $this->submitTaskToApi($nextTask);
+        }
+    }
+
+    /**
+     * 获取任务队列状态
+     *
+     * @return array
+     */
+    public function getQueueStatus(): array
+    {
+        $processingCount = MpGeneratePicTask::where('status', MpGeneratePicTask::STATUS_PROCESSING)->count();
+        $pendingCount = MpGeneratePicTask::where('status', MpGeneratePicTask::STATUS_PENDING)->count();
+        
+        return [
+            'processing_count' => $processingCount,
+            'pending_count' => $pendingCount,
+            'can_submit_new_task' => $processingCount === 0
+        ];
     }
 }

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

@@ -306,7 +306,7 @@ class AIVideoGenerationService
 
         $query = MpGenerateVideoTask::select('*');
         if ($task_id) {
-            $query->where('task_id', $task_id);
+            $query->where('id', $task_id);
         }
         if ($status) {
             $query->where('status', $status);
@@ -511,7 +511,7 @@ class AIVideoGenerationService
                 return [
                     'success' => true,
                     'data' => [
-                        'id' => $task->task_id,
+                        'id' => $task->id,
                         'status' => $this->mapTaskStatus($task->status),
                         'result_url' => $task->result_url,
                         'error_message' => $task->error_message,
@@ -603,7 +603,7 @@ class AIVideoGenerationService
             return [
                 'success' => true,
                 'data' => [
-                    'id' => $task->task_id,
+                    'id' => $task->id,
                     'status' => $this->mapTaskStatus($task->status),
                     'result_url' => $task->result_url,
                     'error_message' => $task->error_message,

+ 3 - 3
app/Services/Anime/AnimeService.php

@@ -53,13 +53,13 @@ class AnimeService
                 ];
                 
                 $task = $this->aiImageGenerationService->createImageGenerationTask($params);
-                $task_id = $task->task_id;
+                $tid = $task->id;
                 
-                if (!$task_id) {
+                if (!$tid) {
                     Utils::throwError("20003: 角色({$role_name})生成图片失败");
                 }
                 
-                $role['task_id'] = $task_id;
+                $role['task_id'] = $tid;
                 $role['task_status'] = 'processing';
             } catch (\Exception $e) {
                 Utils::throwError("20003:" . $e->getMessage());

+ 1 - 1
app/Transformer/AIGeneration/AIGenerationTransformer.php

@@ -31,7 +31,7 @@ class AIGenerationTransformer
             ];
 
             $result[] = [
-                'task_id'               => getProp($item, 'task_id'),
+                'task_id'               => getProp($item, 'id'),
                 'prompt'                => getProp($item, 'prompt'),
                 'seed'                  => getProp($item, 'seed'),
                 'video_resolution'      => getProp($item, 'video_resolution'),