fix(api): 一键生成自动选素材全链路修复,4个核心根因一次性解决 #491

Merged
auto-approve-bot merged 1 commits from fix/auto-material-all-root-causes into develop 2026-07-18 09:21:11 +08:00
Owner

背景

一键生成PIP模板创建计划后,片段asset_id全空、end_time全0,导致渲染找不到可用片段。

全链路系统性排查后,发现不止一个根因,共找到4个核心问题,一次性全部修复。

修复的4个核心根因

🔴 根因1(P0): PIP/VOICE_PIP模式 + 有clip_configs时素材分配完全失败

  • 文件: apps/api/app/services/plan_generator_service.py
  • 问题: ClipType枚举只有main/intro/outro等6种类型,但_distribute_pip/_distribute_voice_pip期望的是overlay/background/corner_voice/b_roll,类型完全不匹配
  • 影响: VOICE_PIP模式→全空;PIP模式→只有第1个main有素材,其余main无素材
  • 之前没暴露: 因为asset_ids为空时_distribute_assets根本不会被调用
  • 修复: 新增_map_clip_types_for_mode方法,_create_clips_from_configs后自动将MAIN类型片段按顺序映射为对应模式的角色类型

🔴 根因2(P0): generate-from-template漏写plan.config.asset_ids

  • 文件: apps/api/app/api/routes/edit_plans_timeline.py
  • 问题: create_plan入口有asset_ids写入config(供兜底3使用),但generate-from-template入口漏掉了
  • 影响: 走timeline入口时,即使PlanGeneratorService分配失败,兜底3也救不了
  • 修复: 补上asset_ids写入config,与create_plan保持一致

🟠 根因3(P1): 兜底2只建片段不分素材

  • 文件: apps/api/app/api/routes/edit_plans_generation.py
  • 问题: _auto_fallback_copy_template_clips从模板复制片段时,只创建片段不分配素材
  • 影响: 如果前端走"空计划→generate"链路,片段有duration但无asset_id
  • 修复: 通过去掉兜底4的material_mode限制间接修复——兜底2创建的无素材片段会通过兜底4自动分配

🟠 根因4(P1): 兜底4 material_mode默认manual永不触发

  • 文件: apps/api/app/api/routes/edit_plans_generation.py
  • 问题: 全代码库只有读取material_mode,没有任何地方设置为auto,最后一道兜底防线形同虚设
  • 修复: 去掉material_mode=="auto"检查,只要有project_id且存在无素材片段,就自动从项目视频素材库选素材兜底

测试

  • 新增2个单元测试:PIP+有clip_configs / VOICE_PIP+有clip_configs 的素材分配
  • 原有14个plan_generator测试全过
  • 145个edit_plan相关测试全过
  • black/isort/ruff格式检查全过
