fix: 视频 filter_complex 排除纯音频 clips 修复 FFmpeg exit=234 #1321

Merged
xiaoxia merged 2 commits from fix/audio-only-clips-in-filter-complex into develop 2026-08-09 15:10:25 +08:00
Owner

Bug 描述

Staging Worker 日志显示渲染失败:FFmpeg 构建 filter_complex 时,对纯音频文件 voice.mp3 也生成了 [3:v]trim=...scale=...[v3] 视频滤镜链,但 voice.mp3 没有视频流,导致 Stream specifier :v matches no streams,exit=234。

根因

_build_filter_complex 遍历所有图层的 clips 生成视频滤镜链,但没有区分视频 clips 和纯音频 clips。配音素材(voice_library)和 TTS 配音片段(clip_type="audio")被错误地加入了视频 filter_complex。

修复

  1. Step 1(预处理): 收集 clips 时跳过 clip_type="audio" 的 clips,不生成 -i 输入和 [N:v] 滤镜链
  2. Step 2(同层串联): 遍历图层时跳过纯音频图层(无视频 clips 的 layer),不参与 concat/xfade
  3. 音频处理: 音频 clips 由 mix_audio() 独立处理,不受影响

测试

新增 6 个单元测试:

  • 纯音频 clip 不出现在 filter_complex
  • 多视频+音频 clip 时只处理视频
  • 只有音频 clips 时抛出 ValueError
  • TTS 配音 clip 同样被排除
  • video clip_type 不会被排除
  • voice_library=True 的 clip 被排除

全量测试通过 ,ruff lint 通过

