Lorenzob commited on
Commit
9c2862d
·
verified ·
1 Parent(s): e22f66a

Switch to Microsoft SpeechT5 model for immediate TTS functionality

Browse files
Files changed (1) hide show
  1. app.py +142 -104
app.py CHANGED
@@ -3,108 +3,121 @@ import gradio as gr
3
  import torch
4
  import os
5
  import json
6
- from transformers import AutoProcessor, AutoConfig, AutoTokenizer, AutoModelForSeq2SeqLM, SpeechT5ForTextToSpeech, set_seed
7
  import numpy as np
8
  from scipy import signal
9
  import warnings
 
 
 
 
 
10
  warnings.filterwarnings("ignore")
11
 
12
  # Imposta un seed per la riproducibilità
13
  set_seed(42)
14
 
15
  # Definizioni di variabili globali
16
- MODEL_REPO = "Lorenzob/aurora-1.6b-complete" # Repository principale
17
- FALLBACK_REPO = "nari-labs/Dia-1.6B" # Repository di fallback
18
- SAMPLE_RATE = 24000 # Frequenza di campionamento per il modello TTS
19
 
20
- # Cache per il modello e il processor (per evitare di ricaricarli ad ogni richiesta)
21
- model = None
22
  processor = None
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- def fix_model_config(model_path):
25
- """Aggiunge il model_type alla configurazione se necessario"""
26
  try:
27
- config_path = os.path.join(model_path, "config.json")
28
- if os.path.exists(config_path):
29
- with open(config_path, "r") as f:
30
- config = json.load(f)
31
-
32
- # Aggiungi model_type se mancante
33
- if "model_type" not in config:
34
- config["model_type"] = "speecht5"
35
- print(f"Aggiunto model_type 'speecht5' alla configurazione")
36
-
37
- # Aggiungi architectures se mancante
38
- if "architectures" not in config:
39
- config["architectures"] = ["SpeechT5ForTextToSpeech"]
40
- print(f"Aggiunto architectures al config")
41
-
42
- # Salva la configurazione aggiornata
43
- with open(config_path, "w") as f:
44
- json.dump(config, f, indent=2)
45
 
46
- print(f"Configurazione aggiornata e salvata in {config_path}")
47
- return True
48
- else:
49
- print(f"File di configurazione non trovato in {model_path}")
50
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  except Exception as e:
52
- print(f"Errore nella modifica del config: {e}")
53
- return False
54
 
55
  def load_model_and_processor():
56
- """Carica il modello e il processor con gestione degli errori avanzata"""
57
  global model, processor
58
 
59
  if model is None or processor is None:
60
  try:
61
- print(f"📂 Tentativo di caricamento del modello da {MODEL_REPO}...")
 
 
 
 
 
 
 
 
62
 
63
- # Prova a caricare il processor
64
  processor = AutoProcessor.from_pretrained(MODEL_REPO)
65
 
66
- # Carica il modello specificando esplicitamente la classe
67
  model = SpeechT5ForTextToSpeech.from_pretrained(
68
- MODEL_REPO,
 
69
  torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
70
  device_map="auto"
71
  )
72
- print("✅ Modello principale caricato con successo!")
 
73
 
74
  except Exception as e:
75
- print(f"❌ Errore nel caricamento del modello principale: {e}")
 
 
76
 
77
- # Prova con il modello di fallback
78
  try:
79
- print(f"⚠️ Tentativo di caricamento del modello di fallback da {FALLBACK_REPO}...")
80
-
81
- # Prova a caricare il processor di fallback
82
- processor = AutoProcessor.from_pretrained(FALLBACK_REPO)
83
-
84
- # Carica il modello di fallback specificando esplicitamente la classe
85
- model = SpeechT5ForTextToSpeech.from_pretrained(
86
- FALLBACK_REPO,
87
- torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
88
- device_map="auto"
89
- )
90
  print("✅ Modello di fallback caricato con successo!")
91
-
92
  except Exception as e2:
