|
|
@@ -2306,16 +2306,52 @@ class AnimeService
|
|
|
DB::beginTransaction();
|
|
|
|
|
|
$now = date('Y-m-d H:i:s');
|
|
|
+
|
|
|
+ // 收集需要创建音频合成任务的segment_id和对应的分镜数据
|
|
|
+ $segment_ids_to_create_task = [];
|
|
|
+ $segments_data = [];
|
|
|
|
|
|
+ // 如果有全局更新,获取该角色的所有分镜数据并检查是否有变化
|
|
|
if (!empty($global_update_data)) {
|
|
|
if (!$target_voice_actor) Utils::throwError('20003:角色异常');
|
|
|
|
|
|
- $global_segment_update_data = $global_update_data;
|
|
|
- $global_segment_update_data['updated_at'] = $now;
|
|
|
- DB::table('mp_episode_segments')
|
|
|
+ $affected_segments = DB::table('mp_episode_segments')
|
|
|
->where('episode_id', $episode_id)
|
|
|
->where('voice_actor', $target_voice_actor)
|
|
|
- ->update($global_segment_update_data);
|
|
|
+ ->select('segment_id', 'audio_url', 'voice_actor', 'dialogue', 'voice_type', 'voice_name', 'voice_audio_url', 'emotion', 'emotion_type', 'gender', 'speed_ratio', 'loudness_ratio', 'emotion_scale', 'pitch')
|
|
|
+ ->get();
|
|
|
+
|
|
|
+ foreach ($affected_segments as $seg) {
|
|
|
+ $seg = (array)$seg;
|
|
|
+ $sid = getProp($seg, 'segment_id');
|
|
|
+
|
|
|
+ // 检查参数是否发生变化
|
|
|
+ $has_changed = false;
|
|
|
+ foreach ($global_update_data as $field => $new_value) {
|
|
|
+ $old_value = getProp($seg, $field);
|
|
|
+ if ($old_value != $new_value) {
|
|
|
+ $has_changed = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($has_changed) {
|
|
|
+ $segment_ids_to_create_task[] = $sid;
|
|
|
+ $segments_data[$sid] = $seg;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 只有在有变化的分镜时才更新
|
|
|
+ if (!empty($segment_ids_to_create_task)) {
|
|
|
+ $global_segment_update_data = $global_update_data;
|
|
|
+ $global_segment_update_data['audio_url'] = ''; // 清空音频URL
|
|
|
+ $global_segment_update_data['updated_at'] = $now;
|
|
|
+ DB::table('mp_episode_segments')
|
|
|
+ ->where('episode_id', $episode_id)
|
|
|
+ ->where('voice_actor', $target_voice_actor)
|
|
|
+ ->whereIn('segment_id', $segment_ids_to_create_task)
|
|
|
+ ->update($global_segment_update_data);
|
|
|
+ }
|
|
|
|
|
|
if ($global_voice_type) {
|
|
|
$episode_roles = json_decode((string)getProp($episode, 'roles'), true);
|
|
|
@@ -2343,51 +2379,103 @@ class AnimeService
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 如果有单个分镜更新,检查是否有变化
|
|
|
if (!empty($segment_update_data)) {
|
|
|
- $segment_update_data['updated_at'] = $now;
|
|
|
- DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update($segment_update_data);
|
|
|
- }
|
|
|
-
|
|
|
- // 收集需要创建音频合成任务的segment_id
|
|
|
- $segment_ids_to_create_task = [];
|
|
|
- $segments_data = [];
|
|
|
-
|
|
|
- // 如果有全局更新,获取该角色的所有分镜数据
|
|
|
- if (!empty($global_update_data)) {
|
|
|
- $affected_segments = DB::table('mp_episode_segments')
|
|
|
- ->where('episode_id', $episode_id)
|
|
|
- ->where('voice_actor', $target_voice_actor)
|
|
|
- ->select('segment_id', 'video_url', 'voice_actor', 'dialogue', 'voice_type', 'voice_name', 'emotion', 'emotion_type', 'gender', 'speed_ratio', 'loudness_ratio', 'emotion_scale', 'pitch')
|
|
|
- ->get();
|
|
|
+ // 获取当前分镜数据
|
|
|
+ $current_segment = DB::table('mp_episode_segments')
|
|
|
+ ->where('segment_id', $segment_id)
|
|
|
+ ->select('segment_id', 'audio_url', 'voice_actor', 'dialogue', 'voice_type', 'voice_name', 'voice_audio_url', 'emotion', 'emotion_type', 'gender', 'speed_ratio', 'loudness_ratio', 'emotion_scale', 'pitch')
|
|
|
+ ->first();
|
|
|
|
|
|
- foreach ($affected_segments as $seg) {
|
|
|
- $seg = (array)$seg;
|
|
|
- $sid = getProp($seg, 'segment_id');
|
|
|
- $segment_ids_to_create_task[] = $sid;
|
|
|
- $segments_data[$sid] = $seg;
|
|
|
+ if ($current_segment) {
|
|
|
+ $current_segment = (array)$current_segment;
|
|
|
+
|
|
|
+ // 检查参数是否发生变化
|
|
|
+ $has_changed = false;
|
|
|
+ foreach ($segment_update_data as $field => $new_value) {
|
|
|
+ $old_value = getProp($current_segment, $field);
|
|
|
+ if ($old_value != $new_value) {
|
|
|
+ $has_changed = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($has_changed) {
|
|
|
+ // 如果该分镜还未在列表中,添加进去
|
|
|
+ if (!in_array($segment_id, $segment_ids_to_create_task)) {
|
|
|
+ $segment_ids_to_create_task[] = $segment_id;
|
|
|
+ $segments_data[$segment_id] = $current_segment;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新分镜数据并清空音频URL
|
|
|
+ $segment_update_data['audio_url'] = '';
|
|
|
+ $segment_update_data['updated_at'] = $now;
|
|
|
+ DB::table('mp_episode_segments')->where('segment_id', $segment_id)->update($segment_update_data);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 如果有单个分镜更新,添加该分镜数据
|
|
|
- if (!empty($segment_update_data)) {
|
|
|
- $segment_ids_to_create_task[] = $segment_id;
|
|
|
-
|
|
|
- // 如果该分镜数据还未获取,则获取
|
|
|
- if (!isset($segments_data[$segment_id])) {
|
|
|
- $segment = DB::table('mp_episode_segments')
|
|
|
- ->where('segment_id', $segment_id)
|
|
|
- ->select('segment_id', 'video_url', 'voice_actor', 'dialogue', 'voice_type', 'voice_name', 'emotion', 'emotion_type', 'gender', 'speed_ratio', 'loudness_ratio', 'emotion_scale', 'pitch')
|
|
|
+ // 为所有有变化的分镜创建音频合成任务
|
|
|
+ if (!empty($segment_ids_to_create_task)) {
|
|
|
+ foreach ($segment_ids_to_create_task as $sid) {
|
|
|
+ // 重新获取更新后的分镜数据
|
|
|
+ $updated_segment = DB::table('mp_episode_segments')
|
|
|
+ ->where('segment_id', $sid)
|
|
|
+ ->select('voice_actor', 'dialogue', 'voice_type', 'voice_name', 'emotion', 'emotion_type', 'gender', 'speed_ratio', 'loudness_ratio', 'emotion_scale', 'pitch')
|
|
|
->first();
|
|
|
|
|
|
- if ($segment) {
|
|
|
- $segments_data[$segment_id] = (array)$segment;
|
|
|
+ if (!$updated_segment) continue;
|
|
|
+
|
|
|
+ $updated_segment = (array)$updated_segment;
|
|
|
+
|
|
|
+ $generate_json = [
|
|
|
+ 'text' => getProp($updated_segment, 'dialogue'),
|
|
|
+ 'role' => getProp($updated_segment, 'voice_actor'),
|
|
|
+ 'voice_type' => getProp($updated_segment, 'voice_type'),
|
|
|
+ 'voice_name' => getProp($updated_segment, 'voice_name'),
|
|
|
+ 'emotion' => getProp($updated_segment, 'emotion'),
|
|
|
+ 'emotion_type' => getProp($updated_segment, 'emotion_type'),
|
|
|
+ 'gender' => getProp($updated_segment, 'gender'),
|
|
|
+ 'speed_ratio' => getProp($updated_segment, 'speed_ratio', 0),
|
|
|
+ 'loudness_ratio' => getProp($updated_segment, 'loudness_ratio', 0),
|
|
|
+ 'emotion_scale' => getProp($updated_segment, 'emotion_scale', 0),
|
|
|
+ 'pitch' => getProp($updated_segment, 'pitch', 0),
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 插入视频配音合成任务
|
|
|
+ $dubTaskId = DB::table('mp_dub_video_tasks')->insertGetId([
|
|
|
+ 'alias_segment_id' => $sid,
|
|
|
+ 'generate_status' => '执行中',
|
|
|
+ 'audio_url' => '',
|
|
|
+ 'generate_json' => json_encode($generate_json, 256),
|
|
|
+ 'created_at' => $now,
|
|
|
+ 'updated_at' => $now,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ if (!$dubTaskId) {
|
|
|
+ dLog('anime')->error('创建配音任务失败', ['segment_id' => $sid]);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 请求远程服务器执行生成
|
|
|
+ try {
|
|
|
+ $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('anime')->error('火山生成音频失败', ['error' => $error_msg, 'task_id' => $dubTaskId, 'segment_id' => $sid]);
|
|
|
+ logDB('anime', 'error', '火山生成音频失败', ['error' => $error_msg, 'task_id' => $dubTaskId, 'segment_id' => $sid]);
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ dLog('anime')->error('调用音频生成API失败', ['error' => $e->getMessage(), 'task_id' => $dubTaskId, 'segment_id' => $sid]);
|
|
|
+ logDB('anime', 'error', '调用音频生成API失败', ['error' => $e->getMessage(), 'task_id' => $dubTaskId, 'segment_id' => $sid]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 去重
|
|
|
- $segment_ids_to_create_task = array_unique($segment_ids_to_create_task);
|
|
|
-
|
|
|
DB::commit();
|
|
|
|
|
|
} catch (\Exception $e) {
|