feat: 统一渲染引擎 + 打通一键生成全链路 #202

Merged
xiaoxia merged 6 commits from feature/unified-rendering-and-pipeline into develop 2026-07-09 22:59:19 +08:00
Owner

变更概述

实现统一渲染引擎(UnifiedRenderService),替换原有的 EditingModeProcessor 分发和 concat demuxer 简单拼接,打通一键生成视频的完整链路。

核心变更

1. 提取共享工具模块

  • video_processing/ffmpeg_utils.py — FFmpeg 工具函数
  • video_processing/oss_helpers.py — OSS 工具函数
  • video_processing/dedup_helpers.py — 查重辅助函数

2. 实现 UnifiedRenderService

  • 按 clip_type/config.role 分组为图层再合成
  • 图层分组:background(z=-1) → main/broll(z=0) → overlay/corner_voice(z=1)
  • 合成流程:预处理 → 同层 xfade 串联 → overlay 合成

3. 重构 render_edit_plan() + generate_video()

  • 统一使用 UnifiedRenderService
  • 集成 VideoDeduplicator 查重

4. 测试覆盖

  • 23 个单元测试 + 14 个四模式集成测试 + 6 个全链路测试

铁律(灵应)

渲染引擎是统一的,引擎不判断模式,只按 clip_type/config.role 分组为图层再合成。

## 变更概述 实现统一渲染引擎(UnifiedRenderService),替换原有的 EditingModeProcessor 分发和 concat demuxer 简单拼接,打通一键生成视频的完整链路。 ## 核心变更 ### 1. 提取共享工具模块 - `video_processing/ffmpeg_utils.py` — FFmpeg 工具函数 - `video_processing/oss_helpers.py` — OSS 工具函数 - `video_processing/dedup_helpers.py` — 查重辅助函数 ### 2. 实现 UnifiedRenderService - 按 clip_type/config.role 分组为图层再合成 - 图层分组:background(z=-1) → main/broll(z=0) → overlay/corner_voice(z=1) - 合成流程:预处理 → 同层 xfade 串联 → overlay 合成 ### 3. 重构 render_edit_plan() + generate_video() - 统一使用 UnifiedRenderService - 集成 VideoDeduplicator 查重 ### 4. 测试覆盖 - 23 个单元测试 + 14 个四模式集成测试 + 6 个全链路测试 ## 铁律(灵应) > 渲染引擎是统一的,引擎不判断模式,只按 clip_type/config.role 分组为图层再合成。
xiaoxia added 5 commits 2026-07-09 22:35:25 +08:00
feat: 扩展剪辑模板体系 + 实现剪辑计划生成器
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 9s
CI/CD Pipeline / Frontend Lint (push) Successful in 1m35s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m50s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 7s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
9287ab9e3f
- EditTemplate 新增 editing_mode 字段,支持四种剪辑模式
  (one_take/pip/voice_over/voice_pip)
- config_schemas 扩展:editing_mode + transition_enabled
- 新建 PlanGeneratorService:基于模板+素材自动生成 EditPlan
  - ONE_TAKE: 素材顺序分配给 main clips
  - PIP: 第1个素材→main,其余→overlay
  - VOICE_OVER: 素材→main clips (B-roll)
  - VOICE_PIP: 第1个→background, 第2个→corner_voice, 其余→b_roll
- 新增 POST /edit-plans/generate-from-template API 端点
- Alembic 迁移 035:edit_templates 表加 editing_mode 列
- 单元测试 32 个(14 个计划生成器 + 18 个模板 editing_mode)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
style: format edit_templates.py with black
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 20s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 20s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m38s
CI/CD Pipeline / Frontend Lint (push) Successful in 1m42s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (pull_request) Has been skipped
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) 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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
45165d7ca1
chore: update schema metadata snapshot for editing_mode field
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 40s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 40s
CI/CD Pipeline / Frontend Lint (push) Successful in 2m14s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 3m0s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
6055040932
fix: update tests for editing_mode and transition_enabled fields
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 1m41s
CI/CD Pipeline / Frontend Lint (push) Successful in 1m42s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 1m42s
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m48s
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Successful in 3m2s
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
7fa3e433a2
- test_config_schemas: template config now has transition_enabled beyond plan config
- test_edit_templates_api: response schema includes editing_mode field
feat: 统一渲染引擎 + 打通一键生成全链路
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 8s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 8s
CI/CD Pipeline / Frontend Lint (push) Successful in 2m4s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m58s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
9c99c9ea96
核心变更:
1. 提取共享工具模块(ffmpeg_utils / oss_helpers / dedup_helpers)
2. 实现 UnifiedRenderService — 按 clip_type/config.role 分组为图层再合成
3. 重构 render_edit_plan() 使用 UnifiedRenderService(替换 concat demuxer)
4. 重构 generate_video() 使用 UnifiedRenderService(替换 EditingModeProcessor)
5. 集成 VideoDeduplicator 查重
6. 补 23 个单元测试 + 14 个四模式集成测试 + 6 个全链路测试

