fix: overlay title text on auto-generated cover frames #1365

Merged
auto-approve-bot merged 4 commits from fix/cover-title-overlay into develop 2026-08-14 12:11:00 +08:00
Owner

Problem

自动生成封面时,从视频中截取关键帧后没有叠加用户选择的标题文字。封面只是一张原始视频帧截图,没有任何文字。

Root Cause

extract_cover_candidates()extract_and_upload_cover_frames() 只是用 FFmpeg 抽取视频帧并上传,没有任何文字渲染步骤。标题文字存储在 plan.config["title"]["text"] 中但没有传递给封面生成函数。

Fix

  1. thumbnail_generator.py: 新增 _overlay_title_on_image() 函数,使用 FFmpeg drawtext 滤镜在封面图上叠加标题文字

    • 白色文字 + 黑色阴影,居中偏下显示
    • 使用中文字体 Noto Sans CJK
    • 字号按画面高度自适应 (h/14)
    • 失败时降级使用原图(不阻断主流程)
  2. extract_cover_candidates(): 新增 title_text 参数,抽帧后调用文字叠加

  3. extract_and_upload_cover_frames(): 新增 title_text 参数并透传

  4. render_adapter.py: 从 plan_config["title"] 提取标题文字并传给封面生成

Result

自动生成封面 = 视频关键帧 + 用户标题文字叠加

