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

新增创建素材和查询素材状态的公共方法

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

Разница между файлами не показана из-за своего большого размера
+ 60 - 1
app/Console/Test/TestCommand.php


+ 40 - 0
app/Models/MpAsset.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class MpAsset extends Model
+{
+    use HasFactory;
+    
+    protected $table = 'mp_assets';
+    
+    protected $fillable = [
+        'asset_id',
+        'group_id',
+        'group_name',
+        'name',
+        'url',
+        'cover_url',
+        'asset_type',
+        'status',
+        'error_message',
+        'extra_params',
+    ];
+    
+    protected $casts = [
+        'extra_params' => 'array',
+    ];
+    
+    // 状态常量
+    const STATUS_PROCESSING = 'Processing';
+    const STATUS_ACTIVE = 'Active';
+    const STATUS_FAILED = 'Failed';
+    
+    // 类型常量
+    const TYPE_IMAGE = 'Image';
+    const TYPE_VIDEO = 'Video';
+    const TYPE_AUDIO = 'Audio';
+}

+ 223 - 0
app/Services/AIGeneration/AIImageGenerationService.php

@@ -3,6 +3,7 @@
 namespace App\Services\AIGeneration;
 
 use App\Models\MpGeneratePicTask;
+use App\Models\MpAsset;
 use App\Services\VolcEngineService;
 use GuzzleHttp\Client;
 use GuzzleHttp\Exception\GuzzleException;