图层分组算法:
  main → main (z=0)
  main+config.role=b_roll → broll (z=0)
  overlay → overlay (z=1)
  background → background (z=-1)
  corner_voice → corner_voice (z=1)
  b_roll → broll (z=0)
  intro/outro → main (z=0)

合成流程:每个 clip 预处理 → 同层 xfade 串联 → overlay 合成 → 音频混入
xiaoxia added 1 commit 2026-07-09 22:44:30 +08:00
fix: resolve CI lint failures (black/isort/flake8 E741)
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 1m24s
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 1m25s
CI/CD Pipeline / Frontend Lint (push) Successful in 1m57s
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m8s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Successful in 3m17s
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
015fbb6d96
- Fix flake8 E741 ambiguous variable name 'l' in unified_render_service.py and test_unified_render_service.py
- Apply black formatting to 4 files
- Apply isort import sorting to 8 files
Author
Owner

PR #202 代码审计报告

结论: 通过(0 P0 / 0 P1 / 0 P2 / 4 P3)


一、总体评价

质量很高的架构重构 PR。统一渲染引擎设计思路清晰,彻底解决了"四种模式各一套代码"的维护难题。共享模块提取合理,测试覆盖充分,全链路打通完整。

  • 11个核心文件,+2282 / -492 行
  • 23个单测 + 14个四模式集成测试 + 6个全链路测试
  • CI 全绿

二、设计原则核对 全部符合

原则 符合性 说明
渲染引擎是统一的,不是四种模式各一套 符合 UnifiedRenderService 一个引擎处理所有模式
渲染引擎不判断模式,只按 clip_type/config.role 分层渲染 符合 _resolve_layer_role 只看 clip_type 和 config.role,无 mode 判断
四种模式差异体现在剪辑计划结构上 符合 _build_plan_and_clips_from_task 在生成虚拟 plan 时决定结构
一键生成链路:生成计划→统一渲染→查重→输出 符合 generate_video 和 render_edit_plan 都走新链路
渲染和模板解耦 符合 渲染引擎输入是 plan+clips,不感知模板存在

三、问题清单(均为 P3 建议,不阻塞合并)

P3-1:editing_modes.py 已成死代码,建议清理

  • 文件apps/worker/video_processing/editing_modes.py
  • 问题:EditingModeProcessor 不再被 generate_video / render_edit_plan 引用,两个核心入口都已切换到 UnifiedRenderService。125行文件保留但无外部调用。
  • 建议:确认没有其他引用后,标记 deprecated 或直接删除,减少维护成本。

P3-2:_build_filter_complex 中 clip 索引查找效率 O(n²)

  • 文件apps/worker/video_processing/unified_render_service.py
  • 位置:第 296 行 layer_clip_indices = [all_clips.index(c) for c in layer.clips]
  • 问题:每个 layer 都用 list.index() 查找,整体 O(n²)。虽然 clip 数量通常不大(几十个以内),但用字典预映射更规范。
  • 建议:构建 clip_id → index 的字典,O(1) 查找。

P3-3:素材原声全部丢失,ONE_TAKE 模式可考虑保留首素材音频

  • 文件apps/worker/video_processing/unified_render_service.py_execute_ffmpeg
  • 问题:渲染引擎只 -map [final_video],不处理任何音频轨。所有模式下素材原声全部丢失,依赖外部配音后处理混音。和老代码行为一致(老代码 normalize_video 用了 -an),不是 regression,但 ONE_TAKE 模式下保留首个素材原声可能是更自然的默认行为。
  • 建议:后续可增加 preserve_source_audio 配置,ONE_TAKE 模式默认开启。

