fix: 预览播放器4个线上问题修复(弹窗裁剪+HEVC黑屏+标题换行+封面400) #1439

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

Bug 1: 弹窗顶部被裁剪

文件: generate.css, GeneratePage.tsx

根因: 全局样式 .ant-modal-content { padding: 0 !important } 影响所有 Ant Design Modal,导致配音校验弹窗等内容紧贴圆角被裁切。

修复:

  • CSS 规则限定到 .xx-preview-modal .ant-modal-content
  • 预览弹窗 Modal 添加 className="xx-preview-modal"

Bug 2: Canvas 预览黑屏(HEVC 编码)

文件: useCanvasPlayer.ts

根因: HEVC/H.265 编码需要 VideoDecoderConfig.description 字段(hvcC box 数据),当前只传了 codec/width/height。

修复:

  • 新增 findCodecConfig 模块级函数,手动解析 MP4 buffer 的 moov→trak→mdia→minf→stbl→stsd 路径
  • 提取 avcC(H.264)或 hvcC(HEVC)box 数据
  • SegmentMeta 新增 description 字段,decoder.configure() 传入

Bug 3: 标题 "/" 手动换行

文件: useCanvasPlayer.ts

需求: 标题文本中 "/" 作为换行符,如 "永康拾脚阔头/来一个笑一个" 显示两行。

修复:

  • drawTitle 按 "/" 分割文本为多行
  • lineHeight = fontSize * 1.3
  • 根据 position(top/center/bottom)计算多行文本的起始 Y 坐标

Bug 4: 封面生成 400 错误

文件: useStep6Cover.ts

根因: 封面 API 依赖后端渲染的预览视频,但当前 Step5 是纯前端 Canvas 播放,未创建后端预览任务。

修复:

  • 封面 API 返回 400 时,自动调用 createPreview 创建后端预览渲染
  • 轮询等待预览完成(3 秒间隔)
  • 完成后自动重试封面生成
## Bug 1: 弹窗顶部被裁剪 **文件**: `generate.css`, `GeneratePage.tsx` **根因**: 全局样式 `.ant-modal-content { padding: 0 !important }` 影响所有 Ant Design Modal,导致配音校验弹窗等内容紧贴圆角被裁切。 **修复**: - CSS 规则限定到 `.xx-preview-modal .ant-modal-content` - 预览弹窗 Modal 添加 `className="xx-preview-modal"` ## Bug 2: Canvas 预览黑屏(HEVC 编码) **文件**: `useCanvasPlayer.ts` **根因**: HEVC/H.265 编码需要 `VideoDecoderConfig.description` 字段(hvcC box 数据),当前只传了 codec/width/height。 **修复**: - 新增 `findCodecConfig` 模块级函数,手动解析 MP4 buffer 的 moov→trak→mdia→minf→stbl→stsd 路径 - 提取 avcC(H.264)或 hvcC(HEVC)box 数据 - `SegmentMeta` 新增 `description` 字段,`decoder.configure()` 传入 ## Bug 3: 标题 "/" 手动换行 **文件**: `useCanvasPlayer.ts` **需求**: 标题文本中 "/" 作为换行符,如 "永康拾脚阔头/来一个笑一个" 显示两行。 **修复**: - `drawTitle` 按 "/" 分割文本为多行 - `lineHeight = fontSize * 1.3` - 根据 position(top/center/bottom)计算多行文本的起始 Y 坐标 ## Bug 4: 封面生成 400 错误 **文件**: `useStep6Cover.ts` **根因**: 封面 API 依赖后端渲染的预览视频,但当前 Step5 是纯前端 Canvas 播放,未创建后端预览任务。 **修复**: - 封面 API 返回 400 时,自动调用 `createPreview` 创建后端预览渲染 - 轮询等待预览完成(3 秒间隔) - 完成后自动重试封面生成
xiaoxia added 1 commit 2026-08-19 14:05:34 +08:00
fix: 预览播放器4个线上问题修复
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 / 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 48s
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 / Frontend Unit Tests (pull_request) Successful in 48s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m43s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m46s
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m54s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m1s
AI Code Review / AI Code Review (pull_request) Failing after 2m24s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m58s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m56s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m20s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 7m45s
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 10s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Has been cancelled
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 35s
1e2d06ec1b
Bug 1: 弹窗顶部被裁剪
- generate.css: .ant-modal-content/.ant-modal-close 规则限定到 .xx-preview-modal
- GeneratePage.tsx: 预览弹窗 Modal 添加 className='xx-preview-modal'