@@ -911,6 +912,228 @@ class AIImageGenerationService
     }
 
     /**
+     * 创建素材
+     *
+     * @param array $params
+     * @return array
+     */
+    public function createAsset(array $params): array
+    {
+        try {
+            // 验证必填参数
+            if (empty($params['url'])) {
+                return [
+                    'code' => 1,
+                    'msg' => '素材URL不能为空',
+                    'data' => null
+                ];
+            }
+
+            // 先获取表中是否已有该url
+            $asset = DB::table('mp_assets')->where('url', $params['url'])->first();
+            if ($asset) {
+                return [
+                    'code' => 0,
+                    'msg' => '创建成功',
+                    'data' => [
+                        'id' => $asset->id,
+                        'asset_id' => $asset->asset_id,
+                        'group_id' => $asset->group_id,
+                        'group_name' => $asset->group_name,
+                    ]
+                ];
+            }
+
+            // 获取API配置
+            $apiKey = env('ZHIZHEN_AI_SK');
+            $apiUrl = 'https://model-relay.zzengine.net';
+            
+            if (empty($apiKey)) {
+                return [
+                    'code' => 1002,
+                    'msg' => '智真AI API KEY未配置,请检查环境变量ZHIZHEN_AI_SK',
+                    'data' => null
+                ];
+            }
+
+            // 构建请求参数
+            $requestData = [
+                'url' => $params['url'],
+                'asset_type' => $params['asset_type'] ?? MpAsset::TYPE_IMAGE,
+            ];
+
+            // 可选参数
+            if (!empty($params['name'])) {
+                $requestData['name'] = $params['name'];
+            }
+            if (!empty($params['group_id'])) {
+                $requestData['group_id'] = $params['group_id'];
+            }
+
+            dLog('generate')->info('智真AI创建素材请求参数: ', $requestData);
+
+            // 调用智真AI API
+            $response = $this->httpClient->post($apiUrl . '/api/v1/asset/create', [
+                'headers' => [
+                    'X-Api-Key' => $apiKey,
+                    'Content-Type' => 'application/json',
+                ],
+                'json' => $requestData,
+            ]);
+
+            $responseData = json_decode($response->getBody()->getContents(), true);
+            dLog('generate')->info('智真AI创建素材响应: ', $responseData);
+            logDB('generate', 'info', '智真AI创建素材', ['params' => $requestData, 'response' => $responseData]);
+
+            if ($responseData['code'] !== 0) {
+                return [
+                    'code' => $responseData['code'],
+                    'msg' => $responseData['msg'] ?? '创建素材失败',
+                    'data' => null
+                ];
+            }
+
+            // 保存素材记录到数据库
+            $assetData = $responseData['data'] ?? [];
+            $asset = MpAsset::create([
+                'asset_id' => $assetData['asset_id'] ?? '',
+                'group_id' => $assetData['group_id'] ?? null,
+                'group_name' => $assetData['group_name'] ?? null,
+                'name' => $params['name'] ?? null,
+                'url' => $params['url'],
+                'asset_type' => $params['asset_type'] ?? MpAsset::TYPE_IMAGE,
+                'status' => MpAsset::STATUS_PROCESSING,
+                'extra_params' => $responseData,
+            ]);
+
+            return [
+                'code' => 0,
+                'msg' => '创建成功',
+                'data' => [
+                    'id' => $asset->id,
+                    'asset_id' => $asset->asset_id,
+                    'group_id' => $asset->group_id,
+                    'group_name' => $asset->group_name,
+                ]
+            ];
+
+        } catch (\Exception $e) {
+            dLog('generate')->error('创建素材异常: ' . $e->getMessage());
+            logDB('generate', 'error', '创建素材异常', ['params' => $params, 'error' => $e->getMessage()]);
+            
+            return [
+                'code' => 20003,
+                'msg' => '创建素材失败: ' . $e->getMessage(),
+                'data' => null
+            ];
+        }
+    }
+
+    /**
+     * 查询素材
+     *
+     * @param string $assetId
+     * @return array
+     */
+    public function getAsset(string $assetId): array
+    {
+        try {
+            // 验证参数
+            if (empty($assetId)) {
+                return [
+                    'code' => 20003,
+                    'msg' => '素材ID不能为空',
+                    'data' => null
+                ];
+            }
+
+            // 先获取表中是否已有该url
+            $assetInfo = DB::table('mp_assets')->where('asset_id', $assetId)->first();
+            if ($assetInfo) {
+                $assetInfo = (array)$assetInfo;
+                $status = getProp($assetInfo, 'status');
+                if (in_array($status, ['Active', 'Failed'])) {
+                    $assetInfo['id'] = $assetInfo['asset_id'];
+                    return [
+                        'code' => 0,
+                        'msg' => '查询成功',
+                        'data' => [
+                            'asset' => $assetInfo
+                        ]
+                    ];
+                }
+            }
+
+            // 获取API配置
+            $apiKey = env('ZHIZHEN_AI_SK');
+            $apiUrl = 'https://model-relay.zzengine.net';
+            
+            if (empty($apiKey)) {
+                return [
+                    'code' => 1002,
+                    'msg' => '智真AI API KEY未配置,请检查环境变量ZHIZHEN_AI_SK',
+                    'data' => null
+                ];
+            }
+
+            dLog('generate')->info('智真AI查询素材: ' . $assetId);
+
+            // 调用智真AI API
+            $response = $this->httpClient->post($apiUrl . '/api/v1/asset/get', [
+                'headers' => [
+                    'X-Api-Key' => $apiKey,
+                    'Content-Type' => 'application/json',
+                ],
+                'json' => [
+                    'asset_id' => $assetId,
+                ],
+            ]);
+
+            $responseData = json_decode($response->getBody()->getContents(), true);
+            dLog('generate')->info('智真AI查询素材响应: ', $responseData);
+            logDB('generate', 'info', '智真AI查询素材', ['asset_id' => $assetId, 'response' => $responseData]);
+
+            if ($responseData['code'] !== 0) {
+                return [
+                    'code' => $responseData['code'],
+                    'msg' => $responseData['msg'] ?? '查询素材失败',
+                    'data' => null
+                ];
+            }
+
+            $assetInfo = $responseData['data']['asset'] ?? [];
+
+            // 更新本地数据库记录
+            $localAsset = MpAsset::where('asset_id', $assetId)->first();
+            if ($localAsset) {
+                $localAsset->update([
+                    'status' => $assetInfo['status'] ?? MpAsset::STATUS_PROCESSING,
+                    'cover_url' => $assetInfo['url'] ?? null,
+                    'extra_params' => $responseData,
+                ]);
+            }
+
+            return [
+                'code' => 0,
+                'msg' => '查询成功',
+                'data' => [
+                    'asset' => $assetInfo
+                ]
+            ];
+
+        } catch (\Exception $e) {
+            dLog('generate')->error('查询素材异常: ' . $e->getMessage());
+            logDB('generate', 'error', '查询素材异常', ['asset_id' => $assetId, 'error' => $e->getMessage()]);
+            
+            return [
+                'code' => 20003,
+                'msg' => '查询素材失败: ' . $e->getMessage(),
+                'data' => null
+            ];
+        }
+    }
+
+    /**
      * 更新所有待处理任务的状态
      *
      * @return void

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

@@ -323,7 +323,7 @@ class AIVideoGenerationService
             logDB('generate', 'info', '即梦AI视频生成任务成功', ['id' => $task->id, 'result_url' => $statusInfo['result_url']]);
             $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
             
-            // 同步调整分镜视频状态和结果(兼容片段模式)
+            // 同步调整分镜视频状态和结果(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id && isset($statusInfo['result_url'])) {
                 try {
@@ -372,7 +372,7 @@ class AIVideoGenerationService
             logDB('generate', 'error', '即梦AI视频生成任务失败', ['id' => $task->id, 'error' => $statusInfo['error_message']]);
             $task->updateStatus(MpGenerateVideoTask::STATUS_FAILED, $statusInfo);
             
-            // 同步更新分镜表状态为失败(兼容片段模式)
+            // 同步更新分镜表状态为失败(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id) {
                 $this->updateSegmentTable($task, [
@@ -391,7 +391,7 @@ class AIVideoGenerationService
                 'error_message' => '任务处理超时(超过12小时)'
             ]);
             
-            // 同步更新分镜表状态为失败(兼容片段模式)
+            // 同步更新分镜表状态为失败(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id) {
                 $this->updateSegmentTable($task, [
@@ -587,7 +587,7 @@ class AIVideoGenerationService
             logDB('generate', 'info', 'Seedance视频生成任务成功', ['id' => $task->id, 'result_url' => $statusInfo['result_url']]);
             $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
             
-            // 同步调整分镜视频状态和结果(兼容片段模式)
+            // 同步调整分镜视频状态和结果(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id && isset($statusInfo['result_url'])) {
                 try {
@@ -611,7 +611,7 @@ class AIVideoGenerationService
                         $segmentUpdateData['video_duration'] = $statusInfo['video_duration'];
                         $segmentUpdateData['video_time_point_start'] = 0;
                         
-                        // 获取video_time_point_end(兼容片段模式)
+                        // 获取video_time_point_end(兼容全能模式)
                         $audio_duration = $this->getAudioDuration($task, $segment_id, $statusInfo['video_duration'] ?? null);
                         $segmentUpdateData['video_time_point_end'] = $audio_duration ?? 0;
                     }
@@ -640,7 +640,7 @@ class AIVideoGenerationService
                 'result_json'   => $statusInfo['result_json'] ?? []
             ]);
             
-            // 同步更新分镜表状态为失败(兼容片段模式)
+            // 同步更新分镜表状态为失败(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id) {
                 $this->updateSegmentTable($task, [
@@ -659,7 +659,7 @@ class AIVideoGenerationService
                 'error_message' => '任务处理超时(超过48小时)'
             ]);
             
-            // 同步更新分镜表状态为失败(兼容片段模式)
+            // 同步更新分镜表状态为失败(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id) {
                 $this->updateSegmentTable($task, [
@@ -1474,7 +1474,7 @@ class AIVideoGenerationService
             logDB('generate', 'info', '可灵AI Omni视频生成任务成功', ['id' => $task->id, 'result_url' => $statusInfo['result_url']]);
             $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
             
-            // 同步调整分镜视频状态和结果(兼容片段模式)
+            // 同步调整分镜视频状态和结果(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id && isset($statusInfo['result_url'])) {
                 try {
@@ -1498,7 +1498,7 @@ class AIVideoGenerationService
                         $segmentUpdateData['video_duration'] = $statusInfo['video_duration'];
                         $segmentUpdateData['video_time_point_start'] = 0;
                         
-                        // 获取video_time_point_end(兼容片段模式)
+                        // 获取video_time_point_end(兼容全能模式)
                         $audio_duration = $this->getAudioDuration($task, $segment_id, $statusInfo['video_duration']);
                         $segmentUpdateData['video_time_point_end'] = $audio_duration ?? 0;
                     }
@@ -1526,7 +1526,7 @@ class AIVideoGenerationService
                 'result_json' => $statusInfo['result_json'] ?? []
             ]);
             
-            // 同步更新分镜表状态为失败(兼容片段模式)
+            // 同步更新分镜表状态为失败(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id) {
                 $this->updateSegmentTable($task, [
@@ -1545,7 +1545,7 @@ class AIVideoGenerationService
                 'error_message' => '任务处理超时(超过24小时)'
             ]);
             
-            // 同步更新分镜表状态为失败(兼容片段模式)
+            // 同步更新分镜表状态为失败(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id) {
                 $this->updateSegmentTable($task, [
@@ -2030,7 +2030,7 @@ class AIVideoGenerationService
     /**
      * 根据task获取segment_id或act_id(兼容act模式)
      * 分镜模式:返回segment_id用于查询
-     * 片段模式:返回act_id用于查询(因为segment_id为空)
+     * 全能模式:返回act_id用于查询(因为segment_id为空)
      */
     private function getSegmentIdFromTask($task)
     {
@@ -2041,7 +2041,7 @@ class AIVideoGenerationService
             return $segment_id;
         }
         
