Woziii commited on
Commit
163771f
·
verified ·
1 Parent(s): 9bf10fe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +132 -121
app.py CHANGED
@@ -1,138 +1,149 @@
1
  import subprocess
 
2
  import gradio as gr
3
  from TTS.api import TTS
4
- import os
5
- import time
6
 
7
- # Initialisation du modèle TTS
8
  tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2", gpu=False)
9
 
10
- # Dossier pour les fichiers audio générés
11
  output_folder = "output_audio"
12
  os.makedirs(output_folder, exist_ok=True)
13
 
14
- def create_project(project_name, speaker, agree):
15
- if not agree:
16
- raise gr.Error("Veuillez accepter les conditions d'utilisation.")
17
-
18
- project_folder = os.path.join(output_folder, project_name)
19
- os.makedirs(project_folder, exist_ok=True)
20
- return project_folder
21
-
22
- def generate_audio(prompt, speaker, project_folder, section_name):
23
- speaker_wav_paths = [os.path.join("examples", f) for f in os.listdir("examples") if f.startswith(speaker) and f.endswith(".wav")]
24
- if not speaker_wav_paths:
25
- raise gr.Error(f"Aucun fichier audio trouvé pour le speaker : {speaker}")
26
-
27
- output_path = os.path.join(project_folder, f"{section_name}.wav")
28
-
29
- tts.tts_to_file(
30
- text=prompt,
31
- file_path=output_path,
32
- speaker_wav=speaker_wav_paths,
33
- language="fr"
34
- )
35
-
36
- return output_path
37
-
38
- custom_css = """
39
- .gradio-container {
40
- font-family: 'Roboto', sans-serif;
41
- background-color: #f7f9fc;
42
- }
43
- .gr-form {
44
- background-color: white;
45
- border-radius: 15px;
46
- padding: 30px;
47
- box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
48
- }
49
- .gr-button {
50
- background-color: #4a90e2;
51
- border: none;
52
- color: white;
53
- font-weight: bold;
54
- transition: all 0.3s ease;
55
- }
56
- .gr-button:hover {
57
- background-color: #3a7bc8;
58
- transform: translateY(-2px);
59
- }
60
- .gr-input, .gr-dropdown {
61
- border: 1px solid #e0e0e0;
62
- border-radius: 8px;
63
- padding: 10px;
64
- }
65
- .gr-checkbox {
66
- margin-top: 10px;
67
- }
68
- .gr-form > div {
69
- margin-bottom: 20px;
70
- }
71
- """
72
-
73
- title = "🎙️ Synthèse Vocale XTTS"
74
- description = """
75
- <h3 style='text-align: center; margin-bottom: 1em;'>Bienvenue sur notre outil de synthèse vocale XTTS !</h3>
76
- <p style='text-align: center;'>Générez une voix naturelle à partir de votre texte en français. Créez un projet et ajoutez des sections pour votre script.</p>
77
- """
78
-
79
- available_speakers = list(set([f.split('_')[0] for f in os.listdir("examples") if f.endswith(".wav")]))
80
-
81
- with gr.Blocks(css=custom_css) as demo:
82
-
83
  # Étape 1 : Création du Projet
84
- gr.Markdown(f"<h1 style='text-align: center; color: #4a90e2;'>{title}</h1>")
85
- gr.Markdown(description)
86
-
87
- with gr.Row():
88
- project_name = gr.Textbox(label="Nom du projet", placeholder="Entrez le nom du projet")
89
- speaker = gr.Dropdown(label="Voix", choices=available_speakers, value=available_speakers[0] if available_speakers else None)
90
- agree = gr.Checkbox(label="J'accepte les conditions d'utilisation", value=False)
91
-
92
- create_project_btn = gr.Button("Créer le Projet", variant="primary")
93
-
94
  # Étape 2 : Gestion des Sections
95
- sections = []
96
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  def add_section(sections):
98
- section_name = f"Section {len(sections) + 1}"
99
- sections.append({"name": section_name, "text": ""})
100
  return sections
101
-
 
 
102
  def remove_section(sections):
103
  if sections:
104
  sections.pop()
105
  return sections
