From c58dbf0608dd0006f6234f890c03e6ed7b855660 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Sun, 19 Jul 2026 09:39:53 +0800 Subject: [PATCH] =?UTF-8?q?fix(P0):=20=E4=B8=80=E9=94=AE=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=8E=A5=E5=85=A5BGM/ASR=E5=AD=97=E5=B9=95/=E6=A0=87=E9=A2=98?= =?UTF-8?q?=20-=20=E4=BF=AE=E5=A4=8D=E6=A8=A1=E6=9D=BFplan=20config?= =?UTF-8?q?=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:_load_template_plan_config读取不存在的template.config字段, 实际上TemplateModel的bgm/subtitle/title配置存在三个独立字段。 修复:从title_config/subtitle_config/bgm_config三个字段 组装成plan.config格式{title, subtitle, bgm}注入到virtual_plan。 --- apps/worker/worker_app/tasks/generation.py | 25 +++-- tests/unit/test_oneclick_gen_p0_fixes.py | 105 +++++++++++++++++++++ 2 files changed, 123 insertions(+), 7 deletions(-) diff --git a/apps/worker/worker_app/tasks/generation.py b/apps/worker/worker_app/tasks/generation.py index 1a3fc6e7e..b7e40b03b 100755 --- a/apps/worker/worker_app/tasks/generation.py +++ b/apps/worker/worker_app/tasks/generation.py @@ -921,8 +921,10 @@ def _validate_template_exists(template_id: str) -> None: def _load_template_plan_config(template_id: str) -> dict: - """从模板加载 plan 级配置(BGM、字幕、滤镜等效果层)。 + """从模板加载 plan 级配置(BGM、字幕、标题等效果层)。 + TemplateModel 里 bgm_config / subtitle_config / title_config 是独立字段, + 需要组装成 plan.config 的格式({bgm, subtitle, title})后再注入。 模板不存在时返回空 dict,不阻塞主流程。 """ if not template_id: @@ -943,17 +945,26 @@ def _load_template_plan_config(template_id: str) -> dict: if template is None: logger.warning("模板不存在,跳过配置加载: template_id=%s", template_id) return {} - config = template.config or {} - if isinstance(config, str): - import json - config = json.loads(config) + # 从独立字段组装成 plan.config 格式 + plan_config: dict[str, Any] = {} + title_cfg = template.title_config or {} + subtitle_cfg = template.subtitle_config or {} + bgm_cfg = template.bgm_config or {} + + if title_cfg: + plan_config["title"] = title_cfg + if subtitle_cfg: + plan_config["subtitle"] = subtitle_cfg + if bgm_cfg: + plan_config["bgm"] = bgm_cfg + logger.info( "模板配置加载成功: template_id=%s keys=%s", template_id, - list(config.keys()), + list(plan_config.keys()), ) - return config + return plan_config finally: session.close() except Exception as e: diff --git a/tests/unit/test_oneclick_gen_p0_fixes.py b/tests/unit/test_oneclick_gen_p0_fixes.py index 1c4a3624d..6914fd7e6 100755 --- a/tests/unit/test_oneclick_gen_p0_fixes.py +++ b/tests/unit/test_oneclick_gen_p0_fixes.py @@ -408,3 +408,108 @@ class TestTemplateClipEffectMapping: result = _extract_intro_outro_from_clip_configs(clip_configs) assert result == {} + + +class TestTemplatePlanConfigLoading: + """验证从模板加载 plan 级配置(BGM、字幕、标题)的逻辑。""" + + def _mock_template( + self, + title_config=None, + subtitle_config=None, + bgm_config=None, + is_active=True, + ): + template = MagicMock() + template.id = "tmpl_001" + template.name = "Test Template" + template.is_active = is_active + template.title_config = title_config or {} + template.subtitle_config = subtitle_config or {} + template.bgm_config = bgm_config or {} + return template + + def _mock_session(self, template): + session = MagicMock() + mock_query = MagicMock() + session.query.return_value = mock_query + filter_result = MagicMock() + mock_query.filter.return_value = filter_result + filter_result.first.return_value = template + return session + + def test_load_template_config_assembles_three_fields(self): + """模板的三个独立字段正确组装成 plan.config 格式。""" + from worker_app.tasks.generation import _load_template_plan_config + + title_cfg = {"enabled": True, "text": "我的标题", "font_size": 36} + subtitle_cfg = {"enabled": True, "auto_generated": True, "language": "zh"} + bgm_cfg = {"enabled": True, "preset_id": "bgm-001", "volume": 0.5} + + template = self._mock_template( + title_config=title_cfg, + subtitle_config=subtitle_cfg, + bgm_config=bgm_cfg, + ) + session = self._mock_session(template) + + with patch("worker_app.tasks.generation.SessionLocal", return_value=session): + result = _load_template_plan_config("tmpl_001") + + assert result["title"] == title_cfg + assert result["subtitle"] == subtitle_cfg + assert result["bgm"] == bgm_cfg + + def test_load_template_config_empty_template_returns_empty(self): + """模板三个字段都为空时返回空 dict。""" + from worker_app.tasks.generation import _load_template_plan_config + + template = self._mock_template() + session = self._mock_session(template) + + with patch("worker_app.tasks.generation.SessionLocal", return_value=session): + result = _load_template_plan_config("tmpl_001") + + assert result == {} + + def test_load_template_config_only_bgm(self): + """只有 BGM 配置时只返回 bgm 字段。""" + from worker_app.tasks.generation import _load_template_plan_config + + bgm_cfg = {"enabled": True, "audio_url": "https://example.com/bgm.mp3"} + template = self._mock_template(bgm_config=bgm_cfg) + session = self._mock_session(template) + + with patch("worker_app.tasks.generation.SessionLocal", return_value=session): + result = _load_template_plan_config("tmpl_001") + + assert "bgm" in result + assert result["bgm"] == bgm_cfg + assert "title" not in result + assert "subtitle" not in result + + def test_load_template_config_empty_template_id(self): + """空 template_id 直接返回空 dict。""" + from worker_app.tasks.generation import _load_template_plan_config + + result = _load_template_plan_config("") + assert result == {} + + result = _load_template_plan_config(None) + assert result == {} + + def test_load_template_config_not_found_returns_empty(self): + """模板不存在时返回空 dict,不抛异常。""" + from worker_app.tasks.generation import _load_template_plan_config + + session = MagicMock() + mock_query = MagicMock() + session.query.return_value = mock_query + filter_result = MagicMock() + mock_query.filter.return_value = filter_result + filter_result.first.return_value = None + + with patch("worker_app.tasks.generation.SessionLocal", return_value=session): + result = _load_template_plan_config("tmpl_nonexist") + + assert result == {} -- 2.54.0