## Problem 自动生成封面时,从视频中截取关键帧后没有叠加用户选择的标题文字。封面只是一张原始视频帧截图,没有任何文字。 ## Root Cause `extract_cover_candidates()` 和 `extract_and_upload_cover_frames()` 只是用 FFmpeg 抽取视频帧并上传,没有任何文字渲染步骤。标题文字存储在 `plan.config["title"]["text"]` 中但没有传递给封面生成函数。 ## Fix 1. **thumbnail_generator.py**: 新增 `_overlay_title_on_image()` 函数,使用 FFmpeg drawtext 滤镜在封面图上叠加标题文字 - 白色文字 + 黑色阴影,居中偏下显示 - 使用中文字体 Noto Sans CJK - 字号按画面高度自适应 (h/14) - 失败时降级使用原图(不阻断主流程) 2. **extract_cover_candidates()**: 新增 `title_text` 参数,抽帧后调用文字叠加 3. **extract_and_upload_cover_frames()**: 新增 `title_text` 参数并透传 4. **render_adapter.py**: 从 `plan_config["title"]` 提取标题文字并传给封面生成 ## Result 自动生成封面 = 视频关键帧 + 用户标题文字叠加
xiaoxia added 1 commit 2026-08-14 11:30:59 +08:00
fix: overlay title text on auto-generated cover frames
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
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 / 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 37s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m15s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m33s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m42s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m44s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (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
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
7914be887a
When auto-generating cover images from video keyframes, the title text
from plan config was not being overlaid on the cover images. Users saw
raw video frames without any title text.

Changes:
- thumbnail_generator.py: Add _overlay_title_on_image() using FFmpeg
  drawtext filter with Chinese font (Noto Sans CJK), white text with
  shadow, centered at bottom area of the image
- extract_cover_candidates(): Accept optional title_text parameter,
  overlay title on each extracted frame
- extract_and_upload_cover_frames(): Accept and pass title_text through
- render_adapter.py: Extract title text from plan.config['title']['text']
  and pass to cover generation

The title overlay gracefully falls back to the original image if
FFmpeg drawtext fails (e.g., font not found).

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1365 | | 预览链接 | [https://pr-1365.preview.xiaoxiajianji.com](https://pr-1365.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot added 1 commit 2026-08-14 11:34:12 +08:00
style: auto-format with black + isort + prettier [skip ci-format-check]
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 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 - Migration (alembic) (pull_request) Successful in 1m19s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m22s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m24s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m44s
AI Code Review / AI Code Review (pull_request) Failing after 2m15s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m42s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m29s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m44s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m48s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 4m39s
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 / Integration Tests (pull_request) Successful in 11m11s
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
8a44786242
auto-approve-bot approved these changes 2026-08-14 11:40:30 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

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

CI全绿,自动审批通过。

CI全绿,自动审批通过。
xiaoxia added 1 commit 2026-08-14 11:58:28 +08:00
fix: add [ ] escaping for FFmpeg drawtext & guard plan_config None
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 43s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m20s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m34s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m46s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m44s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 2m27s
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (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
AI Code Review / AI Code Review (pull_request) Successful in 2m27s
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
48a14f8fea
- thumbnail_generator: _overlay_title_on_image now escapes [ and ]
  characters to prevent FFmpeg filter syntax errors when title
  contains brackets (e.g. '[Tag]')
- render_adapter: use (plan_config or {}).get(...) to guard against
  None plan_config in cover candidate generation block

Addresses AI Code Review findings on PR #1365.
Collaborator

【阻塞级判定】

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

📊 审查概览

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

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

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

  1. [apps/worker/video_processing/thumbnail_generator.py: 144] 硬编码字体路径存在环境依赖风险

    • 具体内容:代码中硬编码了字体路径 /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc。如果部署环境(如不同版本的 Linux 发行版或精简容器)中不存在此路径,FFmpeg 将报错,导致标题叠加功能静默失败(虽然有异常捕获,但功能不可用)。建议将字体路径配置化,或增加常见的字体路径回退机制(如尝试多个可能的路径)。
  2. [apps/worker/video_processing/thumbnail_generator.py: 129] 字符串截断逻辑在转义后进行可能导致显示长度不一致

    • 具体内容:当前逻辑是先转义特殊字符(如 : 变成 \:),再判断长度是否大于 60 进行截断。如果原始文本包含大量需要转义的字符,转义后的字符串长度会翻倍,导致实际显示的文本远少于 60 个字符就被截断。建议先对原始 title_text 进行长度截断,然后再进行转义处理,以保证显示字符数量的稳定性。

良好实践

  • 异常处理完善_overlay_title_on_image 函数中使用了 try...except 块,并在失败时清理临时文件(.tmp.jpg),同时回退到原图,保证了视频处理主流程的鲁棒性。
  • 命令注入防护:使用列表 cmd 传递参数给 run_ffmpeg,有效避免了 Shell 命令注入风险;对 FFmpeg drawtext 滤镜中的特殊字符进行了转义处理,防止了滤镜语法错误。
  • 原子性操作:使用临时文件处理图片,处理完成后使用 shutil.move 原子性地替换原文件,避免了处理过程中写入失败导致原文件损坏的问题。

格式检查通过 | 逻辑审查通过 | 性能无明显瓶颈


🤖 由 AI 代码审查机器人自动生成 | 2026-08-14 04:00:54 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:否 - 阻塞级问题数量:0 个 ### 📊 审查概览 - 整体评价:有建议 - 建议级问题数量:2 个 ### 🔴 阻塞级问题(必须修复) 无 ### 💡 改进建议(不阻塞合并) 1. **[apps/worker/video_processing/thumbnail_generator.py: 144] 硬编码字体路径存在环境依赖风险** - 具体内容:代码中硬编码了字体路径 `/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc`。如果部署环境(如不同版本的 Linux 发行版或精简容器)中不存在此路径,FFmpeg 将报错,导致标题叠加功能静默失败(虽然有异常捕获,但功能不可用)。建议将字体路径配置化,或增加常见的字体路径回退机制(如尝试多个可能的路径)。 2. **[apps/worker/video_processing/thumbnail_generator.py: 129] 字符串截断逻辑在转义后进行可能导致显示长度不一致** - 具体内容:当前逻辑是先转义特殊字符(如 `:` 变成 `\:`),再判断长度是否大于 60 进行截断。如果原始文本包含大量需要转义的字符,转义后的字符串长度会翻倍,导致实际显示的文本远少于 60 个字符就被截断。建议先对原始 `title_text` 进行长度截断,然后再进行转义处理,以保证显示字符数量的稳定性。 ### ✅ 良好实践 - **异常处理完善**:`_overlay_title_on_image` 函数中使用了 `try...except` 块,并在失败时清理临时文件(`.tmp.jpg`),同时回退到原图,保证了视频处理主流程的鲁棒性。 - **命令注入防护**:使用列表 `cmd` 传递参数给 `run_ffmpeg`,有效避免了 Shell 命令注入风险;对 FFmpeg `drawtext` 滤镜中的特殊字符进行了转义处理,防止了滤镜语法错误。 - **原子性操作**:使用临时文件处理图片,处理完成后使用 `shutil.move` 原子性地替换原文件,避免了处理过程中写入失败导致原文件损坏的问题。 --- ✅ 格式检查通过 | ✅ 逻辑审查通过 | ✅ 性能无明显瓶颈 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-14 04:00:54 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot added 1 commit 2026-08-14 12:00:55 +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 E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 41s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m13s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m15s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m28s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m44s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m32s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m32s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m41s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m28s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 4m8s
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 / Canary Release to Production (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 / Integration Tests (pull_request) Successful in 2m0s
CI/CD Pipeline / CI Gate (pull_request) Successful in 5s
AI Code Review / AI Code Review (pull_request) Successful in 6m48s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 48s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m9s
65fff01db0
auto-approve-bot merged commit c00c56a742 into develop 2026-08-14 12:11:00 +08:00
auto-approve-bot deleted branch fix/cover-title-overlay 2026-08-14 12:11:01 +08:00

🗑️ 预览环境已清理

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

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

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