|
import subprocess |
|
import gradio as gr |
|
from TTS.api import TTS |
|
import os |
|
import time |
|
import torch |
|
|
|
|
|
tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2", gpu=True) |
|
|
|
output_folder = "output_audio" |
|
os.makedirs(output_folder, exist_ok=True) |
|
|
|
def predict(prompt, speaker, agree, subfolder_name, file_name): |
|
if not agree: |
|
raise gr.Error("Veuillez accepter les conditions d'utilisation.") |
|
|
|
subfolder_name = subfolder_name.strip() or f"session_{int(time.time())}" |
|
session_folder = os.path.join(output_folder, subfolder_name) |
|
os.makedirs(session_folder, exist_ok=True) |
|
|
|
file_name = file_name.strip() or "output.wav" |
|
if not file_name.endswith(".wav"): |
|
file_name += ".wav" |
|
output_path = os.path.join(session_folder, file_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}") |
|
|
|
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 = """ |
|
<h3 style='text-align: center; margin-bottom: 1em;'>Bienvenue sur notre outil de synthèse vocale XTTS !</h3> |
|
<p style='text-align: center;'>Générez une voix naturelle à partir de votre texte en français. Choisissez une voix, entrez votre texte, et écoutez le résultat !</p> |
|
""" |
|
article = """ |
|
<div style='margin: 20px auto; text-align: center; padding: 10px; background-color: #e8f0fe; border-radius: 10px;'> |
|
<p>En utilisant cette démo, vous acceptez les <a href='https://coqui.ai/cpml' target='_blank' style='color: #4a90e2; text-decoration: none;'>conditions d'utilisation du modèle Coqui Public</a></p> |
|
</div> |
|
""" |
|
|
|
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: |
|
gr.Markdown(f"<h1 style='text-align: center; color: #4a90e2;'>{title}</h1>") |
|
gr.Markdown(description) |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
prompt = gr.Textbox( |
|
label="Texte pour la synthèse vocale", |
|
info="Une ou deux phrases à la fois sont préférables (max : 10)", |
|
placeholder="Bonjour ! Comment allez-vous aujourd'hui ?", |
|
lines=5 |
|
) |
|
with gr.Column(scale=1): |
|
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 |
|
) |
|
subfolder_name = gr.Textbox( |
|
label="Nom du sous-dossier (facultatif)", |
|
placeholder="Nom du sous-dossier pour stocker l'audio" |
|
) |
|
file_name = gr.Textbox( |
|
label="Nom du fichier (facultatif)", |
|
placeholder="Nom du fichier audio généré" |
|
) |
|
|
|
generate_btn = gr.Button("Générer la voix", variant="primary") |
|
audio_output = gr.Audio(label="Audio généré") |
|
|
|
generate_btn.click( |
|
predict, |
|
inputs=[prompt, speaker, agree, subfolder_name, file_name], |
|
outputs=[audio_output] |
|
) |
|
|
|
gr.Markdown(article) |
|
|
|
demo.launch(debug=True) |