From 1157acd2ad197a992fa5db46c0c4ff1793d8d903 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 13 Aug 2026 17:31:26 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(cover):=20=E4=BF=AE=E5=A4=8D=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E8=A7=86=E9=A2=91=E5=AD=98=E5=82=A8=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=AF=BC=E8=87=B4=E5=B0=81=E9=9D=A2=E7=94=9F?= =?UTF-8?q?=E6=88=90=20500?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复两个导致封面生成 MediaKit 404 的存储路径 bug: Bug 1: 统一渲染引擎 storage_key 路径不匹配 - RenderAdapter 实际上传到 rendered/{plan_id}/{job_id}.mp4 - 但 edit_plan_generation.py 硬编码存储 rendered/{plan_id}/output.mp4 - cover.py 通过 storage_key 构造的 URL 指向不存在的文件 → 404 - 修复:从 adapter 返回的 output_url 提取实际 storage_key Bug 2: Worker _upload_and_record 双斜杠路径 - project_id 为空时(模板编辑器草稿),f'generated/projects/{project_id}/tasks/...' 产生 projects//tasks/ 双斜杠 - MediaKit HTTP 客户端规范化 URL(合并 //)→ 404 - 修复:过滤空路径段,新文件不再产生 // --- apps/worker/worker_app/tasks/edit_plan_generation.py | 10 ++++++++-- apps/worker/worker_app/tasks/generation.py | 4 +++- tests/unit/test_mediakit_cover.py | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/worker/worker_app/tasks/edit_plan_generation.py b/apps/worker/worker_app/tasks/edit_plan_generation.py index f1dd917c2..97f39ef82 100644 --- a/apps/worker/worker_app/tasks/edit_plan_generation.py +++ b/apps/worker/worker_app/tasks/edit_plan_generation.py @@ -241,9 +241,15 @@ def _render_with_unified( return {"status": "error", "message": result.error_message or "渲染失败"} output_path = result.output_path or Path("") - output_url = result.output_url + output_url = result.output_url or "" thumbnail_url = result.thumbnail_url or "" - storage_key = f"rendered/{plan_id}/output.mp4" + # adapter 上传到 rendered/{plan_id}/{job_id}.mp4,从 URL 提取实际 key + # 不能用 output.mp4 硬编码,否则 cover 等下游通过 key 构造的 URL 指向不存在的文件 + if output_url: + from packages.shared.storage import get_shared_storage_service + storage_key = get_shared_storage_service().normalize_storage_key(output_url) + else: + storage_key = f"rendered/{plan_id}/{generation_task_id or plan_id}.mp4" # 用 adapter 返回的 clip 明细(以 adapter 的结果为准) rendered_clip_ids = result.rendered_clip_ids or [] diff --git a/apps/worker/worker_app/tasks/generation.py b/apps/worker/worker_app/tasks/generation.py index 62be2f660..f641e66c6 100644 --- a/apps/worker/worker_app/tasks/generation.py +++ b/apps/worker/worker_app/tasks/generation.py @@ -1262,7 +1262,9 @@ def _upload_and_record( Returns: (file_url, duration, file_size, video_count) """ - storage_key = f"generated/projects/{project_id}/tasks/{task_id}/{output_path.name}" + # project_id 可能为空(模板编辑器草稿不属于任何项目),过滤空段避免 OSS key 出现 // + path_parts = [p for p in ("generated", "projects", project_id, "tasks", task_id, output_path.name) if p] + storage_key = "/".join(path_parts) file_size = output_path.stat().st_size # 上传 OSS diff --git a/tests/unit/test_mediakit_cover.py b/tests/unit/test_mediakit_cover.py index d48d65834..51c80eec7 100755 --- a/tests/unit/test_mediakit_cover.py +++ b/tests/unit/test_mediakit_cover.py @@ -342,3 +342,4 @@ class TestGenerateCover: assert result["type"] == "ai_frame" call_kwargs = mock_cover_service.call_args[1] assert call_kwargs["primary_video_url"] is None + -- 2.54.0 From 35d5757c13fb4b3a414e756aee6fb76e1eeefa08 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Thu, 13 Aug 2026 10:03:59 +0000 Subject: [PATCH 2/2] style: auto-format with black + isort + prettier [skip ci-format-check] --- apps/worker/worker_app/tasks/edit_plan_generation.py | 1 + tests/unit/test_mediakit_cover.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/worker/worker_app/tasks/edit_plan_generation.py b/apps/worker/worker_app/tasks/edit_plan_generation.py index 97f39ef82..729a202ce 100644 --- a/apps/worker/worker_app/tasks/edit_plan_generation.py +++ b/apps/worker/worker_app/tasks/edit_plan_generation.py @@ -247,6 +247,7 @@ def _render_with_unified( # 不能用 output.mp4 硬编码,否则 cover 等下游通过 key 构造的 URL 指向不存在的文件 if output_url: from packages.shared.storage import get_shared_storage_service + storage_key = get_shared_storage_service().normalize_storage_key(output_url) else: storage_key = f"rendered/{plan_id}/{generation_task_id or plan_id}.mp4" diff --git a/tests/unit/test_mediakit_cover.py b/tests/unit/test_mediakit_cover.py index 51c80eec7..d48d65834 100755 --- a/tests/unit/test_mediakit_cover.py +++ b/tests/unit/test_mediakit_cover.py @@ -342,4 +342,3 @@ class TestGenerateCover: assert result["type"] == "ai_frame" call_kwargs = mock_cover_service.call_args[1] assert call_kwargs["primary_video_url"] is None - -- 2.54.0