Files
xiaoxia-saas/apps/api/app/schemas/lipsync.py
T
saas-backend-agent 6167e4c865
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 31s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 34s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m18s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m49s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 2m4s
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Unit 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 / 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
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 173h21m56s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 173h21m56s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 173h22m0s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 173h22m2s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 173h22m3s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 173h22m5s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 173h22m5s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 173h22m6s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 173h22m9s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 173h22m7s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 173h56m42s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 173h56m48s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 173h56m51s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 173h56m53s
fix: #1809 对口型接口参数调整,后端内部调TTS合成音频
- Schema: CreateLipsyncJobRequest 改为接收 {voice_id, script_text, video_url}
- Service: create_job 内部调 CosyVoice 合成音频,生成 audio_url 后提交 MediaKit
- Route: 注入 CosyVoiceService + voice_clone_profile_repository,支持克隆音色解析
- TTS 失败时创建 failed 记录并返回 502
- 21 个测试更新通过,57 个关联测试无回归
2026-09-09 10:01:27 +08:00

78 lines
2.3 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.
"""对口型 API Schema 定义 — #1796, #1809 参数调整."""
from __future__ import annotations
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field, field_validator
class LipsyncJobResponse(BaseModel):
"""对口型任务响应."""
id: str
user_id: str
project_id: str
video_url: str
audio_url: str
enable_video_loop: bool
mediakit_task_id: str
status: str
output_video_url: str
output_duration: float
error_message: str
error_code: str
submitted_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class CreateLipsyncJobRequest(BaseModel):
"""创建对口型任务请求 — #1809.
前端传 {voice_id, script_text, video_url},
后端内部调 TTS 生成 audio_url 再提交 MediaKit。
"""
video_url: str = Field(..., description="人物视频 URL(MP4,≤30min,单人真人)")
voice_id: str = Field(..., description="音色 ID(预设音色或克隆音色 profile ID)")
script_text: str = Field(..., description="要合成的脚本文本")
enable_video_loop: bool = Field(False, description="音频长于视频时是否循环画面")
project_id: str = Field("", description="项目 ID(可选)")
@field_validator("video_url")
@classmethod
def validate_video_url(cls, v: str) -> str:
v = v.strip()
if not v:
raise ValueError("video_url 不能为空")
if not v.startswith(("http://", "https://")):
raise ValueError("video_url 必须是 HTTP/HTTPS URL")
lower = v.lower().split("?")[0]
if not lower.endswith(".mp4"):
raise ValueError("video_url 仅支持 MP4 格式")
return v
@field_validator("voice_id")
@classmethod
def validate_voice_id(cls, v: str) -> str:
v = v.strip()
if not v:
raise ValueError("voice_id 不能为空")
return v
@field_validator("script_text")
@classmethod
def validate_script_text(cls, v: str) -> str:
v = v.strip()
if not v:
raise ValueError("script_text 不能为空")
if len(v) > 5000:
raise ValueError("script_text 最长 5000 字符")
return v