fix(api): 一键生成自动选素材,创建计划时从项目视频素材库自动分配ready视频素材 #490

Merged
auto-approve-bot merged 1 commits from fix/auto-select-assets into develop 2026-07-18 08:38:59 +08:00
Owner

问题

一键生成基于PIP模板创建剪辑计划后,片段的asset_id全是空的,导致渲染时找不到可用片段。有6个ready视频素材但一个都没选上。

根因

create_plangenerate-from-template 两个创建计划的入口,如果没有传入 asset_ids,片段的 asset_id 就全为空。
自动选素材的逻辑只在 /{{plan_id}}/generate 阶段的兜底函数 _auto_fallback_auto_material_mode 里有,而且需要 material_mode == "auto" 才触发(默认是 manual)。
一键生成场景下,素材在创建计划时就应该分配好,用户能看到完整的计划内容。

修复

在两个创建计划入口添加自动选素材逻辑:

  1. 未传 asset_ids 但有 project_id 时,从项目视频素材库选全部 ready 状态的视频素材
  2. 按创建时间降序排列(新素材在前)
  3. 提取共享函数 auto_select_video_assets_helpers.py,两个入口复用

影响范围

  • POST /edit-plans — 新增自动选素材
  • POST /edit-plans/generate-from-template — 新增自动选素材
  • 传了 asset_ids 的场景完全不受影响,行为不变
  • 没有项目ID或没有视频素材库的场景也不受影响(自动跳过)

测试

  • plan_generator 14个测试全绿
  • edit_plan_service 82个测试全绿
  • black/isort/ruff 格式检查全过
## 问题 一键生成基于PIP模板创建剪辑计划后,片段的asset_id全是空的,导致渲染时找不到可用片段。有6个ready视频素材但一个都没选上。 ## 根因 `create_plan` 和 `generate-from-template` 两个创建计划的入口,如果没有传入 `asset_ids`,片段的 asset_id 就全为空。 自动选素材的逻辑只在 `/{{plan_id}}/generate` 阶段的兜底函数 `_auto_fallback_auto_material_mode` 里有,而且需要 `material_mode == "auto"` 才触发(默认是 manual)。 一键生成场景下,素材在创建计划时就应该分配好,用户能看到完整的计划内容。 ## 修复 在两个创建计划入口添加自动选素材逻辑: 1. 未传 asset_ids 但有 project_id 时,从项目视频素材库选全部 ready 状态的视频素材 2. 按创建时间降序排列(新素材在前) 3. 提取共享函数 `auto_select_video_assets` 到 `_helpers.py`,两个入口复用 ## 影响范围 - `POST /edit-plans` — 新增自动选素材 - `POST /edit-plans/generate-from-template` — 新增自动选素材 - 传了 `asset_ids` 的场景完全不受影响,行为不变 - 没有项目ID或没有视频素材库的场景也不受影响(自动跳过) ## 测试 - plan_generator 14个测试全绿 - edit_plan_service 82个测试全绿 - black/isort/ruff 格式检查全过
xiaoxia added 1 commit 2026-07-18 08:34:41 +08:00
fix(api): 一键生成自动选素材,创建计划时从项目视频素材库自动分配ready视频素材
CI Build & Deploy Pipeline / Build Staging API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Production (pull_request) Has been skipped
CI Build & Deploy Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 24s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 45s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 37s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 2m20s
Auto Approve CI PRs / Auto Approve on CI Green (pull_request) Successful in 2m57s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m21s
Auto Merge CI PRs / Auto Merge on CI Green + Approved (pull_request) Successful in 4m17s
AI Code Review / AI Code Review (pull_request) Successful in 4m23s
cfd6bbb4b6
- 根因:create_plan/generate-from-template 未传asset_ids时,片段asset_id全为空
  自动选素材逻辑仅在generate阶段兜底且需material_mode=auto(默认manual)
- 修复:在两个创建计划入口添加自动选素材逻辑
  - 未传asset_ids但有project_id时,从项目视频素材库选全部ready视频素材
  - 按创建时间降序排列(新素材在前)
  - 提取共享函数auto_select_video_assets到_helpers.py
- 影响范围:POST /edit-plans、POST /edit-plans/generate-from-template
  传了asset_ids的场景不受影响,行为完全不变