## 背景 一键生成PIP模板创建计划后,片段asset_id全空、end_time全0,导致渲染找不到可用片段。 全链路系统性排查后,发现不止一个根因,共找到4个核心问题,一次性全部修复。 ## 修复的4个核心根因 ### 🔴 根因1(P0): PIP/VOICE_PIP模式 + 有clip_configs时素材分配完全失败 - **文件**: `apps/api/app/services/plan_generator_service.py` - **问题**: ClipType枚举只有main/intro/outro等6种类型,但_distribute_pip/_distribute_voice_pip期望的是overlay/background/corner_voice/b_roll,类型完全不匹配 - **影响**: VOICE_PIP模式→全空;PIP模式→只有第1个main有素材,其余main无素材 - **之前没暴露**: 因为asset_ids为空时_distribute_assets根本不会被调用 - **修复**: 新增_map_clip_types_for_mode方法,_create_clips_from_configs后自动将MAIN类型片段按顺序映射为对应模式的角色类型 ### 🔴 根因2(P0): generate-from-template漏写plan.config.asset_ids - **文件**: `apps/api/app/api/routes/edit_plans_timeline.py` - **问题**: create_plan入口有asset_ids写入config(供兜底3使用),但generate-from-template入口漏掉了 - **影响**: 走timeline入口时,即使PlanGeneratorService分配失败,兜底3也救不了 - **修复**: 补上asset_ids写入config,与create_plan保持一致 ### 🟠 根因3(P1): 兜底2只建片段不分素材 - **文件**: `apps/api/app/api/routes/edit_plans_generation.py` - **问题**: _auto_fallback_copy_template_clips从模板复制片段时,只创建片段不分配素材 - **影响**: 如果前端走"空计划→generate"链路,片段有duration但无asset_id - **修复**: 通过去掉兜底4的material_mode限制间接修复——兜底2创建的无素材片段会通过兜底4自动分配 ### 🟠 根因4(P1): 兜底4 material_mode默认manual永不触发 - **文件**: `apps/api/app/api/routes/edit_plans_generation.py` - **问题**: 全代码库只有读取material_mode,没有任何地方设置为auto,最后一道兜底防线形同虚设 - **修复**: 去掉material_mode=="auto"检查,只要有project_id且存在无素材片段,就自动从项目视频素材库选素材兜底 ## 测试 - 新增2个单元测试:PIP+有clip_configs / VOICE_PIP+有clip_configs 的素材分配 - 原有14个plan_generator测试全过 - 145个edit_plan相关测试全过 - black/isort/ruff格式检查全过
xiaoxia added 1 commit 2026-07-18 09:16:56 +08:00
fix(api): 一键生成自动选素材全链路修复,4个核心根因一次性解决
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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production API Image (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 22s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 45s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 36s
AI Code Review / AI Code Review (pull_request) Successful in 2m29s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 2m17s
Auto Approve CI PRs / Auto Approve on CI Green (pull_request) Successful in 2m44s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m21s
Auto Merge CI PRs / Auto Merge on CI Green + Approved (pull_request) Successful in 4m15s
ddf0bc500d
- 根因1(P0): PIP/VOICE_PIP模式+有clip_configs时素材分配完全失败
  * ClipType枚举只有main/intro/outro等,没有overlay/background/corner_voice/b_roll
  * _distribute_pip/_distribute_voice_pip按类型筛选永远找不到目标片段
  * 修复: _create_clips_from_configs后调用_map_clip_types_for_mode
    将MAIN类型片段按顺序映射为对应模式的角色类型

- 根因2(P0): generate-from-template漏写plan.config.asset_ids
  * create_plan有这一步兜底用,timeline入口漏掉了
  * 修复: 补上asset_ids写入config,与create_plan保持一致

- 根因3(P1): 兜底2 _auto_fallback_copy_template_clips只建片段不分素材
  * 兜底4去掉material_mode限制后,兜底2创建的片段能通过兜底4自动分配
  * 等于间接修复了兜底2的素材问题

- 根因4(P1): 兜底4 material_mode默认manual永不触发
  * 全代码库没有任何地方设置material_mode=auto
  * 修复: 去掉material_mode检查,只要有project_id且有无素材片段就自动选
  * 确保最后一道兜底防线真正生效

新增2个单元测试验证PIP/VOICE_PIP+有clip_configs场景的素材分配
Collaborator

代码审查结果 - PR #491

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

  1. apps/api/app/api/routes/edit_plans_timeline.py 第223行:日志格式化参数类型不匹配,可能导致运行时崩溃。

    • 代码将日志格式由 %s 改为 %d,但在 FastAPI 等框架中,user 参数通常是 User 对象或 Pydantic 模型而非整数 ID。直接传入对象给 %d 会引发 TypeError
    • 建议:保持使用 %s,或者确认 user 为整数后改为 user.id
  2. apps/api/app/api/routes/edit_plans_generation.py 第136行:移除 material_mode 校验可能导致非预期的行为变更。

    • 原逻辑仅在 material_mode == "auto" 时触发兜底,现逻辑只要 project_id 存在且有无素材片段就触发。虽然注释解释了原代码是死代码,但若此函数被用于“手动模式”的编辑场景,强制自动填充素材会违背用户的“手动”意图,导致用户无法保留空片段。
    • 建议:确认该函数仅用于“一键生成”等非手动场景,或者增加更精细的判断条件(如检查 editing_mode 或显式传入 auto_fill 标志)。

💡 建议(2个可选)

  1. apps/api/app/api/routes/edit_plans_timeline.py 第219-226行:在生成流程中直接进行数据库更新可能存在事务风险。

    • generate_from_template 函数内部实例化 EditPlanService 并调用 update_plan,会产生副作用。如果外层事务回滚,这里的更新可能造成数据不一致;反之亦然。
    • 建议:确保 db 作用域和事务管理在调用链路中是安全的,或者将 Config 的更新逻辑上移至事务边界更清晰的地方。
  2. apps/api/app/services/plan_generator_service.py 第220-234行:硬编码字符串赋值给枚举字段存在类型安全隐患。

    • 代码直接将 "overlay", "background" 等字符串赋值给 clip.clip_type。如果 EditPlanClip 模型中的 clip_type 字段定义了严格的 ClipType 枚举校验,这种赋值可能会导致数据校验失败或后续处理异常。
    • 建议:确认 ClipType 枚举或数据库 Schema 支持这些新增的字符串值,或者确保该字段在模型层是宽松的字符串类型。

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


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

## 代码审查结果 - PR #491 ### ⚠️ 问题(2个需要修改) 1. **apps/api/app/api/routes/edit_plans_timeline.py 第223行**:日志格式化参数类型不匹配,可能导致运行时崩溃。 - 代码将日志格式由 `%s` 改为 `%d`,但在 FastAPI 等框架中,`user` 参数通常是 User 对象或 Pydantic 模型而非整数 ID。直接传入对象给 `%d` 会引发 `TypeError`。 - **建议**:保持使用 `%s`,或者确认 `user` 为整数后改为 `user.id`。 2. **apps/api/app/api/routes/edit_plans_generation.py 第136行**:移除 `material_mode` 校验可能导致非预期的行为变更。 - 原逻辑仅在 `material_mode == "auto"` 时触发兜底,现逻辑只要 `project_id` 存在且有无素材片段就触发。虽然注释解释了原代码是死代码,但若此函数被用于“手动模式”的编辑场景,强制自动填充素材会违背用户的“手动”意图,导致用户无法保留空片段。 - **建议**:确认该函数仅用于“一键生成”等非手动场景,或者增加更精细的判断条件(如检查 `editing_mode` 或显式传入 `auto_fill` 标志)。 ### 💡 建议(2个可选) 1. **apps/api/app/api/routes/edit_plans_timeline.py 第219-226行**:在生成流程中直接进行数据库更新可能存在事务风险。 - 在 `generate_from_template` 函数内部实例化 `EditPlanService` 并调用 `update_plan`,会产生副作用。如果外层事务回滚,这里的更新可能造成数据不一致;反之亦然。 - **建议**:确保 `db` 作用域和事务管理在调用链路中是安全的,或者将 Config 的更新逻辑上移至事务边界更清晰的地方。 2. **apps/api/app/services/plan_generator_service.py 第220-234行**:硬编码字符串赋值给枚举字段存在类型安全隐患。 - 代码直接将 `"overlay"`, `"background"` 等字符串赋值给 `clip.clip_type`。如果 `EditPlanClip` 模型中的 `clip_type` 字段定义了严格的 `ClipType` 枚举校验,这种赋值可能会导致数据校验失败或后续处理异常。 - **建议**:确认 `ClipType` 枚举或数据库 Schema 支持这些新增的字符串值,或者确保该字段在模型层是宽松的字符串类型。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-07-18 09:19:25 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot approved these changes 2026-07-18 09:19:40 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

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

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot merged commit 810096bf23 into develop 2026-07-18 09:21:11 +08:00
auto-approve-bot deleted branch fix/auto-material-all-root-causes 2026-07-18 09:21:11 +08:00
Sign in to join this conversation.