omarbajouk commited on
Commit
c57fa68
·
verified ·
1 Parent(s): 4ecdcb7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -55
app.py CHANGED
@@ -84,73 +84,62 @@ def _safe_name(stem, ext=".mp4"):
84
  return f"{stem}_{uuid.uuid4().hex[:6]}{ext}"
85
 
86
  # ============================================================
87
- # SYNTHÈSE VOCALE — Parler-TTS multivoix (FR & NL) + gTTS fallback
88
  # ============================================================
89
- from transformers import pipeline
 
90
  import soundfile as sf
91
 
92
- print("[TTS] Initialisation des modèles Parler-TTS...")
93
-
94
- # Charger les modèles FR et NL
95
- try:
96
- tts_fr = pipeline("text-to-speech", model="parler-tts/parler_tts_mini_v0.1", speaker="fr_female_1")
97
- tts_nl = pipeline("text-to-speech", model="parler-tts/parler_tts_mini_v0.1", speaker="nl_female_1")
98
- print("[TTS] Modèles Parler-TTS chargés avec succès (FR/NL).")
99
- except Exception as e:
100
- print(f"[TTS] Erreur de chargement Parler-TTS : {e}")
101
- tts_fr = tts_nl = None
102
-
103
-
104
- # --- Liste des voix disponibles ---
105
- PARLER_VOICES = {
106
- "🇫🇷 Femme 1 (Jeanne)": "fr_female_1",
107
- "🇫🇷 Femme 2 (Chloé)": "fr_female_2",
108
- "🇫🇷 Homme 1 (Louis)": "fr_male_1",
109
- "🇫🇷 Homme 2 (Hugo)": "fr_male_2",
110
- "🇳🇱 Vrouw 1 (Anke)": "nl_female_1",
111
- "🇳🇱 Vrouw 2 (Sofie)": "nl_female_2",
112
- "🇳🇱 Man 1 (Bart)": "nl_male_1",
113
- "🇳🇱 Man 2 (Tom)": "nl_male_2",
114
  }
115
 
116
 
117
- def get_parler_voices(lang="fr"):
118
- """Retourne les voix disponibles selon la langue (FR/NL)."""
119
  if lang == "fr":
120
- return [v for k, v in PARLER_VOICES.items() if k.startswith("🇫🇷")]
121
  elif lang == "nl":
122
- return [v for k, v in PARLER_VOICES.items() if k.startswith("🇳🇱")]
123
- return list(PARLER_VOICES.values())
124
 
125
 
126
- def tts_parler(text: str, langue: str = "fr", speaker: str = None) -> str:
127
- """Génère un fichier WAV avec Parler-TTS (FR/NL)."""
128
- out = os.path.join(TMP_DIR, f"parler_{langue}_{uuid.uuid4().hex}.wav")
129
- try:
130
- if langue == "nl":
131
- model = tts_nl
132
- else:
133
- model = tts_fr
134
 
135
- if model is None:
136
- raise RuntimeError("Modèle Parler non chargé.")
137
 
138
- result = model(text, speaker=speaker or ("nl_female_1" if langue == "nl" else "fr_female_1"))
139
- sf.write(out, result["audio"], result["sampling_rate"])
 
 
 
140
  return out
141
  except Exception as e:
142
- print(f"[TTS] Erreur Parler-TTS ({e}), fallback gTTS.")
143
- return tts_gtts(text, lang=langue)
144
 
145
 
146
  def tts_gtts(text: str, lang: str = "fr") -> str:
147
- """Fallback simple via Google Text-to-Speech (gTTS)."""
148
  from gtts import gTTS
149
  out = os.path.join(TMP_DIR, f"gtts_{uuid.uuid4().hex}.mp3")
150
  gTTS(text=text, lang=lang).save(out)
151
  return out
152
 
153
-
154
  def _normalize_audio_to_wav(in_path: str) -> str:
