feat: integrate Silero TTS as default TTS engine

- Add SileroTTS service with GPU/CPU support
- Update TTS API to support configurable engines (silero/edge)
- Add TTS_ENGINE and SILERO_SPEAKER config options
- Set Silero as default TTS engine
- Update requirements.txt with silero dependency
This commit is contained in:
Azimkin
2026-04-08 16:06:21 +02:00
parent c7d023e5ef
commit e12660db95
5 changed files with 112 additions and 4 deletions

View File

@@ -0,0 +1,87 @@
"""Silero TTS service for text-to-speech conversion."""
import os
import logging
from typing import Optional
import torch
import numpy as np
import soundfile as sf
logger = logging.getLogger(__name__)
class SileroTTSService:
"""Service for converting text to speech using Silero TTS."""
def __init__(self, device: str = 'cuda', speaker: str = 'v5_ru'):
"""
Initialize Silero TTS service.
Args:
device: Device to use ('cuda' or 'cpu')
speaker: Speaker model to use (e.g., 'v5_ru')
"""
self.device = device if torch.cuda.is_available() else 'cpu'
self.speaker = speaker
self.model = None
self._load_model()
logger.info(f"Silero TTS Service initialized with speaker: {speaker}, device: {self.device}")
def _load_model(self):
"""Load Silero TTS model."""
try:
# Import silero here to avoid loading at module level
from silero import silero_tts
self.model, _ = silero_tts(
language='ru',
speaker=self.speaker,
device=self.device
)
logger.info(f"Silero TTS model loaded successfully on {self.device}")
except Exception as e:
logger.error(f"Failed to load Silero TTS model: {e}")
raise
def text_to_speech(self, text: str, output_path: str, speed: float = 1.0) -> str:
"""
Convert text to speech and save to file.
Args:
text: Text to convert
output_path: Path to save audio file
speed: Speech speed multiplier (not supported by Silero, kept for API compatibility)
Returns:
Path to generated audio file
"""
logger.info(f"Generating TTS with Silero for text: {text[:50]}...")
try:
# Generate audio
audio = self.model.apply_tts(text=text)
# Convert to numpy array
audio_np = audio.numpy() if torch.is_tensor(audio) else np.array(audio)
# Ensure float32 format
audio_np = audio_np.astype(np.float32)
# Save as WAV (Silero uses 16000 Hz by default)
sf.write(output_path, audio_np, 16000)
logger.info(f"Silero TTS generated: {output_path}")
return output_path
except Exception as e:
logger.error(f"Silero TTS generation failed: {e}")
raise
def get_supported_voices(self) -> list:
"""Get list of supported speakers."""
# Silero Russian models
voices = [
"v5_ru", # Default Russian voice (best quality)
"v4_ru",
"v3_1_ru",
"v3_ru",
]
return voices