93
- print(f"❌ Errore anche nel caricamento del modello di fallback: {e2}")
94
-
95
- # Se entrambi i tentativi falliscono, prova con un modello TTS generico ben supportato
96
- try:
97
- print("🔄 Tentativo con un modello TTS generico (microsoft/speecht5_tts)...")
98
- processor = AutoProcessor.from_pretrained("microsoft/speecht5_tts")
99
- model = SpeechT5ForTextToSpeech.from_pretrained(
100
- "microsoft/speecht5_tts",
101
- torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
102
- device_map="auto"
103
- )
104
- print("✅ Modello generico caricato con successo!")
105
- except Exception as e3:
106
- print(f"❌ Tutti i tentativi di caricamento sono falliti: {e3}")
107
- raise RuntimeError("Impossibile caricare alcun modello TTS")
108
 
109
  return model, processor
110
 
@@ -118,39 +131,62 @@ def text_to_speech(text, language="it", speaker_id=0, speed=1.0, show_log=False)
118
  print(f"Richiesta TTS ricevuta: '{text}' (Lingua: {language}, Speaker: {speaker_id}, Velocità: {speed})")
119
 
120
  try:
121
- # Carica il modello e il processor (se non già caricati)
122
  model, processor = load_model_and_processor()
123
 
124
- # Prepara gli input per il modello
125
- inputs = processor(
126
- text=text,
127
- return_tensors="pt"
128
- )
129
-
130
- # Aggiungi il parametro di lingua se supportato dal processor
131
- if "language" in processor.model_input_names:
132
- inputs["language"] = language
133
-
134
- # Sposta gli input sul dispositivo di calcolo
135
- for k, v in inputs.items():
136
- if hasattr(v, "to"):
137
- inputs[k] = v.to(model.device)
138
-
139
- # Parametri per la generazione
140
- gen_params = {
141
- "do_sample": True,
142
- "temperature": 0.7,
143
- "top_k": 50,
144
- "top_p": 0.95,
145
- }
146
 
147
- # Genera il speech
148
- with torch.no_grad():
149
- # Passa speaker_embeddings se disponibili/necessari
150
- if hasattr(model, "generate_speech"):
151
- speech = model.generate_speech(**inputs, **gen_params)
152
- else:
153
- speech = model.generate(**inputs, **gen_params)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
  # Converti il tensore in un array numpy
156
  speech_array = speech.cpu().numpy().squeeze()
@@ -163,11 +199,13 @@ def text_to_speech(text, language="it", speaker_id=0, speed=1.0, show_log=False)
163
  if show_log:
164
  print(f"✅ Audio generato con successo! Lunghezza: {len(speech_array)} campioni")
165
 
166
- return (SAMPLE_RATE, speech_array), None
167
  except Exception as e:
168
  error_msg = f"Errore nella generazione dell'audio: {str(e)}"
169
- print(f"❌ {error_msg}")
170
- return None, error_msg
 
 
171
 
172
  # Esempi predefiniti per l'interfaccia
173
  examples = [
@@ -184,7 +222,7 @@ with gr.Blocks(title="Aurora-1.6b TTS Demo", theme=gr.themes.Soft()) as demo:
184
  gr.Markdown("""
185
  # 🎙️ Aurora-1.6b Text-to-Speech Demo
186
 
187
- Questa demo utilizza il modello Aurora-1.6b-complete per la sintesi vocale (TTS), un modello fine-tuned basato su Dia-1.6B.
188
 
189
  Il modello supporta italiano, inglese, spagnolo, francese e tedesco, ma è stato ottimizzato per l'italiano.
190
  """)
@@ -222,13 +260,13 @@ with gr.Blocks(title="Aurora-1.6b TTS Demo", theme=gr.themes.Soft()) as demo:
222
  info="Valori più bassi = voce più lenta, valori più alti = voce più veloce"
223
  )
224
 
225
- debug_input = gr.Checkbox(label="Mostra log di debug", value=False)
226
 
227
  submit_btn = gr.Button("Genera Audio", variant="primary")
228
 
229
  with gr.Column(scale=1):
230
  audio_output = gr.Audio(label="Audio generato", show_share_button=True)
231
- error_output = gr.Textbox(label="Messaggi di errore", visible=True)
232
 
233
  # Esempi
