diff --git a/frontend/app/web-gold/src/components/VoiceSelector.vue b/frontend/app/web-gold/src/components/VoiceSelector.vue index 468bac0880..2eb8e21b43 100644 --- a/frontend/app/web-gold/src/components/VoiceSelector.vue +++ b/frontend/app/web-gold/src/components/VoiceSelector.vue @@ -50,7 +50,7 @@ const { setSpeechRate, resetPreviewState } = useTTS({ - provider: TTS_PROVIDERS.QWEN + provider: TTS_PROVIDERS.SILICONFLOW }) // 当前选中的音色ID diff --git a/frontend/app/web-gold/src/composables/useTTS.js b/frontend/app/web-gold/src/composables/useTTS.js index 48ef4f9d2f..34a9b02d1c 100644 --- a/frontend/app/web-gold/src/composables/useTTS.js +++ b/frontend/app/web-gold/src/composables/useTTS.js @@ -10,28 +10,15 @@ import { normalizeProviderType, VOICE_PROVIDER_TYPES } from '@/config/voiceConfi // 兼容旧代码的导出 const TTS_PROVIDERS = VOICE_PROVIDER_TYPES -// 供应商默认配置(使用标准化后的键名) -const DEFAULT_CONFIG = { - cosyvoice: { +const DEFAULT_CONFIG = { apiEndpoint: '/api/tik/voice/tts', audioFormat: 'mp3', supportedFormats: ['mp3', 'wav'] - }, - azure: { - apiEndpoint: '/api/tik/voice/azure/tts', - audioFormat: 'mp3', - supportedFormats: ['mp3', 'wav', 'ogg'] - }, - aws: { - apiEndpoint: '/api/tik/voice/aws/tts', - audioFormat: 'mp3', - supportedFormats: ['mp3', 'wav', 'ogg'] - } } export function useTTS(options = {}) { const { - provider = VOICE_PROVIDER_TYPES.COSYVOICE, + provider = VOICE_PROVIDER_TYPES.SILICONFLOW, customConfig = {} } = options @@ -49,9 +36,7 @@ export function useTTS(options = {}) { // 获取当前供应商配置 const getProviderConfig = () => { - const normalizedProvider = normalizeProviderType(provider) - const config = DEFAULT_CONFIG[normalizedProvider] || DEFAULT_CONFIG.cosyvoice - return { ...config, ...customConfig } + return DEFAULT_CONFIG } /** diff --git a/frontend/app/web-gold/src/config/voiceConfig.js b/frontend/app/web-gold/src/config/voiceConfig.js index 1e100a3795..a89aa7e0ba 100644 --- a/frontend/app/web-gold/src/config/voiceConfig.js +++ b/frontend/app/web-gold/src/config/voiceConfig.js @@ -20,17 +20,14 @@ export const VOICE_PROVIDER_OPTIONS = [ { label: '硅基流动 SiliconFlow', value: VOICE_PROVIDER_TYPES.SILICONFLOW } ] -// 供应商别名映射(兼容旧名称) -export const PROVIDER_ALIAS_MAP = { - [VOICE_PROVIDER_TYPES.QWEN]: VOICE_PROVIDER_TYPES.COSYVOICE -} + /** - * 标准化供应商类型(处理别名映射) + * 标准化供应商类型 */ export function normalizeProviderType(providerType) { if (!providerType) return DEFAULT_VOICE_PROVIDER - return PROVIDER_ALIAS_MAP[providerType] || providerType + return VOICE_PROVIDER_TYPES[providerType] || providerType } /** @@ -41,21 +38,13 @@ export function getProviderLabel(providerType) { return option?.label || providerType } -/** - * 检查供应商是否支持 - */ -export function isProviderSupported(providerType) { - const normalized = normalizeProviderType(providerType) - return Object.values(VOICE_PROVIDER_TYPES).includes(normalized) -} + // 默认导出配置对象 export default { VOICE_PROVIDER_TYPES, DEFAULT_VOICE_PROVIDER, VOICE_PROVIDER_OPTIONS, - PROVIDER_ALIAS_MAP, normalizeProviderType, getProviderLabel, - isProviderSupported } diff --git a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/CosyVoiceClient.java b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/CosyVoiceClient.java index b8af69d005..0534ef43f7 100644 --- a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/CosyVoiceClient.java +++ b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/CosyVoiceClient.java @@ -57,6 +57,15 @@ public class CosyVoiceClient { if (!config.isEnabled()) { throw exception0(VOICE_TTS_FAILED.getCode(), "未配置 CosyVoice API Key"); } + + // 添加详细的参数检查日志 + String text = request != null ? request.getText() : null; + log.error("[CosyVoice][TTS参数检查][request={}, text={}, voiceId={}, model={}]", + request != null ? "存在" : "为null", + text != null ? "'" + text + "' (长度:" + text.length() + ")" : "为null", + request != null ? request.getVoiceId() : null, + request != null ? request.getModel() : null); + if (request == null || StrUtil.isBlank(request.getText())) { throw exception0(VOICE_TTS_FAILED.getCode(), "TTS 文本不能为空"); } @@ -86,7 +95,9 @@ public class CosyVoiceClient { if (StrUtil.isNotBlank(request.getInstruction())) { param.setInstruction(request.getInstruction()); } - + + log.error("[CosyVoice][SDK参数][param={}, text='{}']", param, request.getText()); + // 初始化合成器(同步调用传 null) synthesizer = new SpeechSynthesizer(param, null); diff --git a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/CosyVoiceProvider.java b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/CosyVoiceProvider.java index 4797cba7ff..91473c5df0 100644 --- a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/CosyVoiceProvider.java +++ b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/CosyVoiceProvider.java @@ -92,6 +92,9 @@ public class CosyVoiceProvider implements VoiceCloneProvider { .preview(request.isPreview()) .build(); + log.error("[CosyVoiceProvider][构建的cosyRequest][text='{}', voiceId={}, fileUrl={}]", + cosyRequest.getText(), cosyRequest.getVoiceId(), cosyRequest.getFileUrl()); + // 调用底层 Client cn.iocoder.yudao.module.tik.voice.client.dto.CosyVoiceTtsResult cosyResult = cosyVoiceClient.synthesize(cosyRequest); diff --git a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/dto/SiliconFlowTtsRequest.java b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/dto/SiliconFlowTtsRequest.java index e60e1eaf09..e7f4f662ae 100644 --- a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/dto/SiliconFlowTtsRequest.java +++ b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/voice/client/dto/SiliconFlowTtsRequest.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.tik.voice.client.dto; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; import lombok.Data; @@ -20,8 +21,9 @@ public class SiliconFlowTtsRequest { private String model; /** - * 待合成文本 + * 待合成文本(API 参数名:text) */ + @JsonProperty("text") private String input; /** @@ -37,11 +39,13 @@ public class SiliconFlowTtsRequest { /** * 采样率(如 24000) */ + @JsonProperty("sample_rate") private Integer sampleRate; /** - * 响应格式(mp3, wav, pcm) + * 响应格式(mp3, wav, pcm)(API 参数名:format) */ + @JsonProperty("format") private String responseFormat; } diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 6275812b75..2b163e6661 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -231,7 +231,7 @@ yudao: default-model: cosyvoice-v3-flash siliconflow: enabled: true - api-key: sk-epsakfenqnyzoxhmbucsxlhkdqlcbnimslqoivkshalvdozz + api-key: sk-kcvifijrafkzxsmnxbgxspnxdvjiaawcbyoiqhmfobykynpx base-url: https://api.siliconflow.cn default-model: IndexTeam/IndexTTS-2 ice: diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index a134437bd5..876fcd2c12 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -214,7 +214,7 @@ spring: yudao: voice: - default-provider: cosyvoice + default-provider: siliconflow cosyvoice: enabled: true api-key: sk-10c746f8cb8640738f8d6b71af699003 @@ -225,8 +225,8 @@ yudao: tts-url: https://dashscope.aliyuncs.com/api/v1/services/audio/tts/speech-synthesis voice-enrollment-url: https://dashscope.aliyuncs.com/api/v1/services/audio/tts/voice-enrollment siliconflow: - enabled: false - api-key: ${SILICONFLOW_API_KEY:} + enabled: true + api-key: sk-kcvifijrafkzxsmnxbgxspnxdvjiaawcbyoiqhmfobykynpx base-url: https://api.siliconflow.cn default-model: IndexTeam/IndexTTS-2 sample-rate: 24000