Spaces:
Paused
Paused
| """ | |
| tts.py — Kokoro TTS wrapper for on-device voice synthesis. | |
| Kokoro is an 82M-parameter TTS model (MIT license) that runs | |
| entirely locally. It's tiny enough to keep us under the Tiny | |
| Titan threshold alongside MiniCPM 2.5B and Nemotron-Parse. | |
| Usage: | |
| from tts import generate_speech | |
| audio_path = generate_speech("Hello from your future self.") | |
| # -> returns path to a WAV file | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| import os | |
| import tempfile | |
| from typing import Optional | |
| logger = logging.getLogger(__name__) | |
| def generate_speech(text: str, voice: str = "af_heart") -> Optional[str]: | |
| """ | |
| Synthesize speech from text using Kokoro TTS. | |
| Args: | |
| text: Text to speak (max 500 chars for reliability). | |
| voice: Kokoro voice ID. Common options: | |
| "af_heart" - warm, intimate (default) | |
| "af_bella" - clear and articulate | |
| "am_adam" - steady masculine | |
| "am_mich" - warm masculine | |
| "af_sky" - soft feminine | |
| "af_nicole" - bright, energetic | |
| Returns path to generated WAV file, or None on failure. | |
| """ | |
| if not text or not text.strip(): | |
| return None | |
| try: | |
| from kokoro import KPipeline | |
| pipeline = KPipeline(lang_code="a") | |
| generator = pipeline( | |
| text.strip()[:500], | |
| voice=voice, | |
| speed=1.0, | |
| ) | |
| output_dir = tempfile.mkdtemp(prefix="futureself_tts_") | |
| output_path = os.path.join(output_dir, "transmission.wav") | |
| audio_chunks = [] | |
| for _, _, audio in generator: | |
| if audio is not None: | |
| audio_chunks.append(audio) | |
| if not audio_chunks: | |
| logger.warning("Kokoro produced no audio") | |
| return None | |
| import numpy as np | |
| import soundfile as sf | |
| combined = np.concatenate(audio_chunks) | |
| sf.write(output_path, combined, samplerate=24000) | |
| logger.info("TTS generated at %s (%d samples)", output_path, len(combined)) | |
| return output_path | |
| except ImportError: | |
| logger.warning( | |
| "kokoro not installed — install with: pip install kokoro " | |
| ) | |
| return None | |
| except Exception as exc: | |
| logger.warning("TTS failed: %s", exc) | |
| return None | |
| def get_voice_for_cast_member(cast_member: str) -> str: | |
| """Map FutureSelves cast members to Kokoro voice IDs.""" | |
| voice_map = { | |
| "future_self": "af_heart", | |
| "future_partner": "af_bella", | |
| "future_mentor": "am_adam", | |
| "future_best_friend": "af_sky", | |
| "shadow": "af_nicole", | |
| "alternate_self": "af_heart", | |
| "future_stranger": "af_nicole", | |
| "future_employee": "am_mich", | |
| "future_customer": "af_bella", | |
| "future_child": "af_sky", | |
| } | |
| return voice_map.get(cast_member, "af_heart") | |