feat(#1195): 新增克隆音色试听接口 /voice-clones/{id}/preview #1201

Merged
xiaoxia merged 3 commits from feat/voice-clone-preview-1195 into develop 2026-07-30 16:47:50 +08:00
Owner

功能

  • 新增 GET /api/v1/voice-clones/{clone_id}/preview 端点
  • 克隆音色 ready 状态下可实时 TTS 合成试听音频
  • 支持默认试听文本(缓存7天)和自定义文本
  • 对应前端 #1195 克隆音色不能播放

变更

  • apps/api/app/schemas/voice_clone.py: 新增 VoiceClonePreviewResponse
  • apps/api/app/api/routes/voice_clones.py: 新增 preview 路由
  • tests/unit/test_voice_clone_preview.py: 10个单元测试

测试

本地10个单测全绿,覆盖:

  • 正常试听(ready状态)
  • 自定义试听文本
  • 404(克隆不存在)
  • 400(pending/processing/failed 状态)
  • 502(TTS合成失败)
  • 缓存机制(默认文本)
  • 自定义文本不缓存
  • 非所有者无权限
## 功能 - 新增 `GET /api/v1/voice-clones/{clone_id}/preview` 端点 - 克隆音色 ready 状态下可实时 TTS 合成试听音频 - 支持默认试听文本(缓存7天)和自定义文本 - 对应前端 #1195 克隆音色不能播放 ## 变更 - apps/api/app/schemas/voice_clone.py: 新增 VoiceClonePreviewResponse - apps/api/app/api/routes/voice_clones.py: 新增 preview 路由 - tests/unit/test_voice_clone_preview.py: 10个单元测试 ## 测试 本地10个单测全绿,覆盖: - ✅ 正常试听(ready状态) - ✅ 自定义试听文本 - ✅ 404(克隆不存在) - ✅ 400(pending/processing/failed 状态) - ✅ 502(TTS合成失败) - ✅ 缓存机制(默认文本) - ✅ 自定义文本不缓存 - ✅ 非所有者无权限
xiaoxia added 1 commit 2026-07-30 14:02:53 +08:00
feat(#1195): 新增克隆音色试听接口 /voice-clones/{id}/preview
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 22s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Failing after 1m13s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m36s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m37s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m10s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m29s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
1437120634
- 新增 GET /voice-clones/{clone_id}/preview 端点
- 支持默认试听文本(缓存7天)和自定义文本
- 状态校验:仅 ready 状态可试听
- 10 个单元测试覆盖成功/失败/缓存/权限等场景

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1201 | | 预览链接 | [https://pr-1201.preview.xiaoxiajianji.com](https://pr-1201.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
xiaoxia added 1 commit 2026-07-30 14:31:25 +08:00
fix(test): 修复voice_clone_preview测试污染GetVoiceCloneUseCase类的问题
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 21s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m14s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m17s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 45s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
d6dfb48687
测试中用delattr删除了类原生execute方法,导致后续测试文件
test_voice_clone_use_cases.py中GetVoiceCloneUseCase.execute丢失。
改为保存原始方法并在finally中恢复。
xiaoxia force-pushed feat/voice-clone-preview-1195 from 52ead68415 to d6dfb48687 2026-07-30 14:31:25 +08:00 Compare
auto-approve-bot added 1 commit 2026-07-30 14:33:56 +08:00
style: auto-format with black + isort + prettier [skip ci-format-check]
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 56s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m11s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m55s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m58s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m59s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 48s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 47s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m18s
AI Code Review / AI Code Review (pull_request) Successful in 4m19s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m3s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m3s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 4m57s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 5m45s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m45s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 9m12s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 49s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 49s
b23bd2a942
Collaborator

代码审查结果 - PR #1201

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

  1. apps/api/app/api/routes/voice_clones.py 第251-263行:缓存逻辑存在并发安全问题(竞态条件/惊群效应)。
    • 代码在检查缓存(if clone_id in _clone_preview_cache)和写入缓存(_clone_preview_cache[clone_id] = ...)之间存在时间窗口。由于 synthesize_speech 是耗时操作,在多线程/并发环境下,多个请求可能同时通过缓存检查,导致对同一个 clone_id 重复调用昂贵的 TTS 接口,造成资源浪费和计费异常。
  2. apps/api/app/api/routes/voice_clones.py 第40行:全局缓存字典存在内存泄漏风险。
    • _clone_preview_cache 为全局字典,仅在读操作时检查 TTL,从未有过期清理机制。随着时间推移,如果 clone_id 不断增长或产生大量废弃 ID,该字典将无限膨胀,导致服务内存溢出(OOM)。

💡 建议(2个可选)

  1. apps/api/app/api/routes/voice_clones.py 第236行:建议增加 text 参数的长度校验。
    • 目前直接将用户传入的 text 传递给下游 TTS 服务。如果用户传入超长文本,可能导致请求耗时过长或费用异常。建议限制最大长度(如 500 字符)。
  2. apps/api/app/schemas/voice_clone.py:Python 源码文件不应具有可执行权限。
    • Diff 显示该文件权限从 100644 变更为 100755。Python 脚本通常不需要可执行权限,这不符合安全最佳实践和 Git 规范。

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


🤖 由 AI 代码审查机器人自动生成 | 2026-07-30 06:38:12 | 模型:

## 代码审查结果 - PR #1201 ### ⚠️ 问题(2个需要修改) 1. **apps/api/app/api/routes/voice_clones.py 第251-263行**:缓存逻辑存在并发安全问题(竞态条件/惊群效应)。 - 代码在检查缓存(`if clone_id in _clone_preview_cache`)和写入缓存(`_clone_preview_cache[clone_id] = ...`)之间存在时间窗口。由于 `synthesize_speech` 是耗时操作,在多线程/并发环境下,多个请求可能同时通过缓存检查,导致对同一个 `clone_id` 重复调用昂贵的 TTS 接口,造成资源浪费和计费异常。 2. **apps/api/app/api/routes/voice_clones.py 第40行**:全局缓存字典存在内存泄漏风险。 - `_clone_preview_cache` 为全局字典,仅在读操作时检查 TTL,从未有过期清理机制。随着时间推移,如果 `clone_id` 不断增长或产生大量废弃 ID,该字典将无限膨胀,导致服务内存溢出(OOM)。 ### 💡 建议(2个可选) 1. **apps/api/app/api/routes/voice_clones.py 第236行**:建议增加 `text` 参数的长度校验。 - 目前直接将用户传入的 `text` 传递给下游 TTS 服务。如果用户传入超长文本,可能导致请求耗时过长或费用异常。建议限制最大长度(如 500 字符)。 2. **apps/api/app/schemas/voice_clone.py**:Python 源码文件不应具有可执行权限。 - Diff 显示该文件权限从 `100644` 变更为 `100755`。Python 脚本通常不需要可执行权限,这不符合安全最佳实践和 Git 规范。 --- ✅ 格式检查通过 | ❌ 逻辑审查审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-30 06:38:12 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
xiaoxia merged commit c861e90289 into develop 2026-07-30 16:47:50 +08:00

🗑️ 预览环境已清理

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

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

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