main
py 114 lines 3.12 KB
Raw
1 from __future__ import annotations
2
3 import asyncio
4 from pathlib import Path
5
6 from plugins._kokoro_tts.helpers import runtime
7
8
9 PROJECT_ROOT = Path(__file__).resolve().parents[1]
10
11
12 def test_config_keeps_legacy_voice_and_normalizes_weighted_blends() -> None:
13 legacy = runtime.normalize_config(
14 {"voice": "custom/voice.pt", "speed": 2.2}
15 )
16 assert legacy == {
17 "voice": "custom/voice.pt",
18 "voice_weights": {},
19 "speed": 2.2,
20 }
21
22 weighted = runtime.normalize_config(
23 {
24 "voice": "ignored_when_weights_are_present",
25 "voice_weights": {
26 "af_heart": "3",
27 "am_puck": 1,
28 "../bad.pt": 5,
29 "am_onyx": float("nan"),
30 "am_echo": 0,
31 },
32 "speed": float("inf"),
33 }
34 )
35 assert weighted == {
36 "voice": "af_heart,am_puck",
37 "voice_weights": {"af_heart": 3.0, "am_puck": 1.0},
38 "speed": 1.1,
39 }
40
41
42 def test_weighted_blend_reuses_the_existing_pipeline() -> None:
43 class FakePipeline:
44 packs = {"af_heart": 2.0, "am_puck": 10.0}
45
46 def __init__(self) -> None:
47 self.loaded: list[str] = []
48
49 def load_single_voice(self, voice: str) -> float:
50 self.loaded.append(voice)
51 return self.packs[voice]
52
53 pipeline = FakePipeline()
54 blend = runtime._resolve_voice(
55 pipeline,
56 "legacy",
57 {"af_heart": 3.0, "am_puck": 1.0},
58 )
59
60 assert blend == 4.0
61 assert pipeline.loaded == ["af_heart", "am_puck"]
62 assert runtime._resolve_voice(pipeline, "am_puck,am_onyx", {}) == (
63 "am_puck,am_onyx"
64 )
65
66
67 def test_synthesis_forwards_normalized_weights(monkeypatch) -> None:
68 captured: dict = {}
69
70 async def fake_synthesize(sentences, **kwargs):
71 captured.update({"sentences": sentences, **kwargs})
72 return "audio"
73
74 monkeypatch.setattr(runtime, "_synthesize_sentences", fake_synthesize)
75
76 result = asyncio.run(
77 runtime.synthesize_sentences(
78 ["Hello"],
79 {
80 "voice": "legacy",
81 "voice_weights": {"af_heart": 2, "am_puck": 1},
82 "speed": 1.4,
83 },
84 )
85 )
86
87 assert result == "audio"
88 assert captured == {
89 "sentences": ["Hello"],
90 "voice": "af_heart,am_puck",
91 "voice_weights": {"af_heart": 2.0, "am_puck": 1.0},
92 "speed": 1.4,
93 }
94
95
96 def test_settings_expose_catalog_weights_and_speed_without_disk_blends() -> None:
97 config_ui = (
98 PROJECT_ROOT / "plugins/_kokoro_tts/webui/config.html"
99 ).read_text(encoding="utf-8")
100 store = (
101 PROJECT_ROOT / "plugins/_kokoro_tts/webui/kokoro-tts-store.js"
102 ).read_text(encoding="utf-8")
103
104 assert "af_heart" in config_ui
105 assert "am_puck" in config_ui
106 assert "am_onyx" in config_ui
107 assert "config.voice_weights" in config_ui
108 assert "Use equal weights" in config_ui
109 assert 'type="range"' in config_ui
110 assert 'min="0.5"' in config_ui
111 assert 'max="3"' in config_ui
112 assert "create_blend" not in config_ui
113 assert "lang_code" not in config_ui
114 assert "voiceSummary" in store