Files
xiaoxia-saas/apps/api/app/schemas/lipsync.py
T
saas-backend-agent 5493c38dd9
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
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
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 / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
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 / PR Build API Image (pull_request) Successful in 33s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 34s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 46s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m43s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 1m58s
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
feat: #1796 MediaKit 对口型后端对接
- MediaKitClient: 封装火山引擎 AI MediaKit 对口型 API
  - POST /api/v1/tools/lip-sync 提交任务
  - GET /api/v1/tasks/{task_id} 查询状态
  - 错误处理:超时/网络/HTTP 错误统一 MediaKitError
  - 未配置 API Key 时自动降级
- LipsyncJobModel: 对口型任务 ORM 模型
  - 用户隔离 + 项目关联
  - 状态流转: pending → submitted → completed/failed
- LipsyncService: 业务逻辑层
  - create_job / get_job / list_jobs / refresh_job_status / cancel_job
  - 分页查询 + 状态过滤 + 用户隔离
- RESTful API: /api/v1/lipsync/jobs
  - POST   /jobs           提交对口型任务
  - GET    /jobs           任务列表(分页+过滤)
  - GET    /jobs/{id}      任务详情
  - POST   /jobs/{id}/refresh  刷新状态
  - POST   /jobs/{id}/cancel   取消任务
- Schema: 输入校验(视频仅 MP4,音频 mp3/aac/wav/m4a/flac)
- 数据库迁移: 071_add_lipsync_jobs_table
  - lipsync_jobs 表 + 复合索引(user_id+status, project_id+user_id)
- 30 个单元测试(13 客户端 + 17 路由/Service)
- 不破坏现有功能(65 测试全过)
2026-09-08 16:22:53 +08:00

71 lines
2.2 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."""
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):
"""创建对口型任务请求."""
video_url: str = Field(..., description="人物视频 URLMP4,≤30min,单人真人)")
audio_url: str = Field(..., description="驱动音频 URLmp3/aac/wav/m4a/flac")
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")
# 仅支持 MP4
lower = v.lower().split("?")[0]
if not lower.endswith(".mp4"):
raise ValueError("video_url 仅支持 MP4 格式")
return v
@field_validator("audio_url")
@classmethod
def validate_audio_url(cls, v: str) -> str:
v = v.strip()
if not v:
raise ValueError("audio_url 不能为空")
if not v.startswith(("http://", "https://")):
raise ValueError("audio_url 必须是 HTTP/HTTPS URL")
# 支持的音频格式
lower = v.lower().split("?")[0]
allowed_exts = (".mp3", ".aac", ".wav", ".m4a", ".flac")
if not any(lower.endswith(ext) for ext in allowed_exts):
raise ValueError(f"audio_url 格式不支持,仅支持: {', '.join(allowed_exts)}")
return v