106
-
107
- def update_section_text(index, text, sections):
108
- if index < len(sections):
109
- sections[index]["text"] = text
110
- return sections
111
-
112
- section_outputs = []
113
-
114
- with gr.Column():
115
- section_list = gr.State(value=sections)
116
-
117
- def render_sections(sections):
118
- return [gr.Row([
119
- gr.Textbox(label=f"Texte pour {section['name']}", value=section['text'], lines=5).change(update_section_text, inputs=[sections.index(section), _, section_list], outputs=None),
120
- gr.Textbox(label="Nom du fichier", value=section['name'], interactive=False),
121
- 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']}")])
122
- ]) for section in sections]
123
-
124
- with gr.Row():
125
- add_section_btn = gr.Button("+ Ajouter une section")
126
- remove_section_btn = gr.Button("- Supprimer la dernière section")
127
-
128
- add_section_btn.click(add_section, inputs=[section_list], outputs=section_list)
129
- remove_section_btn.click(remove_section, inputs=[section_list], outputs=section_list)
130
-
131
- section_output_area = gr.Column()
132
-
133
- # Dynamically render sections
134
- with section_output_area:
135
- for section in render_sections(sections):
136
- section_output_area.append(section)
137
-
138
- demo.launch(debug=True)
 
1
  import subprocess
2
+ import os
3
  import gradio as gr
4
  from TTS.api import TTS
 
 
5
 
6
+ # Initialisation du modèle TTS avec GPU désactivé
7
  tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2", gpu=False)
8
 
9
+ # Répertoire de sortie pour tous les fichiers audio
10
  output_folder = "output_audio"
11
  os.makedirs(output_folder, exist_ok=True)
12
 
13
+ # Fonction pour générer un fichier audio à partir d'une section
14
+ def generate_section_audio(project_name, section_name, text, speaker):
15
+ try:
16
+ # Création du sous-dossier pour le projet
17
+ project_path = os.path.join(output_folder, project_name)
18
+ os.makedirs(project_path, exist_ok=True)
19
+
20
+ # Définir le chemin de sortie pour cette section
21
+ file_name = f"{section_name}.wav"
22
+ output_path = os.path.join(project_path, file_name)
23
+
24
+ # Vérifier la disponibilité des fichiers audio pour le speaker
25
+ speaker_wav_paths = [os.path.join("examples", f) for f in os.listdir("examples") if f.startswith(speaker) and f.endswith(".wav")]
26
+ if not speaker_wav_paths:
27
+ raise ValueError(f"Aucun fichier audio trouvé pour le speaker : {speaker}")
28
+
29
+ # Génération de l'audio
30
+ tts.tts_to_file(
31
+ text=text,
32
+ file_path=output_path,
33
+ speaker_wav=speaker_wav_paths,
34
+ language="fr"
35
+ )
36
+
37
+ return output_path # Retourne le chemin de l'audio généré
38
+ except Exception as e:
39
+ return str(e) # Retourne l'erreur pour gestion dans l'interface
40
+
41
+ # Interface Gradio
42
+ with gr.Blocks() as demo:
43
+ # État global pour gérer les étapes et les sections
44
+ step = gr.State(value=1)
45
+ sections = gr.State(value=[]) # Liste dynamique des sections ajoutées
46
+
47
+ # Introduction et explication globale
48
+ gr.Markdown("""
49
+ # 🎙️ Synthèse Vocale Margaux
50
+ ## 👋 Bienvenue sur Margaux - Votre outil de synthèse vocale avancée
51
+ Margaux vous permet de générer des voix off naturelles à partir de textes, structurées par sections pour une meilleure qualité audio.
52
+ **Étapes principales :**
53
+ 1. 🛠️ **Créer un projet** : Définissez le nom du projet et choisissez la voix.
54
+ 2. ✍️ **Ajouter des sections** : Divisez votre texte en parties claires, chacune avec un nom unique.
55
+ 3. 🎧 **Générer les audios** : Chaque section est transformée en fichier audio individuel.
56
+ 4. 📁 **Sauvegardez le projet** : Finalisez et récupérez les fichiers validés.
57
+ """)
58
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  # Étape 1 : Création du Projet
60
+ with gr.Row(visible=True) as step1:
61
+ gr.Markdown("### 🛠️ Étape 1 : Création du Projet")
62
+ gr.Markdown("**📂 Définissez les informations générales pour votre projet.**")
63
+ project_name = gr.Textbox(label="Nom du Projet", placeholder="Exemple : Capsule_Video_PLU")
64
+ speaker = gr.Dropdown(label="Voix 🎙️", choices=["Margaux"], value="Margaux") # Liste de voix
65
+ agree = gr.Checkbox(label=" J'accepte les conditions d'utilisation")
66
+ project_message = gr.Markdown(value="", visible=False) # Composant pour afficher les messages
67
+ next_btn_1 = gr.Button("Suivant ➡️")
68
+
 
