Files
voicebox/backend/config.py
T
James Pine 3584283d84 feat: Kokoro 82M TTS engine + voice profile type system
Add Kokoro-82M as a new TTS engine — 82M params, CPU realtime, 8 languages,
Apache 2.0. Unlike cloning engines, Kokoro uses pre-built voice styles, which
required a new profile type system to support non-cloning engines cleanly.

Kokoro engine:
- New kokoro_backend.py implementing TTSBackend protocol
- 50 built-in voices across en/es/fr/hi/it/pt/ja/zh
- KPipeline API with language-aware G2P routing via misaki
- PyInstaller bundling for misaki, language_tags, espeakng_loader, en_core_web_sm

Voice profile type system:
- New voice_type column: 'cloned' | 'preset' | 'designed' (future)
- Preset profiles store engine + voice ID instead of audio samples
- default_engine field on profiles — auto-selects engine on profile pick
- Create Voice dialog: toggle between 'Clone from audio' and 'Built-in voice'
- Edit dialog shows preset voice info instead of sample list for preset profiles
- Engine selector locks to preset engine when preset profile is selected
- Profile grid filters by engine — shows Kokoro voices when Kokoro selected
- Custom empty state when no preset profiles exist for selected engine

Bug fixes:
- Fix relative audio paths in DB causing 404s in production builds
- config.set_data_dir() now resolves to absolute paths
- Startup migration converts existing relative paths to absolute

Also updates PROJECT_STATUS.md and tts-engines.mdx developer guide.
2026-03-19 10:09:48 -07:00

79 lines
1.9 KiB
Python

"""
Configuration module for voicebox backend.
Handles data directory configuration for production bundling.
"""
import logging
import os
from pathlib import Path
logger = logging.getLogger(__name__)
# Allow users to override the HuggingFace model download directory.
# Set VOICEBOX_MODELS_DIR to an absolute path before starting the server.
# This sets HF_HUB_CACHE so all huggingface_hub downloads go to that path.
_custom_models_dir = os.environ.get("VOICEBOX_MODELS_DIR")
if _custom_models_dir:
os.environ["HF_HUB_CACHE"] = _custom_models_dir
logger.info("Model download path set to: %s", _custom_models_dir)
# Default data directory (used in development)
_data_dir = Path("data").resolve()
def set_data_dir(path: str | Path):
"""
Set the data directory path.
Args:
path: Path to the data directory
"""
global _data_dir
_data_dir = Path(path).resolve()
_data_dir.mkdir(parents=True, exist_ok=True)
logger.info("Data directory set to: %s", _data_dir)
def get_data_dir() -> Path:
"""
Get the data directory path.
Returns:
Path to the data directory
"""
return _data_dir
def get_db_path() -> Path:
"""Get database file path."""
return _data_dir / "voicebox.db"
def get_profiles_dir() -> Path:
"""Get profiles directory path."""
path = _data_dir / "profiles"
path.mkdir(parents=True, exist_ok=True)
return path
def get_generations_dir() -> Path:
"""Get generations directory path."""
path = _data_dir / "generations"
path.mkdir(parents=True, exist_ok=True)
return path
def get_cache_dir() -> Path:
"""Get cache directory path."""
path = _data_dir / "cache"
path.mkdir(parents=True, exist_ok=True)
return path
def get_models_dir() -> Path:
"""Get models directory path."""
path = _data_dir / "models"
path.mkdir(parents=True, exist_ok=True)
return path