Woziii commited on
Commit
11501d1
·
verified ·
1 Parent(s): 0df1e09

Update app.py

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