| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- <?php
- namespace App\Console\Anime;
- use Illuminate\Console\Command;
- use Illuminate\Support\Facades\DB;
- use GuzzleHttp\Client;
- class SegmentCheckAudioCommand extends Command
- {
- /**
- * The name and signature of the console command.
- *
- * @var string
- */
- protected $signature = 'Segment:checkAudio';
- /**
- * The console command description.
- *
- * @var string
- */
- protected $description = '检查分镜音频信息';
- public function __construct()
- {
- parent::__construct();
- }
- /**
- * Execute the console command.
- *
- * @return int
- */
- public function handle()
- {
- dLog('command')->info('====================开始检查分镜音频信息====================');
- $time_start = microtime(true);
- $timeout = 50; // 超时时间50秒
- $check_interval = 3; // 每3秒检查一次
-
- while (true) {
- // 检查是否超时
- $elapsed_time = microtime(true) - $time_start;
- if ($elapsed_time >= $timeout) {
- dLog('command')->info('检查超时,退出循环');
- break;
- }
- // 1. 查询mp_dub_video_tasks表中1分钟之前创建的generate_status=执行中的任务,并重新调用API
- $oneMinuteAgo = date('Y-m-d H:i:s', strtotime('-1 minute'));
- $pendingTasks = DB::table('mp_dub_video_tasks')
- ->where('generate_status', '执行中')
- ->where('created_at', '<=', $oneMinuteAgo)
- ->limit(10) // 每次处理10个任务
- ->get();
-
- if ($pendingTasks->isNotEmpty()) {
- dLog('command')->info('找到待重试的音频任务', ['count' => $pendingTasks->count()]);
-
- foreach ($pendingTasks as $task) {
- try {
- $dubTaskId = $task->id;
-
- sleep(1);
- // 请求远程服务器执行生成
- $client = new Client(['timeout' => 300, 'verify' => false]);
- $result = $client->get("http://122.9.129.83:5000/api/anime/genAudio?taskId={$dubTaskId}");
- $response = $result->getBody()->getContents();
- $response_arr = json_decode($response, true);
-
- if (!isset($response_arr['code']) || (int)$response_arr['code'] !== 0) {
- $error_msg = isset($response_arr['msg']) ? $response_arr['msg'] : '未知错误';
- dLog('command')->error('火山生成音频失败', ['error' => $error_msg, 'task_id' => $dubTaskId]);
- logDB('command', 'error', '火山生成音频失败', ['error' => $error_msg, 'task_id' => $dubTaskId]);
-
- // 标记任务为失败
- DB::table('mp_dub_video_tasks')
- ->where('id', $dubTaskId)
- ->update([
- 'generate_status' => '失败',
- 'updated_at' => date('Y-m-d H:i:s')
- ]);
- } else {
- dLog('command')->info('音频任务重试成功', ['task_id' => $dubTaskId]);
- }
- } catch (\Exception $e) {
- dLog('command')->error('重试音频任务异常', [
- 'task_id' => $task->id,
- 'error' => $e->getMessage()
- ]);
- }
- }
- }
- // 2. 查询mp_episode_segments表中img_url不为空但audio_url为空的分镜
- $segmentsNeedAudio = DB::table('mp_episode_segments')
- ->whereNotNull('img_url')
- ->where('img_url', '!=', '')
- ->where('voice_type', '!=', '')
- ->where(function($query) {
- $query->whereNull('audio_url')
- ->orWhere('audio_url', '');
- })
- ->limit(10) // 每次处理2个分镜
- ->get();
-
- if ($segmentsNeedAudio->isNotEmpty()) {
- dLog('command')->info('找到需要生成音频的分镜', ['count' => $segmentsNeedAudio->count()]);
-
- foreach ($segmentsNeedAudio as $segment) {
- try {
- $segment_id = $segment->segment_id;
- $dialogue = getProp($segment, 'dialogue');
- $now = date('Y-m-d H:i:s');
-
- // 如果有对话内容,创建视频配音合成任务
- if (!empty($dialogue)) {
- $generate_json = [
- 'text' => $dialogue,
- 'role' => getProp($segment, 'voice_actor'),
- 'voice_type' => getProp($segment, 'voice_type'),
- 'voice_name' => getProp($segment, 'voice_name'),
- 'emotion' => getProp($segment, 'emotion'),
- 'emotion_type' => getProp($segment, 'emotion_type'),
- 'gender' => getProp($segment, 'gender'),
- 'speed_ratio' => getProp($segment, 'speed_ratio', 0),
- 'loudness_ratio' => getProp($segment, 'loudness_ratio', 0),
- 'emotion_scale' => getProp($segment, 'emotion_scale', 0),
- 'pitch' => getProp($segment, 'pitch', 0),
- ];
-
- // 插入视频配音合成任务
- $dubTaskId = DB::table('mp_dub_video_tasks')->insertGetId([
- 'alias_segment_id' => $segment_id,
- 'generate_status' => '执行中',
- 'audio_url' => '',
- 'generate_json' => json_encode($generate_json, 256),
- 'created_at' => $now,
- 'updated_at' => $now,
- ]);
-
- if (!$dubTaskId) {
- dLog('command')->error('创建配音任务失败', ['segment_id' => $segment_id]);
- continue;
- }
-
- // 先更新分镜表,将audio_url设置为空字符串(标记正在生成)
- DB::table('mp_episode_segments')
- ->where('segment_id', $segment_id)
- ->update([
- 'audio_url' => '',
- 'updated_at' => $now
- ]);
-
- dLog('command')->info('开始请求远程服务器生成音频', ['task_id' => $dubTaskId, 'segment_id' => $segment_id]);
-
- sleep(1);
- // 请求远程服务器执行生成(远程服务器会更新audio_url字段)
- $client = new Client(['timeout' => 300, 'verify' => false]);
- $result = $client->get("http://122.9.129.83:5000/api/anime/genAudio?taskId={$dubTaskId}");
- $response = $result->getBody()->getContents();
- $response_arr = json_decode($response, true);
-
- if (!isset($response_arr['code']) || (int)$response_arr['code'] !== 0) {
- $error_msg = isset($response_arr['msg']) ? $response_arr['msg'] : '未知错误';
- dLog('command')->error('火山生成音频失败', ['error' => $error_msg, 'task_id' => $dubTaskId, 'segment_id' => $segment_id]);
- logDB('command', 'error', '火山生成音频失败', ['error' => $error_msg, 'task_id' => $dubTaskId, 'segment_id' => $segment_id]);
- } else {
- dLog('command')->info('音频任务创建成功', ['task_id' => $dubTaskId, 'segment_id' => $segment_id]);
- }
- } else {
- // dialogue为空时,直接写入默认音频信息
- DB::table('mp_episode_segments')
- ->where('segment_id', $segment_id)
- ->update([
- 'audio_url' => 'https://zw-audiobook.tos-cn-beijing.volces.com/effects/ellipses_2s.mp3',
- 'audio_duration' => 2.0,
- 'subtitle_info' => json_encode(['duration' => 2.0, 'words' => []], 256),
- 'updated_at' => $now
- ]);
-
- dLog('command')->info('分镜无对话,写入默认音频', ['segment_id' => $segment_id]);
- }
- } catch (\Exception $e) {
- dLog('command')->error('处理分镜音频异常', [
- 'segment_id' => $segment->segment_id,
- 'error' => $e->getMessage()
- ]);
- }
- }
- }
- // 如果没有待处理的任务,退出循环
- if ($pendingTasks->isEmpty() && $segmentsNeedAudio->isEmpty()) {
- dLog('command')->info('没有待处理的音频任务,退出循环');
- break;
- }
- // 等待3秒后继续下一次检查
- sleep($check_interval);
- }
- $time_end = microtime(true);
- $execution_time = round($time_end - $time_start, 2);
- dLog('command')->info('脚本执行时间: '.round($time_end-$time_start, 2).'秒');
- dLog('command')->info('====================结束检查分镜音频信息====================');
- }
-
- }
|