fix: 预览标题坐标系与后端 ASS 烧录 1:1 对齐 #1502

Closed
xiaoxia wants to merge 1 commits from fix/preview-coord-system into develop
Owner

问题

CSS 预览层硬编码 1280x720 坐标系,后端竖屏实际输出 1080x1920,导致标题位置、字号、边距与最终渲染视频不一致。

修复

  • 根据 videoRatio 动态选择后端实际分辨率(9:16→1080x1920, 16:9→1920x1080, 1:1→1080x1080)
  • 字号缩放分母从 720 改为实际 PlayResY,移除 96 上限
  • 水平边距百分比分母从 1280 改为实际 PlayResX
  • 垂直边距按实际 PlayResY 计算百分比
  • 描边/阴影按容器缩放比例同步放大
  • FrontendPreviewPlayer 标题叠加层同时支持半角/和全角/换行

涉及文件

  • PreviewVideoPanel.tsx(死代码组件,但一并修正)
  • FrontendPreviewPlayer.tsx(当前实际使用的预览播放器)
## 问题 CSS 预览层硬编码 1280x720 坐标系,后端竖屏实际输出 1080x1920,导致标题位置、字号、边距与最终渲染视频不一致。 ## 修复 - 根据 videoRatio 动态选择后端实际分辨率(9:16→1080x1920, 16:9→1920x1080, 1:1→1080x1080) - 字号缩放分母从 720 改为实际 PlayResY,移除 96 上限 - 水平边距百分比分母从 1280 改为实际 PlayResX - 垂直边距按实际 PlayResY 计算百分比 - 描边/阴影按容器缩放比例同步放大 - FrontendPreviewPlayer 标题叠加层同时支持半角/和全角/换行 ## 涉及文件 - PreviewVideoPanel.tsx(死代码组件,但一并修正) - FrontendPreviewPlayer.tsx(当前实际使用的预览播放器)
xiaoxia added 1 commit 2026-08-25 21:17:41 +08:00
fix: 预览标题坐标系与后端 ASS 烧录 1:1 对齐
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 21s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m16s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m12s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m41s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 54s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m45s
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Failing after 3m36s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m30s
CI/CD Pipeline / PR Build 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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m40s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m59s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 32s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 9m24s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 36s
CI/CD Pipeline / CI Gate (pull_request) Successful in 10s
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
1fc62c9476
问题:CSS 预览层硬编码 1280x720 坐标系,后端竖屏实际输出 1080x1920,
导致标题位置、字号、边距与最终渲染视频不一致,视觉上出现"标题重叠"。

修复(PreviewVideoPanel.tsx + FrontendPreviewPlayer.tsx):
- 根据 videoRatio 动态选择后端实际分辨率:
  · 9:16 → 1080x1920
  · 16:9 → 1920x1080
  · 1:1 → 1080x1080
- 字号缩放分母从 720 改为实际 PlayResY,不设 96 上限
- 水平边距百分比分母从 1280 改为实际 PlayResX
- 垂直边距(top/bottom)按实际 PlayResY 计算百分比
- 描边宽度、阴影模糊/偏移按容器缩放比例同步放大
- FrontendPreviewPlayer 标题叠加层同时支持半角/和全角/换行
- 移除 paddingLeft/paddingRight hack,改用 left/right 边距(与 ASS MarginL/R 一致)
Collaborator

【阻塞级判定】

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

📊 审查概览

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

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

  1. [apps/web/src/pages/generate/components/PreviewVideoPanel.tsx: 111-112] 标题描边与阴影未随分辨率缩放
    • 问题类型:逻辑bug
    • 问题描述:在 buildTitleStyle 函数中,WebkitTextStroketextShadow 的值被硬编码为 "1px""2px 2px 4px",没有根据 containerHeightplayResY 进行比例缩放。相比之下,FrontendPreviewPlayer.tsx 中正确实现了基于 titleScale 的缩放逻辑。
    • 修改建议:参照 FrontendPreviewPlayer.tsx 的实现,计算 scale = containerHeight / playResY,并将描边宽度设为 Math.max(1, 2 * scale),阴影参数也相应乘以 scale,确保在不同尺寸预览中视觉效果与后端渲染一致。

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

  1. [apps/web/src/pages/generate/components/PreviewVideoPanel.tsx & FrontendPreviewPlayer.tsx] 常量与分辨率计算逻辑重复

    • 具体内容:TITLE_MARGIN_TOPTITLE_MARGIN_BOTTOMTITLE_MARGIN_SIDE 常量以及 getResolution (或 playRes) 计算逻辑在两个文件中重复定义。建议将这些与后端 ass_subtitle_builder.py 强相关的配置提取到共享的常量文件(如 src/shared/constants/subtitle.ts),以避免未来修改时出现不一致。
  2. [apps/web/src/pages/generate/components/PreviewVideoPanel.tsx: 118-120] 初始状态字号的计算逻辑不一致

    • 具体内容:当 containerHeight 为 0 时,PreviewVideoPanel.tsx 使用 (settings.size / playResY) * 400 作为默认字号(假定高度400),而 FrontendPreviewPlayer.tsx 直接使用 settings.size。虽然这只是渲染瞬间的差异,但建议统一处理策略,例如都使用 playResY 作为基准高度,或者都使用原始字号,以保持代码逻辑的一致性。