P3-4:图层 z_index 命名有歧义,与实际合成顺序不完全一致

  • 文件apps/worker/video_processing/unified_render_service.py
  • 位置_LAYER_Z_INDEX 常量 + _build_filter_complex Step 3
  • 问题:main 和 broll 都是 z=0,但实际合成时 broll 是叠加在 background 之上的,层级关系靠代码硬编码顺序决定,不是 z_index 排序决定。易引起后续维护者误解。
  • 建议:要么 z_index 精确反映层级(broll=0, main=1?不对),要么在注释中明确 z_index 只是分组参考,实际合成顺序见 Step 3 代码。

四、做得好的地方 👏

  1. 架构升级彻底:从四种模式各一套 FFmpeg 命令 → 统一图层渲染引擎,模式差异收敛到 plan 结构层面,可维护性大幅提升。
  2. 共享模块提取合理:ffmpeg_utils / oss_helpers / dedup_helpers 三个模块职责单一、边界清晰,generation.py 和 edit_plan_generation.py 代码量分别减少了 50%+。
  3. 测试金字塔完整:单元测试(白盒验证图层逻辑)→ 集成测试(四模式端到端渲染)→ 全链路测试(fallback/混音/查重完整流程)。
  4. 错误处理分层清晰:素材缺失跳过、渲染失败抛异常、混音失败降级、查重异常不阻塞主流程——每一层的失败策略都合理。
  5. 虚拟 Plan/Clip 模式巧妙:generate_video 不需要写数据库建真实 plan,内存中构建虚拟对象即可复用 UnifiedRenderService,设计干净。
  6. 代码规范好:logging 用 lazy 格式化(%s 传参)、nosec 标注合理、docstring 完整、分区注释清晰。

五、安全审查

  • 命令注入 FFmpeg 命令用 list 形式传参,无 shell=True;filter_complex 中的动态值(duration/position等)均为数值或枚举映射,无注入风险。
  • 路径遍历 素材文件路径来自 asset_path_map(经过 OSS 下载到受控临时目录),无用户直接可控的文件系统路径。
  • 数据越权 渲染在 worker 侧执行,输入来自数据库已鉴权的数据,无新的鉴权面。
  • 资源耗尽⚠️ 临时文件在 TemporaryDirectory 中自动清理,FFmpeg 进程无超时限制(和老代码一致,非新增问题)。

六、性能考量

  • 单次 FFmpeg filter_complex 完成全部合成,避免了多次编码的质量损失和时间开销
  • 素材下载有 SHA256 缓存机制,同任务内重复素材只下载一次
  • xfade 转场仅在同层多 clip 时使用,单 clip 直接透传
  • 暂未发现明显性能瓶颈

综合结论:可合并。4个P3均为建议优化项,不影响功能正确性和上线。

