真人/虚拟人像库app build

This commit is contained in:
2026-07-07 15:18:52 +08:00
parent 6026ec8670
commit 98e8fe145f
15 changed files with 648 additions and 615 deletions
@@ -46,6 +46,9 @@ from app.utils.id_gen import generate_id
DOMAIN = "private_portrait"
PRIVATE_PORTRAIT_VIDEO_MIN_DURATION_SECONDS = 2
PRIVATE_PORTRAIT_VIDEO_MAX_DURATION_SECONDS = 15
def _json(data: Any) -> str | None:
if data is None:
@@ -118,6 +121,18 @@ def _assert_enabled_asset_type(asset_type: str) -> None:
raise HTTPException(status_code=400, detail="Audio 暂未开放,当前仅支持 Image/Video")
def _assert_private_asset_video_duration(payload: PrivatePortraitAssetCreate) -> None:
if payload.asset_type != PrivatePortraitAssetType.VIDEO.value:
return
duration = payload.video_duration
if duration is None:
raise HTTPException(status_code=400, detail="Video 素材必须提供 video_duration")
if duration < PRIVATE_PORTRAIT_VIDEO_MIN_DURATION_SECONDS:
raise HTTPException(status_code=400, detail=f"视频素材最短不能少于 {PRIVATE_PORTRAIT_VIDEO_MIN_DURATION_SECONDS}")
if duration > PRIVATE_PORTRAIT_VIDEO_MAX_DURATION_SECONDS:
raise HTTPException(status_code=400, detail=f"视频素材最长不能超过 {PRIVATE_PORTRAIT_VIDEO_MAX_DURATION_SECONDS}")
def validate_session_to_out(session: PrivatePortraitValidateSession, *, include_user: bool = False) -> PrivatePortraitValidateSessionOut:
return PrivatePortraitValidateSessionOut(
id=session.id,
@@ -402,6 +417,7 @@ async def create_asset(
library_type: str | None = None,
) -> PrivatePortraitAsset:
_assert_enabled_asset_type(payload.asset_type)
_assert_private_asset_video_duration(payload)
project = await get_user_project(db, user_id=user_id, project_id=project_id, library_type=library_type)
if project.status != PrivatePortraitProjectStatus.ACTIVE.value:
raise HTTPException(status_code=400, detail="项目未激活,不能上传素材")
@@ -90,6 +90,8 @@ def _fill_private_portrait_reference_display_fields(ref: Any, asset: PrivatePort
expected_ref_type = _ASSET_TYPE_TO_REFERENCE_TYPE.get(asset.asset_type)
if expected_ref_type:
_ref_set(ref, "type", expected_ref_type)
if asset.asset_type == PrivatePortraitAssetType.VIDEO.value and asset.video_duration is not None:
_ref_set(ref, "duration", asset.video_duration)
if not _ref_get(ref, "name") and asset.name:
_ref_set(ref, "name", asset.name)
@@ -293,6 +295,10 @@ async def resolve_private_portrait_references(
_ref_set(ref, "preview_url", display_url)
if expected_ref_type:
_ref_set(ref, "type", expected_ref_type)
if asset.asset_type == PrivatePortraitAssetType.VIDEO.value:
if asset.video_duration is None:
raise HTTPException(status_code=400, detail="私域视频素材缺少 video_duration,不能用于生成")
_ref_set(ref, "duration", asset.video_duration)
if not _ref_get(ref, "name") and asset.name:
_ref_set(ref, "name", asset.name)