From 951184c23a75e052ebf3f184e4bd4059926c87f3 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Sun, 23 Aug 2026 15:47:12 +0800 Subject: [PATCH] =?UTF-8?q?fix(worker):=20=E4=BF=AE=E5=A4=8DEditPlan?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E8=B7=AF=E5=BE=84=E9=85=8D=E9=9F=B3=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E6=96=87=E4=BB=B6=E6=B3=84=E6=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _render_from_edit_plan 现在返回 voiceover_path,generate_video 在渲染完成、上传OSS后清理临时配音文件,避免磁盘泄漏。 新增 order=0 边界测试。 --- apps/worker/worker_app/tasks/generation.py | 15 ++++++++---- tests/unit/test_batch_clips_endpoint.py | 28 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/apps/worker/worker_app/tasks/generation.py b/apps/worker/worker_app/tasks/generation.py index da4f3773b..d0d151ab7 100644 --- a/apps/worker/worker_app/tasks/generation.py +++ b/apps/worker/worker_app/tasks/generation.py @@ -1295,7 +1295,7 @@ def _render_from_edit_plan( """从 EditPlan 数据库记录直接渲染(不再内存重建clips)。 Returns: - (output_path, render_duration, cover_candidates) + (output_path, render_duration, cover_candidates, voiceover_path) """ from video_processing.render_adapter import RenderAdapter from worker_app.db import SessionLocal @@ -1335,11 +1335,9 @@ def _render_from_edit_plan( output_path = result.output_path cover_candidates = getattr(result, "cover_candidates", None) - return output_path, result.duration, cover_candidates + return output_path, result.duration, cover_candidates, voiceover_path finally: db.close() - # 清理临时配音文件 - # voiceover_path 在外部作用域,这里不直接引用 def generate_video(self, task_id: str) -> dict: @@ -1439,7 +1437,7 @@ def generate_video(self, task_id: str) -> dict: gen_task.append_log("渲染模式", "从草稿数据渲染(与预览一致)") _flush_logs(task_id, gen_task) - output_path, render_duration, cover_candidates = _render_from_edit_plan( + output_path, render_duration, cover_candidates, voiceover_tmp_path = _render_from_edit_plan( task_id=task_id, source_edit_plan_id=source_edit_plan_id, task_info=task_info, @@ -1587,6 +1585,13 @@ def generate_video(self, task_id: str) -> dict: file_size, ) + # 清理临时配音文件 + if voiceover_tmp_path: + try: + Path(voiceover_tmp_path).unlink(missing_ok=True) + except OSError: + logger.warning("[task_id=%s] 清理临时配音文件失败: %s", task_id, voiceover_tmp_path) + return { "status": "completed", "task_id": task_id, diff --git a/tests/unit/test_batch_clips_endpoint.py b/tests/unit/test_batch_clips_endpoint.py index 83641155e..6ad3c9bea 100755 --- a/tests/unit/test_batch_clips_endpoint.py +++ b/tests/unit/test_batch_clips_endpoint.py @@ -110,6 +110,34 @@ class TestBatchUpdateClips: assert clips_data[0]["start_time"] == 0.0 assert clips_data[0]["duration"] == 3.0 + def test_batch_update_order_zero_preserved(self, mock_services): + """order=0 是合法值,不能被 or 表达式误覆盖为循环索引。""" + from app.api.routes.templates_editor.draft import batch_update_clips + from app.api.routes.templates_editor.schemas import ( + EditorClipBatchItem, + EditorClipBatchUpdateRequest, + ) + + _, plan_svc = mock_services + req = EditorClipBatchUpdateRequest( + clips=[ + EditorClipBatchItem(asset_id="a1", start_time=0.0, duration=3.0, order=0), + EditorClipBatchItem(asset_id="a2", start_time=3.0, duration=5.0, order=1), + ] + ) + + batch_update_clips( + template_id="tpl-1", + req=req, + plan_id="plan-1", + services=mock_services, + _=MagicMock(), + ) + + clips_data = plan_svc.replace_all_clips_transactional.call_args[0][1] + assert clips_data[0]["order"] == 0 + assert clips_data[1]["order"] == 1 + class TestEditorClipBatchItemValidation: """验证 schema 校验规则。"""