fix(P0): 一键生成接入BGM/ASR字幕/标题 - 修复模板plan config读取 #565

Merged
auto-approve-bot merged 1 commits from fix/p1-oneclick-bgm-subtitles into develop 2026-07-19 09:46:05 +08:00
2 changed files with 123 additions and 7 deletions
+18 -7
View File
@@ -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:
+105
View File
@@ -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 == {}