diff --git a/requirements.txt b/requirements.txt index 8f703ba..ff2799e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,7 @@ coqui-tts[languages] # Silero TTS - actively maintained, small efficient models # Note: Silero models are loaded via torch.hub, no package install needed # Models: ~50-100MB each, CPU-friendly, real-time capable +omegaconf # Required by Silero TTS # Chatterbox - emotion control, 23 languages (Resemble AI) # Install from git since no PyPI package exists yet # 🦝 RACCOON NOTE: Disabled due to dependency conflict with Coqui TTS diff --git a/speech.py b/speech.py index 9589ecb..9e26b74 100755 --- a/speech.py +++ b/speech.py @@ -113,35 +113,59 @@ class xtts_wrapper(): self.last_used = time.time() class silero_wrapper(): - """Wrapper for Silero TTS models""" - def __init__(self, language='en', speaker='v4_en', device='cpu'): + """Wrapper for Silero TTS models + + Silero torch.hub.load returns: (model, example_text) + The model has a method apply_tts(text, speaker, sample_rate) + """ + def __init__(self, language='en', speaker='v3_en', device='cpu'): self.language = language self.speaker = speaker self.device = device - logger.info(f"Loading Silero model for {language} on {device}") + logger.info(f"Loading Silero model for {language} with speaker {speaker} on {device}") import torch - self.model, self.symbols, self.sample_rate, self.example_text, self.apply_tts = torch.hub.load( - repo_or_dir='snakers4/silero-models', - model='silero_tts', - language=language, - speaker=speaker - ) - self.model = self.model.to(device) + try: + # torch.hub.load returns (model, example_text) + self.model, example_text = torch.hub.load( + repo_or_dir='snakers4/silero-models', + model='silero_tts', + language=language, + speaker=speaker, + verbose=False + ) - def tts(self, text, speaker_id='en_0'): + logger.info(f"Model loaded, type: {type(self.model)}") + self.model.to(device) # Move to device (in-place for Silero) + self.sample_rate = 48000 # Silero uses 48kHz + logger.info(f"Successfully loaded Silero {language}/{speaker}, example: {example_text}") + except Exception as e: + logger.error(f"Failed to load Silero model: {e}") + raise + + def tts(self, text, speaker_id='lj_16khz'): """Generate speech from text""" import torch + + logger.info(f"Silero tts() called: model={self.model}, speaker_id={speaker_id}") + + if self.model is None: + raise RuntimeError("Silero model is None - model failed to load") + + if not hasattr(self.model, 'apply_tts'): + logger.error(f"Model has no apply_tts method. Model type: {type(self.model)}, dir: {dir(self.model)}") + raise AttributeError(f"Silero model {type(self.model)} has no apply_tts method") + with torch.no_grad(): - audio = self.apply_tts( + # Use model's apply_tts method + audio = self.model.apply_tts( text=text, speaker=speaker_id, sample_rate=self.sample_rate ) - # Convert to float32 PCM - audio_np = audio.cpu().numpy() - return audio_np.tobytes() + # audio is a tensor, convert to numpy float32 + return audio.cpu().numpy().tobytes() def default_exists(filename: str): if not os.path.exists(filename): diff --git a/voice_to_speaker.default.yaml b/voice_to_speaker.default.yaml index 3eac7cf..58bef45 100644 --- a/voice_to_speaker.default.yaml +++ b/voice_to_speaker.default.yaml @@ -58,27 +58,601 @@ tts-1-hd: top_p: 0.85 comment: You can add a comment here also, which will be persistent and otherwise ignored. tts-1-silero: + # OpenAI-compatible voice aliases (for compatibility) alloy: language: en speaker: en_0 - silero_speaker: v4_en + silero_speaker: v3_en echo: language: en speaker: en_1 - silero_speaker: v4_en + silero_speaker: v3_en fable: language: en speaker: en_2 - silero_speaker: v4_en + silero_speaker: v3_en onyx: language: en speaker: en_3 - silero_speaker: v4_en + silero_speaker: v3_en nova: language: en speaker: en_4 - silero_speaker: v4_en + silero_speaker: v3_en shimmer: language: en speaker: en_5 - silero_speaker: v4_en \ No newline at end of file + silero_speaker: v3_en + # All 118 Silero v3_en voices with proper names + en_0: + language: en + speaker: en_0 + silero_speaker: v3_en + en_1: + language: en + speaker: en_1 + silero_speaker: v3_en + en_2: + language: en + speaker: en_2 + silero_speaker: v3_en + en_3: + language: en + speaker: en_3 + silero_speaker: v3_en + en_4: + language: en + speaker: en_4 + silero_speaker: v3_en + en_5: + language: en + speaker: en_5 + silero_speaker: v3_en + en_6: + language: en + speaker: en_6 + silero_speaker: v3_en + en_7: + language: en + speaker: en_7 + silero_speaker: v3_en + en_8: + language: en + speaker: en_8 + silero_speaker: v3_en + en_9: + language: en + speaker: en_9 + silero_speaker: v3_en + en_10: + language: en + speaker: en_10 + silero_speaker: v3_en + en_11: + language: en + speaker: en_11 + silero_speaker: v3_en + en_12: + language: en + speaker: en_12 + silero_speaker: v3_en + en_13: + language: en + speaker: en_13 + silero_speaker: v3_en + en_14: + language: en + speaker: en_14 + silero_speaker: v3_en + en_15: + language: en + speaker: en_15 + silero_speaker: v3_en + en_16: + language: en + speaker: en_16 + silero_speaker: v3_en + en_17: + language: en + speaker: en_17 + silero_speaker: v3_en + en_18: + language: en + speaker: en_18 + silero_speaker: v3_en + en_19: + language: en + speaker: en_19 + silero_speaker: v3_en + en_20: + language: en + speaker: en_20 + silero_speaker: v3_en + en_21: + language: en + speaker: en_21 + silero_speaker: v3_en + en_22: + language: en + speaker: en_22 + silero_speaker: v3_en + en_23: + language: en + speaker: en_23 + silero_speaker: v3_en + en_24: + language: en + speaker: en_24 + silero_speaker: v3_en + en_25: + language: en + speaker: en_25 + silero_speaker: v3_en + en_26: + language: en + speaker: en_26 + silero_speaker: v3_en + en_27: + language: en + speaker: en_27 + silero_speaker: v3_en + en_28: + language: en + speaker: en_28 + silero_speaker: v3_en + en_29: + language: en + speaker: en_29 + silero_speaker: v3_en + en_30: + language: en + speaker: en_30 + silero_speaker: v3_en + en_31: + language: en + speaker: en_31 + silero_speaker: v3_en + en_32: + language: en + speaker: en_32 + silero_speaker: v3_en + en_33: + language: en + speaker: en_33 + silero_speaker: v3_en + en_34: + language: en + speaker: en_34 + silero_speaker: v3_en + en_35: + language: en + speaker: en_35 + silero_speaker: v3_en + en_36: + language: en + speaker: en_36 + silero_speaker: v3_en + en_37: + language: en + speaker: en_37 + silero_speaker: v3_en + en_38: + language: en + speaker: en_38 + silero_speaker: v3_en + en_39: + language: en + speaker: en_39 + silero_speaker: v3_en + en_40: + language: en + speaker: en_40 + silero_speaker: v3_en + en_41: + language: en + speaker: en_41 + silero_speaker: v3_en + en_42: + language: en + speaker: en_42 + silero_speaker: v3_en + en_43: + language: en + speaker: en_43 + silero_speaker: v3_en + en_44: + language: en + speaker: en_44 + silero_speaker: v3_en + en_45: + language: en + speaker: en_45 + silero_speaker: v3_en + en_46: + language: en + speaker: en_46 + silero_speaker: v3_en + en_47: + language: en + speaker: en_47 + silero_speaker: v3_en + en_48: + language: en + speaker: en_48 + silero_speaker: v3_en + en_49: + language: en + speaker: en_49 + silero_speaker: v3_en + en_50: + language: en + speaker: en_50 + silero_speaker: v3_en + en_51: + language: en + speaker: en_51 + silero_speaker: v3_en + en_52: + language: en + speaker: en_52 + silero_speaker: v3_en + en_53: + language: en + speaker: en_53 + silero_speaker: v3_en + en_54: + language: en + speaker: en_54 + silero_speaker: v3_en + en_55: + language: en + speaker: en_55 + silero_speaker: v3_en + en_56: + language: en + speaker: en_56 + silero_speaker: v3_en + en_57: + language: en + speaker: en_57 + silero_speaker: v3_en + en_58: + language: en + speaker: en_58 + silero_speaker: v3_en + en_59: + language: en + speaker: en_59 + silero_speaker: v3_en + en_60: + language: en + speaker: en_60 + silero_speaker: v3_en + en_61: + language: en + speaker: en_61 + silero_speaker: v3_en + en_62: + language: en + speaker: en_62 + silero_speaker: v3_en + en_63: + language: en + speaker: en_63 + silero_speaker: v3_en + en_64: + language: en + speaker: en_64 + silero_speaker: v3_en + en_65: + language: en + speaker: en_65 + silero_speaker: v3_en + en_66: + language: en + speaker: en_66 + silero_speaker: v3_en + en_67: + language: en + speaker: en_67 + silero_speaker: v3_en + en_68: + language: en + speaker: en_68 + silero_speaker: v3_en + en_69: + language: en + speaker: en_69 + silero_speaker: v3_en + en_70: + language: en + speaker: en_70 + silero_speaker: v3_en + en_71: + language: en + speaker: en_71 + silero_speaker: v3_en + en_72: + language: en + speaker: en_72 + silero_speaker: v3_en + en_73: + language: en + speaker: en_73 + silero_speaker: v3_en + en_74: + language: en + speaker: en_74 + silero_speaker: v3_en + en_75: + language: en + speaker: en_75 + silero_speaker: v3_en + en_76: + language: en + speaker: en_76 + silero_speaker: v3_en + en_77: + language: en + speaker: en_77 + silero_speaker: v3_en + en_78: + language: en + speaker: en_78 + silero_speaker: v3_en + en_79: + language: en + speaker: en_79 + silero_speaker: v3_en + en_80: + language: en + speaker: en_80 + silero_speaker: v3_en + en_81: + language: en + speaker: en_81 + silero_speaker: v3_en + en_82: + language: en + speaker: en_82 + silero_speaker: v3_en + en_83: + language: en + speaker: en_83 + silero_speaker: v3_en + en_84: + language: en + speaker: en_84 + silero_speaker: v3_en + en_85: + language: en + speaker: en_85 + silero_speaker: v3_en + en_86: + language: en + speaker: en_86 + silero_speaker: v3_en + en_87: + language: en + speaker: en_87 + silero_speaker: v3_en + en_88: + language: en + speaker: en_88 + silero_speaker: v3_en + en_89: + language: en + speaker: en_89 + silero_speaker: v3_en + en_90: + language: en + speaker: en_90 + silero_speaker: v3_en + en_91: + language: en + speaker: en_91 + silero_speaker: v3_en + en_92: + language: en + speaker: en_92 + silero_speaker: v3_en + en_93: + language: en + speaker: en_93 + silero_speaker: v3_en + en_94: + language: en + speaker: en_94 + silero_speaker: v3_en + en_95: + language: en + speaker: en_95 + silero_speaker: v3_en + en_96: + language: en + speaker: en_96 + silero_speaker: v3_en + en_97: + language: en + speaker: en_97 + silero_speaker: v3_en + en_98: + language: en + speaker: en_98 + silero_speaker: v3_en + en_99: + language: en + speaker: en_99 + silero_speaker: v3_en + en_100: + language: en + speaker: en_100 + silero_speaker: v3_en + en_101: + language: en + speaker: en_101 + silero_speaker: v3_en + en_102: + language: en + speaker: en_102 + silero_speaker: v3_en + en_103: + language: en + speaker: en_103 + silero_speaker: v3_en + en_104: + language: en + speaker: en_104 + silero_speaker: v3_en + en_105: + language: en + speaker: en_105 + silero_speaker: v3_en + en_106: + language: en + speaker: en_106 + silero_speaker: v3_en + en_107: + language: en + speaker: en_107 + silero_speaker: v3_en + en_108: + language: en + speaker: en_108 + silero_speaker: v3_en + en_109: + language: en + speaker: en_109 + silero_speaker: v3_en + en_110: + language: en + speaker: en_110 + silero_speaker: v3_en + en_111: + language: en + speaker: en_111 + silero_speaker: v3_en + en_112: + language: en + speaker: en_112 + silero_speaker: v3_en + en_113: + language: en + speaker: en_113 + silero_speaker: v3_en + en_114: + language: en + speaker: en_114 + silero_speaker: v3_en + en_115: + language: en + speaker: en_115 + silero_speaker: v3_en + en_116: + language: en + speaker: en_116 + silero_speaker: v3_en + en_117: + language: en + speaker: en_117 + silero_speaker: v3_en + random: + language: en + speaker: random + silero_speaker: v3_en + # Russian voices (v4_ru model) + ru_aidar: + language: ru + speaker: aidar + silero_speaker: v4_ru + ru_baya: + language: ru + speaker: baya + silero_speaker: v4_ru + ru_kseniya: + language: ru + speaker: kseniya + silero_speaker: v4_ru + ru_xenia: + language: ru + speaker: xenia + silero_speaker: v4_ru + ru_eugene: + language: ru + speaker: eugene + silero_speaker: v4_ru + ru_random: + language: ru + speaker: random + silero_speaker: v4_ru + # German voices (v3_de model) + de_bernd_ungerer: + language: de + speaker: bernd_ungerer + silero_speaker: v3_de + de_eva_k: + language: de + speaker: eva_k + silero_speaker: v3_de + de_friedrich: + language: de + speaker: friedrich + silero_speaker: v3_de + de_hokuspokus: + language: de + speaker: hokuspokus + silero_speaker: v3_de + de_karlsson: + language: de + speaker: karlsson + silero_speaker: v3_de + de_random: + language: de + speaker: random + silero_speaker: v3_de + # Spanish voices (v1_es model) + es_0: + language: es + speaker: es_0 + silero_speaker: v1_es + es_1: + language: es + speaker: es_1 + silero_speaker: v1_es + es_2: + language: es + speaker: es_2 + silero_speaker: v1_es + es_random: + language: es + speaker: random + silero_speaker: v1_es + # French voices (v3_fr model) + fr_0: + language: fr + speaker: fr_0 + silero_speaker: v3_fr + fr_1: + language: fr + speaker: fr_1 + silero_speaker: v3_fr + fr_2: + language: fr + speaker: fr_2 + silero_speaker: v3_fr + fr_3: + language: fr + speaker: fr_3 + silero_speaker: v3_fr + fr_4: + language: fr + speaker: fr_4 + silero_speaker: v3_fr + fr_5: + language: fr + speaker: fr_5 + silero_speaker: v3_fr + fr_random: + language: fr + speaker: random + silero_speaker: v3_fr \ No newline at end of file