Woziii commited on
Commit
bc681ea
·
verified ·
1 Parent(s): 56cf82b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +152 -132
app.py CHANGED
@@ -1,148 +1,168 @@
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
- # Fonction pour gérer la visibilité des étapes
42
- def update_steps(current_step, target_step):
43
- return {"visible": target_step == 1}, {"visible": target_step == 2}, {"visible": target_step == 3}
44
-
45
- # Interface Gradio
46
- with gr.Blocks() as demo:
47
- # Liste dynamique des sections
48
- sections = gr.State(value=[])
49
-
50
- # Introduction et explication globale
51
- gr.Markdown("""
52
- # 🎙️ Synthèse Vocale Margaux
53
- ## 👋 Bienvenue sur Margaux - Votre outil de synthèse vocale avancée
54
- Margaux vous permet de générer des voix off naturelles à partir de textes, structurées par sections pour une meilleure qualité audio.
55
- **Étapes principales :**
56
- 1. 🛠️ **Créer un projet** : Définissez le nom du projet et choisissez la voix.
57
- 2. ✍️ **Ajouter des sections** : Divisez votre texte en parties claires, chacune avec un nom unique.
58
- 3. 🎧 **Générer les audios** : Chaque section est transformée en fichier audio individuel.
59
- 4. 📁 **Sauvegardez le projet** : Finalisez et récupérez les fichiers validés.
60
- """)
61
-
62
- # Étape 1 : Création du Projet
63
- with gr.Row(visible=True) as step1:
64
- gr.Markdown("### 🛠️ Étape 1 : Création du Projet")
65
- project_name = gr.Textbox(label="Nom du Projet", placeholder="Exemple : Capsule_Video_PLU")
66
- speaker = gr.Dropdown(label="Voix 🎙️", choices=["Margaux"], value="Margaux") # Liste de voix
67
- agree = gr.Checkbox(label="✅ J'accepte les conditions d'utilisation")
68
- project_message = gr.Markdown(value="", visible=False) # Composant pour afficher les messages
69
- next_btn_1 = gr.Button("Suivant ➡️")
70
-
71
- # Étape 2 : Gestion des Sections
72
- with gr.Row(visible=False) as step2:
73
- gr.Markdown("### ✍️ Étape 2 : Ajoutez vos Sections")
74
- gr.Markdown("""
75
- **📝 Divisez votre script en plusieurs sections pour une meilleure qualité.**
76
- Chaque section doit avoir :
77
- - Un **nom unique** 🏷️ qui servira à nommer le fichier audio.
78
- - Un **texte clair et concis** ✏️.
79
- """)
80
- sections_list = gr.Column() # Conteneur dynamique pour afficher les sections ajoutées
81
- add_section_btn = gr.Button("+ Ajouter une Section ➕")
82
- remove_section_btn = gr.Button("- Supprimer la dernière Section ➖")
83
- prev_btn_2 = gr.Button("⬅️ Précédent")
84
- next_btn_2 = gr.Button("Suivant ➡️")
85
-
86
- # Étape 3 : Génération des Audios et Sauvegarde
87
- with gr.Row(visible=False) as step3:
88
- gr.Markdown("### 🎧 Étape 3 : Génération et Gestion des Audios")
89
- gr.Markdown("""
90
- **🎶 Générez un fichier audio pour chaque section.**
91
- - 🔄 Régénérez l’audio d’une section indépendamment si nécessaire.
92
- - ⚠️ En cas d’erreur, seuls les audios de sections valides seront disponibles.
93
- """)
94
- generate_btn = gr.Button("Générer les Audios ▶️")
95
- results_output = gr.Column() # Conteneur pour afficher les lecteurs audio et les boutons de régénération
96
- prev_btn_3 = gr.Button("⬅️ Précédent")
97
- save_project_btn = gr.Button("Sauvegarder le Projet ✅")
98
-
99
- # Actions des Boutons
100
- def create_project(project_name, speaker, agree):
101
- if not agree:
102
- return "❗ Veuillez accepter les conditions d'utilisation.", 1
103
- if not project_name:
104
- return " Le nom du projet est obligatoire.", 1
105
- os.makedirs(os.path.join(output_folder, project_name), exist_ok=True)
106
- return f"✅ Projet '{project_name}' créé avec succès !", 2
107
-
108
- next_btn_1.click(
109
- create_project,
 
 
 
 
 
 
 
110
  inputs=[project_name, speaker, agree],
111
- outputs=[project_message, step1],
112
  )
113
 
114
- def add_section(sections):
115
- section = {"name": f"Section_{len(sections) + 1}", "text": ""}
116
- sections.append(section)
117
- return sections
118
-
119
- add_section_btn.click(add_section, inputs=[sections], outputs=[sections_list])
120
-
121
- def remove_section(sections):
122
- if sections:
123
- sections.pop()
124
- return sections
125
-
126
- remove_section_btn.click(remove_section, inputs=[sections], outputs=[sections_list])
127
-
128
- def generate_audios(project_name, sections, speaker):
129
- results = []
130
- for section in sections:
131
- name = section["name"]
132
- text = section["text"]
133
- audio_path = generate_section_audio(project_name, name, text, speaker)
134
- results.append(audio_path)
135
- return results
136
-
137
- generate_btn.click(
138
- generate_audios,
139
- inputs=[project_name, sections, speaker],
140
- outputs=[results_output],
141
- )
142
 
