Spaces:
Runtime error
Runtime error
| 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() | |