auto-approve-bot approved these changes 2026-07-18 08:37:39 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-07-18 08:37:39 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot merged commit d86246a295 into develop 2026-07-18 08:38:59 +08:00
auto-approve-bot deleted branch fix/auto-select-assets 2026-07-18 08:38:59 +08:00
Collaborator

代码审查结果 - PR #490

⚠️ 问题(2个需要修改)

  1. apps/api/app/api/routes/edit_plans.py 第425行list(body.asset_ids) 存在潜在的空指针异常风险。

    • 如果 body.asset_ids 在 Pydantic 模型中定义为 Optional[List[str]] 且未传值(即为 None),调用 list(None) 会直接抛出 TypeError,导致接口崩溃。
    • 建议修改为:resolved_asset_ids = list(body.asset_ids or []) 或先判断 if body.asset_ids is None
  2. apps/api/app/api/routes/edit_plans_timeline.py 第187行:同上,list(body.asset_ids) 存在相同的空指针异常风险。

    • 建议修改为:resolved_asset_ids = list(body.asset_ids or [])
  3. apps/api/app/api/routes/_helpers.py 第76-82行:存在严重的性能隐患(N+1 查询及内存过滤)。

    • asset_repo.find_by_library(video_lib.id) 可能会拉取该素材库下所有素材到内存中,再通过列表推导式进行过滤。如果素材库包含大量(如上万)非 ready 状态或非视频类型的文件,会造成不必要的内存占用和 CPU 消耗,响应时间显著增加。
    • 建议在 Repository 层增加支持按 statusmime_type 过滤的查询方法(如 find_ready_videos_by_library),将过滤逻辑下推到数据库层。

💡 建议(2个可选)

  1. apps/api/app/api/routes/_helpers.py 第56-62行:代码重复,建议提取枚举值获取逻辑。

    • lib.kinda.status 的取值逻辑(hasattr 判断)重复出现。建议提取一个内部辅助函数 _get_enum_value(obj) 来统一处理,保持代码整洁。
  2. apps/api/app/api/routes/_helpers.py 第56-62行:循环查找可优化。

    • 使用 next((lib for lib in libs if ...), None) 替代显式的 for 循环和 break,代码会更简洁且意图更明确。

格式检查通过 | 逻辑审查需修改 | ⚠️ 建议关注性能


🤖 由 AI 代码审查机器人自动生成 | 2026-07-18 08:39:07 | 模型:

## 代码审查结果 - PR #490 ### ⚠️ 问题(2个需要修改) 1. **apps/api/app/api/routes/edit_plans.py 第425行**:`list(body.asset_ids)` 存在潜在的空指针异常风险。 - 如果 `body.asset_ids` 在 Pydantic 模型中定义为 `Optional[List[str]]` 且未传值(即为 `None`),调用 `list(None)` 会直接抛出 `TypeError`,导致接口崩溃。 - 建议修改为:`resolved_asset_ids = list(body.asset_ids or [])` 或先判断 `if body.asset_ids is None`。 2. **apps/api/app/api/routes/edit_plans_timeline.py 第187行**:同上,`list(body.asset_ids)` 存在相同的空指针异常风险。 - 建议修改为:`resolved_asset_ids = list(body.asset_ids or [])`。 3. **apps/api/app/api/routes/_helpers.py 第76-82行**:存在严重的性能隐患(N+1 查询及内存过滤)。 - `asset_repo.find_by_library(video_lib.id)` 可能会拉取该素材库下所有素材到内存中,再通过列表推导式进行过滤。如果素材库包含大量(如上万)非 ready 状态或非视频类型的文件,会造成不必要的内存占用和 CPU 消耗,响应时间显著增加。 - 建议在 Repository 层增加支持按 `status` 和 `mime_type` 过滤的查询方法(如 `find_ready_videos_by_library`),将过滤逻辑下推到数据库层。 ### 💡 建议(2个可选) 1. **apps/api/app/api/routes/_helpers.py 第56-62行**:代码重复,建议提取枚举值获取逻辑。 - `lib.kind` 和 `a.status` 的取值逻辑(`hasattr` 判断)重复出现。建议提取一个内部辅助函数 `_get_enum_value(obj)` 来统一处理,保持代码整洁。 2. **apps/api/app/api/routes/_helpers.py 第56-62行**:循环查找可优化。 - 使用 `next((lib for lib in libs if ...), None)` 替代显式的 `for` 循环和 `break`,代码会更简洁且意图更明确。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-18 08:39:07 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
Sign in to join this conversation.