143
- prev_btn_2.click(lambda: update_steps(2, 1), inputs=None, outputs=[step1, step2, step3])
144
- next_btn_2.click(lambda: update_steps(2, 3), inputs=None, outputs=[step1, step2, step3])
145
- prev_btn_3.click(lambda: update_steps(3, 2), inputs=None, outputs=[step1, step2, step3])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
- # Lancement de l'interface
148
- demo.launch(debug=True)
 
1
  import subprocess
2
  import os
3
+ import time
4
  import gradio as gr
5
  from TTS.api import TTS
6
 
7
+ # Initialisation du modèle TTS
8
  tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2", gpu=False)
9
 
 
10
  output_folder = "output_audio"
11
  os.makedirs(output_folder, exist_ok=True)
12
 
13
+ def create_project(project_name, speaker, agree):
14
+ if not agree:
15
+ raise gr.Error("🚨 Veuillez accepter les conditions d'utilisation.")
16
+
17
+ project_folder = os.path.join(output_folder, project_name.strip())
18
+ os.makedirs(project_folder, exist_ok=True)
19
+ return project_folder
20
+
21
+ def generate_audio_section(text, section_name, project_folder, speaker):
22
+ file_name = f"{section_name.strip()}.wav"
23
+ output_path = os.path.join(project_folder, file_name)
24
+
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 gr.Error(f"🚨 Aucun fichier audio trouvé pour le speaker : {speaker}")
28
+
29
+ tts.tts_to_file(
30
+ text=text,
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. Choisissez une voix, entrez votre texte, et écoutez le résultat ! 🎤</p>
77
+ """
78
+ article = """
79
+ <div style='margin: 20px auto; text-align: center; padding: 10px; background-color: #e8f0fe; border-radius: 10px;'>
80
+ <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>
81
+ </div>
82
+ """
83
+
84
+ available_speakers = list(set([f.split('_')[0] for f in os.listdir("examples") if f.endswith(".wav")]))
85
+
86
+ with gr.Blocks(css=custom_css) as demo:
87
+ gr.Markdown(f"<h1 style='text-align: center; color: #4a90e2;'>{title}</h1>")
88
+ gr.Markdown(description)
89
+
90
+ with gr.Row():
91
+ with gr.Column(scale=1):
92
+ project_name = gr.Textbox(
93
+ label="🗂️ Nom du projet",
94
+ placeholder="Entrez le nom du projet",
95
+ lines=1
96
+ )
97
+ speaker = gr.Dropdown(
98
+ label="🎤 Voix",
99
+ choices=available_speakers,
100
+ value=available_speakers[0] if available_speakers else None
101
+ )
102
+ agree = gr.Checkbox(
103
+ label=" J'accepte les conditions d'utilisation",
104
+ value=False
105
+ )
106
+ create_project_btn = gr.Button("🔨 Créer le projet", variant="primary")
107
+
108
+ project_folder_output = gr.State()
109
+
110
+ def on_create_project(name, spkr, agr):
111
+ folder_path = create_project(name, spkr, agr)
112
+ return folder_path
113
+
114
+ create_project_btn.click(
115
+ on_create_project,
116
  inputs=[project_name, speaker, agree],
117
+ outputs=[project_folder_output]
118
  )
119
 
120
+ section_textboxes = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
+ def add_section():
123
+ section_textbox = gr.Textbox(
124
+ label=f"✏️ Texte de la section {len(section_textboxes) + 1}",
125
+ placeholder="Entrez le texte pour cette section",
126
+ lines=5
127
+ )
128
+ section_name_textbox = gr.Textbox(
129
+ label=f"📝 Nom de la section {len(section_textboxes) + 1}",
130
+ placeholder="Entrez le nom du fichier pour cette section",
131
+ lines=1
132
+ )
133
+ section_textboxes.append((section_textbox, section_name_textbox))
134
+ return [textbox for textbox_pair in section_textboxes for textbox in textbox_pair]
135
+
136
+ add_section_btn = gr.Button("➕ Ajouter une section")
137
+
138
+ def remove_section():
139
+ if section_textboxes:
140
+ removed_section = section_textboxes.pop()
141
+ return [textbox for textbox_pair in section_textboxes for textbox in textbox_pair]
142
+ return []
143
+
144
+ remove_section_btn = gr.Button("➖ Supprimer une section")
145
+
146
+ add_section_btn.click(add_section)
147
+ remove_section_btn.click(remove_section)
148
+
149
+ generate_audio_btn = gr.Button("🎶 Générer l'audio")
150
+
151
+ audio_outputs_display = []
152
+
153
+ def generate_all_sections(sections_data, proj_folder):
154
+ audio_outputs = []
155
+ for text_box, name_box in sections_data:
156
+ text = text_box.value
157
+ name = name_box.value
158
+ audio_path = generate_audio_section(text, name.strip(), proj_folder.value, speaker.value)
159
+ audio_outputs.append(audio_path)
160
+ return audio_outputs
161
+
162
+ generate_audio_btn.click(
163
+ generate_all_sections,
164
+ inputs=[section_textboxes, project_folder_output],
165
+ outputs=audio_outputs_display
166
+ )
167
 
168
+ demo.launch(debug=True)