返回 MoneyPrinterTurbo
test_subtitle_background_settings.py
根目录 / test / services / test_subtitle_background_settings.py
1 import json
2 from pathlib import Path
3 import unittest
4
5 import numpy as np
6
7 from app.models.schema import VideoParams
8 from app.services import video
9
10
11 class TestSubtitleBackgroundSettings(unittest.TestCase):
12 def test_all_locales_include_subtitle_background_labels(self):
13 """
14 WebUI 新增字幕背景开关和颜色选择器后,所有已有语言都必须包含对应
15 翻译 key,避免某些语言界面直接显示英文内部 key。
16 """
17 i18n_dir = Path(__file__).parent.parent.parent / "webui" / "i18n"
18 required_keys = {
19 "Enable Subtitle Background",
20 "Subtitle Background Color",
21 "No Voice",
22 }
23
24 for locale_file in i18n_dir.glob("*.json"):
25 with self.subTest(locale=locale_file.name):
26 data = json.loads(locale_file.read_text(encoding="utf-8"))
27 translations = data.get("Translation", {})
28 missing_keys = required_keys - translations.keys()
29
30 self.assertEqual(missing_keys, set())
31
32 def test_video_params_accepts_disabled_and_colored_subtitle_background(self):
33 """
34 UI 会根据开关向后端传递 False 或颜色字符串。这里验证 schema 仍然
35 接受这两种值,避免后续依赖或类型调整破坏 WebUI 与合成逻辑的契约。
36 """
37 base_params = {
38 "video_subject": "subtitle background smoke",
39 }
40
41 disabled_params = VideoParams(
42 **base_params,
43 text_background_color=False,
44 )
45 colored_params = VideoParams(
46 **base_params,
47 text_background_color="#123456",
48 )
49
50 self.assertFalse(disabled_params.text_background_color)
51 self.assertEqual(colored_params.text_background_color, "#123456")
52
53 def test_visible_text_position_centers_actual_mask_bounds(self):
54 """
55 TextClip 的画布会包含字体行高和 baseline 空白,直接居中画布会让
56 字幕在背景里看起来偏下。这里用一个假 mask 模拟“可见文字像素
57 在画布下半部分”的情况,验证 helper 会按真实可见区域重新计算 y。
58 """
59
60 class FakeMask:
61 def get_frame(self, _):
62 mask = np.zeros((46, 100), dtype=float)
63 mask[12:46, 10:90] = 1.0
64 return mask
65
66 class FakeTextClip:
67 w = 100
68 h = 46
69 mask = FakeMask()
70
71 x, y = video._get_visible_center_position(
72 FakeTextClip(), container_width=100, container_height=93
73 )
74
75 self.assertEqual(x, 0)
76 # 可见像素高度为 34px,放在 93px 容器中应上下各约 29px;
77 # 因为 mask 顶部从 12px 开始,所以 TextClip 本身需要向上移动到 18px。
78 self.assertEqual(y, 18)
79
80 def test_wrap_text_keeps_closing_punctuation_with_text(self):
81 """
82 中文长句按字符换行时,句号等闭合标点不能独占一行,否则字幕背景
83 会被一个单独的小点撑高。这里复现大字号中文长句的边界情况。
84 """
85 font_path = (
86 Path(__file__).parent.parent.parent
87 / "resource"
88 / "fonts"
89 / "MicrosoftYaHeiBold.ttc"
90 )
91
92 wrapped_text, _ = video.wrap_text(
93 "如果你调整字号,中文笔画也不能被黑色背景遮挡。",
94 max_width=1642,
95 font=str(font_path),
96 fontsize=72,
97 )
98
99 self.assertNotIn("\n。", wrapped_text)
100 self.assertIn("挡。", wrapped_text)
101
101 lines PYTHON