feat: SceneChange 场景检测前置到渲染前 + 场景点缓存到素材 metadata #1622

Merged
auto-approve-bot merged 2 commits from feat/scene-change-pre-render into develop 2026-09-02 08:40:37 +08:00
Owner

依赖

基于 #1620(评分噪声)分支,合并顺序:#1620 → 本 PR。

问题

SceneChange 场景检测是 from-assets 接口返回后的后台任务_update_mediakit_recommendations_async):视频已用 _calc_random_start_time 随机起点渲染,检测结果只更新 DB 里的 start_time,对当前成片查重率完全无作用。且镜头段按固定顺序分配(第 N 个 clip 固定分第 N 段),同样素材组合起始帧仍相同。

改动

  1. 场景点缓存到素材 metadatascene_change_points: list[float]。后台任务检测前查 metadata 缓存命中则跳过 MediaKit 调用;detect_scene_changes 成功后写入 metadata 并持久化,后续生成直接复用。

  2. from-assets 渲染前同步读缓存(clips.py):

    • 素材加载时 extract_scene_points_from_metadata 读缓存
    • 有缓存:build_scene_segmentsrandom.shuffle 镜头段 → 段内随机取点 → 越界检查 → 与 used_segments 冲突避让(含 1.5s 边缘间隙),第一个不冲突段即用
    • 无缓存 / 镜头段全冲突:回退 _calc_random_start_time(受控复用逻辑不变)
    • 新素材首次生成仍走随机起点,后台任务检测后缓存,下次生成起生效
  3. 一键生成路径同步改造(plan_generator_service + plan_generator_utils):distribute_assets 新增 asset_scene_points 参数,7 个素材分配点统一走 _resolve_start_time(场景优先、随机兜底);预览随机模式不读 DB。

  4. 工具函数下沉 domain 层build_scene_segments / pick_start_in_scene_segment / pick_scene_aware_start / extract_scene_points_from_metadata,两条路径共用;clips.py 保留旧名别名兼容。

测试

新增 19 个测试(test_scene_change_prerender.py):缓存解析(合法/脏数据/自动补 0/排序/负值拒绝)、段内取点边界、冲突避让、shuffle 覆盖多个镜头段、两条路径集成验证起点落在镜头段内、后台任务写缓存验证。全量 14032 单测通过。

不改动_calc_random_start_time(保留为兜底)、dedup 查重逻辑、降级策略(analyze_videos fallback 保持)。

## 依赖 基于 #1620(评分噪声)分支,合并顺序:#1620 → 本 PR。 ## 问题 SceneChange 场景检测是 from-assets 接口返回后的**后台任务**(`_update_mediakit_recommendations_async`):视频已用 `_calc_random_start_time` 随机起点渲染,检测结果只更新 DB 里的 start_time,**对当前成片查重率完全无作用**。且镜头段按固定顺序分配(第 N 个 clip 固定分第 N 段),同样素材组合起始帧仍相同。 ## 改动 1. **场景点缓存到素材 metadata**:`scene_change_points: list[float]`。后台任务检测前查 metadata 缓存命中则跳过 MediaKit 调用;`detect_scene_changes` 成功后写入 metadata 并持久化,后续生成直接复用。 2. **from-assets 渲染前同步读缓存**(clips.py): - 素材加载时 `extract_scene_points_from_metadata` 读缓存 - 有缓存:`build_scene_segments` → **random.shuffle 镜头段** → 段内随机取点 → 越界检查 → 与 used_segments 冲突避让(含 1.5s 边缘间隙),第一个不冲突段即用 - 无缓存 / 镜头段全冲突:回退 `_calc_random_start_time`(受控复用逻辑不变) - 新素材首次生成仍走随机起点,后台任务检测后缓存,**下次生成**起生效 3. **一键生成路径同步改造**(plan_generator_service + plan_generator_utils):`distribute_assets` 新增 `asset_scene_points` 参数,7 个素材分配点统一走 `_resolve_start_time`(场景优先、随机兜底);预览随机模式不读 DB。 4. **工具函数下沉 domain 层**:`build_scene_segments` / `pick_start_in_scene_segment` / `pick_scene_aware_start` / `extract_scene_points_from_metadata`,两条路径共用;clips.py 保留旧名别名兼容。 ## 测试 新增 19 个测试(test_scene_change_prerender.py):缓存解析(合法/脏数据/自动补 0/排序/负值拒绝)、段内取点边界、冲突避让、shuffle 覆盖多个镜头段、两条路径集成验证起点落在镜头段内、后台任务写缓存验证。全量 14032 单测通过。 **不改动**:`_calc_random_start_time`(保留为兜底)、dedup 查重逻辑、降级策略(analyze_videos fallback 保持)。

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1622 | | 预览链接 | [https://pr-1622.preview.xiaoxiajianji.com](https://pr-1622.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot approved these changes 2026-09-02 01:32:33 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-09-02 01:32:34 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
xiaoxia added 2 commits 2026-09-02 08:28:54 +08:00
feat: SceneChange 场景检测前置到渲染前,场景点缓存到素材 metadata
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
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 / Build Staging API Image (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 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m57s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 5m3s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 5m52s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 5m52s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m55s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 6m10s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m15s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 6m15s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 7m16s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 8m20s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 10m20s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 4m10s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 4m22s
c4068c1d3f
现状问题:
- 场景检测是接口返回后的后台任务,视频已用随机 start_time 渲染完,
  SceneChange 更新 DB 对当前成片查重率无作用
- 首次生成的素材没有缓存,渲染前仍走随机起点(后台任务异步补缓存)
- 镜头段固定顺序分配(第N个clip固定用第N段),同样素材组合起始帧仍相同

改动:
1. 场景点持久化到素材 metadata(scene_change_points: list[float])
   - 后台 _update_mediakit_recommendations_async:检测前查缓存命中跳过,
     detect_scene_changes 成功后写入 asset.metadata 并 repo.update
2. 渲染前同步读缓存选镜头段(clips.py from-assets 主流程)
   - 素材加载时 extract_scene_points_from_metadata 读缓存
   - 有缓存:build_scene_segments → shuffle 随机镜头段顺序 →
     pick_scene_aware_start 段内取点 + 越界检查 + used_segments 冲突避让
     (含 1.5s 边缘间隙)
   - 无缓存/全冲突:回退 _calc_random_start_time(受控复用逻辑不变)
3. 一键生成路径同步改造(plan_generator_service + plan_generator_utils)
   - distribute_assets 新增 asset_scene_points 参数,7 个分配点统一
     走 _resolve_start_time(场景优先、随机兜底)
   - _fetch_asset_scene_points 读 metadata;预览随机模式不读 DB
4. 镜头段工具下沉 domain 层:build_scene_segments /
   pick_start_in_scene_segment / pick_scene_aware_start /
   extract_scene_points_from_metadata,clips.py 保留旧名兼容别名
   - 镜头段必须 shuffle 后遍历,不按固定顺序分配

测试:新增 19 个测试覆盖缓存解析(合法/脏数据/自动补0)、
段内取点/冲突避让/shuffle 覆盖多段、两条路径集成、后台写缓存。
全量 14032 单测通过。
xiaoxia force-pushed feat/scene-change-pre-render from b153fd9675 to c4068c1d3f 2026-09-02 08:28:54 +08:00 Compare
auto-approve-bot merged commit 24e66da061 into develop 2026-09-02 08:40:37 +08:00
auto-approve-bot deleted branch feat/scene-change-pre-render 2026-09-02 08:40:37 +08:00

🗑️ 预览环境已清理

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

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

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