diff --git a/apps/worker/video_processing/dedup.py b/apps/worker/video_processing/dedup.py index a1f57b390..113908dfe 100755 --- a/apps/worker/video_processing/dedup.py +++ b/apps/worker/video_processing/dedup.py @@ -1216,9 +1216,17 @@ def check_duplicate_task(self: Task, generated_video_id: str) -> dict: raise ValueError(f"Generated video {generated_video_id} not found") local_path = os.path.join(temp_dir, f"{generated_video_id}.mp4") - storage_service.download_file( - f"projects/{video.project_id}/generated/{generated_video_id}/{generated_video_id}.mp4", local_path - ) + # Issue #1702: recompute 走的是 OSS 重新下载路径(正常生成流程用本地渲染文件, + # 不经此任务)。成片真实 OSS key 是生成时的 + # generated/projects/{pid}/tasks/{task_id}/rendered_*.mp4(见 generation.py + # _upload_and_record),旧代码硬编码 projects/{pid}/generated/{vid}/{vid}.mp4 + # 这个从不存在的 key,导致所有 recompute 任务下载 404、查重数据永远无法重算。 + # 优先从 file_url 解析真实 key,旧 key 模式仅作回退。 + download_key = getattr(video, "file_url", "") or "" + if not download_key: + download_key = f"projects/{video.project_id}/generated/{generated_video_id}/{generated_video_id}.mp4" + logger.warning("video %s has no file_url, falling back to legacy key %s", generated_video_id, download_key) + storage_service.download_file(download_key, local_path) fingerprint = deduplicator.compute_fingerprint(local_path) diff --git a/tests/unit/test_dedup_1702_zero_rate_fix.py b/tests/unit/test_dedup_1702_zero_rate_fix.py index e8d2fdafd..6ddf8eab6 100644 --- a/tests/unit/test_dedup_1702_zero_rate_fix.py +++ b/tests/unit/test_dedup_1702_zero_rate_fix.py @@ -359,3 +359,31 @@ class TestZeroMatchLogging: result = _check(ddp, fp, [existing]) assert result is None assert any("no match" in r.message for r in caplog.records) + + +# ── recompute 任务下载路径(#1702 连带修复:旧硬编码 key 404) ───── + + +class TestRecomputeDownloadPath: + """recompute-dedup 走 check_duplicate_task,需要从 OSS 重新下载成片。 + + 旧代码硬编码 projects/{pid}/generated/{vid}/{vid}.mp4(从不存在), + 真实 key 在 file_url:generated/projects/{pid}/tasks/{tid}/rendered_*.mp4。 + """ + + def test_task_downloads_from_file_url(self): + import inspect + + import video_processing.dedup as dedup_mod + + source = inspect.getsource(dedup_mod.check_duplicate_task) + # 下载 key 必须来自 video.file_url + assert 'getattr(video, "file_url"' in source or "video.file_url" in source + # 旧的硬编码 key 只能作为回退存在,不能是主路径 + assert "falling back to legacy key" in source + # download_file 接收的是派生 key 而非硬编码 f-string + assert "storage_service.download_file(download_key" in source + assert '/generated/{generated_video_id}/{generated_video_id}.mp4"' not in source.replace( + 'download_key = f"projects/{video.project_id}/generated/{generated_video_id}/{generated_video_id}.mp4"', + "", + )