-        // 如果有alias_act_id,返回act_id(片段模式,segment_id为空)
+        // 如果有alias_act_id,返回act_id(全能模式,segment_id为空)
         $act_id = getProp($task, 'alias_act_id');
         if ($act_id) {
             return $act_id; // 直接返回act_id,不需要查segment_id
@@ -2053,7 +2053,7 @@ class AIVideoGenerationService
     /**
      * 更新分镜表(兼容act模式)
      * 分镜模式:使用segment_id字段更新
-     * 片段模式:使用id字段更新
+     * 全能模式:使用id字段更新
      */
     private function updateSegmentTable($task, $updateData)
     {
@@ -2064,7 +2064,7 @@ class AIVideoGenerationService
             // 分镜模式:使用segment_id更新
             return DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update($updateData);
         } elseif ($act_id) {
-            // 片段模式(全能模式):使用id更新
+            // 全能模式(全能模式):使用id更新
             return DB::table('mp_episode_segments')->where('id', $act_id)->update($updateData);
         }
         
@@ -2074,10 +2074,10 @@ class AIVideoGenerationService
     /**
      * 获取audio_duration(兼容act模式)
      * 分镜模式:使用segment_id查询
-     * 片段模式:使用id查询
+     * 全能模式:使用id查询
      * @param array $task 任务数据
      * @param string|int $segmentIdOrActId segment_id或act_id
-     * @param float|null $video_duration 视频时长(如果传入,片段模式直接返回此值)
+     * @param float|null $video_duration 视频时长(如果传入,全能模式直接返回此值)
      * @return float
      */
     private function getAudioDuration($task, $segmentIdOrActId, $video_duration = null)
@@ -2089,7 +2089,7 @@ class AIVideoGenerationService
             // 分镜模式:使用segment_id查询
             return DB::table('mp_episode_segments')->where('segment_id', $segmentIdOrActId)->value('audio_duration');
         } elseif ($act_id) {
-            // 片段模式(全能模式):如果传入了video_duration直接返回,否则查询audio_duration
+            // 全能模式(全能模式):如果传入了video_duration直接返回,否则查询audio_duration
             if ($video_duration !== null && $video_duration > 0) {
                 return $video_duration;
             }
@@ -2102,7 +2102,7 @@ class AIVideoGenerationService
     /**
      * 添加视频生成对话记录
      * @param array $task 任务数据
-     * @param string|int $segmentIdOrActId segment_id(分镜模式)或 act_id(片段模式)
+     * @param string|int $segmentIdOrActId segment_id(分镜模式)或 act_id(全能模式)
      * @param string $videoUrl 视频URL
      * @return void
      */
@@ -2119,7 +2119,7 @@ class AIVideoGenerationService
                     ->select('b.user_id as uid', 'a.anime_id', 'a.episode_number', 'a.tail_frame', 'a.segment_id')
                     ->first();
             } elseif ($act_id) {
-                // 片段模式:使用id查询
+                // 全能模式:使用id查询
                 $segment = DB::table('mp_episode_segments as a')->leftJoin('mp_animes as b', 'a.anime_id', 'b.id')
                     ->where('a.id', $segmentIdOrActId)
                     ->select('b.user_id as uid', 'a.anime_id', 'a.episode_number', 'a.tail_frame', 'a.segment_id', 'a.id')
@@ -2142,7 +2142,7 @@ class AIVideoGenerationService
                 $recordField = 'segment_id';
                 $recordValue = $segmentIdOrActId;
             } else {
-                // 片段模式:保存act_id字段
+                // 全能模式:保存act_id字段
                 $recordField = 'act_id';
                 $recordValue = $segmentIdOrActId;
             }
