fix: Canvas播放器修复 - 片段自动切换+宽高比+移除死代码+进度节流 #1437

Closed
xiaoxia wants to merge 1 commits from fix/canvas-player-issues into develop
Owner

修复内容

基于灵应的核实报告,修复6个问题中的核心4个:

已修复

  1. 片段自动切换:初始化时加载所有片段数据并逐段解码,帧时间戳按全局偏移对齐,播放完一个片段自动继续下一个
  2. Canvas宽高比:新增 computeDrawRect 计算 letterbox/pillarbox,保持视频原始比例不变形
  3. 移除死代码:删除未使用的 audioCtxRef/audioSourceRef(音频由外部 HTMLAudio 处理)
  4. 进度更新节流:从 0.1s 阈值改为 200ms(5fps),减少 React re-render
  5. FrameQueue容量:从5提升到10,多片段场景下帧队列更充裕
  6. fallback预加载优化:当前片段 preload=auto / 下一个 metadata / 其余 none

不修复(说明)

  • @types/mp4box 缺失:mp4box v2.4.1 已内置类型定义,不存在此问题
  • 60fps fallback进度:fallback路径由 useSegmentScheduler 控制,本次不动

涉及文件

  • apps/web/src/pages/generate/hooks/useCanvasPlayer.ts — 核心重写
  • apps/web/src/pages/generate/components/FrontendPreviewPlayer.tsx — fallback预加载优化
## 修复内容 基于灵应的核实报告,修复6个问题中的核心4个: ### ✅ 已修复 1. **片段自动切换**:初始化时加载所有片段数据并逐段解码,帧时间戳按全局偏移对齐,播放完一个片段自动继续下一个 2. **Canvas宽高比**:新增 computeDrawRect 计算 letterbox/pillarbox,保持视频原始比例不变形 3. **移除死代码**:删除未使用的 audioCtxRef/audioSourceRef(音频由外部 HTMLAudio 处理) 4. **进度更新节流**:从 0.1s 阈值改为 200ms(5fps),减少 React re-render 5. **FrameQueue容量**:从5提升到10,多片段场景下帧队列更充裕 6. **fallback预加载优化**:当前片段 preload=auto / 下一个 metadata / 其余 none ### 不修复(说明) - `@types/mp4box` 缺失:mp4box v2.4.1 已内置类型定义,不存在此问题 - 60fps fallback进度:fallback路径由 useSegmentScheduler 控制,本次不动 ### 涉及文件 - `apps/web/src/pages/generate/hooks/useCanvasPlayer.ts` — 核心重写 - `apps/web/src/pages/generate/components/FrontendPreviewPlayer.tsx` — fallback预加载优化
xiaoxia added 1 commit 2026-08-19 12:48:49 +08:00
fix: Canvas播放器修复 - 片段自动切换+宽高比+移除死代码+进度节流
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 43s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m47s
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m48s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m49s
AI Code Review / AI Code Review (pull_request) Failing after 1m50s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m5s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m32s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m9s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m1s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m31s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 6m41s
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 / Canary Release to 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 11s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Has been cancelled
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 43s
a07d6c9a87
1. 片段自动切换:初始化时加载所有片段数据并逐段解码,帧时间戳按全局偏移对齐
2. Canvas宽高比:computeDrawRect计算letterbox/pillarbox,保持视频原始比例
3. 移除未使用的audioCtxRef/audioSourceRef(音频由外部HTMLAudio处理)
4. 进度更新节流到200ms(5fps),减少React re-render
5. FrameQueue容量从5提升到10,多片段场景更流畅
6. fallback路径优化预加载:当前片段auto/下一个metadata/其余none
Collaborator

【阻塞级判定】

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

📊 审查概览

  • 整体评价:需修改
  • 建议级问题数量:2 个

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

  1. [apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 538] 初始化解码逻辑导致帧丢失与播放失败

    • 问题类型:逻辑bug
    • 问题描述:在 useEffect 的初始化逻辑中,代码通过循环 for (const meta of metas) 一次性解码所有视频片段。然而,frameQueueRef 是一个固定大小为 10 的环形缓冲区。随着循环进行,新片段的帧不断推入队列,导致旧片段(尤其是视频开头)的帧被 shift() 丢弃。当初始化完成时,队列中仅保留了最后几个片段的帧。此时用户开始播放(currentTime=0),getCurrentFrame 无法找到对应帧,导致黑屏。同时,seek 函数虽然清空了队列,但并未触发重新解码,导致 Seek 功能彻底失效。
    • 修改建议:修改解码策略,不要在初始化时解码所有片段。应根据播放进度或当前时间,动态解码当前播放片段及其前后的片段,确保播放头所在的帧始终在队列中。
  2. [apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 298] 不可靠的异步同步机制

    • 问题类型:逻辑bug
    • 问题描述:在 decodeSegment 函数中,使用 await new Promise((resolve) => setTimeout(resolve, 10)) 来等待 mp4boxonSamples 回调执行。这是一种极其脆弱的 Hack 写法。虽然 mp4box 的解析通常是同步的,但依赖固定的 10ms 延迟来保证数据收集完成存在严重的竞态条件风险。如果主线程阻塞或解析耗时略微波动,samplesCollected 可能为空,导致该片段解码静默失败。
    • 修改建议:mp4box.jsappendBufferstart() 通常是同步触发回调的。如果必须确保异步完成,应使用 Promise 或计数器在 onSamples 回调中显式 resolve,而不是使用 setTimeout 猜测时间。

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

  1. [apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 全局] 音频功能移除确认

    • 具体内容:Diff 中删除了所有 Web Audio API 相关的代码(audioCtxRef, audioSourceRef 等)。请确认 FrontendPreviewPlayer 组件作为预览器是否确实不再需要音频播放。如果需要音频,此次变更属于功能回退,需恢复音频逻辑。
  2. [apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 520] 内存与首屏性能风险

    • 具体内容:初始化逻辑中使用了 for (const seg of segments) await loadSegment(seg),这意味着在播放开始前会并发/串行下载所有视频片段到内存。对于包含多个片段的长视频,这会导致巨大的内存占用和极长的首屏加载时间。建议仅预加载第一个片段,并利用空闲时间预加载后续片段。

