fix(P0): 预置音色试听-实时TTS合成试听音频 #587

Merged
auto-approve-bot merged 2 commits from fix/p0-preset-voice-preview into develop 2026-07-19 15:06:00 +08:00
Owner

问题

配音库页面点击预置音色(如龙小夏、龙小淳)的试听按钮,没有任何声音。PRESET_VOICES中所有预置音色的preview_url都是空字符串。

方案

采用方案B:点击试听时实时调用TTS合成一句示例文本,返回音频URL。

相比方案A(配置固定demo音频)的优势:

  • 不需要手动准备和维护8个demo音频文件
  • 用户可以用自定义文本试听(text参数)
  • 音色有更新时试听自动同步

实现

  • 新增 GET /voices/presets/{voice_id}/preview 端点
  • 默认试听文本:「你好,我是{name},很高兴认识你。」
  • 内存缓存7天TTL,相同音色重复调用直接返回缓存(减少TTS调用)
  • 支持自定义 text 参数(自定义文本不缓存)
  • 合成失败返回502错误

前端适配

前端点击试听按钮时调用新接口,拿到audio_url后播放即可。

## 问题 配音库页面点击预置音色(如龙小夏、龙小淳)的试听按钮,没有任何声音。PRESET_VOICES中所有预置音色的preview_url都是空字符串。 ## 方案 采用方案B:点击试听时实时调用TTS合成一句示例文本,返回音频URL。 相比方案A(配置固定demo音频)的优势: - 不需要手动准备和维护8个demo音频文件 - 用户可以用自定义文本试听(text参数) - 音色有更新时试听自动同步 ## 实现 - 新增 GET /voices/presets/{voice_id}/preview 端点 - 默认试听文本:「你好,我是{name},很高兴认识你。」 - 内存缓存7天TTL,相同音色重复调用直接返回缓存(减少TTS调用) - 支持自定义 text 参数(自定义文本不缓存) - 合成失败返回502错误 ## 前端适配 前端点击试听按钮时调用新接口,拿到audio_url后播放即可。
xiaoxia reviewed 2026-07-19 14:20:48 +08:00
xiaoxia left a comment
Author
Owner

LGTM

LGTM

🚀 预览环境已部署

