feat: 跨视频片段避让 — 生成前注入已用区间 #1670 #1671

Merged
xiaoxia merged 2 commits from feat/cross-video-avoidance-1670 into develop 2026-09-03 22:42:11 +08:00
Owner

背景

生成新视频(含预览和正式生成)时,查询该用户已有视频使用过的素材区间,注入到片段截取逻辑中,让新视频避开已被大量使用的片段,降低不同视频之间的画面重复率。

改动

1. Repository 层

  • edit_plan_clip_repository.py 新增 list_used_segments_by_user()
    • JOIN edit_plans 表,按 created_by_user_id + status=completed 过滤
    • 只查 status=renderedasset_id 非空的 clips
    • created_at DESC 取最近 50 个 plan
    • 返回 {asset_id: [(start_time, start_time + duration), ...]}

2. Domain 层

  • distribute_assets() 及所有 _distribute_* 子函数新增 external_used_segments 参数
  • 深拷贝注入 used_segments,让 _resolve_start_time / _calc_random_start_time 自动避让
  • external_used_segments=None 时行为不变(向后兼容)

3. Service 层

  • _distribute_assets() 新增 user_id 参数
  • generate_from_template() 透传 created_by_user_id
  • 预览和正式生成都查询已用区间
  • 查询失败不阻塞,回退纯随机

4. 单元测试

  • 12 个新测试覆盖 Repository / Domain / Service 三层
  • 所有 29 个旧 plan_generator 测试 + 64 个 plan_generator_utils 测试通过

技术约束

  • API 不变,纯内部逻辑改造
  • 避让查询失败时不阻塞生成,回退到纯随机
  • external_used_segments 深拷贝,不修改外部数据

Closes #1670

## 背景 生成新视频(含预览和正式生成)时,查询该用户已有视频使用过的素材区间,注入到片段截取逻辑中,让新视频避开已被大量使用的片段,降低不同视频之间的画面重复率。 ## 改动 ### 1. Repository 层 - `edit_plan_clip_repository.py` 新增 `list_used_segments_by_user()` - JOIN `edit_plans` 表,按 `created_by_user_id` + `status=completed` 过滤 - 只查 `status=rendered` 且 `asset_id` 非空的 clips - 按 `created_at DESC` 取最近 50 个 plan - 返回 `{asset_id: [(start_time, start_time + duration), ...]}` ### 2. Domain 层 - `distribute_assets()` 及所有 `_distribute_*` 子函数新增 `external_used_segments` 参数 - 深拷贝注入 `used_segments`,让 `_resolve_start_time` / `_calc_random_start_time` 自动避让 - `external_used_segments=None` 时行为不变(向后兼容) ### 3. Service 层 - `_distribute_assets()` 新增 `user_id` 参数 - `generate_from_template()` 透传 `created_by_user_id` - 预览和正式生成都查询已用区间 - 查询失败不阻塞,回退纯随机 ### 4. 单元测试 - 12 个新测试覆盖 Repository / Domain / Service 三层 - 所有 29 个旧 plan_generator 测试 + 64 个 plan_generator_utils 测试通过 ## 技术约束 - API 不变,纯内部逻辑改造 - 避让查询失败时不阻塞生成,回退到纯随机 - `external_used_segments` 深拷贝,不修改外部数据 Closes #1670
xiaoxia added 1 commit 2026-09-03 22:18:25 +08:00
feat: 跨视频片段避让 — 生成前注入已用区间 #1670
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 31s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 32s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m38s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m40s
AI Code Review / AI Code Review (pull_request) Successful in 1m53s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m52s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m54s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 2m59s
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
af4dd31dd1
- Repository: list_used_segments_by_user() JOIN edit_plans 查用户最近
  已完成 plan 的已渲染 clips,聚合为 {asset_id: [(start, end), ...]}
- Domain: distribute_assets / _distribute_* 子函数新增 external_used_segments
  参数,深拷贝注入 used_segments,让 _resolve_start_time 自动避让
- Service: _distribute_assets 新增 user_id 参数,预览和正式生成都查询
  已用区间;查询失败时不阻塞,回退纯随机
- 12 个单元测试覆盖 Repository/Domain/Service 三层

🚀 预览环境已部署

项目 详情
PR号 #1671
预览链接 https://pr-1671.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1671 | | 预览链接 | [https://pr-1671.preview.xiaoxiajianji.com](https://pr-1671.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot added 1 commit 2026-09-03 22:21:27 +08:00
style: auto-format with black + isort + prettier [skip ci-format-check]
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 21s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 21s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m42s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m46s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 1m48s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m57s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m20s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m2s
AI Code Review / AI Code Review (pull_request) Successful in 6m42s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m48s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 16s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 2m16s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 30m18s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 3s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
9d31818222
Collaborator

