mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 13:40:27 +02:00
refactor: migrate preview and conversion code to use TTSBackendRegistry
Migrate all preview/debug/conversion pipeline creation to use TTSBackendRegistry.create_backend() instead of direct imports: - debug_tts_runner._load_pipeline(): Kokoro via registry - preview.get_preview_pipeline(): Kokoro via registry - preview.generate_preview_audio(): Supertonic via registry - voice.get_preview_pipeline(): Kokoro via registry - conversion_runner._load_pipeline(): both backends via registry - conversion_runner inline pipeline creation: both via registry - test: update mock to target tts_backend_registry.create_backend
This commit is contained in:
@@ -40,14 +40,14 @@ from abogen.utils import (
|
|||||||
get_user_output_path,
|
get_user_output_path,
|
||||||
load_config,
|
load_config,
|
||||||
)
|
)
|
||||||
from abogen.tts_backends.kokoro import load_numpy_kpipeline
|
from abogen.tts_backend_registry import create_backend
|
||||||
from abogen.tts_backend import TTSBackend
|
from abogen.tts_backend import TTSBackend
|
||||||
from abogen.voice_cache import ensure_voice_assets
|
from abogen.voice_cache import ensure_voice_assets
|
||||||
from abogen.voice_formulas import extract_voice_ids, get_new_voice
|
from abogen.voice_formulas import extract_voice_ids, get_new_voice
|
||||||
from abogen.voice_profiles import load_profiles, normalize_profile_entry
|
from abogen.voice_profiles import load_profiles, normalize_profile_entry
|
||||||
from abogen.pronunciation_store import increment_usage
|
from abogen.pronunciation_store import increment_usage
|
||||||
from abogen.llm_client import LLMClientError
|
from abogen.llm_client import LLMClientError
|
||||||
from abogen.tts_backends.supertonic import DEFAULT_SUPERTONIC_VOICES, SupertonicPipeline
|
from abogen.tts_backends.supertonic import DEFAULT_SUPERTONIC_VOICES
|
||||||
|
|
||||||
from .service import Job, JobStatus
|
from .service import Job, JobStatus
|
||||||
|
|
||||||
@@ -1582,7 +1582,8 @@ def run_conversion_job(job: Job) -> None:
|
|||||||
return existing
|
return existing
|
||||||
|
|
||||||
if provider_norm == "supertonic":
|
if provider_norm == "supertonic":
|
||||||
pipelines[provider_norm] = SupertonicPipeline(
|
pipelines[provider_norm] = create_backend(
|
||||||
|
"supertonic",
|
||||||
sample_rate=SAMPLE_RATE,
|
sample_rate=SAMPLE_RATE,
|
||||||
auto_download=True,
|
auto_download=True,
|
||||||
total_steps=int(getattr(job, "supertonic_total_steps", 5) or 5),
|
total_steps=int(getattr(job, "supertonic_total_steps", 5) or 5),
|
||||||
@@ -1595,11 +1596,10 @@ def run_conversion_job(job: Job) -> None:
|
|||||||
device = "cpu"
|
device = "cpu"
|
||||||
if not disable_gpu:
|
if not disable_gpu:
|
||||||
device = _select_device()
|
device = _select_device()
|
||||||
_np, KPipeline = load_numpy_kpipeline()
|
|
||||||
# Create KPipeline instance directly (conforms to TTSBackend protocol)
|
# Create KPipeline instance directly (conforms to TTSBackend protocol)
|
||||||
pipelines[provider_norm] = KPipeline(
|
pipelines[provider_norm] = create_backend(
|
||||||
|
"kokoro",
|
||||||
lang_code=job.language,
|
lang_code=job.language,
|
||||||
repo_id="hexgrad/Kokoro-82M",
|
|
||||||
device=device
|
device=device
|
||||||
)
|
)
|
||||||
if not kokoro_cache_ready:
|
if not kokoro_cache_ready:
|
||||||
@@ -2443,7 +2443,8 @@ def _load_pipeline(job: Job):
|
|||||||
disable_gpu = not job.use_gpu or not cfg.get("use_gpu", True)
|
disable_gpu = not job.use_gpu or not cfg.get("use_gpu", True)
|
||||||
provider = str(getattr(job, "tts_provider", "kokoro") or "kokoro").strip().lower()
|
provider = str(getattr(job, "tts_provider", "kokoro") or "kokoro").strip().lower()
|
||||||
if provider == "supertonic":
|
if provider == "supertonic":
|
||||||
return SupertonicPipeline(
|
return create_backend(
|
||||||
|
"supertonic",
|
||||||
sample_rate=SAMPLE_RATE,
|
sample_rate=SAMPLE_RATE,
|
||||||
auto_download=True,
|
auto_download=True,
|
||||||
total_steps=int(getattr(job, "supertonic_total_steps", 5) or 5),
|
total_steps=int(getattr(job, "supertonic_total_steps", 5) or 5),
|
||||||
@@ -2452,8 +2453,7 @@ def _load_pipeline(job: Job):
|
|||||||
device = "cpu"
|
device = "cpu"
|
||||||
if not disable_gpu:
|
if not disable_gpu:
|
||||||
device = _select_device()
|
device = _select_device()
|
||||||
_np, KPipeline = load_numpy_kpipeline()
|
return create_backend("kokoro", lang_code=job.language, device=device)
|
||||||
return KPipeline(lang_code=job.language, repo_id="hexgrad/Kokoro-82M", device=device)
|
|
||||||
|
|
||||||
|
|
||||||
def _select_device() -> str:
|
def _select_device() -> str:
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from abogen.normalization_settings import build_apostrophe_config
|
|||||||
from abogen.text_extractor import extract_from_path
|
from abogen.text_extractor import extract_from_path
|
||||||
from abogen.voice_cache import ensure_voice_assets
|
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.webui.conversion_runner import SAMPLE_RATE, SPLIT_PATTERN, _select_device, _to_float32, _resolve_voice, _spec_to_voice_ids
|
||||||
from abogen.tts_backends.kokoro import load_numpy_kpipeline
|
from abogen.tts_backend_registry import create_backend
|
||||||
|
|
||||||
|
|
||||||
_MARKER_RE = re.compile(re.escape(MARKER_PREFIX) + r"(?P<code>[A-Z0-9_]+)" + re.escape(MARKER_SUFFIX))
|
_MARKER_RE = re.compile(re.escape(MARKER_PREFIX) + r"(?P<code>[A-Z0-9_]+)" + re.escape(MARKER_SUFFIX))
|
||||||
@@ -45,8 +45,7 @@ def _load_pipeline(language: str, use_gpu: bool) -> Any:
|
|||||||
device = "cpu"
|
device = "cpu"
|
||||||
if use_gpu:
|
if use_gpu:
|
||||||
device = _select_device()
|
device = _select_device()
|
||||||
_np, KPipeline = load_numpy_kpipeline()
|
return create_backend("kokoro", lang_code=language, device=device)
|
||||||
return KPipeline(lang_code=language, repo_id="hexgrad/Kokoro-82M", device=device)
|
|
||||||
|
|
||||||
|
|
||||||
def _extract_cases_from_text(text: str) -> List[Tuple[str, str]]:
|
def _extract_cases_from_text(text: str) -> List[Tuple[str, str]]:
|
||||||
|
|||||||
@@ -78,10 +78,9 @@ def get_preview_pipeline(language: str, device: str) -> Any:
|
|||||||
pipeline = _preview_pipelines.get(key)
|
pipeline = _preview_pipelines.get(key)
|
||||||
if pipeline is not None:
|
if pipeline is not None:
|
||||||
return pipeline
|
return pipeline
|
||||||
from abogen.tts_backends.kokoro import load_numpy_kpipeline
|
from abogen.tts_backend_registry import create_backend
|
||||||
|
|
||||||
_, KPipeline = load_numpy_kpipeline()
|
pipeline = create_backend("kokoro", lang_code=language, device=device)
|
||||||
pipeline = KPipeline(lang_code=language, repo_id="hexgrad/Kokoro-82M", device=device)
|
|
||||||
_preview_pipelines[key] = pipeline
|
_preview_pipelines[key] = pipeline
|
||||||
return pipeline
|
return pipeline
|
||||||
|
|
||||||
@@ -137,9 +136,9 @@ def generate_preview_audio(
|
|||||||
normalized_text = source_text
|
normalized_text = source_text
|
||||||
|
|
||||||
if provider == "supertonic":
|
if provider == "supertonic":
|
||||||
from abogen.tts_backends.supertonic import SupertonicPipeline
|
from abogen.tts_backend_registry import create_backend
|
||||||
|
|
||||||
pipeline = SupertonicPipeline(sample_rate=SAMPLE_RATE, auto_download=True, total_steps=supertonic_total_steps)
|
pipeline = create_backend("supertonic", sample_rate=SAMPLE_RATE, auto_download=True, total_steps=supertonic_total_steps)
|
||||||
segments = pipeline(
|
segments = pipeline(
|
||||||
normalized_text,
|
normalized_text,
|
||||||
voice=voice_spec,
|
voice=voice_spec,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from abogen.constants import (
|
|||||||
VOICES_INTERNAL,
|
VOICES_INTERNAL,
|
||||||
)
|
)
|
||||||
from abogen.speaker_configs import list_configs
|
from abogen.speaker_configs import list_configs
|
||||||
from abogen.tts_backends.kokoro import load_numpy_kpipeline
|
from abogen.tts_backend_registry import create_backend
|
||||||
from abogen.webui.conversion_runner import _select_device, _to_float32, SAMPLE_RATE, SPLIT_PATTERN
|
from abogen.webui.conversion_runner import _select_device, _to_float32, SAMPLE_RATE, SPLIT_PATTERN
|
||||||
|
|
||||||
_preview_pipeline_lock = threading.RLock()
|
_preview_pipeline_lock = threading.RLock()
|
||||||
@@ -741,8 +741,7 @@ def get_preview_pipeline(language: str, device: str):
|
|||||||
pipeline = _preview_pipelines.get(key)
|
pipeline = _preview_pipelines.get(key)
|
||||||
if pipeline is not None:
|
if pipeline is not None:
|
||||||
return pipeline
|
return pipeline
|
||||||
_, KPipeline = load_numpy_kpipeline()
|
pipeline = create_backend("kokoro", lang_code=language, device=device)
|
||||||
pipeline = KPipeline(lang_code=language, repo_id="hexgrad/Kokoro-82M", device=device)
|
|
||||||
_preview_pipelines[key] = pipeline
|
_preview_pipelines[key] = pipeline
|
||||||
return pipeline
|
return pipeline
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ def test_preview_applies_manual_override_before_normalization(monkeypatch):
|
|||||||
|
|
||||||
# And stub the kokoro pipeline path so generate_preview_audio won't proceed.
|
# And stub the kokoro pipeline path so generate_preview_audio won't proceed.
|
||||||
# We'll instead validate by calling the override logic through generate_preview_audio
|
# We'll instead validate by calling the override logic through generate_preview_audio
|
||||||
# with provider=supertonic and stub SupertonicPipeline to capture input.
|
# with provider=supertonic and stub create_backend to capture input.
|
||||||
captured = {}
|
captured = {}
|
||||||
|
|
||||||
class DummyPipeline:
|
class DummyPipeline:
|
||||||
@@ -30,11 +30,16 @@ def test_preview_applies_manual_override_before_normalization(monkeypatch):
|
|||||||
captured["text"] = text
|
captured["text"] = text
|
||||||
return iter(())
|
return iter(())
|
||||||
|
|
||||||
monkeypatch.setitem(
|
from abogen import tts_backend_registry
|
||||||
__import__("sys").modules,
|
|
||||||
"abogen.tts_backends.supertonic",
|
original_create_backend = tts_backend_registry.create_backend
|
||||||
type("M", (), {"SupertonicPipeline": DummyPipeline}),
|
|
||||||
)
|
def _mock_create_backend(backend_id, **kwargs):
|
||||||
|
if backend_id == "supertonic":
|
||||||
|
return DummyPipeline(**kwargs)
|
||||||
|
return original_create_backend(backend_id, **kwargs)
|
||||||
|
|
||||||
|
monkeypatch.setattr(tts_backend_registry, "create_backend", _mock_create_backend)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
preview.generate_preview_audio(
|
preview.generate_preview_audio(
|
||||||
|
|||||||
Reference in New Issue
Block a user