import gradio as gr import torch import os import tempfile import time from TTS.api import TTS # Global variable to store the TTS model model = None def load_model(): global model try: # Load model on first run if model is None: print("Loading XTTS model... (this may take a few minutes)") model = TTS("tts_models/multilingual/multi-dataset/xtts_v2") print("Model loaded successfully!") return True except Exception as e: print(f"Error loading model: {str(e)}") return False def clone_voice(text, audio_file, progress=gr.Progress()): """ Generate speech using XTTS with the uploaded reference audio """ if not text or not audio_file: return None, "Please provide both text and a voice sample." progress(0.1, desc="Loading model...") # Try to load the model (if not already loaded) model_loaded = load_model() if not model_loaded: return None, "Failed to load the TTS model. This might be due to memory constraints." progress(0.3, desc="Processing voice sample...") try: # Generate speech with the cloned voice progress(0.6, desc="Generating speech (this may take a while on CPU)...") # Create a temporary directory for output temp_dir = tempfile.gettempdir() output_path = os.path.join(temp_dir, "xtts_output.wav") # Use the model to generate speech start_time = time.time() model.tts_to_file( text=text, file_path=output_path, speaker_wav=audio_file, language="en" ) generation_time = time.time() - start_time progress(1.0, desc="Done!") return output_path, f"Generation completed in {generation_time:.1f} seconds." except Exception as e: error_message = str(e) if "CUDA" in error_message: return None, "CUDA error: This Space is running on CPU. Please keep your text short for better performance." elif "memory" in error_message.lower(): return None, "Memory error: The model ran out of memory. Try with shorter text or a smaller voice sample." else: return None, f"Error generating speech: {error_message}" # Create the Gradio interface with gr.Blocks(theme=gr.themes.Soft()) as demo: gr.Markdown("# XTTS Voice Cloning") gr.Markdown(""" This app uses XTTS v2 to clone a voice from a sample and generate speech with that voice. ⚠️ **CPU Warning**: This is running on a CPU, so generation may take 1-3 minutes. Keep your text short (1-2 sentences) for best results. """) with gr.Row(): with gr.Column(): text_input = gr.Textbox( label="Text to speech", placeholder="Enter text to be spoken in the cloned voice (keep it short)...", lines=3 ) audio_input = gr.Audio( label="Voice reference (5-10 second sample)", type="filepath" ) with gr.Row(): clear_btn = gr.Button("Clear") submit_btn = gr.Button("Generate", variant="primary") with gr.Column(): output_audio = gr.Audio(label="Generated Speech") output_message = gr.Textbox(label="Status") # Set up interactions submit_btn.click( fn=clone_voice, inputs=[text_input, audio_input], outputs=[output_audio, output_message] ) clear_btn.click( fn=lambda: (None, None, ""), inputs=[], outputs=[text_input, output_audio, output_message] ) gr.Markdown(""" ## Tips for better results: 1. Use a clear voice recording with minimal background noise 2. Keep the sample 5-10 seconds long 3. For faster generation, keep your text very short (1-2 sentences max) 4. Be patient! CPU generation takes time ## License This app uses the XTTS v2 model under the Coqui Public Model License for non-commercial use only. """) # Comment out the problematic line - we don't need it # demo.load(lambda: None, None, None, _js="() => {console.log('Loading model in the background...')}") # Launch the app demo.queue().launch()