feat: 视频渲染后随机边缘裁剪 2-5% 降重 #1664 #1682

Merged
auto-approve-bot merged 3 commits from feat/random-edge-crop-1664 into develop 2026-09-04 11:56:19 +08:00
Owner

改动

渲染完成后、上传 OSS 前,自动对视频四个边缘做随机裁剪再缩放回原分辨率,改变 pHash 指纹。

ffmpeg_utils.py — 新增 random_edge_crop()

  • probe_video_info 获取原始 W×H
  • 四边各自 random.uniform(2%, 5%) 随机裁剪
  • ffmpeg 滤镜:crop=W_new:H_new:x_offset:y_offset,scale=W_orig:H_orig
  • 裁剪后奇数尺寸自动调整为偶数(ffmpeg 编码器常要求偶数)
  • output_path=None 时覆盖原文件;指定时写入新文件
  • 分辨率无效(W/H ≤ 0)时跳过裁剪

generation.py — 渲染后插入裁剪步骤

# ── 3.5 随机边缘裁剪降重(#1664)──
try:
    cropped_path = random_edge_crop(output_path)
    ...
except Exception as crop_err:
    logger.warning("裁剪失败,使用原始视频继续: %s", crop_err)
  • try/except 包裹,失败仅 warning 不中断
  • gen_task 日志记录裁剪结果

测试 — 9 个单测

测试 覆盖
test_returns_input_path_when_output_none 覆盖原文件
test_returns_output_path_when_specified 指定输出
test_skip_when_invalid_resolution 无效分辨率跳过
test_ffmpeg_crop_and_scale_filter 滤镜正确
test_crop_amounts_within_range 裁剪量在范围内
test_uses_libx264_codec 编码器正确
test_ffmpeg_failure_raises_exception ffmpeg 失败传播
test_probe_failure_propagates probe 失败传播
test_odd_crop_dimensions_adjusted_to_even 奇数尺寸调整

验证

  • black + ruff 通过
  • 9 个新单测 + 40 个已有 ffmpeg 单测全过
