diff --git a/abogen/tts_backends/__init__.py b/abogen/tts_backends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/abogen/tts_backends/kokoro.py b/abogen/tts_backends/kokoro.py new file mode 100644 index 0000000..7e3ab5a --- /dev/null +++ b/abogen/tts_backends/kokoro.py @@ -0,0 +1,5 @@ +def load_numpy_kpipeline(): + import numpy as np + from kokoro import KPipeline # type: ignore[import-not-found] + + return np, KPipeline diff --git a/abogen/tts_supertonic.py b/abogen/tts_backends/supertonic.py similarity index 100% rename from abogen/tts_supertonic.py rename to abogen/tts_backends/supertonic.py diff --git a/abogen/utils.py b/abogen/utils.py index 156e9f8..9c5b875 100644 --- a/abogen/utils.py +++ b/abogen/utils.py @@ -529,13 +529,6 @@ def prevent_sleep_end(): _sleep_procs[system] = None -def load_numpy_kpipeline(): - import numpy as np - from kokoro import KPipeline # type: ignore[import-not-found] - - return np, KPipeline - - class LoadPipelineThread(Thread): def __init__(self, callback): super().__init__() @@ -543,6 +536,8 @@ class LoadPipelineThread(Thread): def run(self): try: + from abogen.tts_backends.kokoro import load_numpy_kpipeline + np_module, kpipeline_class = load_numpy_kpipeline() self.callback(np_module, kpipeline_class, None) except Exception as e: diff --git a/abogen/voice_profiles.py b/abogen/voice_profiles.py index 608b943..784b252 100644 --- a/abogen/voice_profiles.py +++ b/abogen/voice_profiles.py @@ -3,7 +3,7 @@ import os from typing import Any, Dict, Iterable, List, Tuple from abogen.constants import VOICES_INTERNAL -from abogen.tts_supertonic import DEFAULT_SUPERTONIC_VOICES +from abogen.tts_backends.supertonic import DEFAULT_SUPERTONIC_VOICES from abogen.utils import get_user_config_path diff --git a/abogen/webui/conversion_runner.py b/abogen/webui/conversion_runner.py index 5be0019..1dd6318 100644 --- a/abogen/webui/conversion_runner.py +++ b/abogen/webui/conversion_runner.py @@ -39,15 +39,15 @@ from abogen.utils import ( get_user_cache_path, get_user_output_path, load_config, - load_numpy_kpipeline, ) +from abogen.tts_backends.kokoro import load_numpy_kpipeline from abogen.tts_backend import TTSBackend from abogen.voice_cache import ensure_voice_assets from abogen.voice_formulas import extract_voice_ids, get_new_voice from abogen.voice_profiles import load_profiles, normalize_profile_entry from abogen.pronunciation_store import increment_usage from abogen.llm_client import LLMClientError -from abogen.tts_supertonic import DEFAULT_SUPERTONIC_VOICES, SupertonicPipeline +from abogen.tts_backends.supertonic import DEFAULT_SUPERTONIC_VOICES, SupertonicPipeline from .service import Job, JobStatus diff --git a/abogen/webui/debug_tts_runner.py b/abogen/webui/debug_tts_runner.py index abfab4c..06396f3 100644 --- a/abogen/webui/debug_tts_runner.py +++ b/abogen/webui/debug_tts_runner.py @@ -15,7 +15,7 @@ from abogen.normalization_settings import build_apostrophe_config from abogen.text_extractor import extract_from_path from abogen.voice_cache import ensure_voice_assets from abogen.webui.conversion_runner import SAMPLE_RATE, SPLIT_PATTERN, _select_device, _to_float32, _resolve_voice, _spec_to_voice_ids -from abogen.utils import load_numpy_kpipeline +from abogen.tts_backends.kokoro import load_numpy_kpipeline _MARKER_RE = re.compile(re.escape(MARKER_PREFIX) + r"(?P[A-Z0-9_]+)" + re.escape(MARKER_SUFFIX)) diff --git a/abogen/webui/routes/utils/preview.py b/abogen/webui/routes/utils/preview.py index 58b2391..e4573d7 100644 --- a/abogen/webui/routes/utils/preview.py +++ b/abogen/webui/routes/utils/preview.py @@ -78,7 +78,7 @@ def get_preview_pipeline(language: str, device: str) -> Any: pipeline = _preview_pipelines.get(key) if pipeline is not None: return pipeline - from abogen.utils import load_numpy_kpipeline + from abogen.tts_backends.kokoro import load_numpy_kpipeline _, KPipeline = load_numpy_kpipeline() pipeline = KPipeline(lang_code=language, repo_id="hexgrad/Kokoro-82M", device=device) @@ -137,7 +137,7 @@ def generate_preview_audio( normalized_text = source_text if provider == "supertonic": - from abogen.tts_supertonic import SupertonicPipeline + from abogen.tts_backends.supertonic import SupertonicPipeline pipeline = SupertonicPipeline(sample_rate=SAMPLE_RATE, auto_download=True, total_steps=supertonic_total_steps) segments = pipeline( diff --git a/abogen/webui/routes/utils/voice.py b/abogen/webui/routes/utils/voice.py index 3d9081a..48e34cc 100644 --- a/abogen/webui/routes/utils/voice.py +++ b/abogen/webui/routes/utils/voice.py @@ -20,7 +20,7 @@ from abogen.constants import ( VOICES_INTERNAL, ) from abogen.speaker_configs import list_configs -from abogen.utils import load_numpy_kpipeline +from abogen.tts_backends.kokoro import load_numpy_kpipeline from abogen.webui.conversion_runner import _select_device, _to_float32, SAMPLE_RATE, SPLIT_PATTERN _preview_pipeline_lock = threading.RLock() diff --git a/tests/test_preview_applies_manual_overrides.py b/tests/test_preview_applies_manual_overrides.py index 0f08512..4b61c36 100644 --- a/tests/test_preview_applies_manual_overrides.py +++ b/tests/test_preview_applies_manual_overrides.py @@ -32,7 +32,7 @@ def test_preview_applies_manual_override_before_normalization(monkeypatch): monkeypatch.setitem( __import__("sys").modules, - "abogen.tts_supertonic", + "abogen.tts_backends.supertonic", type("M", (), {"SupertonicPipeline": DummyPipeline}), ) diff --git a/tests/test_tts_supertonic_unsupported_chars.py b/tests/test_tts_supertonic_unsupported_chars.py index c08ca2c..ecb14dd 100644 --- a/tests/test_tts_supertonic_unsupported_chars.py +++ b/tests/test_tts_supertonic_unsupported_chars.py @@ -1,6 +1,6 @@ import numpy as np -from abogen.tts_supertonic import SupertonicPipeline +from abogen.tts_backends.supertonic import SupertonicPipeline class _DummyTTS: diff --git a/tests/test_voice_formula_resolution.py b/tests/test_voice_formula_resolution.py index 2bc3430..250aeb2 100644 --- a/tests/test_voice_formula_resolution.py +++ b/tests/test_voice_formula_resolution.py @@ -1,7 +1,7 @@ from __future__ import annotations from abogen.webui.conversion_runner import _resolve_voice, _supertonic_voice_from_spec -from abogen.tts_supertonic import DEFAULT_SUPERTONIC_VOICES +from abogen.tts_backends.supertonic import DEFAULT_SUPERTONIC_VOICES def test_resolve_voice_formula_without_pipeline_does_not_crash() -> None: