feat: 功能优化
This commit is contained in:
@@ -50,7 +50,7 @@ const {
|
|||||||
setSpeechRate,
|
setSpeechRate,
|
||||||
resetPreviewState
|
resetPreviewState
|
||||||
} = useTTS({
|
} = useTTS({
|
||||||
provider: TTS_PROVIDERS.QWEN
|
provider: TTS_PROVIDERS.SILICONFLOW
|
||||||
})
|
})
|
||||||
|
|
||||||
// 当前选中的音色ID
|
// 当前选中的音色ID
|
||||||
|
|||||||
@@ -10,28 +10,15 @@ import { normalizeProviderType, VOICE_PROVIDER_TYPES } from '@/config/voiceConfi
|
|||||||
// 兼容旧代码的导出
|
// 兼容旧代码的导出
|
||||||
const TTS_PROVIDERS = VOICE_PROVIDER_TYPES
|
const TTS_PROVIDERS = VOICE_PROVIDER_TYPES
|
||||||
|
|
||||||
// 供应商默认配置(使用标准化后的键名)
|
const DEFAULT_CONFIG = {
|
||||||
const DEFAULT_CONFIG = {
|
|
||||||
cosyvoice: {
|
|
||||||
apiEndpoint: '/api/tik/voice/tts',
|
apiEndpoint: '/api/tik/voice/tts',
|
||||||
audioFormat: 'mp3',
|
audioFormat: 'mp3',
|
||||||
supportedFormats: ['mp3', 'wav']
|
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 = {}) {
|
export function useTTS(options = {}) {
|
||||||
const {
|
const {
|
||||||
provider = VOICE_PROVIDER_TYPES.COSYVOICE,
|
provider = VOICE_PROVIDER_TYPES.SILICONFLOW,
|
||||||
customConfig = {}
|
customConfig = {}
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
@@ -49,9 +36,7 @@ export function useTTS(options = {}) {
|
|||||||
|
|
||||||
// 获取当前供应商配置
|
// 获取当前供应商配置
|
||||||
const getProviderConfig = () => {
|
const getProviderConfig = () => {
|
||||||
const normalizedProvider = normalizeProviderType(provider)
|
return DEFAULT_CONFIG
|
||||||
const config = DEFAULT_CONFIG[normalizedProvider] || DEFAULT_CONFIG.cosyvoice
|
|
||||||
return { ...config, ...customConfig }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,17 +20,14 @@ export const VOICE_PROVIDER_OPTIONS = [
|
|||||||
{ label: '硅基流动 SiliconFlow', value: VOICE_PROVIDER_TYPES.SILICONFLOW }
|
{ label: '硅基流动 SiliconFlow', value: VOICE_PROVIDER_TYPES.SILICONFLOW }
|
||||||
]
|
]
|
||||||
|
|
||||||
// 供应商别名映射(兼容旧名称)
|
|
||||||
export const PROVIDER_ALIAS_MAP = {
|
|
||||||
[VOICE_PROVIDER_TYPES.QWEN]: VOICE_PROVIDER_TYPES.COSYVOICE
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标准化供应商类型(处理别名映射)
|
* 标准化供应商类型
|
||||||
*/
|
*/
|
||||||
export function normalizeProviderType(providerType) {
|
export function normalizeProviderType(providerType) {
|
||||||
if (!providerType) return DEFAULT_VOICE_PROVIDER
|
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
|
return option?.label || providerType
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查供应商是否支持
|
|
||||||
*/
|
|
||||||
export function isProviderSupported(providerType) {
|
|
||||||
const normalized = normalizeProviderType(providerType)
|
|
||||||
return Object.values(VOICE_PROVIDER_TYPES).includes(normalized)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 默认导出配置对象
|
// 默认导出配置对象
|
||||||
export default {
|
export default {
|
||||||
VOICE_PROVIDER_TYPES,
|
VOICE_PROVIDER_TYPES,
|
||||||
DEFAULT_VOICE_PROVIDER,
|
DEFAULT_VOICE_PROVIDER,
|
||||||
VOICE_PROVIDER_OPTIONS,
|
VOICE_PROVIDER_OPTIONS,
|
||||||
PROVIDER_ALIAS_MAP,
|
|
||||||
normalizeProviderType,
|
normalizeProviderType,
|
||||||
getProviderLabel,
|
getProviderLabel,
|
||||||
isProviderSupported
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,15 @@ public class CosyVoiceClient {
|
|||||||
if (!config.isEnabled()) {
|
if (!config.isEnabled()) {
|
||||||
throw exception0(VOICE_TTS_FAILED.getCode(), "未配置 CosyVoice API Key");
|
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())) {
|
if (request == null || StrUtil.isBlank(request.getText())) {
|
||||||
throw exception0(VOICE_TTS_FAILED.getCode(), "TTS 文本不能为空");
|
throw exception0(VOICE_TTS_FAILED.getCode(), "TTS 文本不能为空");
|
||||||
}
|
}
|
||||||
@@ -86,7 +95,9 @@ public class CosyVoiceClient {
|
|||||||
if (StrUtil.isNotBlank(request.getInstruction())) {
|
if (StrUtil.isNotBlank(request.getInstruction())) {
|
||||||
param.setInstruction(request.getInstruction());
|
param.setInstruction(request.getInstruction());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.error("[CosyVoice][SDK参数][param={}, text='{}']", param, request.getText());
|
||||||
|
|
||||||
// 初始化合成器(同步调用传 null)
|
// 初始化合成器(同步调用传 null)
|
||||||
synthesizer = new SpeechSynthesizer(param, null);
|
synthesizer = new SpeechSynthesizer(param, null);
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,9 @@ public class CosyVoiceProvider implements VoiceCloneProvider {
|
|||||||
.preview(request.isPreview())
|
.preview(request.isPreview())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
log.error("[CosyVoiceProvider][构建的cosyRequest][text='{}', voiceId={}, fileUrl={}]",
|
||||||
|
cosyRequest.getText(), cosyRequest.getVoiceId(), cosyRequest.getFileUrl());
|
||||||
|
|
||||||
// 调用底层 Client
|
// 调用底层 Client
|
||||||
cn.iocoder.yudao.module.tik.voice.client.dto.CosyVoiceTtsResult cosyResult =
|
cn.iocoder.yudao.module.tik.voice.client.dto.CosyVoiceTtsResult cosyResult =
|
||||||
cosyVoiceClient.synthesize(cosyRequest);
|
cosyVoiceClient.synthesize(cosyRequest);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.yudao.module.tik.voice.client.dto;
|
package cn.iocoder.yudao.module.tik.voice.client.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -20,8 +21,9 @@ public class SiliconFlowTtsRequest {
|
|||||||
private String model;
|
private String model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 待合成文本
|
* 待合成文本(API 参数名:text)
|
||||||
*/
|
*/
|
||||||
|
@JsonProperty("text")
|
||||||
private String input;
|
private String input;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,11 +39,13 @@ public class SiliconFlowTtsRequest {
|
|||||||
/**
|
/**
|
||||||
* 采样率(如 24000)
|
* 采样率(如 24000)
|
||||||
*/
|
*/
|
||||||
|
@JsonProperty("sample_rate")
|
||||||
private Integer sampleRate;
|
private Integer sampleRate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 响应格式(mp3, wav, pcm)
|
* 响应格式(mp3, wav, pcm)(API 参数名:format)
|
||||||
*/
|
*/
|
||||||
|
@JsonProperty("format")
|
||||||
private String responseFormat;
|
private String responseFormat;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ yudao:
|
|||||||
default-model: cosyvoice-v3-flash
|
default-model: cosyvoice-v3-flash
|
||||||
siliconflow:
|
siliconflow:
|
||||||
enabled: true
|
enabled: true
|
||||||
api-key: sk-epsakfenqnyzoxhmbucsxlhkdqlcbnimslqoivkshalvdozz
|
api-key: sk-kcvifijrafkzxsmnxbgxspnxdvjiaawcbyoiqhmfobykynpx
|
||||||
base-url: https://api.siliconflow.cn
|
base-url: https://api.siliconflow.cn
|
||||||
default-model: IndexTeam/IndexTTS-2
|
default-model: IndexTeam/IndexTTS-2
|
||||||
ice:
|
ice:
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ spring:
|
|||||||
|
|
||||||
yudao:
|
yudao:
|
||||||
voice:
|
voice:
|
||||||
default-provider: cosyvoice
|
default-provider: siliconflow
|
||||||
cosyvoice:
|
cosyvoice:
|
||||||
enabled: true
|
enabled: true
|
||||||
api-key: sk-10c746f8cb8640738f8d6b71af699003
|
api-key: sk-10c746f8cb8640738f8d6b71af699003
|
||||||
@@ -225,8 +225,8 @@ yudao:
|
|||||||
tts-url: https://dashscope.aliyuncs.com/api/v1/services/audio/tts/speech-synthesis
|
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
|
voice-enrollment-url: https://dashscope.aliyuncs.com/api/v1/services/audio/tts/voice-enrollment
|
||||||
siliconflow:
|
siliconflow:
|
||||||
enabled: false
|
enabled: true
|
||||||
api-key: ${SILICONFLOW_API_KEY:}
|
api-key: sk-kcvifijrafkzxsmnxbgxspnxdvjiaawcbyoiqhmfobykynpx
|
||||||
base-url: https://api.siliconflow.cn
|
base-url: https://api.siliconflow.cn
|
||||||
default-model: IndexTeam/IndexTTS-2
|
default-model: IndexTeam/IndexTTS-2
|
||||||
sample-rate: 24000
|
sample-rate: 24000
|
||||||
|
|||||||
Reference in New Issue
Block a user