|
|
@@ -76,7 +76,9 @@ export class AliyunTtsProvider implements ITtsProvider {
|
|
|
|
|
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
|
try {
|
|
|
- // 构建请求体
|
|
|
+ // 构建请求体(参考 tonggan/scripts/generate-tts.mjs 的成功调用格式)
|
|
|
+ // ⚠️ 重要:cosyvoice 不传 format/sample_rate,否则返回 400 InvalidParameter
|
|
|
+ // 阿里云百炼新版本会自动用 wav 格式(.wav 扩展名)作为默认
|
|
|
const requestBody: any = {
|
|
|
model: activeModel,
|
|
|
input: {
|
|
|
@@ -86,10 +88,7 @@ export class AliyunTtsProvider implements ITtsProvider {
|
|
|
},
|
|
|
};
|
|
|
if (isCosyVoice) {
|
|
|
- requestBody.input.format = 'mp3';
|
|
|
- requestBody.input.sample_rate = 24000;
|
|
|
- // Instruct 情感控制:只支持固定格式 设置情感:{emotion}。
|
|
|
- // CosyVoice v3-flash 系统音色不支持通过 instruction 控制语速/音调/音量
|
|
|
+ // CosyVoice v3-flash 系统音色支持 instruction 情感控制(固定格式 设置情感:{emotion}。)
|
|
|
if ((params as any).instructText) {
|
|
|
requestBody.input.instruction = (params as any).instructText;
|
|
|
}
|
|
|
@@ -114,8 +113,12 @@ export class AliyunTtsProvider implements ITtsProvider {
|
|
|
}
|
|
|
|
|
|
// 千问: 同步非流式
|
|
|
+ // 根据模型动态选择 endpoint
|
|
|
+ const apiPath = activeModel.includes('cosyvoice')
|
|
|
+ ? 'https://dashscope.aliyuncs.com/api/v1/services/audio/tts/SpeechSynthesizer'
|
|
|
+ : 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation';
|
|
|
const response = await withAiLog(
|
|
|
- () => axios.post(this.ttsApiPath, requestBody, {
|
|
|
+ () => axios.post(apiPath, requestBody, {
|
|
|
headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' },
|
|
|
timeout: 600000,
|
|
|
}),
|
|
|
@@ -168,8 +171,15 @@ export class AliyunTtsProvider implements ITtsProvider {
|
|
|
* CosyVoice SSE 流式合成:边生成边接收,无超时限制
|
|
|
*/
|
|
|
private async synthesizeStream(requestBody: any, outputPath: string): Promise<string> {
|
|
|
- console.log(`🔊 [Aliyun SSE] 请求: ${this.ttsApiPath}, model=${this.modelId}, voice=${requestBody.input?.voice || 'default'}, textLen=${requestBody.input?.text?.length || 0}`);
|
|
|
- const response = await axios.post(this.ttsApiPath, requestBody, {
|
|
|
+ // 根据模型动态选择 endpoint:
|
|
|
+ // - cosyvoice-* → /api/v1/services/audio/tts/SpeechSynthesizer
|
|
|
+ // - qwen3-tts-* → /api/v1/services/aigc/multimodal-generation/generation
|
|
|
+ const modelName = requestBody.model || this.modelId;
|
|
|
+ const apiPath = modelName.includes('cosyvoice')
|
|
|
+ ? 'https://dashscope.aliyuncs.com/api/v1/services/audio/tts/SpeechSynthesizer'
|
|
|
+ : 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation';
|
|
|
+ console.log(`🔊 [Aliyun SSE] 请求: ${apiPath}, model=${modelName}, voice=${requestBody.input?.voice || 'default'}, textLen=${requestBody.input?.text?.length || 0}`);
|
|
|
+ const response = await axios.post(apiPath, requestBody, {
|
|
|
headers: {
|
|
|
'Authorization': `Bearer ${this.apiKey}`,
|
|
|
'Content-Type': 'application/json',
|