良好实践

  • FrontendPreviewPlayer.tsx 中对 preload 属性的动态调整(当前播放片段 auto,下一段 metadata,其余 none)是很好的带宽优化策略。
  • renderFrame 中增加了状态更新节流(200ms),有效减少了 React 重渲染频率,提升性能。
  • useCanvasPlayer.ts 中增加了 computeDrawRect 函数处理 Letterbox/Pillarbox,保证了不同分辨率视频的正确显示比例。

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


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

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:2 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:2 个 ### 🔴 阻塞级问题(必须修复) 1. **[apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 538] 初始化解码逻辑导致帧丢失与播放失败** - 问题类型:逻辑bug - 问题描述:在 `useEffect` 的初始化逻辑中,代码通过循环 `for (const meta of metas)` 一次性解码所有视频片段。然而,`frameQueueRef` 是一个固定大小为 10 的环形缓冲区。随着循环进行,新片段的帧不断推入队列,导致旧片段(尤其是视频开头)的帧被 `shift()` 丢弃。当初始化完成时,队列中仅保留了最后几个片段的帧。此时用户开始播放(`currentTime=0`),`getCurrentFrame` 无法找到对应帧,导致黑屏。同时,`seek` 函数虽然清空了队列,但并未触发重新解码,导致 Seek 功能彻底失效。 - 修改建议:修改解码策略,不要在初始化时解码所有片段。应根据播放进度或当前时间,动态解码当前播放片段及其前后的片段,确保播放头所在的帧始终在队列中。 2. **[apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 298] 不可靠的异步同步机制** - 问题类型:逻辑bug - 问题描述:在 `decodeSegment` 函数中,使用 `await new Promise((resolve) => setTimeout(resolve, 10))` 来等待 `mp4box` 的 `onSamples` 回调执行。这是一种极其脆弱的 Hack 写法。虽然 `mp4box` 的解析通常是同步的,但依赖固定的 10ms 延迟来保证数据收集完成存在严重的竞态条件风险。如果主线程阻塞或解析耗时略微波动,`samplesCollected` 可能为空,导致该片段解码静默失败。 - 修改建议:`mp4box.js` 的 `appendBuffer` 和 `start()` 通常是同步触发回调的。如果必须确保异步完成,应使用 Promise 或计数器在 `onSamples` 回调中显式 resolve,而不是使用 `setTimeout` 猜测时间。 ### 💡 改进建议(不阻塞合并) 1. **[apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 全局] 音频功能移除确认** - 具体内容:Diff 中删除了所有 Web Audio API 相关的代码(`audioCtxRef`, `audioSourceRef` 等)。请确认 `FrontendPreviewPlayer` 组件作为预览器是否确实不再需要音频播放。如果需要音频,此次变更属于功能回退,需恢复音频逻辑。 2. **[apps/web/src/pages/generate/hooks/useCanvasPlayer.ts: 520] 内存与首屏性能风险** - 具体内容:初始化逻辑中使用了 `for (const seg of segments) await loadSegment(seg)`,这意味着在播放开始前会并发/串行下载所有视频片段到内存。对于包含多个片段的长视频,这会导致巨大的内存占用和极长的首屏加载时间。建议仅预加载第一个片段,并利用空闲时间预加载后续片段。 ### ✅ 良好实践 - `FrontendPreviewPlayer.tsx` 中对 `preload` 属性的动态调整(当前播放片段 `auto`,下一段 `metadata`,其余 `none`)是很好的带宽优化策略。 - `renderFrame` 中增加了状态更新节流(200ms),有效减少了 React 重渲染频率,提升性能。 - `useCanvasPlayer.ts` 中增加了 `computeDrawRect` 函数处理 Letterbox/Pillarbox,保证了不同分辨率视频的正确显示比例。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-19 04:50:38 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->

🚀 预览环境已部署

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

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

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

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

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

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-08-19 12:51:50 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
xiaoxia closed this pull request 2026-08-19 20:48:10 +08:00

🗑️ 预览环境已清理

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

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

🗑️ **预览环境已清理** PR #1437 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Some checks are pending
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 43s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m47s
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m48s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m49s
AI Code Review / AI Code Review (pull_request) Failing after 1m50s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m5s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m32s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m9s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m1s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m31s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 6m41s
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 / Canary Release to 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 11s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Has been cancelled
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 43s

Pull request closed

Sign in to join this conversation.