134 lines
3.3 KiB
Markdown
134 lines
3.3 KiB
Markdown
|
|
# Technical Design: Voice Clone Provider Refactoring
|
|||
|
|
|
|||
|
|
## Context
|
|||
|
|
|
|||
|
|
当前语音克隆功能直接依赖阿里云 CosyVoice 的 SDK 和 API。Service 层直接调用 `CosyVoiceClient`,导致:
|
|||
|
|
|
|||
|
|
1. **强耦合**:无法轻松切换或添加其他供应商
|
|||
|
|
2. **测试困难**:难以 mock 外部依赖
|
|||
|
|
3. **扩展性差**:添加新供应商需要修改 Service 层
|
|||
|
|
|
|||
|
|
## Goals / Non-Goals
|
|||
|
|
|
|||
|
|
### Goals
|
|||
|
|
- 解耦 Service 层与具体供应商实现
|
|||
|
|
- 支持多供应商并存和动态切换
|
|||
|
|
- 保持现有功能完全兼容
|
|||
|
|
- 为添加硅基流动 IndexTTS-2 打下基础
|
|||
|
|
|
|||
|
|
### Non-Goals
|
|||
|
|
- 不改变现有 API 行为
|
|||
|
|
- 不修改数据库结构
|
|||
|
|
- 不改变前端交互
|
|||
|
|
|
|||
|
|
## Decisions
|
|||
|
|
|
|||
|
|
### 1. 采用策略模式 + 工厂模式
|
|||
|
|
|
|||
|
|
**Why**:
|
|||
|
|
- 策略模式:定义统一接口,各供应商独立实现
|
|||
|
|
- 工厂模式:根据配置动态获取 Provider 实例
|
|||
|
|
- 符合开闭原则,扩展时无需修改现有代码
|
|||
|
|
|
|||
|
|
**架构**:
|
|||
|
|
```
|
|||
|
|
VoiceCloneProvider (interface)
|
|||
|
|
├── CosyVoiceProvider (impl) - 阿里云 CosyVoice (DashScope)
|
|||
|
|
├── SiliconFlowProvider (impl) - 阶段二:硅基流动 IndexTTS-2
|
|||
|
|
└── VoiceCloneProviderFactory
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**说明**:
|
|||
|
|
- `CosyVoiceProvider` 对应阿里云 DashScope 的语音服务
|
|||
|
|
- 默认模型:`cosyvoice-v3-flash`
|
|||
|
|
- 扩展时添加新的 Provider 实现
|
|||
|
|
|
|||
|
|
### 2. 统一 DTO 设计
|
|||
|
|
|
|||
|
|
**Why**: 屏蔽不同供应商的 API 差异
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 统一请求
|
|||
|
|
VoiceCloneRequest {
|
|||
|
|
String audioUrl; // 音频 URL
|
|||
|
|
String prefix; // 音色前缀
|
|||
|
|
String targetModel; // 目标模型
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 统一响应
|
|||
|
|
VoiceCloneResult {
|
|||
|
|
String voiceId; // 生成的音色 ID
|
|||
|
|
String requestId; // 请求 ID
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 配置结构设计
|
|||
|
|
|
|||
|
|
**新配置结构**:
|
|||
|
|
```yaml
|
|||
|
|
yudao:
|
|||
|
|
voice:
|
|||
|
|
# 默认供应商
|
|||
|
|
default-provider: cosyvoice
|
|||
|
|
|
|||
|
|
# 供应商配置
|
|||
|
|
providers:
|
|||
|
|
cosyvoice: # 阿里云 CosyVoice
|
|||
|
|
enabled: true
|
|||
|
|
api-key: ${DASHSCOPE_API_KEY}
|
|||
|
|
default-model: cosyvoice-v3-flash
|
|||
|
|
# ... 其他配置
|
|||
|
|
|
|||
|
|
siliconflow: # 阶段二添加
|
|||
|
|
enabled: false
|
|||
|
|
api-key: ${SILICONFLOW_API_KEY}
|
|||
|
|
base-url: https://api.siliconflow.cn
|
|||
|
|
default-model: indextts-2
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**向后兼容**:
|
|||
|
|
- 读取旧配置 `yudao.cosyvoice.*` 并合并到新结构
|
|||
|
|
- 优先使用新配置,旧配置作为 fallback
|
|||
|
|
|
|||
|
|
### 4. 错误处理策略
|
|||
|
|
|
|||
|
|
- Provider 调用失败时,记录详细日志
|
|||
|
|
- 返回统一的业务异常 `VOICE_TTS_FAILED`
|
|||
|
|
- 不暴露底层供应商的技术细节
|
|||
|
|
|
|||
|
|
## Risks / Trade-offs
|
|||
|
|
|
|||
|
|
| Risk | Mitigation |
|
|||
|
|
|------|------------|
|
|||
|
|
| 破坏现有功能 | 充分测试,保持 DTO 兼容 |
|
|||
|
|
| 配置迁移复杂 | 支持旧配置自动映射 |
|
|||
|
|
| 性能开销 | 工厂缓存 Provider 实例 |
|
|||
|
|
|
|||
|
|
## Migration Plan
|
|||
|
|
|
|||
|
|
### 阶段一:CosyVoice 重构
|
|||
|
|
1. 创建接口和工厂
|
|||
|
|
2. 重构 CosyVoice 为 Provider 实现
|
|||
|
|
3. 更新 Service 层使用接口
|
|||
|
|
4. 测试验证
|
|||
|
|
|
|||
|
|
### 阶段二:添加 SiliconFlow
|
|||
|
|
1. 实现 SiliconFlowProvider
|
|||
|
|
2. 添加配置支持
|
|||
|
|
3. 集成测试
|
|||
|
|
|
|||
|
|
### 回滚方案
|
|||
|
|
- 保留原有配置支持
|
|||
|
|
- Feature Flag 控制新逻辑
|
|||
|
|
|
|||
|
|
## Open Questions
|
|||
|
|
|
|||
|
|
1. **Q**: 是否需要支持运行时动态切换供应商?
|
|||
|
|
**A**: 初期不支持,通过配置切换即可
|
|||
|
|
|
|||
|
|
2. **Q**: 是否需要 Provider 健康检查?
|
|||
|
|
**A**: 阶段二考虑添加
|
|||
|
|
|
|||
|
|
3. **Q**: DTO 字段差异如何处理?
|
|||
|
|
**A**: 使用公共字段,扩展字段放 `Map<String, Object> extensions`
|