良好实践

  • 使用 ResizeObserver 监听容器尺寸变化,实现了响应式的字体和位置缩放,比监听 window resize 更精确。
  • FrontendPreviewPlayer.tsx 中对 titleSettings.title 进行了正则分割 /[//]/ 处理换行,兼容了全角和半角斜杠,细节处理良好。
  • 使用 useMemo 缓存样式计算对象,避免不必要的重渲染。

🤖 由 AI 代码审查机器人自动生成 | 2026-08-25 13:21:38 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:1 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:2 个 ### 🔴 阻塞级问题(必须修复) 1. **[apps/web/src/pages/generate/components/PreviewVideoPanel.tsx: 111-112] 标题描边与阴影未随分辨率缩放** - 问题类型:逻辑bug - 问题描述:在 `buildTitleStyle` 函数中,`WebkitTextStroke` 和 `textShadow` 的值被硬编码为 `"1px"` 和 `"2px 2px 4px"`,没有根据 `containerHeight` 和 `playResY` 进行比例缩放。相比之下,`FrontendPreviewPlayer.tsx` 中正确实现了基于 `titleScale` 的缩放逻辑。 - 修改建议:参照 `FrontendPreviewPlayer.tsx` 的实现,计算 `scale = containerHeight / playResY`,并将描边宽度设为 `Math.max(1, 2 * scale)`,阴影参数也相应乘以 `scale`,确保在不同尺寸预览中视觉效果与后端渲染一致。 ### 💡 改进建议(不阻塞合并) 1. **[apps/web/src/pages/generate/components/PreviewVideoPanel.tsx & FrontendPreviewPlayer.tsx] 常量与分辨率计算逻辑重复** - 具体内容:`TITLE_MARGIN_TOP`、`TITLE_MARGIN_BOTTOM`、`TITLE_MARGIN_SIDE` 常量以及 `getResolution` (或 `playRes`) 计算逻辑在两个文件中重复定义。建议将这些与后端 `ass_subtitle_builder.py` 强相关的配置提取到共享的常量文件(如 `src/shared/constants/subtitle.ts`),以避免未来修改时出现不一致。 2. **[apps/web/src/pages/generate/components/PreviewVideoPanel.tsx: 118-120] 初始状态字号的计算逻辑不一致** - 具体内容:当 `containerHeight` 为 0 时,`PreviewVideoPanel.tsx` 使用 `(settings.size / playResY) * 400` 作为默认字号(假定高度400),而 `FrontendPreviewPlayer.tsx` 直接使用 `settings.size`。虽然这只是渲染瞬间的差异,但建议统一处理策略,例如都使用 `playResY` 作为基准高度,或者都使用原始字号,以保持代码逻辑的一致性。 ### ✅ 良好实践 - 使用 `ResizeObserver` 监听容器尺寸变化,实现了响应式的字体和位置缩放,比监听 window resize 更精确。 - `FrontendPreviewPlayer.tsx` 中对 `titleSettings.title` 进行了正则分割 `/[//]/` 处理换行,兼容了全角和半角斜杠,细节处理良好。 - 使用 `useMemo` 缓存样式计算对象,避免不必要的重渲染。 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-25 13:21:38 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->

🚀 预览环境已部署

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

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

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

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

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

🗑️ 预览环境已清理

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

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

🗑️ **预览环境已清理** PR #1502 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Some checks are pending
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 21s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m16s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m12s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m41s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 54s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m45s
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Failing after 3m36s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m30s
CI/CD Pipeline / PR Build 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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m40s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m59s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 32s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 9m24s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 36s
CI/CD Pipeline / CI Gate (pull_request) Successful in 10s
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

Pull request closed

Sign in to join this conversation.