pierreguillou commited on
Commit
d91a245
·
verified ·
1 Parent(s): beb567e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +131 -131
app.py CHANGED
@@ -25,15 +25,15 @@ lang_pipe = pipeline(
25
  def convert_to_wav(audio_path):
26
  """Converte qualquer arquivo de áudio para WAV mono 16 kHz."""
27
  try:
28
- audio = AudioSegment.from_file(audio_path)
29
- audio = audio.set_channels(1)
30
- audio = audio.set_frame_rate(16000)
31
- wav_path = os.path.splitext(audio_path)[0] + ".wav"
32
- audio.export(wav_path, format="wav")
33
- return wav_path
34
  except Exception as e:
35
- print(f"Erro ao converter para WAV: {e}")
36
- return None
37
 
38
  def make_speech_head_wav(input_wav_path, max_seconds=7):
39
  """
@@ -41,47 +41,47 @@ def make_speech_head_wav(input_wav_path, max_seconds=7):
41
  après suppression du silence initial (avec protection contre les boucles).
42
  """
43
  try:
44
- audio = AudioSegment.from_wav(input_wav_path)
45
-
46
- # Si l'audio est déjà très court, le retourner tel quel
47
- if len(audio) <= max_seconds * 1000:
48
- return input_wav_path
49
-
50
- # Normalisation simple
51
- normalized = effects.normalize(audio)
52
-
53
- # Tentative rapide de suppression du silence initial
54
- try:
55
- silence_thresh = normalized.dBFS - 20
56
- # Limiter la recherche aux 30 premières secondes maximum
57
- search_audio = normalized[:30000]
58
- start_trim = silence.detect_leading_silence(
59
- search_audio,
60
- silence_threshold=silence_thresh,
61
- chunk_size=100
62
- )
63
- # Limiter le trim à 15 secondes max pour éviter les cas extrêmes
64
- start_trim = min(start_trim, 15000)
65
- trimmed = normalized[start_trim:]
66
- except:
67
- # En cas d'erreur, utiliser l'audio original
68
- trimmed = normalized
69
-
70
- # Si trop court après trim, utiliser l'original
71
- if len(trimmed) < 2000: # Moins de 2 secondes
72
- trimmed = normalized
73
-
74
- # Prendre simplement les premiers max_seconds
75
- clip = trimmed[:max_seconds * 1000]
76
-
77
- short_path = os.path.splitext(input_wav_path)[0] + f"_head_{max_seconds}s.wav"
78
- clip.export(short_path, format="wav")
79
- return short_path
80
 
81
  except Exception as e:
82
- print(f"Erro ao criar o trecho: {e}")
83
- # En cas d'erreur, retourner le fichier original
84
- return input_wav_path
85
 
86
  def detect_language_on_upload(filepath):
87
  """
@@ -91,74 +91,74 @@ def detect_language_on_upload(filepath):
91
  return "auto"
92
 
93
  try:
94
- print(f"Début détection langue pour: {filepath}")
95
-
96
- wav_filepath = convert_to_wav(filepath)
97
- if not wav_filepath:
98
- print("Échec conversion WAV")
99
- return "auto"
100
-
101
- # Créer un extrait court (5 secondes max)
102
- short_wav = make_speech_head_wav(wav_filepath, max_seconds=7)
103
- if not short_wav:
104
- short_wav = wav_filepath
105
-
106
- print(f"Analyse du fichier: {short_wav}")
107
-
108
- # Transcrição avec paramètres conservateurs
109
- outputs = lang_pipe(
110
- short_wav,
111
- chunk_length_s=5,
112
- return_timestamps=False,
113
- generate_kwargs={"max_new_tokens": 50} # Limiter pour éviter les timeouts
114
- )
115
-
116
- transcribed_text = outputs.get("text", "").strip()
117
- print(f"Texte transcrit: {transcribed_text[:100]}...")
118
-
119
- # Priorité au language détecté par Whisper
120
- whisper_lang = outputs.get("language")
121
- if whisper_lang and isinstance(whisper_lang, str) and len(whisper_lang) <= 5:
122
- print(f"Langue Whisper détectée: {whisper_lang}")
123
- return whisper_lang
124
-
125
- # Si texte trop court, retourner auto
126
- if len(transcribed_text) < 10:
127
- print("Texte trop court, retour auto")
128
- return "auto"
129
-
130
- # Fallback avec LangDetect
131
- detected_lang = detect(transcribed_text)
132
- print(f"Langue LangDetect: {detected_lang}")
133
-
134
- # Mapping des codes de langue
135
- lang_mapping = {
136
- 'fr': 'fr', 'en': 'en', 'es': 'es', 'de': 'de', 'it': 'it',
137
- 'pt': 'pt', 'nl': 'nl', 'pl': 'pl', 'ru': 'ru', 'ja': 'ja',
138
- 'ko': 'ko', 'zh-cn': 'zh', 'zh': 'zh'
139
- }
140
-
141
- result = lang_mapping.get(detected_lang, "auto")
142
- print(f"Résultat final: {result}")
143
- return result
144
 
145
  except Exception as e:
146
- print(f"Erreur détection langue: {e}")
147
- return "auto"
148
 
149
  def ensure_mp3_same_name_as_input(input_path, source_wav_path):
150
  """
151
  Cria um arquivo MP3 com o mesmo nome base do arquivo de entrada.
152
  """
153
  try:
154
- base, _ = os.path.splitext(os.path.basename(input_path))
155
- mp3_path = f"{base}.mp3"
156
- audio = AudioSegment.from_wav(source_wav_path)
157
- audio.export(mp3_path, format="mp3", bitrate="192k")
158
- return mp3_path
159
  except Exception as e:
160
- print(f"Erro ao exportar MP3: {e}")
161
- return None
162
 
163
  # --- Fonction principale ---
164
 
@@ -191,47 +191,47 @@ with gr.Blocks() as demo:
191
 
192
  gr.Markdown("""
193
  ## ⚡ **Version optimisée**
194
- - **Détection rapide** : Analyse les 5 premières secondes (hors silence initial)
195
  - **Robuste** : Fonctionne avec tous types de fichiers
196
  - **Timeout protection** : Évite les blocages
197
  """)
198
 
199
  with gr.Row():
200
- with gr.Column():
201
- audio_input = gr.Audio(type="filepath", label="Envoyer un fichier audio")
202
- language_dropdown = gr.Dropdown(
203
- choices=["auto", "fr", "en", "es", "de", "it", "pt", "nl", "pl", "ru", "ja", "ko", "zh"],
204
- value="auto",
205
- label="Langue (auto = détection automatique)",
206
- info="Détection automatique rapide après upload"
207
- )
208
- submit_btn = gr.Button("Générer MP3", variant="primary")
209
- reset_btn = gr.Button("Reset", variant="secondary")
210
- with gr.Column():
211
- language_info_output = gr.Textbox(label="Information sur la langue", lines=1)
212
- mp3_download = gr.File(label="Télécharger la sortie (.mp3)")
213
- mp3_playback = gr.Audio(label="Écouter la sortie (.mp3)", type="filepath")
214
 
215
  # Détection automatique de langue lors de l'upload
216
  audio_input.change(
217
- fn=detect_language_on_upload,
218
- inputs=audio_input,
219
- outputs=language_dropdown
220
  )
221
 
222
  submit_btn.click(
223
- fn=make_output_mp3,
224
- inputs=[audio_input, language_dropdown],
225
- outputs=[mp3_download, mp3_playback, language_info_output]
226
  )
227
 
228
  def reset_fields():
229
- return None, None, "auto", ""
230
 
231
  reset_btn.click(
232
- fn=reset_fields,
233
- inputs=[],
234
- outputs=[audio_input, mp3_download, language_dropdown, language_info_output]
235
  )
236
 
237
  demo.launch(share=True)
 
25
  def convert_to_wav(audio_path):
26
  """Converte qualquer arquivo de áudio para WAV mono 16 kHz."""
27
  try:
28
+ audio = AudioSegment.from_file(audio_path)
29
+ audio = audio.set_channels(1)
30
+ audio = audio.set_frame_rate(16000)
31
+ wav_path = os.path.splitext(audio_path)[0] + ".wav"
32
+ audio.export(wav_path, format="wav")
33
+ return wav_path
34
  except Exception as e:
35
+ print(f"Erro ao converter para WAV: {e}")
36
+ return None
37
 
38
  def make_speech_head_wav(input_wav_path, max_seconds=7):
39
  """
 
41
  après suppression du silence initial (avec protection contre les boucles).
42
  """
43
  try:
44
+ audio = AudioSegment.from_wav(input_wav_path)
45
+
46
+ # Si l'audio est déjà très court, le retourner tel quel
47
+ if len(audio) <= max_seconds * 1000:
48
+ return input_wav_path
49
+
50
+ # Normalisation simple
51
+ normalized = effects.normalize(audio)
52
+
53
+ # Tentative rapide de suppression du silence initial
54
+ try:
55
+ silence_thresh = normalized.dBFS - 20
56
+ # Limiter la recherche aux 30 premières secondes maximum
57
+ search_audio = normalized[:30000]
58
+ start_trim = silence.detect_leading_silence(
59
+ search_audio,
60
+ silence_threshold=silence_thresh,
61
+ chunk_size=100
62
+ )
63
+ # Limiter le trim à 15 secondes max pour éviter les cas extrêmes
64
+ start_trim = min(start_trim, 15000)
65
+ trimmed = normalized[start_trim:]
66
+ except:
67
+ # En cas d'erreur, utiliser l'audio original
68
+ trimmed = normalized
69
+
70
+ # Si trop court après trim, utiliser l'original
71
+ if len(trimmed) < 2000: # Moins de 2 secondes
72
+ trimmed = normalized
73
+
74
+ # Prendre simplement les premiers max_seconds
75
+ clip = trimmed[:max_seconds * 1000]
76
+
77
+ short_path = os.path.splitext(input_wav_path)[0] + f"_head_{max_seconds}s.wav"
78
+ clip.export(short_path, format="wav")
79
+ return short_path
80
 
81
  except Exception as e:
82
+ print(f"Erro ao criar o trecho: {e}")
83
+ # En cas d'erreur, retourner le fichier original
84
+ return input_wav_path
85
 
86
  def detect_language_on_upload(filepath):
87
  """
 
91
  return "auto"
92
 
93
  try:
94
+ print(f"Début détection langue pour: {filepath}")
95
+
96
+ wav_filepath = convert_to_wav(filepath)
97
+ if not wav_filepath:
98
+ print("Échec conversion WAV")
99
+ return "auto"
100
+
101
+ # Créer un extrait court (5 secondes max)
102
+ short_wav = make_speech_head_wav(wav_filepath, max_seconds=7)
103
+ if not short_wav:
104
+ short_wav = wav_filepath
105
+
106
+ print(f"Analyse du fichier: {short_wav}")
107
+
108
+ # Transcrição avec paramètres conservateurs
109
+ outputs = lang_pipe(
110
+ short_wav,
111
+ chunk_length_s=5,
112
+ return_timestamps=False,
113
+ generate_kwargs={"max_new_tokens": 50} # Limiter pour éviter les timeouts
114
+ )
115
+
116
+ transcribed_text = outputs.get("text", "").strip()
117
+ print(f"Texte transcrit: {transcribed_text[:100]}...")
118
+
119
+ # Priorité au language détecté par Whisper
120
+ whisper_lang = outputs.get("language")
121
+ if whisper_lang and isinstance(whisper_lang, str) and len(whisper_lang) <= 5:
122
+ print(f"Langue Whisper détectée: {whisper_lang}")
123
+ return whisper_lang
124
+
125
+ # Si texte trop court, retourner auto
126
+ if len(transcribed_text) < 10:
127
+ print("Texte trop court, retour auto")
128
+ return "auto"
129
+
130
+ # Fallback avec LangDetect
131
+ detected_lang = detect(transcribed_text)
132
+ print(f"Langue LangDetect: {detected_lang}")
133
+
134
+ # Mapping des codes de langue
135
+ lang_mapping = {
136
+ 'fr': 'fr', 'en': 'en', 'es': 'es', 'de': 'de', 'it': 'it',
137
+ 'pt': 'pt', 'nl': 'nl', 'pl': 'pl', 'ru': 'ru', 'ja': 'ja',
138
+ 'ko': 'ko', 'zh-cn': 'zh', 'zh': 'zh'
139
+ }
140
+
141
+ result = lang_mapping.get(detected_lang, "auto")
142
+ print(f"Résultat final: {result}")
143
+ return result
144
 
145
  except Exception as e:
146
+ print(f"Erreur détection langue: {e}")
147
+ return "auto"
148
 
149
  def ensure_mp3_same_name_as_input(input_path, source_wav_path):
150
  """
151
  Cria um arquivo MP3 com o mesmo nome base do arquivo de entrada.
152
  """
153
  try:
154
+ base, _ = os.path.splitext(os.path.basename(input_path))
155
+ mp3_path = f"{base}.mp3"
156
+ audio = AudioSegment.from_wav(source_wav_path)
157
+ audio.export(mp3_path, format="mp3", bitrate="192k")
158
+ return mp3_path
159
  except Exception as e:
160
+ print(f"Erro ao exportar MP3: {e}")
161
+ return None
162
 
163
  # --- Fonction principale ---
164
 
 
191
 
192
  gr.Markdown("""
193
  ## ⚡ **Version optimisée**
194
+ - **Détection rapide** : Analyse les 7 premières secondes (hors silence initial)
195
  - **Robuste** : Fonctionne avec tous types de fichiers
196
  - **Timeout protection** : Évite les blocages
197
  """)
198
 
199
  with gr.Row():
200
+ with gr.Column():
201
+ audio_input = gr.Audio(type="filepath", label="Envoyer un fichier audio")
202
+ language_dropdown = gr.Dropdown(
203
+ choices=["auto", "fr", "en", "es", "de", "it", "pt", "nl", "pl", "ru", "ja", "ko", "zh"],
204
+ value="auto",
205
+ label="Langue (auto = détection automatique)",
206
+ info="Détection automatique rapide après upload"
207
+ )
208
+ submit_btn = gr.Button("Générer MP3", variant="primary")
209
+ reset_btn = gr.Button("Reset", variant="secondary")
210
+ with gr.Column():
211
+ language_info_output = gr.Textbox(label="Information sur la langue", lines=1)
212
+ mp3_download = gr.File(label="Télécharger la sortie (.mp3)")
213
+ mp3_playback = gr.Audio(label="Écouter la sortie (.mp3)", type="filepath")
214
 
215
  # Détection automatique de langue lors de l'upload
216
  audio_input.change(
217
+ fn=detect_language_on_upload,
218
+ inputs=audio_input,
219
+ outputs=language_dropdown
220
  )
221
 
222
  submit_btn.click(
223
+ fn=make_output_mp3,
224
+ inputs=[audio_input, language_dropdown],
225
+ outputs=[mp3_download, mp3_playback, language_info_output]
226
  )
227
 
228
  def reset_fields():
229
+ return None, None, "auto", ""
230
 
231
  reset_btn.click(
232
+ fn=reset_fields,
233
+ inputs=[],
234
+ outputs=[audio_input, mp3_download, language_dropdown, language_info_output]
235
  )
236
 
237
  demo.launch(share=True)