Spaces:
Runtime error
Runtime error
File size: 10,979 Bytes
78ff707 b5b5037 9c2862d 78ff707 9c2862d b5b5037 78ff707 b5b5037 78ff707 9c2862d b5b5037 d98c95d 9c2862d b5b5037 78ff707 b5b5037 d98c95d b5b5037 d98c95d b5b5037 d98c95d b5b5037 d98c95d 9c2862d b5b5037 9c2862d b5b5037 e22f66a b5b5037 78ff707 b5b5037 78ff707 b5b5037 e22f66a b5b5037 78ff707 b5b5037 9c2862d b5b5037 78ff707 b5b5037 78ff707 d98c95d b5b5037 78ff707 b5b5037 9c2862d b5b5037 9c2862d b5b5037 9c2862d b5b5037 9c2862d b5b5037 78ff707 b5b5037 78ff707 9c2862d 78ff707 9c2862d 78ff707 b5b5037 78ff707 b5b5037 78ff707 b5b5037 78ff707 b5b5037 78ff707 b5b5037 78ff707 b5b5037 78ff707 d98c95d 78ff707 d98c95d 78ff707 d98c95d 78ff707 9c2862d 78ff707 9c2862d 78ff707 d98c95d 78ff707 b5b5037 d98c95d 78ff707 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
import gradio as gr
import torch
import os
import numpy as np
from scipy import signal
import warnings
from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech, SpeechT5HifiGan, set_seed
import requests
import tempfile
from pathlib import Path
import traceback
warnings.filterwarnings("ignore")
# Imposta un seed per la riproducibilità
set_seed(42)
# Definizioni di variabili globali
CACHE_DIR = "./model_cache" # Directory per la cache del modello
SAMPLE_RATE = 16000 # Frequenza di campionamento per il modello Microsoft
# Cache per i componenti del modello
processor = None
model = None
vocoder = None
speaker_embeddings_cache = {}
def download_file(url, save_path):
"""Scarica un file da un URL"""
try:
response = requests.get(url, stream=True)
response.raise_for_status()
os.makedirs(os.path.dirname(save_path), exist_ok=True)
with open(save_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
return save_path
except Exception as e:
print(f"Errore nel download del file: {e}")
return None
def get_correct_speaker_embeddings(speaker_id):
"""Ottieni gli speaker embeddings corretti per il modello SpeechT5"""
global speaker_embeddings_cache
# Correggi il valore di speaker_id per essere tra 1 e 10 (e non 0-9)
# poiché i file su Hugging Face sono numerati da 01 a 24
speaker_id = max(1, min(10, speaker_id + 1))
if speaker_id in speaker_embeddings_cache:
return speaker_embeddings_cache[speaker_id]
try:
# Url corretto per gli speaker embeddings
url = f"https://huggingface.co/datasets/Matthijs/cmu-arctic-xvectors/resolve/main/cmu_us_{speaker_id:02d}_xvector.pt"
# Crea un file temporaneo per gli embeddings
tmp_dir = os.path.join(CACHE_DIR, "speakers")
os.makedirs(tmp_dir, exist_ok=True)
tmp_file = os.path.join(tmp_dir, f"speaker_{speaker_id:02d}.pt")
# Scarica gli embeddings se non esistono già
if not os.path.exists(tmp_file):
print(f"Scaricamento degli speaker embeddings per lo speaker {speaker_id}...")
filepath = download_file(url, tmp_file)
if not filepath:
raise ValueError(f"Impossibile scaricare gli embeddings per lo speaker {speaker_id}")
# Carica gli embeddings
speaker_embeddings = torch.load(tmp_file)
# Memorizza gli embeddings nella cache
speaker_embeddings_cache[speaker_id] = speaker_embeddings
print(f"Speaker embeddings caricati per lo speaker {speaker_id}")
return speaker_embeddings
except Exception as e:
print(f"Errore nel caricamento degli speaker embeddings: {e}")
# Prova a utilizzare un embedding predefinito dal speaker 1
try:
fallback_id = 1
url = f"https://huggingface.co/datasets/Matthijs/cmu-arctic-xvectors/resolve/main/cmu_us_{fallback_id:02d}_xvector.pt"
tmp_file = os.path.join(tmp_dir, f"speaker_{fallback_id:02d}.pt")
if not os.path.exists(tmp_file):
download_file(url, tmp_file)
speaker_embeddings = torch.load(tmp_file)
speaker_embeddings_cache[speaker_id] = speaker_embeddings
print(f"Utilizzando speaker embeddings di fallback (speaker {fallback_id})")
return speaker_embeddings
except:
# Se tutto fallisce, crea una embedding vuota
print("Creazione di embeddings vuoti")
default_embeddings = torch.zeros((1, 512))
speaker_embeddings_cache[speaker_id] = default_embeddings
return default_embeddings
def load_tts_components():
"""Carica tutti i componenti TTS"""
global processor, model, vocoder
if processor is None or model is None or vocoder is None:
try:
print("📂 Caricamento dei componenti TTS...")
# Carica il processor, modello e vocoder
processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")
model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts")
vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan")
print("✅ Componenti TTS caricati con successo!")
return True
except Exception as e:
print(f"❌ Errore nel caricamento dei componenti TTS: {e}")
traceback_str = traceback.format_exc()
print(f"Traceback completo:\n{traceback_str}")
return False
def text_to_speech(text, language="it", speaker_id=0, speed=1.0, show_log=False):
"""Converte testo in voce utilizzando il modello TTS"""
if not text.strip():
return None, "Per favore, inserisci del testo da convertire in voce."
# Log di debug
if show_log:
print(f"Richiesta TTS ricevuta: '{text}' (Lingua: {language}, Speaker: {speaker_id}, Velocità: {speed})")
try:
# Carica i componenti se non già caricati
if not load_tts_components():
return None, "Errore nel caricamento dei componenti TTS. Riprova più tardi."
# Ottieni gli speaker embeddings
speaker_emb = get_correct_speaker_embeddings(speaker_id)
# Microsoft SpeechT5 non supporta il parametro language, quindi lo ignoriamo
if show_log:
print(f"Elaborazione del testo: '{text}'")
# Crea input IDs dal testo
inputs = processor(text=text, return_tensors="pt")
# Genera l'audio con speaker embeddings
if show_log:
print("Generazione dell'audio...")
with torch.no_grad():
# Sposta gli speaker embeddings sul dispositivo di calcolo
if hasattr(model, "device"):
speaker_emb = speaker_emb.to(model.device)
# Genera l'audio
speech = model.generate_speech(
inputs["input_ids"],
speaker_emb,
vocoder=vocoder
)
# Imposta la frequenza di campionamento
sample_rate = SAMPLE_RATE
# Converti il tensore in un array numpy
speech_array = speech.numpy()
# Applica il controllo della velocità
if speed != 1.0:
# Usa scipy.signal per ricampionare l'audio e cambiare la velocità
speech_array = signal.resample(speech_array, int(len(speech_array) / speed))
if show_log:
print(f"✅ Audio generato con successo! Lunghezza: {len(speech_array)} campioni")
return (sample_rate, speech_array), None
except Exception as e:
error_msg = f"Errore nella generazione dell'audio: {str(e)}"
traceback_str = traceback.format_exc()
detailed_error = f"{error_msg}\n\nTraceback dettagliato:\n{traceback_str}"
print(f"❌ {detailed_error}")
return None, detailed_error
# Esempi predefiniti per l'interfaccia
examples = [
["Ciao, mi chiamo Aurora e sono un assistente vocale italiano.", "it", 0, 1.0, False],
["Hello, my name is Aurora and I'm an Italian voice assistant.", "en", 1, 1.0, False],
["Hola, me llamo Aurora y soy un asistente de voz italiano.", "es", 2, 1.0, False],
["La vita è bella e il sole splende nel cielo azzurro.", "it", 3, 1.0, False],
["Mi piace viaggiare e scoprire nuove città e culture.", "it", 4, 1.2, False],
["L'intelligenza artificiale sta trasformando il modo in cui interagiamo con i computer e con il mondo che ci circonda.", "it", 5, 0.9, False]
]
# Definizione dell'interfaccia Gradio
with gr.Blocks(title="Aurora TTS Demo", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🎙️ Text-to-Speech Demo
Questa demo utilizza il modello Microsoft SpeechT5 per la sintesi vocale (TTS).
Puoi selezionare diversi stili di voce cambiando lo Speaker ID.
""")
with gr.Row():
with gr.Column(scale=2):
text_input = gr.Textbox(
label="Testo da convertire in voce",
placeholder="Inserisci qui il testo da convertire...",
lines=5,
value="Ciao, sono Aurora, un assistente vocale italiano basato su intelligenza artificiale."
)
with gr.Row():
language_input = gr.Dropdown(
choices=["it", "en", "es", "fr", "de"],
label="Lingua",
value="it",
info="Seleziona la lingua del testo (nota: il modello attuale si comporta meglio con l'inglese)"
)
speaker_input = gr.Slider(
label="Speaker ID",
value=0,
minimum=0,
maximum=9,
step=1,
info="ID dello speaker (0-9, ogni ID ha caratteristiche vocali diverse)"
)
speed_input = gr.Slider(
minimum=0.5,
maximum=1.5,
value=1.0,
step=0.1,
label="Velocità",
info="Valori più bassi = voce più lenta, valori più alti = voce più veloce"
)
debug_input = gr.Checkbox(label="Mostra log di debug", value=True)
submit_btn = gr.Button("Genera Audio", variant="primary")
with gr.Column(scale=1):
audio_output = gr.Audio(label="Audio generato", show_share_button=True)
error_output = gr.Textbox(label="Messaggi di errore", visible=True, lines=4)
# Esempi
gr.Examples(
examples=examples,
inputs=[text_input, language_input, speaker_input, speed_input, debug_input],
outputs=[audio_output, error_output],
fn=text_to_speech,
cache_examples=True,
)
# Info aggiuntive
gr.Markdown("""
## 📝 Note sull'utilizzo
- Il modello funziona meglio con frasi di lunghezza media (fino a 20-30 parole)
- Puoi cambiare lo Speaker ID per ottenere voci con caratteristiche diverse
- La velocità di generazione dipende dalle risorse disponibili sul server
## 🔗 Crediti
- [Microsoft SpeechT5](https://huggingface.co/microsoft/speecht5_tts) (modello base)
- [CMU Arctic XVectors](https://huggingface.co/datasets/Matthijs/cmu-arctic-xvectors) (speaker embeddings)
""")
# Configurazione degli eventi
submit_btn.click(
fn=text_to_speech,
inputs=[text_input, language_input, speaker_input, speed_input, debug_input],
outputs=[audio_output, error_output],
)
# Avvia l'interfaccia
demo.launch()
|