重构了tts
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-01-05 17:34:15 +08:00
parent bd7eca1bd0
commit be3eb17490
24 changed files with 170 additions and 1593 deletions

View File

@@ -19,15 +19,15 @@ export type SupportedAlphabets =
export const TextSpeakerItemSchema = z.object({
text: z.string(),
ipa: z.string().optional(),
locale: z.string(),
language: z.string(),
});
export const TextSpeakerArraySchema = z.array(TextSpeakerItemSchema);
export const WordDataSchema = z.object({
locales: z
languages: z
.tuple([z.string(), z.string()])
.refine(([first, second]) => first !== second, {
message: "Locales must be different",
message: "Languages must be different",
}),
wordPairs: z
.array(z.tuple([z.string(), z.string()]))
@@ -47,8 +47,8 @@ export const WordDataSchema = z.object({
export const TranslationHistorySchema = z.object({
text1: z.string(),
text2: z.string(),
locale1: z.string(),
locale2: z.string(),
language1: z.string(),
language2: z.string(),
});
export const TranslationHistoryArraySchema = z.array(TranslationHistorySchema);

View File

@@ -1,3 +1,6 @@
"use server";
// ==================== 类型定义 ====================
/**
* 支持的语音合成模型
@@ -135,13 +138,12 @@ class QwenTTSService {
body: JSON.stringify(requestBody),
});
const data: TTSResponse = await response.json();
// 4. 错误处理
if (data.status_code !== 200) {
throw new Error(`API错误: [${data.code}] ${data.message}`);
if (response.status !== 200) {
throw new Error(`TTS API错误: [${response.status}] ${response.statusText}}`);
}
const data: TTSResponse = await response.json();
return data;
} catch (error) {
@@ -149,74 +151,6 @@ class QwenTTSService {
throw error;
}
}
/**
* 流式合成语音边生成边输出Base64音频数据
*/
async synthesizeStream(
text: string,
options: {
voice?: string;
language?: SupportedLanguage;
model?: TTSModel;
onAudioChunk?: (chunk: string) => void; // 接收音频片段的回调
} = {}
): Promise<void> {
const {
voice = 'Cherry',
language = 'Auto',
model = 'qwen3-tts-flash',
onAudioChunk
} = options;
this.validateTextLength(text, model);
const requestBody: TTSRequest = {
model,
input: {
text,
voice,
language_type: language
},
parameters: {
stream: true // 启用流式输出
}
};
try {
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
'X-DashScope-SSE': 'enable' // 关键:启用服务器发送事件
},
body: JSON.stringify(requestBody),
});
if (!response.ok || !response.body) {
throw new Error(`流式请求失败: ${response.status}`);
}
// 处理流式响应此处为简化示例实际需解析SSE格式
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
if (onAudioChunk && chunk.trim()) {
onAudioChunk(chunk); // 处理音频数据片段
}
}
} catch (error) {
console.error('流式合成失败:', error);
throw error;
}
}
}
export type TTS_SUPPORTED_LANGUAGES = 'Auto' | 'Chinese' | 'English' | 'German' | 'Italian' | 'Portuguese' | 'Spanish' | 'Japanese' | 'Korean' | 'French' | 'Russian';
@@ -231,7 +165,7 @@ export async function getTTSUrl(text: string, lang: TTS_SUPPORTED_LANGUAGES) {
throw "API Key设置错误";
}
const ttsService = new QwenTTSService(
process.env.DASHSCOPE_API_KEY || 'sk-xxx',
process.env.DASHSCORE_API_KEY
);
const result = await ttsService.synthesize(
text,