AiVideoTask.php 6.1 KB
<?php
/**
 * @remark :
 * @name   :AiVideoTask.php
 * @author :lyh
 * @method :post
 * @time   :2025/4/30 11:18
 */

namespace App\Console\Commands\Ai;

use App\Models\Ai\AiVideo;
use App\Models\Project\AiVideoTask as AiVideoTaskModel;
use App\Models\RouteMap\RouteMap;
use App\Services\AiVideoService;
use App\Services\DingService;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class AiVideoTask extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'save_ai_video';

    public $updateProject = [];//需更新的列表
    public $routes = [];//需要更新的路由

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '查询ai_video是否已经生成';

    /**
     * @return bool
     * @throws \Exception
     */
    public function handle(){
        while (true){
            //获取任务id
            $task_id = $this->getTaskId();
            if(empty($task_id)){
                sleep(300);
                continue;
            }
            $this->_action($task_id);
        }
        return true;
    }

    /**
     * 获取任务id
     * @param int $finish_at
     * @return mixed
     */
    public function getTaskId($finish_at = 2)
    {
        $task_id = Redis::rpop('ai_video_task');
        if (empty($task_id)) {
//            if(!empty($this->updateProject)){
//                $this->updateProject($this->updateProject);
//                $this->updateProject = [];
//            }
//            if(!empty($this->routes)){
//                $this->updateRoutes($this->routes);
//                $this->routes = [];
//            }
            $aiVideoTaskModel = new AiVideoTaskModel();
            $finish_at = date('Y-m-d H:i:s', strtotime('-' . $finish_at . ' hour'));
            $ids = $aiVideoTaskModel->formatQuery(['status'=>$aiVideoTaskModel::STATUS_RUNNING,'updated_at'=>['<=',$finish_at]])->pluck('id');
            if(!empty($ids)){
                foreach ($ids as $id) {
                    Redis::lpush('ai_video_task', $id);
                }
            }
            $task_id = Redis::rpop('ai_video_task');
        }
        return $task_id;
    }

    /**
     * @remark :请求
     * @name   :sendRequest
     * @author :lyh
     * @method :post
     * @time   :2025/4/30 11:31
     */
    public function _action($task_id){
        $aiVideoTaskModel = new AiVideoTaskModel();
        $item = $aiVideoTaskModel->read(['id'=>$task_id]);
        $this->output('ai_video->start:project ID: ' . $item['project_id'] . ',task ID: ' . $task_id);
        $aiVideoService = new AiVideoService($item['project_id']);
        $aiVideoService->task_id = $item['task_id'];
        //拉取文章数据
        $result = $aiVideoService->getVideoDetail();
        if(empty($result['status']) || ($result['status'] != 200)){
            if($item['number'] < 5){
                $aiVideoTaskModel->edit(['number'=>$item['number'] + 1],['id'=>$item['id']]);
            }else{
                $aiVideoTaskModel->edit(['status'=>9],['id'=>$item['id']]);
                // 钉钉通知
                $dingService = new DingService();
                $body = [
                    'keyword' => 'AI_VIDEO获取失败',
                    'msg' => '任务ID:' . $item['task_id'] . PHP_EOL . '返回信息:' . json_encode($result,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
                    'isAtAll' => false, // 是否@所有人
                ];
                $dingService->handle($body);
            }
            $this->output('error: 数据获取失败,status:' . $result['status'] . ',message: ' . ($result['message'] ?? 'null'));
            return false;
        }
        //保存当前项目ai_blog数据
        ProjectServer::useProject($item['project_id']);
        $aiVideoModel = new AiVideo();
        $aiVideoInfo = $aiVideoModel->read(['task_id'=>$item['task_id']],['id','route']);
        if($aiVideoInfo === false){
            // 钉钉通知
            $dingService = new DingService();
            $body = [
                'keyword' => 'AI_VIDEO生成错误',
                'msg' => '任务ID:' . $item['task_id'] . ', 子库获取数据失败, 检查子库数据是否被删除!',
                'isAtAll' => false, // 是否@所有人
            ];
            $dingService->handle($body);
            $this->output('error: 子库获取数据失败, task id: ' . $task_id);
            $aiVideoTaskModel->edit(['status'=>9],['id'=>$item['id']]);
            DB::disconnect('custom_mysql');
            return false;
        }
        //拿到返回的路由查看是否重复
        $route = RouteMap::setRoute($result['data']['url'], RouteMap::SOURCE_AI_VIDEO, $aiVideoInfo['id'], $item['project_id']);
        if($route != $result['data']['url']){
            $aiVideoService->updateDetail(['route'=>$route,'task_id'=>$item['task_id']]);
        }
        $saveData = [
            'title'=>$result['data']['title'],
            'image'=>$result['data']['thumb'],
            'video_url'=>$result['data']['video_url'],
            'route'=>$route,
            'author_id'=>$result['data']['author_id'],
            'keyword'=>json_encode($result['data']['keyword'],true),
            'content'=>$result['data']['content'],
            'text'=>$result['data']['"section'],
            'status'=>$aiVideoTaskModel::STATUS_FINISH
        ];
        $aiVideoModel->edit($saveData,['task_id'=>$item['task_id']]);
        DB::disconnect('custom_mysql');
        $aiVideoTaskModel->edit(['status'=>$aiVideoTaskModel::STATUS_FINISH],['id'=>$item['id']]);
        $this->output('success: task id: ' . $task_id);
        return true;
    }

    /**
     * 输入日志
     * @param $message
     * @return bool
     */
    public function output($message)
    {
        $message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
        echo $message;
        file_put_contents(storage_path('logs/AiVideo/') . date('Ymd') . '.log', $message, FILE_APPEND);
        return true;
    }
}