项目 详情
PR号 #587
预览链接 https://pr-587.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #587 | | 预览链接 | [https://pr-587.preview.xiaoxiajianji.com](https://pr-587.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
xiaoxia added 1 commit 2026-07-19 14:43:37 +08:00
fix(P0): 预置音色试听 - 新增实时TTS合成试听接口
CI Build & Deploy Pipeline / Build Staging API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Production (pull_request) Has been skipped
CI Build & Deploy Pipeline / Production Browser E2E (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Failing after 16s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 17s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Failing after 30s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 43s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 3m59s
Auto Merge CI PRs / Auto Merge on CI Green + Approved (pull_request) Successful in 4m18s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 6m12s
Auto Approve CI PRs / Auto Approve on CI Green (pull_request) Successful in 6m21s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m38s
7493f6d2b8
- 新增 GET /voices/presets/{voice_id}/preview 端点
- 支持自定义试听文本,默认使用预置音色名称的问候语
- 默认试听音频7天内存缓存,减少重复TTS调用
- 修复预置音色全没声音的问题

Issue: #578
xiaoxia force-pushed fix/p0-preset-voice-preview from f1719533ba to 7493f6d2b8 2026-07-19 14:43:37 +08:00 Compare
xiaoxia added 1 commit 2026-07-19 14:52:18 +08:00
fix: 修复import排序问题(isort)
CI Build & Deploy Pipeline / Build Staging API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Production (pull_request) Has been skipped
CI Build & Deploy Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 20s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Successful in 32s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m1s
AI Code Review / AI Code Review (pull_request) Successful in 2m41s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 6m28s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 8m51s
Auto Approve CI PRs / Auto Approve on CI Green (pull_request) Successful in 8m58s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m47s
Auto Merge CI PRs / Auto Merge on CI Green + Approved (pull_request) Successful in 13m41s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 19s
25d3fdd087
Collaborator

代码审查结果 - PR #587

⚠️ 问题(3个需要修改)

  1. apps/api/app/api/routes/voices.py 第30行:内存泄漏风险

    • 问题描述:全局字典 _preset_preview_cache 只有写入逻辑,没有过期清理机制。虽然读取时会检查 TTL,但过期的 key-value 对永远不会从字典中删除。随着时间推移和不同音色的访问,内存占用会持续增长直至 OOM。
    • 修改建议:使用 cachetools.TTLCache 或引入 Redis 等外部缓存服务,自动处理过期淘汰。
  2. apps/api/app/api/routes/voices.py 第228行:参数校验缺失导致 DoS 风险

    • 问题描述:text 参数没有最大长度限制。恶意用户可以传入超长字符串(如几 MB 的文本),直接传递给 TTS 服务,可能导致上游服务崩溃、API 响应超时或服务器资源耗尽。
    • 修改建议:在 Query 中添加 max_length 限制(例如 Query("", max_length=500, ...)),或在函数开始处显式校验文本长度。
  3. apps/api/app/api/routes/voices.py 第30行:多进程环境缓存失效

    • 问题描述:使用模块级全局变量作为缓存,在 Gunicorn/uvicorn 多进程(多 Worker)部署模式下,每个进程拥有独立的缓存副本。这不仅导致缓存命中率大幅下降(重复计算),还无法实现预期的“减少重复 TTS 调用”效果。
    • 修改建议:若必须使用本地缓存,需明确仅限单进程模式;生产环境建议迁移至 Redis 等集中式缓存。

💡 建议(1个可选)

  1. apps/api/app/api/routes/voices.py 第230行:代码规范建议
    • 具体内容:建议将 import time 移至文件顶部,与其他 import 语句放在一起,避免在函数内部进行导入操作。

格式检查通过 | 逻辑审查需修改 | ⚠️ 建议关注性能


🤖 由 AI 代码审查机器人自动生成 | 2026-07-19 14:54:57 | 模型:

## 代码审查结果 - PR #587 ### ⚠️ 问题(3个需要修改) 1. **apps/api/app/api/routes/voices.py 第30行**:内存泄漏风险 - 问题描述:全局字典 `_preset_preview_cache` 只有写入逻辑,没有过期清理机制。虽然读取时会检查 TTL,但过期的 key-value 对永远不会从字典中删除。随着时间推移和不同音色的访问,内存占用会持续增长直至 OOM。 - 修改建议:使用 `cachetools.TTLCache` 或引入 Redis 等外部缓存服务,自动处理过期淘汰。 2. **apps/api/app/api/routes/voices.py 第228行**:参数校验缺失导致 DoS 风险 - 问题描述:`text` 参数没有最大长度限制。恶意用户可以传入超长字符串(如几 MB 的文本),直接传递给 TTS 服务,可能导致上游服务崩溃、API 响应超时或服务器资源耗尽。 - 修改建议:在 `Query` 中添加 `max_length` 限制(例如 `Query("", max_length=500, ...)`),或在函数开始处显式校验文本长度。 3. **apps/api/app/api/routes/voices.py 第30行**:多进程环境缓存失效 - 问题描述:使用模块级全局变量作为缓存,在 Gunicorn/uvicorn 多进程(多 Worker)部署模式下,每个进程拥有独立的缓存副本。这不仅导致缓存命中率大幅下降(重复计算),还无法实现预期的“减少重复 TTS 调用”效果。 - 修改建议:若必须使用本地缓存,需明确仅限单进程模式;生产环境建议迁移至 Redis 等集中式缓存。 ### 💡 建议(1个可选) 1. **apps/api/app/api/routes/voices.py 第230行**:代码规范建议 - 具体内容:建议将 `import time` 移至文件顶部,与其他 import 语句放在一起,避免在函数内部进行导入操作。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-19 14:54:57 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot approved these changes 2026-07-19 15:01:16 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-07-19 15:01:17 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot merged commit 29e15158b3 into develop 2026-07-19 15:06:00 +08:00
auto-approve-bot deleted branch fix/p0-preset-voice-preview 2026-07-19 15:06:00 +08:00

🗑️ 预览环境已清理

PR #587 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #587 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.