Files
xiaoxia-saas/alembic/versions/073_add_lipsync_tts_fields.py
T
xiaoxia a27ed596b4
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m52s
AI Code Review / AI Code Review (pull_request) Successful in 6m37s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 164h7m21s
feat(ai-avatar): TTS直生对口型 + 语速/情绪透传 + MediaKit智能封面 + 契约文档
- 对口型支持 TTS 直生模式:POST /lipsync/jobs 传 voice_id+script_text(+speed/emotion),
  后端内部调 CosyVoice 合成音频→转存OSS→提交 MediaKit;保留 audio_url 直接音频模式
- cosyvoice_service: 新增 emotion 参数 + normalize_emotion(中文 自然/兴奋/沉稳/亲切
  映射 natural/excited/calm/friendly),空值不透传
- TTS 链路 speed/emotion 全链路透传:schema→use_case(metadata)→workflow(单段/分段/重合成)
  →submit_synthesize_task(rate/emotion);preview 即时试听同步
- lipsync refresh: 中间状态(running/processing)同步DB;completed 输出视频转存自家OSS防过期
- 修复 lipsync/ai-avatar 路由 current_user.id → current_user.user.id(AuthenticatedUser 无 .id)
- 新增 POST /ai-avatar/render/smart-cover 独立封面接口:复用 MediaKit extract_frames
  + cover_frame_scorer 评分选最佳帧(非 FFmpeg 首帧),渲染管线封面同样优先智能选帧
- 迁移 073: lipsync_jobs 增加 voice_id/script_text/speed/emotion 列,audio_url 改可空
- docs/ai-avatar-api-contract-1822.md: 前后端接口契约 + title_config 字段清单
- 新增 11 个单测(情绪归一化/payload透传/TTS直生/中间状态/智能封面),相关 82 测试全绿

Refs #1797 #1822
2026-09-09 19:13:03 +08:00

46 lines
1.5 KiB
Python
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.
"""lipsync_jobs 增加 TTS 直生字段(voice_id/script_text/speed/emotion)
Revision ID: 073_add_lipsync_tts_fields
Revises: 072_add_ai_avatar_render
Create Date: 2026-09-09
"""
import sqlalchemy as sa
from alembic import op
revision = "073_add_lipsync_tts_fields"
down_revision = "072_add_ai_avatar_render"
branch_labels = None
depends_on = None
def upgrade() -> None:
# 对口型支持「传音色 + 文案直接生成」:后端内部先 TTS 合成音频再提交对口型
op.add_column(
"lipsync_jobs",
sa.Column("voice_id", sa.String(200), nullable=False, server_default=""),
)
op.add_column(
"lipsync_jobs",
sa.Column("script_text", sa.Text(), nullable=False, server_default=""),
)
op.add_column(
"lipsync_jobs",
sa.Column("speed", sa.Float(), nullable=False, server_default=sa.text("1.0")),
)
op.add_column(
"lipsync_jobs",
sa.Column("emotion", sa.String(20), nullable=False, server_default=""),
)
# audio_url 改为可空:直生模式下音频由后端 TTS 合成后回填
op.alter_column("lipsync_jobs", "audio_url", existing_type=sa.Text(), nullable=True)
def downgrade() -> None:
op.alter_column("lipsync_jobs", "audio_url", existing_type=sa.Text(), nullable=False)
op.drop_column("lipsync_jobs", "emotion")
op.drop_column("lipsync_jobs", "speed")
op.drop_column("lipsync_jobs", "script_text")
op.drop_column("lipsync_jobs", "voice_id")