xTTS-fr / app.py
Woziii's picture
Update app.py
eb7e5d2 verified
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)