Spaces:
Runtime error
Runtime error
File size: 15,465 Bytes
78ff707 42b3672 78ff707 9c2862d 42b3672 9c2862d 78ff707 42b3672 78ff707 42b3672 9c2862d 42b3672 78ff707 42b3672 78ff707 9c2862d d98c95d 9c2862d 42b3672 78ff707 42b3672 d98c95d 42b3672 b5b5037 d98c95d 42b3672 d98c95d 42b3672 d98c95d 42b3672 d98c95d 42b3672 ed5e263 42b3672 9c2862d 42b3672 e22f66a 42b3672 78ff707 42b3672 78ff707 42b3672 b5b5037 42b3672 78ff707 42b3672 78ff707 42b3672 78ff707 d98c95d 42b3672 78ff707 42b3672 9c2862d 42b3672 9c2862d b5b5037 42b3672 78ff707 42b3672 78ff707 9c2862d 78ff707 9c2862d 78ff707 42b3672 78ff707 42b3672 78ff707 42b3672 78ff707 42b3672 78ff707 b5b5037 78ff707 42b3672 78ff707 d98c95d 78ff707 d98c95d 78ff707 d98c95d 78ff707 9c2862d 78ff707 ed5e263 42b3672 78ff707 d98c95d 78ff707 42b3672 78ff707 42b3672 d98c95d 78ff707 42b3672 78ff707 ed5e263 |
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 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
import gradio as gr
import torch
import os
import json
import numpy as np
from scipy import signal
import warnings
import requests
import tempfile
import shutil
from pathlib import Path
import traceback
warnings.filterwarnings("ignore")
# Imposta un seed per la riproducibilità
torch.manual_seed(42)
# Definizioni di variabili globali
MODEL_REPO = "Lorenzob/aurora-1.6b-complete" # Repository del modello
CACHE_DIR = "./model_cache" # Directory per la cache del modello
SAMPLE_RATE = 24000 # Frequenza di campionamento
# Cache per componenti del modello
processor = None
model = None
speaker_embeddings_cache = {}
def download_file(url, save_path):
"""Scarica un file da un URL"""
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
def get_speaker_embeddings(speaker_id=0):
"""Ottieni gli speaker embeddings"""
global speaker_embeddings_cache
# Correggi l'indice dello speaker (gli embeddings disponibili sono numerati da 01 a 24)
speaker_id = max(1, min(10, speaker_id + 1))
if speaker_id in speaker_embeddings_cache:
print(f"Usando embeddings in cache per speaker {speaker_id}")
return speaker_embeddings_cache[speaker_id]
try:
url = f"https://huggingface.co/datasets/Matthijs/cmu-arctic-xvectors/resolve/main/cmu_us_{speaker_id:02d}_xvector.pt"
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")
if not os.path.exists(tmp_file):
print(f"Scaricamento embeddings per speaker {speaker_id}...")
download_file(url, tmp_file)
print(f"Caricamento embeddings per speaker {speaker_id} da {tmp_file}")
speaker_embeddings = torch.load(tmp_file)
speaker_embeddings_cache[speaker_id] = speaker_embeddings
return speaker_embeddings
except Exception as e:
print(f"Errore nel caricamento embeddings per speaker {speaker_id}: {e}")
print("Utilizzo embeddings predefiniti")
default_embeddings = torch.zeros((1, 512))
speaker_embeddings_cache[speaker_id] = default_embeddings
return default_embeddings
def fix_aurora_config():
"""Scarica e corregge la configurazione di Aurora"""
config_url = f"https://huggingface.co/{MODEL_REPO}/resolve/main/config.json"
local_config_path = os.path.join(CACHE_DIR, "config.json")
# Crea la directory cache se non esiste
os.makedirs(CACHE_DIR, exist_ok=True)
try:
# Scarica il file di configurazione
print(f"Scaricamento della configurazione da {config_url}...")
download_file(config_url, local_config_path)
# Leggi il file di configurazione
with open(local_config_path, "r") as f:
config = json.load(f)
# Modifica la configurazione per SpeechT5
config["model_type"] = "speecht5"
if "architectures" not in config or not config["architectures"]:
config["architectures"] = ["SpeechT5ForTextToSpeech"]
# Salva la configurazione modificata
with open(local_config_path, "w") as f:
json.dump(config, f, indent=2)
print(f"Configurazione aggiornata salvata in {local_config_path}")
return local_config_path
except Exception as e:
print(f"Errore nella configurazione del modello: {e}")
return None
def load_aurora_model_manually():
"""Carica manualmente il modello Aurora-1.6b-complete"""
global processor, model
# Se il modello è già caricato, ritorna
if model is not None and processor is not None:
return model, processor
try:
print("🔄 Caricamento manuale del modello Aurora-1.6b-complete...")
# Prima correggi la configurazione
config_path = fix_aurora_config()
if not config_path:
raise ValueError("Impossibile correggere la configurazione del modello")
# Importa le classi dopo la correzione della configurazione
from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech
# Scarica i file del processor
processor_files = {
"tokenizer_config.json": f"https://huggingface.co/{MODEL_REPO}/resolve/main/tokenizer_config.json",
"tokenizer.json": f"https://huggingface.co/{MODEL_REPO}/resolve/main/tokenizer.json",
"special_tokens_map.json": f"https://huggingface.co/{MODEL_REPO}/resolve/main/special_tokens_map.json"
}
for filename, url in processor_files.items():
local_path = os.path.join(CACHE_DIR, filename)
if not os.path.exists(local_path):
try:
print(f"Scaricamento di {filename}...")
download_file(url, local_path)
except Exception as e:
print(f"Errore nel download di {filename}: {e}")
# Carica il processor dalla directory cache
try:
# Usa il config modificato
print("Tentativo di caricamento del processor dalla cache...")
processor = SpeechT5Processor.from_pretrained(CACHE_DIR)
print("Processor caricato con successo!")
except Exception as e:
print(f"Errore nel caricamento del processor: {e}")
# Fallback a microsoft
print("Utilizzo processor di Microsoft come fallback...")
processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")
# Scarica i pesi del modello
model_file = "model.safetensors"
model_url = f"https://huggingface.co/{MODEL_REPO}/resolve/main/{model_file}"
local_model_path = os.path.join(CACHE_DIR, model_file)
if not os.path.exists(local_model_path):
print(f"Scaricamento dei pesi del modello da {model_url}...")
download_file(model_url, local_model_path)
# Carica il modello usando il config modificato
print("Caricamento del modello con config modificato...")
model = SpeechT5ForTextToSpeech.from_pretrained(
CACHE_DIR,
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
device_map="auto"
)
print("✅ Modello e processor caricati con successo!")
return model, processor
except Exception as e:
print(f"❌ Errore nel caricamento manuale di Aurora: {e}")
traceback_str = traceback.format_exc()
print(f"Traceback completo:\n{traceback_str}")
# Se tutto fallisce, utilizza il modello Microsoft
try:
from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech
print("⚠️ Fallback al modello Microsoft...")
processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")
model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts")
print("✅ Modello Microsoft caricato come fallback")
except Exception as e2:
print(f"❌ Anche il fallback è fallito: {e2}")
raise RuntimeError("Impossibile caricare alcun modello TTS")
return model, processor
def text_to_speech(text, language="it", speaker_id=0, speed=1.0, show_log=True):
"""Converte testo in voce utilizzando Aurora-1.6b-complete"""
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 il modello e il processor
model, processor = load_aurora_model_manually()
# Controlla se stiamo usando il modello Microsoft (fallback)
is_microsoft_model = "microsoft" in str(type(model))
# Ottieni gli speaker embeddings
speaker_emb = get_speaker_embeddings(speaker_id)
if is_microsoft_model:
# Usa il modello Microsoft
if show_log:
print("Utilizzo del modello Microsoft SpeechT5 (fallback)...")
# Crea input IDs dal testo
inputs = processor(text=text, return_tensors="pt")
# Genera l'audio
with torch.no_grad():
speech = model.generate_speech(
inputs["input_ids"],
speaker_emb
)
# Imposta la frequenza di campionamento
sample_rate = 16000 # Microsoft usa 16kHz
else:
# Usa il modello Aurora
if show_log:
print("Utilizzo del modello Aurora-1.6b-complete...")
# Prepara gli input - IMPORTANTE: non includiamo 'language' che non è supportato
inputs = processor(
text=text,
return_tensors="pt"
)
# Sposta gli input sul dispositivo di calcolo
for k, v in inputs.items():
if hasattr(v, "to"):
inputs[k] = v.to(model.device)
# Sposta gli speaker embeddings sul dispositivo di calcolo
if hasattr(model, "device"):
speaker_emb = speaker_emb.to(model.device)
# Mostra i dettagli degli inputs per debug
if show_log:
print(f"Input keys: {list(inputs.keys())}")
print(f"Speaker embeddings shape: {speaker_emb.shape}")
# Genera il speech usando generate_speech
with torch.no_grad():
if show_log:
print("Chiamata a model.generate_speech()...")
speech = model.generate_speech(
inputs["input_ids"],
speaker_emb
)
# Imposta la frequenza di campionamento
sample_rate = SAMPLE_RATE
# Converti il tensore in un array numpy
speech_array = speech.cpu().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, True],
["Hello, my name is Aurora and I'm an Italian voice assistant.", "en", 1, 1.0, True],
["Hola, me llamo Aurora y soy un asistente de voz italiano.", "es", 2, 1.0, True],
["La vita è bella e il sole splende nel cielo azzurro.", "it", 3, 1.0, True],
["Mi piace viaggiare e scoprire nuove città e culture.", "it", 4, 1.2, True],
["L'intelligenza artificiale sta trasformando il modo in cui interagiamo con i computer e con il mondo che ci circonda.", "it", 5, 0.9, True]
]
# Definizione dell'interfaccia Gradio
with gr.Blocks(title="Aurora-1.6b-complete TTS Demo", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🎙️ Aurora-1.6b-complete Text-to-Speech Demo
Questa demo utilizza il modello **Aurora-1.6b-complete** per la sintesi vocale (TTS), un modello fine-tuned basato su Dia-1.6B.
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="La lingua del testo (attualmente ignorata dal modello)"
)
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=6)
# 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
- Il checkbox "Mostra log di debug" è utile per diagnosticare eventuali problemi
## 🔗 Crediti
- [Lorenzob/aurora-1.6b-complete](https://huggingface.co/Lorenzob/aurora-1.6b-complete) (modello completo)
- [nari-labs/Dia-1.6B](https://huggingface.co/nari-labs/Dia-1.6B) (modello base originale)
- [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],
)
# Precarica il modello all'avvio
print("Inizializzazione del modello Aurora-1.6b-complete...")
try:
load_aurora_model_manually()
except Exception as e:
print(f"Errore nell'inizializzazione: {e}")
# Avvia l'interfaccia
demo.launch()
|