155
  # Convertit n'importe quel format (mp3/wav) en WAV standard (44.1kHz stéréo)
156
  from pydub import AudioSegment
@@ -342,14 +331,14 @@ def build_capsule(titre, sous_titre, texte_voix, texte_ecran, theme,
342
  position_presentateur="bottom-right", plein=False,
343
  moteur_voix="Parler-TTS (offline)", langue="fr", speaker=None):
344
 
345
- # 1) TTS (Parler-TTS multivoix ou fallback)
346
  try:
347
- audio_mp = tts_parler(texte_voix, langue=langue, speaker=speaker)
348
  except Exception as e:
349
- print(f"[Capsule] Erreur TTS Parler ({e}), fallback gTTS.")
350
  audio_mp = tts_gtts(texte_voix, lang=langue)
351
-
352
- # 🔧 S'assurer qu'on a un WAV standard
353
  audio_wav = audio_mp
354
  if not audio_mp.lower().endswith(".wav"):
355
  try:
@@ -357,6 +346,7 @@ def build_capsule(titre, sous_titre, texte_voix, texte_ecran, theme,
357
  except Exception as e:
358
  print(f"[Audio] Normalisation échouée ({e}), on garde {audio_mp}")
359
 
 
360
  # 2) Fond (PIL)
361
  fond_path = make_background(titre, sous_titre, texte_ecran, theme,
362
  logo_path, logo_pos, image_fond, fond_mode)
@@ -503,20 +493,19 @@ with gr.Blocks(title="Créateur de Capsules CPAS – SadTalker + Kokoro",
503
 
504
  def maj_voix(lang):
505
  try:
506
- voices = get_parler_voices(lang)
507
  return gr.update(choices=voices, value=voices[0] if voices else None)
508
  except Exception as e:
509
  return gr.update(choices=[], value=None)
510
 
511
  speaker_id = gr.Dropdown(
512
- label="🎙 Voix Parler-TTS",
513
- choices=get_parler_voices("fr"),
514
- value="fr_female_1",
515
  info="Choisissez la voix selon la langue (FR/NL)"
516
  )
517
  langue.change(maj_voix, [langue], [speaker_id])
518
 
519
-
520
  voix_type = gr.Radio(["Féminine","Masculine"], label="Voix IA", value="Féminine")
521
  moteur_voix = gr.Radio(
522
  ["Kokoro (HuggingFace, offline)", "gTTS (en ligne)"],
 
84
  return f"{stem}_{uuid.uuid4().hex[:6]}{ext}"
85
 
86
  # ============================================================
87
+ # SYNTHÈSE VOCALE — Edge-TTS multivoix (FR/NL) + gTTS fallback
88
  # ============================================================
89
+ import asyncio
90
+ import edge_tts
91
  import soundfile as sf
92
 
93
+ # --- Voix Edge disponibles ---
94
+ EDGE_VOICES = {
95
+ # Français
96
+ "🇫🇷 Denise (Femme, France)": "fr-FR-DeniseNeural",
97
+ "🇫🇷 Henri (Homme, France)": "fr-FR-HenriNeural",
98
+ "🇫🇷 Vivienne (Femme, Belgique)": "fr-BE-VivienneNeural",
99
+ "🇫🇷 Charline (Femme, Canada)": "fr-CA-CharlineNeural",
100
+
101
+ # Néerlandais
102
+ "🇳🇱 Maaike (Femme, Pays-Bas)": "nl-NL-MaaikeNeural",
103
+ "🇳🇱 Coen (Homme, Pays-Bas)": "nl-NL-CoenNeural",
104
+ "🇳🇱 Arnaud (Homme, Belgique)": "nl-BE-ArnaudNeural",
105
+ "🇳🇱 Dena (Femme, Belgique)": "nl-BE-DenaNeural",
 
 
 
 
 
 
 
 
 
106
  }
107
 
108
 
109
+ def get_edge_voices(lang="fr"):
110
+ """Retourne les voix Edge disponibles selon la langue."""
111
  if lang == "fr":
112
+ return [v for k, v in EDGE_VOICES.items() if k.startswith("🇫🇷")]
113
  elif lang == "nl":
114
+ return [v for k, v in EDGE_VOICES.items() if k.startswith("🇳🇱")]
115
+ return list(EDGE_VOICES.values())
116
 
117
 
118
+ async def _edge_tts_async(text, voice, outfile):
119
+ """Appel asynchrone à edge-tts."""
120
+ communicate = edge_tts.Communicate(text, voice)
121
+ await communicate.save(outfile)
122
+ return outfile
 
 
 
123
 
 
 
124
 
125
+ def tts_edge(text: str, voice: str = "fr-FR-DeniseNeural") -> str:
126
+ """Génère un fichier audio .mp3 avec Edge-TTS."""
127
+ out = os.path.join(TMP_DIR, f"edge_{uuid.uuid4().hex}.mp3")
128
+ try:
129
+ asyncio.run(_edge_tts_async(text, voice, out))
130
  return out
131
  except Exception as e:
132
+ print(f"[Edge-TTS] Erreur: {e}")
133
+ return tts_gtts(text, lang="fr" if voice.startswith("fr") else "nl")
134
 
135
 
136
  def tts_gtts(text: str, lang: str = "fr") -> str:
137
+ """Fallback simple via Google TTS."""
138
  from gtts import gTTS
139
  out = os.path.join(TMP_DIR, f"gtts_{uuid.uuid4().hex}.mp3")
140
  gTTS(text=text, lang=lang).save(out)
141
  return out
142
 
 
143
  def _normalize_audio_to_wav(in_path: str) -> str:
144
  # Convertit n'importe quel format (mp3/wav) en WAV standard (44.1kHz stéréo)
145
  from pydub import AudioSegment
 
331
  position_presentateur="bottom-right", plein=False,
332
  moteur_voix="Parler-TTS (offline)", langue="fr", speaker=None):
333
 
334
+ # 1) TTS (Edge multivoix ou fallback)
335
  try:
336
+ audio_mp = tts_edge(texte_voix, voice=speaker or ("fr-FR-DeniseNeural" if langue == "fr" else "nl-NL-MaaikeNeural"))
337
  except Exception as e:
338
+ print(f"[Capsule] Erreur TTS Edge ({e}), fallback gTTS.")
339
  audio_mp = tts_gtts(texte_voix, lang=langue)
340
+
341
+ # S'assurer qu'on a un WAV
342
  audio_wav = audio_mp
343
  if not audio_mp.lower().endswith(".wav"):
344
  try:
 
346
  except Exception as e:
347
  print(f"[Audio] Normalisation échouée ({e}), on garde {audio_mp}")
348
 
349
+
350
  # 2) Fond (PIL)
351
  fond_path = make_background(titre, sous_titre, texte_ecran, theme,
352
  logo_path, logo_pos, image_fond, fond_mode)
 
493
 
494
  def maj_voix(lang):
495
  try:
496
+ voices = get_edge_voices(lang)
497
  return gr.update(choices=voices, value=voices[0] if voices else None)
498
  except Exception as e:
499
  return gr.update(choices=[], value=None)
500
 
501
  speaker_id = gr.Dropdown(
502
+ label="🎙 Voix Edge-TTS",
503
+ choices=get_edge_voices("fr"),
504
+ value="fr-FR-DeniseNeural",
505
  info="Choisissez la voix selon la langue (FR/NL)"
506
  )
507
  langue.change(maj_voix, [langue], [speaker_id])
508
 
 
509
  voix_type = gr.Radio(["Féminine","Masculine"], label="Voix IA", value="Féminine")
510
  moteur_voix = gr.Radio(
511
  ["Kokoro (HuggingFace, offline)", "gTTS (en ligne)"],