|
|
@@ -2257,6 +2257,42 @@ class AnimeService
|
|
|
if ($dialogue_item) {
|
|
|
$segment_data[] = $dialogue_item;
|
|
|
}
|
|
|
+
|
|
|
+ // 特殊参数: audio_url,audio_duration,subtitle_info
|
|
|
+ // 这些特殊参数必须同时存在才对当前分镜有效,直接保存但不创建音频任务
|
|
|
+ // 如果不是全部存在,则仍需创建音频任务
|
|
|
+ $special_fields = ['audio_url', 'audio_duration', 'subtitle_info'];
|
|
|
+ $special_update_data = [];
|
|
|
+ $has_all_special_params = false;
|
|
|
+
|
|
|
+ // 从segment_data中提取特殊参数
|
|
|
+ $filtered_segment_data = [];
|
|
|
+ foreach ($segment_data as $item) {
|
|
|
+ $field_name = trim((string)getProp($item, 'name'));
|
|
|
+ if (in_array($field_name, $special_fields)) {
|
|
|
+ $special_update_data[$field_name] = getProp($item, 'value');
|
|
|
+ } else {
|
|
|
+ // 非特殊参数保留,继续后续处理
|
|
|
+ $filtered_segment_data[] = $item;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否三个特殊参数都存在
|
|
|
+ if (count($special_update_data) === 3 &&
|
|
|
+ isset($special_update_data['audio_url']) &&
|
|
|
+ isset($special_update_data['audio_duration']) &&
|
|
|
+ isset($special_update_data['subtitle_info'])) {
|
|
|
+ $has_all_special_params = true;
|
|
|
+
|
|
|
+ // 立即更新到当前分镜
|
|
|
+ $special_update_data['updated_at'] = date('Y-m-d H:i:s');
|
|
|
+ DB::table('mp_episode_segments')
|
|
|
+ ->where('segment_id', $segment_id)
|
|
|
+ ->update($special_update_data);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用过滤后的segment_data继续处理其他参数
|
|
|
+ $segment_data = $filtered_segment_data;
|
|
|
|
|
|
$allow_fields = ['dialogue', 'voice_type', 'speed_ratio', 'loudness_ratio', 'emotion_scale'];
|
|
|
$global_update_data = [];
|
|
|
@@ -2416,8 +2452,14 @@ class AnimeService
|
|
|
}
|
|
|
|
|
|
// 为所有有变化的分镜创建音频合成任务
|
|
|
+ // 但如果当前分镜同时设置了全部三个特殊参数(audio_url, audio_duration, subtitle_info),则跳过该分镜
|
|
|
if (!empty($segment_ids_to_create_task)) {
|
|
|
foreach ($segment_ids_to_create_task as $sid) {
|
|
|
+ // 如果当前分镜同时设置了全部三个特殊参数,则跳过音频任务创建
|
|
|
+ if ($sid === $segment_id && $has_all_special_params) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
// 重新获取更新后的分镜数据
|
|
|
$updated_segment = DB::table('mp_episode_segments')
|
|
|
->where('segment_id', $sid)
|
|
|
@@ -3602,4 +3644,76 @@ class AnimeService
|
|
|
return '图片描述生成失败: ' . $e->getMessage();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 音频试听接口
|
|
|
+ * 创建音频任务并轮询获取结果
|
|
|
+ *
|
|
|
+ * @param array $data 参数数组
|
|
|
+ * @return array 返回音频URL或错误信息
|
|
|
+ */
|
|
|
+ public function previewAudio($data) {
|
|
|
+ $dialogue = getProp($data, 'dialogue');
|
|
|
+
|
|
|
+ // 必填参数验证
|
|
|
+ if (!$dialogue) Utils::throwError('20003:dialogue不能为空');
|
|
|
+
|
|
|
+ // 获取参数,优先使用传入的参数,否则使用分镜中的参数
|
|
|
+ $voice_type = getProp($data, 'voice_type');
|
|
|
+ $voice_name = getProp($data, 'voice_name');
|
|
|
+ $voice_actor = getProp($data, 'voice_actor');
|
|
|
+ $emotion_type = getProp($data, 'emotion_type');
|
|
|
+ $gender = getProp($data, 'gender', 0);
|
|
|
+ $emotion = getProp($data, 'emotion');
|
|
|
+ $speed_ratio = getProp($data, 'speed_ratio', 0);
|
|
|
+ $loudness_ratio = getProp($data, 'loudness_ratio', 0);
|
|
|
+ $emotion_scale = getProp($data, 'emotion_scale', 0);
|
|
|
+ $pitch = getProp($data, 'pitch', 0);
|
|
|
+
|
|
|
+ try {
|
|
|
+ $now = date('Y-m-d H:i:s');
|
|
|
+
|
|
|
+ // 构建生成参数
|
|
|
+ $generate_json = json_encode([
|
|
|
+ 'text' => $dialogue,
|
|
|
+ 'role' => $voice_actor,
|
|
|
+ 'voice_type' => $voice_type,
|
|
|
+ 'voice_name' => $voice_name,
|
|
|
+ 'emotion' => $emotion,
|
|
|
+ 'emotion_type' => $emotion_type,
|
|
|
+ 'gender' => $gender,
|
|
|
+ 'speed_ratio' => $speed_ratio,
|
|
|
+ 'loudness_ratio' => $loudness_ratio,
|
|
|
+ 'emotion_scale' => $emotion_scale,
|
|
|
+ 'pitch' => $pitch,
|
|
|
+ ], 256);
|
|
|
+
|
|
|
+ // 请求远程服务器执行生成
|
|
|
+ $client = new Client(['timeout' => 600, 'verify' => false]);
|
|
|
+ $result = $client->get("http://122.9.129.83:5000/api/anime/audioPreview?generateJson={$generate_json}");
|
|
|
+ $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, 'response_arr' => $response_arr]);
|
|
|
+ Utils::throwError('20003:音频试听任务创建失败: ' . $error_msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ $arr = $response_arr['data'];
|
|
|
+ $subtitle_info = $arr['subtitle_info'];
|
|
|
+ $audio_duration = json_decode($subtitle_info, true)['duration'];
|
|
|
+ if (!isset($arr['url']) || !$audio_duration || !$subtitle_info) Utils::throwError('20003:音频参数生成异常');
|
|
|
+ return [
|
|
|
+ 'audio_url' => $arr['url'],
|
|
|
+ 'subtitle_info' => $subtitle_info,
|
|
|
+ 'audio_duration' => $audio_duration
|
|
|
+ ];
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ dLog('anime')->error('音频试听失败', ['error' => $e->getMessage()]);
|
|
|
+ Utils::throwError('20003:' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|