69
  # Étape 2 : Gestion des Sections
70
+ with gr.Row(visible=False) as step2:
71
+ gr.Markdown("### ✍️ Étape 2 : Ajoutez vos Sections")
72
+ gr.Markdown("""
73
+ **📝 Divisez votre script en plusieurs sections pour une meilleure qualité.**
74
+ Chaque section doit avoir :
75
+ - Un **nom unique** 🏷️ qui servira à nommer le fichier audio.
76
+ - Un **texte clair et concis** ✏️.
77
+ """)
78
+ sections_list = gr.Column() # Conteneur dynamique pour afficher les sections ajoutées
79
+ add_section_btn = gr.Button("+ Ajouter une Section ➕")
80
+ remove_section_btn = gr.Button("- Supprimer la dernière Section ➖")
81
+ prev_btn_2 = gr.Button("⬅️ Précédent")
82
+ next_btn_2 = gr.Button("Suivant ➡️")
83
+
84
+ # Étape 3 : Génération des Audios et Gestion des Sections
85
+ with gr.Row(visible=False) as step3:
86
+ gr.Markdown("### 🎧 Étape 3 : Génération et Gestion des Audios")
87
+ gr.Markdown("""
88
+ **🎶 Générez un fichier audio pour chaque section.**
89
+ - 🔄 Régénérez l’audio d’une section indépendamment si nécessaire.
90
+ - ⚠️ En cas d’erreur, seuls les audios de sections valides seront disponibles.
91
+ """)
92
+ generate_btn = gr.Button("Générer les Audios ▶️")
93
+ results_output = gr.Column() # Conteneur pour afficher les lecteurs audio et les boutons de régénération
94
+ prev_btn_3 = gr.Button("⬅️ Précédent")
95
+ save_project_btn = gr.Button("Sauvegarder le Projet ✅")
96
+
97
+ # Actions des Boutons
98
+ def create_project(project_name, speaker, agree):
99
+ if not agree:
100
+ return "❗ Veuillez accepter les conditions d'utilisation.", 1
101
+ if not project_name:
102
+ return "❗ Le nom du projet est obligatoire.", 1
103
+ os.makedirs(os.path.join(output_folder, project_name), exist_ok=True)
104
+ return f"✅ Projet '{project_name}' créé avec succès !", 2
105
+
106
+ next_btn_1.click(
107
+ create_project,
108
+ inputs=[project_name, speaker, agree],
109
+ outputs=[project_message, step]
110
+ )
111
+
112
  def add_section(sections):
113
+ section = {"name": f"Section_{len(sections) + 1}", "text": ""}
114
+ sections.append(section)
115
  return sections
116
+
117
+ add_section_btn.click(add_section, inputs=[sections], outputs=[sections_list])
118
+
119
  def remove_section(sections):
120
  if sections:
121
  sections.pop()
122
  return sections
123
+
124
+ remove_section_btn.click(remove_section, inputs=[sections], outputs=[sections_list])
125
+
126
+ def generate_audios(project_name, sections, speaker):
127
+ results = []
128
+ for section in sections:
129
+ name = section["name"]
130
+ text = section["text"]
131
+ audio_path = generate_section_audio(project_name, name, text, speaker)
132
+ results.append(audio_path)
133
+ return results
134
+
135
+ generate_btn.click(
136
+ generate_audios,
137
+ inputs=[project_name, sections, speaker],
138
+ outputs=[results_output]
139
+ )
140
+
141
+ next_btn_2.click(lambda: 3, inputs=None, outputs=step)
142
+ prev_btn_2.click(lambda: 1, inputs=None, outputs=step)
143
+ step.change(lambda x: {"visible": x == 2}, inputs=step, outputs=[step1, step2])
144
+
145
+ prev_btn_3.click(lambda: 2, inputs=None, outputs=step)
146
+ save_project_btn.click(lambda: "🎉 Projet sauvegardé avec succès !", outputs=[project_message])
147
+
148
+ # Lancement de l'interface
149
+ demo.launch(debug=True)