## 改动 渲染完成后、上传 OSS 前,自动对视频四个边缘做随机裁剪再缩放回原分辨率,改变 pHash 指纹。 ### ffmpeg_utils.py — 新增 `random_edge_crop()` - `probe_video_info` 获取原始 W×H - 四边各自 `random.uniform(2%, 5%)` 随机裁剪 - ffmpeg 滤镜:`crop=W_new:H_new:x_offset:y_offset,scale=W_orig:H_orig` - 裁剪后奇数尺寸自动调整为偶数(ffmpeg 编码器常要求偶数) - `output_path=None` 时覆盖原文件;指定时写入新文件 - 分辨率无效(W/H ≤ 0)时跳过裁剪 ### generation.py — 渲染后插入裁剪步骤 ```python # ── 3.5 随机边缘裁剪降重(#1664)── try: cropped_path = random_edge_crop(output_path) ... except Exception as crop_err: logger.warning("裁剪失败,使用原始视频继续: %s", crop_err) ``` - try/except 包裹,失败仅 warning 不中断 - gen_task 日志记录裁剪结果 ### 测试 — 9 个单测 | 测试 | 覆盖 | |------|------| | test_returns_input_path_when_output_none | 覆盖原文件 | | test_returns_output_path_when_specified | 指定输出 | | test_skip_when_invalid_resolution | 无效分辨率跳过 | | test_ffmpeg_crop_and_scale_filter | 滤镜正确 | | test_crop_amounts_within_range | 裁剪量在范围内 | | test_uses_libx264_codec | 编码器正确 | | test_ffmpeg_failure_raises_exception | ffmpeg 失败传播 | | test_probe_failure_propagates | probe 失败传播 | | test_odd_crop_dimensions_adjusted_to_even | 奇数尺寸调整 | ## 验证 - ✅ black + ruff 通过 - ✅ 9 个新单测 + 40 个已有 ffmpeg 单测全过
xiaoxia added 1 commit 2026-09-04 11:42:45 +08:00
feat: 视频渲染后随机边缘裁剪 2-5% 降重 #1664
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 6s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 7s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m10s
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 API Image (pull_request) Successful in 25s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 16s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped 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 / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (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 / 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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
a4ef63d76c
- ffmpeg_utils.py 新增 random_edge_crop() 函数:
  - ffprobe 获取原始分辨率
  - 四边各自 random.uniform(2%, 5%) 裁剪
  - crop + scale 滤镜保持输出尺寸不变
  - 裁剪后奇数尺寸自动调整为偶数(ffmpeg 编码器要求)
  - 失败时 warning 不中断,回退使用原始视频

- generation.py 渲染完成后、_upload_and_record 前插入裁剪步骤
  - try/except 包裹,失败仅 log warning
  - gen_task 日志记录裁剪结果

- 9 个单测覆盖:基本流程/滤镜参数/编码参数/错误处理/偶数尺寸
- black + ruff 通过

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1682 | | 预览链接 | [https://pr-1682.preview.xiaoxiajianji.com](https://pr-1682.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot added 1 commit 2026-09-04 11:46:22 +08:00
style: auto-format with black + isort + prettier [skip ci-format-check]
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 6s
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 / 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 / PR Build API Image (pull_request) Successful in 22s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 20s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped 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 / Validate - Python (mypy + alembic) (pull_request) Successful in 1m54s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m4s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m10s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m8s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m38s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m1s
CI/CD Pipeline / Validate - Security (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 Merge on CI Green + Approved (pull_request) Has been cancelled
e531d31032
xiaoxia added 1 commit 2026-09-04 11:51:00 +08:00
chore: re-trigger CI
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
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 / 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 / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped 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 / PR Build API Image (pull_request) Successful in 28s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 30s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m25s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 1m43s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m46s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m48s
AI Code Review / AI Code Review (pull_request) Failing after 2m6s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m11s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m49s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 4m37s
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 / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m26s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 8s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 28s
52e1126631
Collaborator

【阻塞级判定】

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

📊 审查概览

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

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

  1. [apps/worker/video_processing/ffmpeg_utils.py:324] 极小分辨率视频处理逻辑缺陷

    • 问题类型:逻辑bug
    • 问题描述:当输入视频的宽或高为 1 像素时(例如 1x1 或 1920x1),代码逻辑会导致 FFmpeg 报错退出。
      • 原因:代码强制 new_w = max(..., 2),即最小裁剪尺寸为 2。如果原始宽度 W=1,计算出的 new_w 会被强制设为 2。
      • 后果:后续构建的 FFmpeg 滤镜 crop=2:2:... 试图从 1 像素宽的图像中裁剪出 2 像素宽的区域,FFmpeg 会抛出 "Requested area is not within the frame" 错误,导致任务失败。
    • 修改建议:在检查分辨率有效性时,应将阈值从 <= 0 改为 < 2,因为编码器通常要求至少 2 像素,且当前逻辑无法处理 1 像素的情况。
      if W < 2 or H < 2:
          logger.warning("分辨率过小无法裁剪 (W=%d H=%d),跳过: %s", W, H, input_path)
          return input_path
      
  2. [apps/worker/video_processing/ffmpeg_utils.py:346-349] 分辨率处理逻辑与文档描述不符

    • 问题类型:逻辑bug / 数据损坏风险
    • 问题描述:代码在处理奇数分辨率时(如 1921x1081),会将输出分辨率强制修改为偶数(1922x1082),这与函数文档 "缩放回原分辨率" 的描述相悖。
      • 原因:out_w = W if W % 2 == 0 else W + 1
      • 后果:对于依赖精确元数据匹配的下游系统,这会导致视频属性变更。虽然 FFmpeg 编码通常要求偶数,但简单的 +1 会导致轻微的画面拉伸或宽高比变化,且违背了函数承诺。
    • 修改建议:修改文档字符串说明会调整为偶数分辨率,或者修改逻辑使用 pad 滤镜保持分辨率不变(如果业务严格要求分辨率一致)。鉴于目的是“改变 pHash”,建议修改文档字符串以如实反映行为。

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

  1. [apps/worker/video_processing/ffmpeg_utils.py:362] 编码参数设置过于激进

    • 具体内容:使用了 -crf 18,这是一个非常高质量(接近无损)的设置,会导致编码速度变慢且文件体积变大。对于“降重”和“改变指纹”这一非关键任务,建议使用默认值(如 23)或稍高一点的值(如 20-23),以提升处理速度并节省存储空间。
  2. [apps/worker/video_processing/ffmpeg_utils.py:319-321, 352] 模块导入位置不规范

    • 具体内容:import random, import shutil, import tempfile 以及 import os 被放置在函数内部或条件块内部。虽然 Python 允许这样做,但通常建议将所有模块导入放在文件顶部,以符合 PEP8 规范并减少重复执行的开销(尽管有缓存机制)。

良好实践

  • 异常处理设计得当:在 generation.py 中,对 random_edge_crop 的异常捕获非常合理,作为非关键路径的降重功能,失败时记录日志并继续使用原始视频,不会阻塞主流程。
  • 临时文件清理机制:在 ffmpeg_utils.py 中,使用了 try...except 块确保在 FFmpeg 执行失败时清理临时文件,防止残留垃圾文件。
  • 测试覆盖较全:新增的单元测试覆盖了基本路径、参数验证、FFmpeg 命令构造及异常传播,质量较高。

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


🤖 由 AI 代码审查机器人自动生成 | 2026-09-04 03:53:07 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:2 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:2 个 ### 🔴 阻塞级问题(必须修复) 1. **[apps/worker/video_processing/ffmpeg_utils.py:324] 极小分辨率视频处理逻辑缺陷** - 问题类型:逻辑bug - 问题描述:当输入视频的宽或高为 1 像素时(例如 1x1 或 1920x1),代码逻辑会导致 FFmpeg 报错退出。 - 原因:代码强制 `new_w = max(..., 2)`,即最小裁剪尺寸为 2。如果原始宽度 W=1,计算出的 `new_w` 会被强制设为 2。 - 后果:后续构建的 FFmpeg 滤镜 `crop=2:2:...` 试图从 1 像素宽的图像中裁剪出 2 像素宽的区域,FFmpeg 会抛出 "Requested area is not within the frame" 错误,导致任务失败。 - 修改建议:在检查分辨率有效性时,应将阈值从 `<= 0` 改为 `< 2`,因为编码器通常要求至少 2 像素,且当前逻辑无法处理 1 像素的情况。 ```python if W < 2 or H < 2: logger.warning("分辨率过小无法裁剪 (W=%d H=%d),跳过: %s", W, H, input_path) return input_path ``` 2. **[apps/worker/video_processing/ffmpeg_utils.py:346-349] 分辨率处理逻辑与文档描述不符** - 问题类型:逻辑bug / 数据损坏风险 - 问题描述:代码在处理奇数分辨率时(如 1921x1081),会将输出分辨率强制修改为偶数(1922x1082),这与函数文档 "缩放回原分辨率" 的描述相悖。 - 原因:`out_w = W if W % 2 == 0 else W + 1`。 - 后果:对于依赖精确元数据匹配的下游系统,这会导致视频属性变更。虽然 FFmpeg 编码通常要求偶数,但简单的 `+1` 会导致轻微的画面拉伸或宽高比变化,且违背了函数承诺。 - 修改建议:修改文档字符串说明会调整为偶数分辨率,或者修改逻辑使用 `pad` 滤镜保持分辨率不变(如果业务严格要求分辨率一致)。鉴于目的是“改变 pHash”,建议修改文档字符串以如实反映行为。 ### 💡 改进建议(不阻塞合并) 1. **[apps/worker/video_processing/ffmpeg_utils.py:362] 编码参数设置过于激进** - 具体内容:使用了 `-crf 18`,这是一个非常高质量(接近无损)的设置,会导致编码速度变慢且文件体积变大。对于“降重”和“改变指纹”这一非关键任务,建议使用默认值(如 23)或稍高一点的值(如 20-23),以提升处理速度并节省存储空间。 2. **[apps/worker/video_processing/ffmpeg_utils.py:319-321, 352] 模块导入位置不规范** - 具体内容:`import random`, `import shutil`, `import tempfile` 以及 `import os` 被放置在函数内部或条件块内部。虽然 Python 允许这样做,但通常建议将所有模块导入放在文件顶部,以符合 PEP8 规范并减少重复执行的开销(尽管有缓存机制)。 ### ✅ 良好实践 - **异常处理设计得当**:在 `generation.py` 中,对 `random_edge_crop` 的异常捕获非常合理,作为非关键路径的降重功能,失败时记录日志并继续使用原始视频,不会阻塞主流程。 - **临时文件清理机制**:在 `ffmpeg_utils.py` 中,使用了 `try...except` 块确保在 FFmpeg 执行失败时清理临时文件,防止残留垃圾文件。 - **测试覆盖较全**:新增的单元测试覆盖了基本路径、参数验证、FFmpeg 命令构造及异常传播,质量较高。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-09-04 03:53:07 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot merged commit f523548eee into develop 2026-09-04 11:56:19 +08:00
auto-approve-bot deleted branch feat/random-edge-crop-1664 2026-09-04 11:56:19 +08:00

🗑️ 预览环境已清理

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

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

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