Woziii commited on
Commit
328d70f
·
verified ·
1 Parent(s): 3612cc7

Update app.py

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