""" 声音克隆V2路由 提供异步声音克隆的API端点 """ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.database import get_db from app.models.user import User from app.middleware import get_current_user_from_request from app.schemas.model_schema import ApiResponse from app.schemas.audio_v2 import ( VoiceCloneV2CreateRequest, VoiceCloneV2Response, VoiceCloneV2ListResponse, TaskListQueryParams ) from app.services.audio_v2 import VoiceCloneV2Service router = APIRouter(prefix="/voice-clone", tags=["声音克隆V2"]) @router.post("", response_model=ApiResponse[VoiceCloneV2Response]) async def create_voice_clone_task( request: VoiceCloneV2CreateRequest, db: Session = Depends(get_db), current_user: User = Depends(get_current_user_from_request) ): """ 创建声音克隆任务(异步) 提交音频样本进行声音克隆,返回任务ID用于后续查询 Args: request: 创建请求(包含target_model、prefix、audio_url等) Returns: 任务信息(包含task_id) """ if not current_user.apikey: raise HTTPException( status_code=403, detail="未配置API密钥,请在用户设置中配置apikey" ) service = VoiceCloneV2Service(db, current_user.id, current_user.apikey) result = await service.create_task(request) return ApiResponse( code=200, message="声音克隆任务已创建", data=result ) @router.get("/{task_id}", response_model=ApiResponse[VoiceCloneV2Response]) async def get_voice_clone_task( task_id: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_user_from_request) ): """ 查询声音克隆任务详情 根据task_id查询任务状态和克隆结果 Args: task_id: 任务ID Returns: 任务详情(包含状态、voice_id等) """ service = VoiceCloneV2Service(db, current_user.id, current_user.apikey) result = await service.get_task(task_id) return ApiResponse( code=200, message="success", data=result ) @router.get("", response_model=ApiResponse[VoiceCloneV2ListResponse]) async def list_voice_clone_tasks( status: str = None, page: int = 1, page_size: int = 20, order_by: str = "created_at", order: str = "desc", db: Session = Depends(get_db), current_user: User = Depends(get_current_user_from_request) ): """ 查询声音克隆任务列表 支持分页、筛选和排序 Args: status: 状态筛选(PENDING/PROCESSING/SUCCEEDED/FAILED) page: 页码(从1开始) page_size: 每页数量(1-100) order_by: 排序字段(created_at/updated_at) order: 排序方向(asc/desc) Returns: 任务列表(包含总数和分页数据) """ params = TaskListQueryParams( status=status, page=page, page_size=page_size, order_by=order_by, order=order ) service = VoiceCloneV2Service(db, current_user.id, current_user.apikey) result = await service.list_tasks(params) return ApiResponse( code=200, message="success", data=result )