Files
meijiaka-zy/python-api/app/api/v1/materials.py
T

85 lines
2.2 KiB
Python

"""
空镜素材 API
============
提供空镜素材匹配接口(基于 PostgreSQL + Redis 去重)。
"""
from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.session import get_db
from app.schemas.common import ApiResponse, success_response
from app.schemas.materials import (
BatchMatchMaterialRequest,
BatchMatchMaterialResponse,
MatchMaterialRequest,
MaterialInfo,
)
from app.services.material_service import batch_match, match_material
router = APIRouter()
@router.post("/match", response_model=ApiResponse[MaterialInfo | None])
async def match_material_endpoint(
request: MatchMaterialRequest,
db: AsyncSession = Depends(get_db),
):
"""
根据场景描述和所需时长匹配空镜素材
返回匹配到的素材信息,无匹配返回 data: null
"""
result = await match_material(
db,
scene=request.scene,
required_duration=request.duration,
project_id=request.project_id,
)
if result is None:
return success_response(data=None, message="未匹配到素材")
await db.commit()
return success_response(
data=MaterialInfo(url=result["url"], duration=result["duration"]),
message="匹配成功",
)
@router.post("/batch-match", response_model=ApiResponse[BatchMatchMaterialResponse])
async def batch_match_materials_endpoint(
request: BatchMatchMaterialRequest,
db: AsyncSession = Depends(get_db),
):
"""
批量匹配空镜素材
根据分镜列表一次性匹配所有素材,自动进行项目级去重。
"""
raw_scenes = [{"scene": s.scene, "duration": s.duration} for s in request.scenes]
results = await batch_match(
db,
scenes=raw_scenes,
project_id=request.project_id,
)
matched: list[MaterialInfo | None] = [
MaterialInfo(url=r["url"], duration=r["duration"]) if r else None for r in results
]
await db.commit()
success_count = sum(1 for r in matched if r is not None)
return success_response(
data=BatchMatchMaterialResponse(
project_id=request.project_id,
results=matched,
),
message=f"批量匹配完成,成功 {success_count}/{len(matched)}",
)