Files
sionrui/openspec/changes/refactor-voice-provider/design.md
2026-01-27 01:39:08 +08:00

134 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`