feat: store supported voices in TTSBackendMetadata

Add voices field to TTSBackendMetadata so each backend's supported
voice list is part of its metadata rather than external constants.

- Add voices: tuple[str, ...] = () to TTSBackendMetadata
- Create _KOKORO_METADATA / _SUPERTONIC_METADATA as single source
  of truth for both metadata property and registry registration
- Update KokoroBackend.get_available_voices() to use self.metadata.voices
- Update SupertonicBackend.get_available_voices() to use self.metadata.voices
- Add tests for voices field, metadata voice content, and unified instance identity
This commit is contained in:
Artem Akymenko
2026-07-06 17:40:49 +00:00
parent b95df8f217
commit 5816feb6da
4 changed files with 234 additions and 180 deletions
+2
View File
@@ -18,11 +18,13 @@ class TTSBackendMetadata:
id: Unique backend identifier (e.g. ``"kokoro"``, ``"supertonic"``).
name: Human-readable display name.
description: Short description of the backend.
voices: Tuple of supported voice identifiers.
"""
id: str
name: str
description: str
voices: tuple[str, ...] = ()
class TTSBackend(Protocol):
+14 -17
View File
@@ -10,6 +10,16 @@ from typing import Any, Dict, Iterator, List, Optional
import numpy as np
from abogen.constants import VOICES_INTERNAL
from abogen.tts_backend import TTSBackendMetadata
_KOKORO_METADATA = TTSBackendMetadata(
id="kokoro",
name="Kokoro",
description="Kokoro TTS engine",
voices=tuple(VOICES_INTERNAL),
)
def _load_kpipeline():
"""Lazy-load Kokoro dependencies."""
@@ -39,14 +49,8 @@ class KokoroBackend:
self._lang_code = lang_code
@property
def metadata(self):
from abogen.tts_backend import TTSBackendMetadata
return TTSBackendMetadata(
id="kokoro",
name="Kokoro",
description="Kokoro TTS engine",
)
def metadata(self) -> TTSBackendMetadata:
return _KOKORO_METADATA
def __call__(
self,
@@ -89,9 +93,7 @@ class KokoroBackend:
def get_available_voices(self) -> List[str]:
"""Return known Kokoro voice identifiers."""
from abogen.constants import VOICES_INTERNAL
return list(VOICES_INTERNAL)
return list(self.metadata.voices)
def get_supported_formats(self) -> List[str]:
"""Kokoro outputs raw PCM float32 audio."""
@@ -111,14 +113,9 @@ def create_kokoro_backend(**kwargs: Any) -> KokoroBackend:
# --- Registration ---
from abogen.tts_backend import TTSBackendMetadata # noqa: E402
from abogen.tts_backend_registry import register_backend # noqa: E402
register_backend(
metadata=TTSBackendMetadata(
id="kokoro",
name="Kokoro",
description="Kokoro TTS engine",
),
metadata=_KOKORO_METADATA,
factory=create_kokoro_backend,
)
+14 -14
View File
@@ -15,6 +15,15 @@ logger = logging.getLogger(__name__)
DEFAULT_SUPERTONIC_VOICES = ("M1", "M2", "M3", "M4", "M5", "F1", "F2", "F3", "F4", "F5")
from abogen.tts_backend import TTSBackendMetadata
_SUPERTONIC_METADATA = TTSBackendMetadata(
id="supertonic",
name="SuperTonic",
description="SuperTonic TTS engine",
voices=DEFAULT_SUPERTONIC_VOICES,
)
@dataclass
class SupertonicSegment:
@@ -282,12 +291,8 @@ class SupertonicBackend:
"""
@property
def metadata(self) -> "TTSBackendMetadata":
return TTSBackendMetadata(
id="supertonic",
name="SuperTonic",
description="SuperTonic TTS engine",
)
def metadata(self) -> TTSBackendMetadata:
return _SUPERTONIC_METADATA
def __init__(self, **kwargs: Any) -> None:
self._pipeline = SupertonicPipeline(
@@ -333,7 +338,7 @@ class SupertonicBackend:
def get_available_voices(self) -> List[str]:
"""Return the list of built-in SuperTonic voice identifiers."""
return list(DEFAULT_SUPERTONIC_VOICES)
return list(self.metadata.voices)
def get_supported_formats(self) -> List[str]:
return ["wav"]
@@ -379,14 +384,9 @@ def create_supertonic_backend(**kwargs: Any) -> SupertonicBackend:
return SupertonicBackend(**kwargs)
from abogen.tts_backend import TTSBackendMetadata
from abogen.tts_backend_registry import register_backend
from abogen.tts_backend_registry import register_backend # noqa: E402
register_backend(
metadata=TTSBackendMetadata(
id="supertonic",
name="SuperTonic",
description="SuperTonic TTS engine",
),
metadata=_SUPERTONIC_METADATA,
factory=create_supertonic_backend,
)