feat: P2 素材库自动匹配 - 支持 all/random/smart 三种素材选取模式
CI/CD Pipeline / Frontend Lint (push) Failing after 45h41m20s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 45h41m20s
CI/CD Pipeline / Production Browser E2E (push) Failing after 1704h16m48s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1704h16m50s
CI/CD Pipeline / Build Production Runtime Images (push) Failing after 1704h16m52s
CI/CD Pipeline / Deploy Staging (push) Failing after 1704h16m52s
CI/CD Pipeline / Deploy Production (push) Failing after 1704h48m18s
CI/CD Pipeline / Frontend Lint (push) Failing after 45h41m20s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 45h41m20s
CI/CD Pipeline / Production Browser E2E (push) Failing after 1704h16m48s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1704h16m50s
CI/CD Pipeline / Build Production Runtime Images (push) Failing after 1704h16m52s
CI/CD Pipeline / Deploy Staging (push) Failing after 1704h16m52s
CI/CD Pipeline / Deploy Production (push) Failing after 1704h48m18s
- Schema: 新增 asset_select_mode + asset_select_count 字段 - Domain: GenerationTask 新增 asset_select_mode 字段 - Application: Command/UseCase 透传 asset_select_mode - Route: _select_assets_from_library() 辅助函数 + 创建任务集成 - SQLAlchemy: Model/Repository 映射 asset_select_mode - Alembic: 032 号迁移 - Worker: _download_library_assets() 支持 asset_ids 过滤 - 单测: 15 个测试覆盖三种模式 + 边界情况
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import random
|
||||
from typing import Any
|
||||
|
||||
from app.auth import AuthenticatedUser, get_current_user
|
||||
@@ -52,6 +53,7 @@ def _to_generation_task_response(task) -> GenerationTaskResponse:
|
||||
title_ids=task.title_ids,
|
||||
voice_ids=task.voice_ids,
|
||||
source_edit_plan_id=task.source_edit_plan_id or "",
|
||||
asset_select_mode=getattr(task, "asset_select_mode", ""),
|
||||
status=task.status,
|
||||
progress=task.progress,
|
||||
result_count=task.result_count,
|
||||
@@ -86,6 +88,49 @@ def _ensure_library_has_ready_video_assets(assets) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _select_assets_from_library(
|
||||
assets: list,
|
||||
mode: str,
|
||||
count: int,
|
||||
) -> list[str]:
|
||||
"""根据选取模式从素材库中选取 ready 状态的视频素材 ID。
|
||||
|
||||
Args:
|
||||
assets: 素材库中所有素材(Asset 实体列表)
|
||||
mode: 选取模式 — all=全部, random=随机, smart=按质量评分
|
||||
count: 选取数量,0 表示全部(仅 random/smart 模式有效)
|
||||
|
||||
Returns:
|
||||
选中的素材 ID 列表
|
||||
"""
|
||||
ready_video_assets = [a for a in assets if a.status.value == "ready" and a.mime_type.startswith("video")]
|
||||
|
||||
if not ready_video_assets:
|
||||
return []
|
||||
|
||||
if mode == "random":
|
||||
selected = (
|
||||
ready_video_assets if count <= 0 else random.sample(ready_video_assets, min(count, len(ready_video_assets)))
|
||||
)
|
||||
return [a.id for a in selected]
|
||||
|
||||
if mode == "smart":
|
||||
# 按质量分降序排列(质量分高的优先),质量分相同时按时长降序
|
||||
sorted_assets = sorted(
|
||||
ready_video_assets,
|
||||
key=lambda a: (
|
||||
a.quality_score if a.quality_score is not None else 0.0,
|
||||
a.duration if a.duration is not None else 0.0,
|
||||
),
|
||||
reverse=True,
|
||||
)
|
||||
selected = sorted_assets if count <= 0 else sorted_assets[:count]
|
||||
return [a.id for a in selected]
|
||||
|
||||
# 默认 all 模式:返回全部 ready 视频素材
|
||||
return [a.id for a in ready_video_assets]
|
||||
|
||||
|
||||
def _resolve_project_and_library(
|
||||
request: CreateGenerationTaskRequest,
|
||||
project_repository: Any,
|
||||
@@ -137,6 +182,7 @@ def create_generation_task(
|
||||
)
|
||||
|
||||
# asset_library 存在性校验(仅在提供了 asset_library_id 时)
|
||||
resolved_asset_ids: list[str] = list(request.asset_ids)
|
||||
if asset_library_id:
|
||||
library = asset_library_repository.get(asset_library_id)
|
||||
if library is None or (project_id and library.project_id != project_id):
|
||||
@@ -145,6 +191,14 @@ def create_generation_task(
|
||||
assets = asset_repository.find_by_library(asset_library_id)
|
||||
_ensure_library_has_ready_video_assets(assets)
|
||||
|
||||
# 素材库自动匹配:当未显式指定 asset_ids 时,按模式自动选取
|
||||
if not resolved_asset_ids:
|
||||
resolved_asset_ids = _select_assets_from_library(
|
||||
assets,
|
||||
mode=request.asset_select_mode,
|
||||
count=request.asset_select_count,
|
||||
)
|
||||
|
||||
use_case = CreateGenerationTaskUseCase(generation_task_repository)
|
||||
count = request.count
|
||||
created_tasks = []
|
||||
@@ -157,11 +211,12 @@ def create_generation_task(
|
||||
strategy_id=request.strategy_id,
|
||||
voice_library_id=request.voice_library_id,
|
||||
template_id=request.template_id,
|
||||
asset_ids=request.asset_ids,
|
||||
asset_ids=resolved_asset_ids,
|
||||
title_ids=request.title_ids,
|
||||
voice_ids=request.voice_ids,
|
||||
created_by_user_id=authenticated_user.user.id,
|
||||
source_edit_plan_id=request.source_edit_plan_id,
|
||||
asset_select_mode=request.asset_select_mode,
|
||||
)
|
||||
)
|
||||
celery_app.send_task("worker.generate_video", args=[task.id])
|
||||
@@ -245,6 +300,7 @@ def retry_generation_task(
|
||||
voice_ids=task.voice_ids,
|
||||
created_by_user_id=authenticated_user.user.id,
|
||||
source_edit_plan_id=task.source_edit_plan_id or "",
|
||||
asset_select_mode=getattr(task, "asset_select_mode", ""),
|
||||
)
|
||||
)
|
||||
celery_app.send_task("worker.generate_video", args=[retried.id])
|
||||
|
||||
Reference in New Issue
Block a user