## Bug 描述 Staging Worker 日志显示渲染失败:FFmpeg 构建 filter_complex 时,对纯音频文件 voice.mp3 也生成了 `[3:v]trim=...scale=...[v3]` 视频滤镜链,但 voice.mp3 没有视频流,导致 `Stream specifier :v matches no streams`,exit=234。 ## 根因 `_build_filter_complex` 遍历所有图层的 clips 生成视频滤镜链,但没有区分视频 clips 和纯音频 clips。配音素材(voice_library)和 TTS 配音片段(`clip_type="audio"`)被错误地加入了视频 filter_complex。 ## 修复 1. **Step 1(预处理)**: 收集 clips 时跳过 `clip_type="audio"` 的 clips,不生成 `-i` 输入和 `[N:v]` 滤镜链 2. **Step 2(同层串联)**: 遍历图层时跳过纯音频图层(无视频 clips 的 layer),不参与 concat/xfade 3. **音频处理**: 音频 clips 由 `mix_audio()` 独立处理,不受影响 ## 测试 新增 6 个单元测试: - 纯音频 clip 不出现在 filter_complex - 多视频+音频 clip 时只处理视频 - 只有音频 clips 时抛出 ValueError - TTS 配音 clip 同样被排除 - video clip_type 不会被排除 - voice_library=True 的 clip 被排除 全量测试通过 ✅,ruff lint 通过 ✅
xiaoxia added 1 commit 2026-08-09 15:01:29 +08:00
fix: 视频 filter_complex 排除纯音频 clips 修复 FFmpeg exit=234
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 / 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 / Check if frontend-only change (pull_request) Successful in 44s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 44s
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 / Validate - Type Check (mypy) (pull_request) Successful in 59s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m25s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m44s
AI Code Review / AI Code Review (pull_request) Successful in 1m51s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m53s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m54s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m58s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (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 Approve on CI Green (pull_request) Has been cancelled
532947e05c
Bug: _build_filter_complex 遍历所有图层的 clips 生成 [N:v] 视频滤镜链,
但 voice.mp3(用户上传的配音素材)是纯音频文件,没有视频流。FFmpeg 解析
filter_complex 时报错 'Stream specifier :v matches no streams',exit=234。

修复:
- Step 1 (预处理): 收集 clips 时跳过 clip_type='audio' 的 clips
- Step 2 (同层串联): 跳过纯音频图层,只处理视频 clips
- 音频 clips 由 mix_audio() 独立处理,不应出现在视频 filter_complex

新增 6 个单元测试覆盖各种场景(voice_library、TTS、纯音频报错等)。

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1321 | | 预览链接 | [https://pr-1321.preview.xiaoxiajianji.com](https://pr-1321.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot added 1 commit 2026-08-09 15:04:19 +08:00
style: auto-format with black + isort + prettier [skip ci-format-check]
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 / 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 / Check if frontend-only change (pull_request) Successful in 40s
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 / Validate - Migration (alembic) (pull_request) Successful in 59s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 59s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m15s
AI Code Review / AI Code Review (pull_request) Successful in 1m38s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m39s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m48s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m31s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 3m34s
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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m5s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m6s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m22s
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 47s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m41s
c3e5ac2f7f
Collaborator

【阻塞级判定】

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

📊 审查概览

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

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

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

  1. [unified_render_service.py: 1596] 性能优化建议
    • 具体内容:在计算 layer_clip_indices 时使用了列表推导式配合 all_clips.index(c)。由于 list.index() 的时间复杂度是 O(N),若 all_clips 较大且层级较多,这会导致 O(M*N) 的复杂度。建议预先构建一个 {clip: index} 的字典映射,将查找复杂度降为 O(1)。
    • 修改建议:
      # 在循环外构建映射
      clip_index_map = {c: i for i, c in enumerate(all_clips)}
      
      # 在循环内使用
      layer_clip_indices = [clip_index_map[c] for c in video_clips_in_layer]
      

良好实践

  1. [unified_render_service.py] 边界条件处理:在过滤掉纯音频片段后,立即增加了 if not all_clips 的检查并抛出明确的异常,有效防止了后续逻辑在空列表状态下运行导致的不可预知错误。
  2. [unified_render_service.py] 逻辑修复准确:修复逻辑正确地隔离了视频处理与音频处理。通过在收集 all_clips 时排除 audio 类型,并在后续 layer_clip_indices 计算时同步过滤,确保了索引查找的一致性,避免了 ValueError
  3. [test_audio_only_clips_in_filter_complex.py] 测试覆盖全面:新增的单元测试不仅验证了基本的排除逻辑,还覆盖了“仅音频报错”、“TTS音频排除”、“视频+音频混合”等边界和场景,有力保障了修复的正确性。

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

### 【阻塞级判定】 - 是否存在阻塞级问题:否 - 阻塞级问题数量:0 个 ### 📊 审查概览 - 整体评价:通过 - 建议级问题数量:1 个 ### 🔴 阻塞级问题(必须修复) 无 ### 💡 改进建议(不阻塞合并) 1. **[unified_render_service.py: 1596] 性能优化建议** - 具体内容:在计算 `layer_clip_indices` 时使用了列表推导式配合 `all_clips.index(c)`。由于 `list.index()` 的时间复杂度是 O(N),若 `all_clips` 较大且层级较多,这会导致 O(M*N) 的复杂度。建议预先构建一个 `{clip: index}` 的字典映射,将查找复杂度降为 O(1)。 - 修改建议: ```python # 在循环外构建映射 clip_index_map = {c: i for i, c in enumerate(all_clips)} # 在循环内使用 layer_clip_indices = [clip_index_map[c] for c in video_clips_in_layer] ``` ### ✅ 良好实践 1. **[unified_render_service.py] 边界条件处理**:在过滤掉纯音频片段后,立即增加了 `if not all_clips` 的检查并抛出明确的异常,有效防止了后续逻辑在空列表状态下运行导致的不可预知错误。 2. **[unified_render_service.py] 逻辑修复准确**:修复逻辑正确地隔离了视频处理与音频处理。通过在收集 `all_clips` 时排除 `audio` 类型,并在后续 `layer_clip_indices` 计算时同步过滤,确保了索引查找的一致性,避免了 `ValueError`。 3. **[test_audio_only_clips_in_filter_complex.py] 测试覆盖全面**:新增的单元测试不仅验证了基本的排除逻辑,还覆盖了“仅音频报错”、“TTS音频排除”、“视频+音频混合”等边界和场景,有力保障了修复的正确性。 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-09 07:05:56 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
xiaoxia merged commit 41d9713d28 into develop 2026-08-09 15:10:25 +08:00

🗑️ 预览环境已清理

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

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

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