@@ -2517,7 +2517,7 @@ class AIVideoGenerationService
             logDB('generate', 'info', '统一API视频生成任务成功', ['id' => $task->id, 'result_url' => $statusInfo['result_url']]);
             $task->updateStatus(MpGenerateVideoTask::STATUS_SUCCESS, $statusInfo);
             
-            // 同步调整分镜视频状态和结果(兼容片段模式)
+            // 同步调整分镜视频状态和结果(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id && isset($statusInfo['result_url'])) {
                 try {
@@ -2541,7 +2541,7 @@ class AIVideoGenerationService
                         $segmentUpdateData['video_duration'] = $statusInfo['video_duration'];
                         $segmentUpdateData['video_time_point_start'] = 0;
                         
-                        // 获取audio_duration(兼容片段模式)
+                        // 获取audio_duration(兼容全能模式)
                         $audio_duration = $this->getAudioDuration($task, $segment_id, $statusInfo['video_duration'] ?? null);
                         $segmentUpdateData['video_time_point_end'] = $audio_duration ?? 0;
                     }
@@ -2570,7 +2570,7 @@ class AIVideoGenerationService
                 'result_json' => $statusInfo['result_json'] ?? []
             ]);
             
-            // 同步更新分镜表状态为失败(兼容片段模式)
+            // 同步更新分镜表状态为失败(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id) {
                 $this->updateSegmentTable($task, [
@@ -2589,7 +2589,7 @@ class AIVideoGenerationService
                 'error_message' => '任务处理超时(超过48小时)'
             ]);
             
-            // 同步更新分镜表状态为失败(兼容片段模式)
+            // 同步更新分镜表状态为失败(兼容全能模式)
             $segment_id = $this->getSegmentIdFromTask($task);
             if ($segment_id) {
                 $this->updateSegmentTable($task, [