You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8.3 KiB
8.3 KiB
RFC 142: ElevenLabs 音频生成服务集成
状态: ✅ 已实施
创建日期: 2026-02-10
作者: AI Assistant
类型: 新功能
概述
集成 ElevenLabs API,为 Jointo 平台提供专业的音频生成能力,包括:
- 文本转语音(TTS):高质量多语言配音生成
- 音效生成:基于文本描述生成环境音效
- 音色管理:列出和选择可用音色
动机
当前问题
- AIHubMix 仅支持 TTS,不支持专业音效生成
generate_sound()方法抛出NotImplementedError- 缺乏音色管理功能
解决方案
- 引入 ElevenLabs 作为专业音频生成服务
- 遵循现有 Provider 架构模式
- 与积分系统和任务队列无缝集成
技术设计
1. 架构设计
server/app/services/ai_providers/
├── base.py # ✅ 扩展基类
├── elevenlabs_provider.py # ✅ 新增 ElevenLabs Provider
├── factory.py # ✅ 注册 ElevenLabs 模型
├── aihubmix_provider.py # 保持不变
└── mock_provider.py # 保持不变
2. 核心组件
2.1 基类扩展(base.py)
新增方法:
async def generate_sound_effect(
self,
text: str,
duration_seconds: Optional[float] = None,
prompt_influence: float = 0.3,
**kwargs
) -> Dict[str, Any]:
"""生成音效(ElevenLabs 专用方法)"""
async def list_voices(self) -> Dict[str, Any]:
"""列出可用音色(TTS 专用方法)"""
2.2 ElevenLabs Provider(elevenlabs_provider.py)
核心功能:
- 音色列表:
list_voices()- 获取所有可用音色 - 文本转语音:
generate_voice()- 高质量 TTS - 音效生成:
generate_sound_effect()- 环境音效生成
API 集成:
- 认证:
xi-api-keyHeader - 端点:
GET /v1/voices- 音色列表POST /v1/text-to-speech/{voice_id}- TTSPOST /v1/sound-generation- 音效生成
返回格式:
{
'audio_data': bytes, # 原始音频数据
'audio_url': None, # 需上传到 S3
'duration': float,
'metadata': dict
}
2.3 工厂注册(factory.py)
新增模型列表:
ELEVENLABS_MODELS = [
'eleven_multilingual_v2', # 多语言 TTS v2
'eleven_turbo_v2', # 快速 TTS v2
'eleven_turbo_v2_5', # 快速 TTS v2.5
'eleven_monolingual_v1', # 单语言 TTS v1
'eleven_text_to_sound_v2', # 音效生成 v2
]
3. AI Service 更新
3.1 generate_sound() 方法重构
变更前:
async def generate_sound(...):
raise NotImplementedError("音效生成功能暂不可用")
变更后:
async def generate_sound(...):
# 1. 验证用户和项目
# 2. 检查配额
# 3. 计算积分
# 4. 预扣积分
# 5. 创建任务
# 6. 提交 Celery 任务
return {'job_id': ..., 'task_id': ..., 'status': 'pending'}
默认模型:eleven_text_to_sound_v2
4. 配置管理
4.1 环境变量(config.py)
ELEVENLABS_API_KEY: str = ""
ELEVENLABS_BASE_URL: str = "https://api.elevenlabs.io"
4.2 .env 配置
# ElevenLabs 音频生成服务
ELEVENLABS_API_KEY=your_api_key_here
ELEVENLABS_BASE_URL=https://api.elevenlabs.io
5. 依赖管理
requirements.txt
elevenlabs==2.35.0 # ElevenLabs 音频生成服务
API 使用示例
1. 列出音色
from app.services.ai_providers.factory import AIProviderFactory
provider = AIProviderFactory.create_provider('eleven_multilingual_v2')
voices = await provider.list_voices()
# 返回格式
{
'voices': [
{
'voice_id': 'EXAVITQu4vr4xnSDxMaL',
'name': 'Sarah',
'category': 'premade',
'labels': {'accent': 'american', 'age': 'young'}
},
...
]
}
2. 生成配音
# 通过 AI Service
result = await ai_service.generate_voice(
user_id='user_123',
text='你好,欢迎使用 Jointo',
voice_type='EXAVITQu4vr4xnSDxMaL', # 音色 ID
model='eleven_multilingual_v2',
project_id='project_456'
)
# 返回
{
'job_id': 'uuid',
'task_id': 'celery_task_id',
'status': 'pending',
'estimated_credits': 10
}
3. 生成音效
# 通过 AI Service
result = await ai_service.generate_sound(
user_id='user_123',
description='海浪拍打沙滩的声音',
duration=10,
model='eleven_text_to_sound_v2',
prompt_influence=0.5,
loop=False
)
# 返回
{
'job_id': 'uuid',
'task_id': 'celery_task_id',
'status': 'pending',
'estimated_credits': 15
}
数据流
音效生成流程
用户请求
↓
AI Service.generate_sound()
↓
1. 验证用户/项目
2. 检查配额
3. 计算积分(Credit Service)
4. 预扣积分
5. 创建 AIJob 记录
↓
Celery Task (generate_sound_task)
↓
ElevenLabs Provider.generate_sound_effect()
↓
ElevenLabs API
↓
返回音频二进制数据
↓
上传到 S3(File Storage Service)
↓
更新 AIJob 状态和结果
↓
用户获取音频 URL
错误处理
1. API 错误
try:
response = await client.post(url, ...)
response.raise_for_status()
except httpx.HTTPStatusError as e:
logger.error("ElevenLabs API 错误: status=%d", e.response.status_code)
raise ValidationError(f"音效生成失败: {e.response.text}")
2. 配置缺失
if not self.api_key:
raise ValidationError("ELEVENLABS_API_KEY 未配置")
3. 参数验证
if duration_seconds is not None:
if not (0.5 <= duration_seconds <= 30):
raise ValidationError("duration_seconds 必须在 0.5-30 秒之间")
测试策略
1. 单元测试
# tests/unit/services/test_elevenlabs_provider.py
async def test_list_voices():
provider = ElevenLabsProvider('eleven_multilingual_v2')
voices = await provider.list_voices()
assert 'voices' in voices
assert len(voices['voices']) > 0
async def test_generate_sound_effect():
provider = ElevenLabsProvider('eleven_text_to_sound_v2')
result = await provider.generate_sound_effect(
text='海浪声',
duration_seconds=5.0
)
assert 'audio_data' in result
assert len(result['audio_data']) > 0
2. 集成测试
# tests/integration/test_ai_sound_generation.py
async def test_generate_sound_with_credits(client, test_user):
response = await client.post(
'/api/v1/ai/sound',
json={
'description': '雨声',
'duration': 10,
'model': 'eleven_text_to_sound_v2'
},
headers={'Authorization': f'Bearer {test_user.token}'}
)
assert response.status_code == 200
assert 'job_id' in response.json()
部署清单
1. 环境变量配置
- 添加
ELEVENLABS_API_KEY到生产环境 - 验证
ELEVENLABS_BASE_URL配置
2. 依赖安装
docker exec jointo-server-app pip install elevenlabs==1.18.2
3. 数据库迁移
无需迁移(复用现有 ai_jobs 表)
4. 服务重启
docker-compose restart jointo-server-app
docker-compose restart jointo-server-celery-ai
监控指标
1. 关键指标
- ElevenLabs API 调用成功率
- 音效生成平均耗时
- 音频文件大小分布
- 积分消耗统计
2. 日志监控
logger.info("成功生成音效: text=%s, duration=%s, audio_size=%d bytes", ...)
logger.error("ElevenLabs API 错误: status=%d, response=%s", ...)
未来优化
1. 音色缓存
- 缓存
list_voices()结果到 Redis(TTL: 1 小时) - 减少 API 调用次数
2. 音频预处理
- 支持音频格式转换(MP3 → WAV)
- 支持音量归一化
3. 批量生成
- 支持批量音效生成
- 优化积分消耗
4. 音色推荐
- 基于场景推荐合适音色
- 用户音色偏好记录
参考资料
变更记录
| 日期 | 版本 | 变更内容 | 作者 |
|---|---|---|---|
| 2026-02-10 | 1.0.0 | 初始版本 | AI Assistant |