import subprocess import gradio as gr from TTS.api import TTS import os import time # Initialisation du modèle TTS tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2", gpu=False) # Dossier pour les fichiers audio générés output_folder = "output_audio" os.makedirs(output_folder, exist_ok=True) def create_project(project_name, speaker, agree): if not agree: raise gr.Error("Veuillez accepter les conditions d'utilisation.") project_folder = os.path.join(output_folder, project_name) os.makedirs(project_folder, exist_ok=True) return project_folder def generate_audio(prompt, speaker, project_folder, section_name): speaker_wav_paths = [os.path.join("examples", f) for f in os.listdir("examples") if f.startswith(speaker) and f.endswith(".wav")] if not speaker_wav_paths: raise gr.Error(f"Aucun fichier audio trouvé pour le speaker : {speaker}") output_path = os.path.join(project_folder, f"{section_name}.wav") tts.tts_to_file( text=prompt, file_path=output_path, speaker_wav=speaker_wav_paths, language="fr" ) return output_path custom_css = """ .gradio-container { font-family: 'Roboto', sans-serif; background-color: #f7f9fc; } .gr-form { background-color: white; border-radius: 15px; padding: 30px; box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); } .gr-button { background-color: #4a90e2; border: none; color: white; font-weight: bold; transition: all 0.3s ease; } .gr-button:hover { background-color: #3a7bc8; transform: translateY(-2px); } .gr-input, .gr-dropdown { border: 1px solid #e0e0e0; border-radius: 8px; padding: 10px; } .gr-checkbox { margin-top: 10px; } .gr-form > div { margin-bottom: 20px; } """ title = "🎙️ Synthèse Vocale XTTS" description = """

Bienvenue sur notre outil de synthèse vocale XTTS !

Générez une voix naturelle à partir de votre texte en français. Créez un projet et ajoutez des sections pour votre script.

""" available_speakers = list(set([f.split('_')[0] for f in os.listdir("examples") if f.endswith(".wav")])) with gr.Blocks(css=custom_css) as demo: # Étape 1 : Création du Projet gr.Markdown(f"

{title}

") gr.Markdown(description) with gr.Row(): project_name = gr.Textbox(label="Nom du projet", placeholder="Entrez le nom du projet") speaker = gr.Dropdown(label="Voix", choices=available_speakers, value=available_speakers[0] if available_speakers else None) agree = gr.Checkbox(label="J'accepte les conditions d'utilisation", value=False) create_project_btn = gr.Button("Créer le Projet", variant="primary") # Étape 2 : Gestion des Sections sections = [] def add_section(): section_name = f"Section {len(sections) + 1}" sections.append({"name": section_name, "text": ""}) return sections def remove_section(index): if index < len(sections): sections.pop(index) return sections def update_section_text(index, text): if index < len(sections): sections[index]["text"] = text return sections section_outputs = [] with gr.Column(): section_list = gr.State(value=sections) def render_sections(sections): return [gr.Row([ gr.Textbox(label=f"Texte pour {section['name']}", value=section['text'], lines=5).change(update_section_text, inputs=[sections.index(section)], outputs=None), gr.Textbox(label="Nom du fichier", value=section['name'], interactive=False), gr.Button("Régénérer", variant="secondary").click(generate_audio, inputs=[section['text'], speaker, project_folder, section['name']], outputs=[gr.Audio(label=f"Audio {section['name']}")]) ]) for section in sections] with gr.Row(): add_section_btn = gr.Button("+ Ajouter une section") remove_section_btn = gr.Button("- Supprimer la dernière section") add_section_btn.click(add_section, outputs=section_list) remove_section_btn.click(remove_section, inputs=[len(sections)-1], outputs=section_list) section_output_area = gr.Column() # Dynamically render sections with section_output_area: for section in render_sections(sections): section_output_area.append(section) demo.launch(debug=True)