fix(dedup): scope=user跨项目查重不做时长预过滤,同源不同时长视频可互相检出 (#1702) #1708

Merged
auto-approve-bot merged 1 commits from fix/dedup-skip-duration-prefilter-1702 into develop 2026-09-05 10:12:50 +08:00
Owner

背景

Issue #1702 主修复(#1703)及连带修复(#1705 OSS key、#1706 排除自匹配)合并后,staging 第四轮验证发现:两个同源证据视频(20s vs 11s,同镜头同人物)compute_duplicate_rate 已能正确算出 27.27% / 36.36%,但 check_duplicate 判定 is_duplicate 仍为 False。

根因

check_duplicate 的 scope=user 分支用 ±15% 时长窗口预过滤候选:

dur_min = duration_sec * 0.85
dur_max = duration_sec * 1.15
existing_videos = video_repo.list_by_user(user_id, duration_min=dur_min, duration_max=dur_max)

局部片段复用(本次核心支持场景)的两个视频时长必然不同:

  • A(20s) 窗口 [17s, 23s] → 找不到 B(11s)
  • B(11s) 窗口 [9.4s, 12.6s] → 找不到 A(20s)

同源视频互相不在候选列表中,fusion 再准也没有比对对象 → is_duplicate 恒 False。

改动

  • apps/worker/video_processing/dedup.py:scope=user 改为 list_by_user(user_id) 全量遍历同用户视频,不传 duration_min/max,与 compute_duplicate_rate 口径一致。异源视频由 fusion/temporal_coverage 阈值天然过滤(校准数据:staging 真实指纹异源最小汉明距离 24,阈值 12,安全裕度充足)。
  • tests/unit/test_duplicate_rate_scope.py:TestDurationPrefilter 重写为断言 scope=user / scope=project 均不传时长过滤参数(3 用例)。

测试

  • 查重相关全量单测:285 passed, 10 skipped
  • black/isort/ruff 全绿

验收

合并部署 staging 后重算两个证据视频,预期 A/B 均 is_duplicate=Trueduplicate_of 互相指向对方。

## 背景 Issue #1702 主修复(#1703)及连带修复(#1705 OSS key、#1706 排除自匹配)合并后,staging 第四轮验证发现:两个同源证据视频(20s vs 11s,同镜头同人物)`compute_duplicate_rate` 已能正确算出 **27.27% / 36.36%**,但 `check_duplicate` 判定 `is_duplicate` 仍为 False。 ## 根因 `check_duplicate` 的 scope=user 分支用 ±15% 时长窗口预过滤候选: ```python dur_min = duration_sec * 0.85 dur_max = duration_sec * 1.15 existing_videos = video_repo.list_by_user(user_id, duration_min=dur_min, duration_max=dur_max) ``` 局部片段复用(本次核心支持场景)的两个视频时长必然不同: - A(20s) 窗口 [17s, 23s] → 找不到 B(11s) - B(11s) 窗口 [9.4s, 12.6s] → 找不到 A(20s) 同源视频互相不在候选列表中,fusion 再准也没有比对对象 → `is_duplicate` 恒 False。 ## 改动 - `apps/worker/video_processing/dedup.py`:scope=user 改为 `list_by_user(user_id)` 全量遍历同用户视频,不传 duration_min/max,与 `compute_duplicate_rate` 口径一致。异源视频由 fusion/temporal_coverage 阈值天然过滤(校准数据:staging 真实指纹异源最小汉明距离 24,阈值 12,安全裕度充足)。 - `tests/unit/test_duplicate_rate_scope.py`:TestDurationPrefilter 重写为断言 scope=user / scope=project 均不传时长过滤参数(3 用例)。 ## 测试 - 查重相关全量单测:**285 passed, 10 skipped** - black/isort/ruff 全绿 ## 验收 合并部署 staging 后重算两个证据视频,预期 A/B 均 `is_duplicate=True` 且 `duplicate_of` 互相指向对方。
xiaoxia added 1 commit 2026-09-05 10:08:26 +08:00
fix(dedup): scope=user跨项目查重去掉±15%时长预过滤,修复同源不同时长视频互相不可见 (Issue #1702连带修复)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
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 32s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 33s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m45s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 1m45s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m47s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m48s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m13s
AI Code Review / AI Code Review (pull_request) Successful in 2m17s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 3m38s
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 / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m16s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 10s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 17s
49bdc6fd75
check_duplicate 的 scope=user 分支旧逻辑按 duration_sec*0.85~1.15
缩小候选窗口。局部片段复用场景下两个视频时长必然不同(staging 证据
视频 20s vs 11s,差 42%),±15% 窗口导致 A/B 互相不在候选列表中:
compute_duplicate_rate 能算出 27.27%/36.36%,但 is_duplicate 恒 False。

改动:
- scope=user 改为 video_repo.list_by_user(user_id) 全量遍历同用户视频,
  与 compute_duplicate_rate 口径一致;异源视频由 fusion/temporal_coverage
  阈值天然过滤(校准数据:异源最小汉明距离 24,阈值 12)
- TestDurationPrefilter 改为断言 scope=user/project 均不传时长过滤参数
- 全量查重相关单测 285 passed

🚀 预览环境已部署

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

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

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

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

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

代码审查结果 - PR #1708

⚠️ 问题(0个需要修改)

(无)

💡 建议(2个可选)

  1. apps/worker/video_processing/dedup.py 第815行:性能风险提示
    • 移除时长过滤(±15%)后,list_by_user 将全量加载该用户的所有视频数据。对于拥有大量视频(如数万条)的用户,可能会导致数据库查询耗时增加、内存占用升高以及后续指纹比对计算量激增。建议在生产环境监控该接口的耗时与内存占用,或评估是否需要增加更宽松的时长过滤(如 ±50%)或分页处理机制。
  2. tests/unit/test_dedup_1702_zero_rate_fix.py 第291行:测试断言逻辑优化
    • assert args == ("u1",) or args == () 中的 args == () 分支似乎没有必要。代码 dedup.py 中明确调用 list_by_user(user_id),即位置参数传参,Mock 记录的 args 应为 ("u1",)。保留 args == () 会掩盖参数传递方式错误的潜在 Bug(例如误改为关键字参数传参),建议删除 or args == (),使测试更严谨。

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


🤖 由 AI 代码审查机器人自动生成 | 2026-09-05 02:10:44 | 模型:

## 代码审查结果 - PR #1708 ### ⚠️ 问题(0个需要修改) (无) ### 💡 建议(2个可选) 1. **apps/worker/video_processing/dedup.py 第815行**:性能风险提示 - 移除时长过滤(±15%)后,`list_by_user` 将全量加载该用户的所有视频数据。对于拥有大量视频(如数万条)的用户,可能会导致数据库查询耗时增加、内存占用升高以及后续指纹比对计算量激增。建议在生产环境监控该接口的耗时与内存占用,或评估是否需要增加更宽松的时长过滤(如 ±50%)或分页处理机制。 2. **tests/unit/test_dedup_1702_zero_rate_fix.py 第291行**:测试断言逻辑优化 - `assert args == ("u1",) or args == ()` 中的 `args == ()` 分支似乎没有必要。代码 `dedup.py` 中明确调用 `list_by_user(user_id)`,即位置参数传参,Mock 记录的 `args` 应为 `("u1",)`。保留 `args == ()` 会掩盖参数传递方式错误的潜在 Bug(例如误改为关键字参数传参),建议删除 `or args == ()`,使测试更严谨。 --- ✅ 格式检查通过 | ✅ 逻辑审查通过 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-09-05 02:10:44 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot merged commit ca7f875224 into develop 2026-09-05 10:12:50 +08:00
auto-approve-bot deleted branch fix/dedup-skip-duration-prefilter-1702 2026-09-05 10:12:50 +08:00

🗑️ 预览环境已清理

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

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

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