Bug 2: Canvas 黑屏(HEVC 编码不支持)
- useCanvasPlayer.ts: 新增 findCodecConfig 模块级函数解析 MP4 buffer
- 提取 avcC/hvcC box 数据作为 VideoDecoder description
- SegmentMeta 新增 description 字段,decoder.configure 传入

Bug 3: 标题 / 手动换行
- useCanvasPlayer.ts: drawTitle 按 / 分割多行绘制
- lineHeight = fontSize * 1.3,根据 position 居中/对齐

Bug 4: 封面生成 400 错误
- useStep6Cover.ts: 封面 API 返回 400 时自动创建后端预览渲染
- 轮询等待预览完成后重试封面生成

🚀 预览环境已部署

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

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

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

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

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

【阻塞级判定】

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

📊 审查概览

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

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

  1. [apps/web/src/pages/generate/hooks/useStep6Cover.ts: 115-165] 轮询逻辑缺乏超时机制

    • 问题类型:逻辑bug / 边界条件遗漏
    • 问题描述:在 getPreviewStatus 的轮询逻辑中,使用了 setInterval 进行无限轮询,但未设置最大重试次数或总超时时间。如果后端渲染任务一直处于 processing 状态或服务端出现异常未返回 completed/failed,该 Promise 将永远无法 resolve,导致 setGenerating(true) 状态无法重置,前端页面将永久卡在“生成中”状态,用户体验极差且占用资源。
    • 修改建议:在轮询逻辑中增加超时控制(例如最多轮询 60 次或设置 2 分钟总超时),超时后 reject 并提示用户“预览生成超时,请稍后重试”。
  2. [apps/web/src/pages/generate/hooks/useStep6Cover.ts: 118] 错误码 400 的处理逻辑过于宽泛

    • 问题类型:逻辑bug
    • 问题描述:代码捕获所有 statusCode === 400 的错误并尝试通过“创建预览”来自动修复。这假设了 400 错误仅仅是因为“缺少预览视频”。如果后端因为其他原因(如参数校验失败、模板 ID 无效、Asset ID 错过等)返回 400,代码将错误地触发预览创建流程,且后续的 createPreview 可能也会失败,最终掩盖了真实的错误原因,导致用户看到错误的提示信息。
    • 修改建议:在判断 statusCode === 400 后,进一步检查错误响应体中的 codemessage,确认确实是“预览缺失”类错误(例如 err.response.data.code === 'PREVIEW_NOT_FOUND')才执行自动修复逻辑,否则应走常规错误处理流程。

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

  1. [apps/web/src/pages/generate/hooks/useStep6Cover.ts: 160] 错误提示信息不准确
    • 具体内容:在 catch (retryErr) 块中,错误提示固定为“预览视频创建失败,请稍后重试”。实际上,这里的 retryErr 是由 generateCover(封面生成)抛出的,而不是 createPreview(预览创建)。如果预览创建成功但封面生成失败(例如 500 错误),提示用户“预览创建失败”是误导性的。建议根据错误来源区分提示文案,或使用通用的“自动重试失败,请重试”。

良好实践

  • useCanvasPlayer.ts 中新增的 MP4 Box 解析逻辑(findCodecConfigextractCodecDescription)手动实现了二进制数据遍历,边界检查(offset < end - 8)和递归处理较为稳健,且正确处理了 WebCodecs 必需的 description 字段。
  • useCanvasPlayer.ts 中的多行标题绘制逻辑通过计算 totalHeight 动态调整 startY,保证了不同对齐方式(top/center/bottom)下多行文本的垂直位置正确。
  • CSS 修改通过增加 .xx-preview-modal 限定作用域,避免了全局污染,符合组件化样式最佳实践。