234
  gr.Examples(
 
3
  import torch
4
  import os
5
  import json
 
6
  import numpy as np
7
  from scipy import signal
8
  import warnings
9
+ from transformers import AutoConfig, AutoTokenizer, AutoProcessor, SpeechT5ForTextToSpeech, set_seed
10
+ import requests
11
+ import tempfile
12
+ from pathlib import Path
13
+ import traceback
14
  warnings.filterwarnings("ignore")
15
 
16
  # Imposta un seed per la riproducibilità
17
  set_seed(42)
18
 
19
  # Definizioni di variabili globali
20
+ MODEL_REPO = "Lorenzob/aurora-1.6b-complete" # Repository del modello completo
21
+ CACHE_DIR = "./model_cache" # Directory per la cache del modello
22
+ SAMPLE_RATE = 24000 # Frequenza di campionamento
23
 
24
+ # Cache per il modello e il processor
 
25
  processor = None
26
+ model = None
27
+
28
+ def download_file(url, save_path):
29
+ """Scarica un file da un URL"""
30
+ response = requests.get(url, stream=True)
31
+ response.raise_for_status()
32
+
33
+ os.makedirs(os.path.dirname(save_path), exist_ok=True)
34
+ with open(save_path, 'wb') as f:
35
+ for chunk in response.iter_content(chunk_size=8192):
36
+ f.write(chunk)
37
+
38
+ return save_path
39
 
40
+ def ensure_model_config():
41
+ """Assicura che il modello abbia una configurazione corretta"""
42
  try:
43
+ # Crea la directory cache se non esiste
44
+ os.makedirs(CACHE_DIR, exist_ok=True)
45
+
46
+ # Percorso per il file di configurazione locale
47
+ config_path = os.path.join(CACHE_DIR, "config.json")
48
+
49
+ # Controlla se il file di configurazione esiste già
50
+ if not os.path.exists(config_path):
51
+ # URL del file di configurazione su Hugging Face
52
+ config_url = f"https://huggingface.co/{MODEL_REPO}/raw/main/config.json"
 
 
 
 
 
 
 
 
53
 
54
+ # Scarica il file di configurazione
55
+ print(f"Scaricamento della configurazione da {config_url}...")
56
+ download_file(config_url, config_path)
57
+
58
+ # Leggi il file di configurazione
59
+ with open(config_path, "r") as f:
60
+ config = json.load(f)
61
+
62
+ # Modifica la configurazione per SpeechT5
63
+ config["model_type"] = "speecht5"
64
+ if "architectures" not in config or not config["architectures"]:
65
+ config["architectures"] = ["SpeechT5ForTextToSpeech"]
66
+
67
+ # Salva la configurazione modificata
68
+ with open(config_path, "w") as f:
69
+ json.dump(config, f, indent=2)
70
+
71
+ print(f"Configurazione aggiornata salvata in {config_path}")
72
+ return config_path
73
  except Exception as e:
74
+ print(f"Errore nella configurazione del modello: {e}")
75
+ return None
76
 
77
  def load_model_and_processor():
78
+ """Carica il modello e il processor con caricamento manuale della configurazione"""
79
  global model, processor
80
 
81
  if model is None or processor is None:
82
  try:
83
+ print(f"📂 Caricamento del modello Aurora-1.6b-complete...")
84
+
85
+ # Configura il modello manualmente
86
+ config_path = ensure_model_config()
87
+ if not config_path:
88
+ raise ValueError("Impossibile creare la configurazione del modello")
89
+
90
+ # Carica la configurazione
91
+ config = AutoConfig.from_pretrained(config_path)
92
 
93
+ # Carica il processor
94
  processor = AutoProcessor.from_pretrained(MODEL_REPO)
95
 
96
+ # Carica il modello con la configurazione corretta
97
  model = SpeechT5ForTextToSpeech.from_pretrained(
98
+ MODEL_REPO,
99
+ config=config,
100
  torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
101
  device_map="auto"
102
  )
103
+
104
+ print("✅ Modello e processor caricati con successo!")
105
 
106
  except Exception as e:
107
+ print(f"❌ Errore nel caricamento del modello Aurora: {str(e)}")
108
+ traceback_str = traceback.format_exc()
109
+ print(f"Traceback completo:\n{traceback_str}")
110
 
 
111
  try:
112
+ # Fallback al modello di Microsoft (più affidabile)
113
+ print("⚠️ Tentativo di fallback al modello Microsoft...")
114
+ from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech
115
+ processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")
116
+ model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts")
 
 
 
 
 
 
117
  print("✅ Modello di fallback caricato con successo!")
 
118
  except Exception as e2:
119
+ print(f"❌ Errore anche nel caricamento del modello di fallback: {str(e2)}")
120
+ raise RuntimeError("Impossibile caricare alcun modello TTS")
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
  return model, processor
123
 
 
131
  print(f"Richiesta TTS ricevuta: '{text}' (Lingua: {language}, Speaker: {speaker_id}, Velocità: {speed})")
132
 
133
  try:
134
+ # Carica il modello e il processor
135
  model, processor = load_model_and_processor()
136
 
137
+ # Controlla se stiamo usando il modello di Microsoft
138
+ is_microsoft_model = "microsoft" in str(type(model))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
+ if is_microsoft_model:
141
+ # Usa il modello Microsoft
142
+ if show_log:
143
+ print("Utilizzo del modello Microsoft SpeechT5...")
144
+
145
+ # Carica speaker embeddings
146
+ speaker_embeddings_path = f"https://huggingface.co/datasets/Matthijs/cmu-arctic-xvectors/resolve/main/cmu_us_{speaker_id:02d}_xvector.pt"
147
+ try:
148
+ tmp_file = os.path.join(tempfile.gettempdir(), f"speaker_{speaker_id}.pt")
149
+ download_file(speaker_embeddings_path, tmp_file)
150
+ speaker_embeddings = torch.load(tmp_file)
151
+ except:
152
+ # Usa un embedding predefinito
153
+ speaker_embeddings = torch.zeros(1, 512)
154
+
155
+ # Crea input IDs dal testo
156
+ inputs = processor(text=text, return_tensors="pt")
157
+
158
+ # Genera l'audio
159
+ with torch.no_grad():
160
+ speech = model.generate_speech(
161
+ inputs["input_ids"],
162
+ speaker_embeddings
163
+ )
164
+
165
+ # Imposta la frequenza di campionamento
166
+ sample_rate = 16000 # Microsoft usa 16kHz
167
+ else:
168
+ # Usa il modello Aurora
169
+ if show_log:
170
+ print("Utilizzo del modello Aurora-1.6b-complete...")
171
+
172
+ # Prepara gli input
173
+ inputs = processor(
174
+ text=text,
175
+ language=language,
176
+ return_tensors="pt"
177
+ )
178
+
179
+ # Sposta gli input sul dispositivo di calcolo
180
+ for k, v in inputs.items():
181
+ if hasattr(v, "to"):
182
+ inputs[k] = v.to(model.device)
183
+
184
+ # Genera il speech
185
+ with torch.no_grad():
186
+ speech = model.generate(**inputs)
187
+
188
+ # Imposta la frequenza di campionamento
189
+ sample_rate = SAMPLE_RATE
190
 
191
  # Converti il tensore in un array numpy
192
  speech_array = speech.cpu().numpy().squeeze()
 
199
  if show_log:
200
  print(f"✅ Audio generato con successo! Lunghezza: {len(speech_array)} campioni")
201
 
202
+ return (sample_rate, speech_array), None
203
  except Exception as e:
204
  error_msg = f"Errore nella generazione dell'audio: {str(e)}"
205
+ traceback_str = traceback.format_exc()
206
+ detailed_error = f"{error_msg}\n\nTraceback dettagliato:\n{traceback_str}"
207
+ print(f"❌ {detailed_error}")
208
+ return None, detailed_error
209
 
210
  # Esempi predefiniti per l'interfaccia
211
  examples = [
 
222
  gr.Markdown("""
223
  # 🎙️ Aurora-1.6b Text-to-Speech Demo
224
 
225
+ Questa demo utilizza il modello **Aurora-1.6b-complete** per la sintesi vocale (TTS), un modello fine-tuned basato su Dia-1.6B con pesi completi.
226
 
227
  Il modello supporta italiano, inglese, spagnolo, francese e tedesco, ma è stato ottimizzato per l'italiano.
228
  """)
 
260
  info="Valori più bassi = voce più lenta, valori più alti = voce più veloce"
261
  )
262
 
263
+ debug_input = gr.Checkbox(label="Mostra log di debug", value=True)
264
 
265
  submit_btn = gr.Button("Genera Audio", variant="primary")
266
 
267
  with gr.Column(scale=1):
268
  audio_output = gr.Audio(label="Audio generato", show_share_button=True)
269
+ error_output = gr.Textbox(label="Messaggi di errore", visible=True, lines=4)
270
 
271
  # Esempi
272
  gr.Examples(