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 校验规则。"""