fix: demuxSegment改为异步,等待onSamples完成后返回,修复黑屏根因 #1446

Closed
xiaoxia wants to merge 1 commits from fix/demux-async into develop
Owner

问题

demuxSegment 是同步函数,但 MP4Box.js 的 onSamples 回调是异步触发的。

当前代码在 mp4File.appendBuffer() 后立即 return meta,此时 onSamples 尚未执行,meta.samples 始终为空数组 []

→ decodeSegment 拿到空的 samples → 无帧送入 VideoDecoder → Canvas 黑屏。

修复

  1. demuxSegment 改为 async 函数,返回 Promise<SegmentMeta | null>
  2. new Promise 包装 MP4Box.js 回调链
  3. onSamples 完成 samples 过滤后 resolve(meta)
  4. onReady 无视频轨道、onErroronSamples meta 为空时均 resolve(null)
  5. init effect 中 await demuxSegment(buffer, i) 确保数据就绪

验证标准

  • 控制台日志 [useCanvasPlayer] Segment X: N/M samples(N > 0)
  • Canvas 播放 HEVC/H.265 素材视频画面正常(不再黑屏)
  • npm run build 无 TS/ESLint/Prettier 报错
## 问题 demuxSegment 是同步函数,但 MP4Box.js 的 `onSamples` 回调是异步触发的。 当前代码在 `mp4File.appendBuffer()` 后立即 `return meta`,此时 `onSamples` 尚未执行,`meta.samples` 始终为空数组 `[]`。 → decodeSegment 拿到空的 samples → 无帧送入 VideoDecoder → Canvas 黑屏。 ## 修复 1. `demuxSegment` 改为 `async` 函数,返回 `Promise<SegmentMeta | null>` 2. 用 `new Promise` 包装 MP4Box.js 回调链 3. 在 `onSamples` 完成 samples 过滤后 `resolve(meta)` 4. `onReady` 无视频轨道、`onError`、`onSamples` meta 为空时均 `resolve(null)` 5. init effect 中 `await demuxSegment(buffer, i)` 确保数据就绪 ## 验证标准 - 控制台日志 `[useCanvasPlayer] Segment X: N/M samples`(N > 0) - Canvas 播放 HEVC/H.265 素材视频画面正常(不再黑屏) - `npm run build` 无 TS/ESLint/Prettier 报错
xiaoxia added 1 commit 2026-08-19 19:01:12 +08:00
fix: demuxSegment改为异步,等待onSamples完成后再返回,修复黑屏根因
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
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 / Deploy Staging (Watchtower auto-deploy) (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 46s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m0s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m4s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m38s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 17s
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m32s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m45s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m22s
AI Code Review / AI Code Review (pull_request) Successful in 4m27s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m43s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 4m32s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 8m2s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
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 / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 7s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 14m11s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
e20d5a0cf9
- demuxSegment 改为 async 函数,返回 Promise<SegmentMeta | null>
- 用 new Promise 包装 MP4Box.js 回调,在 onSamples 完成后 resolve(meta)
- init 中 await demuxSegment 确保 samples 数据就绪后再进入解码
- onReady 无视频轨道、onSamples meta 为空、onError 均 resolve(null)
- 解决 meta.samples 始终为空数组导致 Canvas 黑屏的根本问题
xiaoxia closed this pull request 2026-08-19 19:01:33 +08:00

🗑️ 预览环境已清理

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

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

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

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1446 | | 预览链接 | [https://pr-1446.preview.xiaoxiajianji.com](https://pr-1446.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
Collaborator

【阻塞级判定】

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

📊 审查概览

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

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

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

  1. [apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 266] 返回值类型一致性

    • 具体内容:在 if (!segment) 判断块中,代码使用了 return 而没有显式返回 null。由于函数签名返回类型为 Promise<SegmentMeta | null>,在 async 函数中直接 return 会返回 Promise<undefined>。虽然下游调用处 if (meta) 能够兼容 undefined(因为它是 falsy 值),但这违反了 TypeScript 的类型契约。建议修改为 return null 以保持类型安全。
  2. [apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 270] 增加超时保护机制

    • 具体内容:当前代码通过 Promise 封装等待 onSamples 回调。如果 MP4Box.js 因为某些异常状态(如文件损坏但未触发 onError,或内部逻辑死锁)导致 onSamples 永远不被触发,Promise 将永远处于 pending 状态,导致前端页面卡死或加载状态无法结束。建议使用 Promise.race 为该异步操作增加一个超时机制(例如 5-10 秒),超时后 reject 或 resolve null,以增强健壮性。

良好实践

  • 异步逻辑重构:将原本同步调用但依赖异步回调(onSamples)的逻辑正确地重构为 async/await 模式,解决了原代码中 meta.samples 为空的数据缺失问题,这是本次修复的核心亮点。
  • 错误处理:在 onError 回调中正确调用了 resolve(null),确保 Promise 能够被处理,不会因解析错误而挂起。
  • 边界检查:在 onSamples 回调开始处增加了 if (!meta) 的检查,这是一种良好的防御性编程实践,防止在未预期的回调顺序下出现空指针异常。

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


🤖 由 AI 代码审查机器人自动生成 | 2026-08-19 11:05:38 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:否 - 阻塞级问题数量:0 个 ### 📊 审查概览 - 整体评价:通过 - 建议级问题数量:2 个 ### 🔴 阻塞级问题(必须修复) 无 ### 💡 改进建议(不阻塞合并) 1. **[apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 266] 返回值类型一致性** - 具体内容:在 `if (!segment)` 判断块中,代码使用了 `return` 而没有显式返回 `null`。由于函数签名返回类型为 `Promise<SegmentMeta | null>`,在 async 函数中直接 `return` 会返回 `Promise<undefined>`。虽然下游调用处 `if (meta)` 能够兼容 `undefined`(因为它是 falsy 值),但这违反了 TypeScript 的类型契约。建议修改为 `return null` 以保持类型安全。 2. **[apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 270] 增加超时保护机制** - 具体内容:当前代码通过 `Promise` 封装等待 `onSamples` 回调。如果 MP4Box.js 因为某些异常状态(如文件损坏但未触发 onError,或内部逻辑死锁)导致 `onSamples` 永远不被触发,Promise 将永远处于 pending 状态,导致前端页面卡死或加载状态无法结束。建议使用 `Promise.race` 为该异步操作增加一个超时机制(例如 5-10 秒),超时后 reject 或 resolve null,以增强健壮性。 ### ✅ 良好实践 - **异步逻辑重构**:将原本同步调用但依赖异步回调(`onSamples`)的逻辑正确地重构为 `async/await` 模式,解决了原代码中 `meta.samples` 为空的数据缺失问题,这是本次修复的核心亮点。 - **错误处理**:在 `onError` 回调中正确调用了 `resolve(null)`,确保 Promise 能够被处理,不会因解析错误而挂起。 - **边界检查**:在 `onSamples` 回调开始处增加了 `if (!meta)` 的检查,这是一种良好的防御性编程实践,防止在未预期的回调顺序下出现空指针异常。 --- ✅ 格式检查通过 | ✅ 逻辑审查通过 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-19 11:05:38 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
Some checks are pending
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
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 / Deploy Staging (Watchtower auto-deploy) (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 46s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m0s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m4s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m38s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 17s
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m32s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m45s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m22s
AI Code Review / AI Code Review (pull_request) Successful in 4m27s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m43s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 4m32s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 8m2s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
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 / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 7s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 14m11s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped

Pull request closed

Sign in to join this conversation.