# PR #202 代码审计报告 **结论:✅ 通过(0 P0 / 0 P1 / 0 P2 / 4 P3)** --- ## 一、总体评价 质量很高的架构重构 PR。统一渲染引擎设计思路清晰,彻底解决了"四种模式各一套代码"的维护难题。共享模块提取合理,测试覆盖充分,全链路打通完整。 - 11个核心文件,+2282 / -492 行 - 23个单测 + 14个四模式集成测试 + 6个全链路测试 - CI 全绿 --- ## 二、设计原则核对 ✅ 全部符合 | 原则 | 符合性 | 说明 | |------|--------|------| | 渲染引擎是统一的,不是四种模式各一套 | ✅ 符合 | UnifiedRenderService 一个引擎处理所有模式 | | 渲染引擎不判断模式,只按 clip_type/config.role 分层渲染 | ✅ 符合 | `_resolve_layer_role` 只看 clip_type 和 config.role,无 mode 判断 | | 四种模式差异体现在剪辑计划结构上 | ✅ 符合 | `_build_plan_and_clips_from_task` 在生成虚拟 plan 时决定结构 | | 一键生成链路:生成计划→统一渲染→查重→输出 | ✅ 符合 | generate_video 和 render_edit_plan 都走新链路 | | 渲染和模板解耦 | ✅ 符合 | 渲染引擎输入是 plan+clips,不感知模板存在 | --- ## 三、问题清单(均为 P3 建议,不阻塞合并) ### P3-1:editing_modes.py 已成死代码,建议清理 - **文件**:`apps/worker/video_processing/editing_modes.py` - **问题**:EditingModeProcessor 不再被 generate_video / render_edit_plan 引用,两个核心入口都已切换到 UnifiedRenderService。125行文件保留但无外部调用。 - **建议**:确认没有其他引用后,标记 deprecated 或直接删除,减少维护成本。 ### P3-2:`_build_filter_complex` 中 clip 索引查找效率 O(n²) - **文件**:`apps/worker/video_processing/unified_render_service.py` - **位置**:第 296 行 `layer_clip_indices = [all_clips.index(c) for c in layer.clips]` - **问题**:每个 layer 都用 `list.index()` 查找,整体 O(n²)。虽然 clip 数量通常不大(几十个以内),但用字典预映射更规范。 - **建议**:构建 `clip_id → index` 的字典,O(1) 查找。 ### P3-3:素材原声全部丢失,ONE_TAKE 模式可考虑保留首素材音频 - **文件**:`apps/worker/video_processing/unified_render_service.py` → `_execute_ffmpeg` - **问题**:渲染引擎只 `-map [final_video]`,不处理任何音频轨。所有模式下素材原声全部丢失,依赖外部配音后处理混音。和老代码行为一致(老代码 normalize_video 用了 `-an`),不是 regression,但 ONE_TAKE 模式下保留首个素材原声可能是更自然的默认行为。 - **建议**:后续可增加 `preserve_source_audio` 配置,ONE_TAKE 模式默认开启。 ### P3-4:图层 z_index 命名有歧义,与实际合成顺序不完全一致 - **文件**:`apps/worker/video_processing/unified_render_service.py` - **位置**:`_LAYER_Z_INDEX` 常量 + `_build_filter_complex` Step 3 - **问题**:main 和 broll 都是 z=0,但实际合成时 broll 是叠加在 background 之上的,层级关系靠代码硬编码顺序决定,不是 z_index 排序决定。易引起后续维护者误解。 - **建议**:要么 z_index 精确反映层级(broll=0, main=1?不对),要么在注释中明确 z_index 只是分组参考,实际合成顺序见 Step 3 代码。 --- ## 四、做得好的地方 👏 1. **架构升级彻底**:从四种模式各一套 FFmpeg 命令 → 统一图层渲染引擎,模式差异收敛到 plan 结构层面,可维护性大幅提升。 2. **共享模块提取合理**:ffmpeg_utils / oss_helpers / dedup_helpers 三个模块职责单一、边界清晰,generation.py 和 edit_plan_generation.py 代码量分别减少了 50%+。 3. **测试金字塔完整**:单元测试(白盒验证图层逻辑)→ 集成测试(四模式端到端渲染)→ 全链路测试(fallback/混音/查重完整流程)。 4. **错误处理分层清晰**:素材缺失跳过、渲染失败抛异常、混音失败降级、查重异常不阻塞主流程——每一层的失败策略都合理。 5. **虚拟 Plan/Clip 模式巧妙**:generate_video 不需要写数据库建真实 plan,内存中构建虚拟对象即可复用 UnifiedRenderService,设计干净。 6. **代码规范好**:logging 用 lazy 格式化(`%s` 传参)、nosec 标注合理、docstring 完整、分区注释清晰。 --- ## 五、安全审查 - **命令注入**:✅ FFmpeg 命令用 list 形式传参,无 shell=True;filter_complex 中的动态值(duration/position等)均为数值或枚举映射,无注入风险。 - **路径遍历**:✅ 素材文件路径来自 asset_path_map(经过 OSS 下载到受控临时目录),无用户直接可控的文件系统路径。 - **数据越权**:✅ 渲染在 worker 侧执行,输入来自数据库已鉴权的数据,无新的鉴权面。 - **资源耗尽**:⚠️ 临时文件在 TemporaryDirectory 中自动清理,FFmpeg 进程无超时限制(和老代码一致,非新增问题)。 --- ## 六、性能考量 - 单次 FFmpeg filter_complex 完成全部合成,避免了多次编码的质量损失和时间开销 ✅ - 素材下载有 SHA256 缓存机制,同任务内重复素材只下载一次 ✅ - xfade 转场仅在同层多 clip 时使用,单 clip 直接透传 ✅ - 暂未发现明显性能瓶颈 --- **综合结论:可合并。4个P3均为建议优化项,不影响功能正确性和上线。**
xiaoxia merged commit 4328854f58 into develop 2026-07-09 22:59:19 +08:00
xiaoxia deleted branch feature/unified-rendering-and-pipeline 2026-07-09 22:59:19 +08:00
Sign in to join this conversation.