🤖 由 AI 代码审查机器人自动生成 | 2026-08-19 06:07:57 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:2 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:1 个 ### 🔴 阻塞级问题(必须修复) 1. **[apps/web/src/pages/generate/hooks/useStep6Cover.ts: 115-165] 轮询逻辑缺乏超时机制** - 问题类型:逻辑bug / 边界条件遗漏 - 问题描述:在 `getPreviewStatus` 的轮询逻辑中,使用了 `setInterval` 进行无限轮询,但未设置最大重试次数或总超时时间。如果后端渲染任务一直处于 `processing` 状态或服务端出现异常未返回 `completed`/`failed`,该 Promise 将永远无法 resolve,导致 `setGenerating(true)` 状态无法重置,前端页面将永久卡在“生成中”状态,用户体验极差且占用资源。 - 修改建议:在轮询逻辑中增加超时控制(例如最多轮询 60 次或设置 2 分钟总超时),超时后 reject 并提示用户“预览生成超时,请稍后重试”。 2. **[apps/web/src/pages/generate/hooks/useStep6Cover.ts: 118] 错误码 400 的处理逻辑过于宽泛** - 问题类型:逻辑bug - 问题描述:代码捕获所有 `statusCode === 400` 的错误并尝试通过“创建预览”来自动修复。这假设了 400 错误**仅仅**是因为“缺少预览视频”。如果后端因为其他原因(如参数校验失败、模板 ID 无效、Asset ID 错过等)返回 400,代码将错误地触发预览创建流程,且后续的 `createPreview` 可能也会失败,最终掩盖了真实的错误原因,导致用户看到错误的提示信息。 - 修改建议:在判断 `statusCode === 400` 后,进一步检查错误响应体中的 `code` 或 `message`,确认确实是“预览缺失”类错误(例如 `err.response.data.code === 'PREVIEW_NOT_FOUND'`)才执行自动修复逻辑,否则应走常规错误处理流程。 ### 💡 改进建议(不阻塞合并) 1. **[apps/web/src/pages/generate/hooks/useStep6Cover.ts: 160] 错误提示信息不准确** - 具体内容:在 `catch (retryErr)` 块中,错误提示固定为“预览视频创建失败,请稍后重试”。实际上,这里的 `retryErr` 是由 `generateCover`(封面生成)抛出的,而不是 `createPreview`(预览创建)。如果预览创建成功但封面生成失败(例如 500 错误),提示用户“预览创建失败”是误导性的。建议根据错误来源区分提示文案,或使用通用的“自动重试失败,请重试”。 ### ✅ 良好实践 - `useCanvasPlayer.ts` 中新增的 MP4 Box 解析逻辑(`findCodecConfig` 和 `extractCodecDescription`)手动实现了二进制数据遍历,边界检查(`offset < end - 8`)和递归处理较为稳健,且正确处理了 WebCodecs 必需的 `description` 字段。 - `useCanvasPlayer.ts` 中的多行标题绘制逻辑通过计算 `totalHeight` 动态调整 `startY`,保证了不同对齐方式(top/center/bottom)下多行文本的垂直位置正确。 - CSS 修改通过增加 `.xx-preview-modal` 限定作用域,避免了全局污染,符合组件化样式最佳实践。 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-19 06:07:57 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot approved these changes 2026-08-19 14:08:32 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

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

CI全绿,自动审批通过。

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

🗑️ 预览环境已清理

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

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

🗑️ **预览环境已清理** PR #1439 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
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 / 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 48s
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 / Frontend Unit Tests (pull_request) Successful in 48s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m43s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m46s
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m54s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m1s
AI Code Review / AI Code Review (pull_request) Failing after 2m24s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m58s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m56s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m20s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 7m45s
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 10s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Has been cancelled
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 35s

Pull request closed

Sign in to join this conversation.