【阻塞级判定】

  • 是否存在阻塞级问题:否
  • 阻塞级问题数量:0 个

📊 审查概览

  • 整体评价:通过
  • 建议级问题数量:3 个

🔴 阻塞级问题(必须修复)

💡 改进建议(不阻塞合并)

  1. [packages/domain/plan_generator_utils.py: 多处] 代码重复

    • 具体内容:_distribute_one_take_distribute_pip_distribute_voice_over_distribute_voice_pip 四个函数中均存在完全相同的 used_segments 初始化逻辑 {k: list(v) for k, v in external_used_segments.items()} if external_used_segments else {}。建议将此逻辑提取为 distribute_assets 内部的一个局部变量处理,或封装为辅助函数,以减少重复代码。
  2. [apps/api/app/services/plan_generator_service.py: 248] 日志信息增强

    • 具体内容:在捕获异常记录 warning 日志时,建议将 user_id 加入日志信息中(如 f"跨视频避让查询失败 (user_id={user_id}),回退到纯随机"),以便在生产环境中排查特定用户的问题。
  3. [packages/adapters/sqlalchemy_impl/edit_plan_clip_repository.py: 142-168] 查询性能优化

    • 具体内容:当前实现先查询 Plan IDs 再查询 Clips,涉及两次数据库交互。虽然 limit_recent 限制了数据量,性能影响可控,但可以考虑使用 join 或子查询在单次查询中完成,减少网络往返开销。

良好实践

  • 异常降级处理:在 plan_generator_service.py 中对 list_used_segments_by_user 进行了 try-except 包裹,查询失败时回退到纯随机模式,避免了因辅助功能异常阻塞核心生成流程,增强了系统鲁棒性。
  • 数据隔离:在 plan_generator_utils.py 中通过列表推导式 {k: list(v) ...}external_used_segments 进行了浅拷贝,防止内部逻辑修改外部传入的数据结构,保证了数据的一致性。
  • 边界条件检查list_used_segments_by_user 中对空 user_id 和空查询结果进行了前置检查,避免了无效的数据库查询。

格式检查通过 | 逻辑审查通过 | 性能表现良好


🤖 由 AI 代码审查机器人自动生成 | 2026-09-03 14:28:26 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:否 - 阻塞级问题数量:0 个 ### 📊 审查概览 - 整体评价:通过 - 建议级问题数量:3 个 ### 🔴 阻塞级问题(必须修复) 无 ### 💡 改进建议(不阻塞合并) 1. **[packages/domain/plan_generator_utils.py: 多处] 代码重复** - 具体内容:`_distribute_one_take`、`_distribute_pip`、`_distribute_voice_over`、`_distribute_voice_pip` 四个函数中均存在完全相同的 `used_segments` 初始化逻辑 `{k: list(v) for k, v in external_used_segments.items()} if external_used_segments else {}`。建议将此逻辑提取为 `distribute_assets` 内部的一个局部变量处理,或封装为辅助函数,以减少重复代码。 2. **[apps/api/app/services/plan_generator_service.py: 248] 日志信息增强** - 具体内容:在捕获异常记录 warning 日志时,建议将 `user_id` 加入日志信息中(如 `f"跨视频避让查询失败 (user_id={user_id}),回退到纯随机"`),以便在生产环境中排查特定用户的问题。 3. **[packages/adapters/sqlalchemy_impl/edit_plan_clip_repository.py: 142-168] 查询性能优化** - 具体内容:当前实现先查询 Plan IDs 再查询 Clips,涉及两次数据库交互。虽然 `limit_recent` 限制了数据量,性能影响可控,但可以考虑使用 `join` 或子查询在单次查询中完成,减少网络往返开销。 ### ✅ 良好实践 - **异常降级处理**:在 `plan_generator_service.py` 中对 `list_used_segments_by_user` 进行了 try-except 包裹,查询失败时回退到纯随机模式,避免了因辅助功能异常阻塞核心生成流程,增强了系统鲁棒性。 - **数据隔离**:在 `plan_generator_utils.py` 中通过列表推导式 `{k: list(v) ...}` 对 `external_used_segments` 进行了浅拷贝,防止内部逻辑修改外部传入的数据结构,保证了数据的一致性。 - **边界条件检查**:`list_used_segments_by_user` 中对空 `user_id` 和空查询结果进行了前置检查,避免了无效的数据库查询。 --- ✅ 格式检查通过 | ✅ 逻辑审查通过 | ✅ 性能表现良好 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-09-03 14:28:26 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
xiaoxia merged commit 159a62f9a5 into develop 2026-09-03 22:42:11 +08:00

🗑️ 预览环境已清理

PR #1671 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1671 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.