rick commited on
Commit
3f5fb93
·
unverified ·
1 Parent(s): 00dd73c

align to PEP8

Browse files
Files changed (1) hide show
  1. app.py +106 -72
app.py CHANGED
@@ -1,16 +1,19 @@
1
- import streamlit as st
2
- from openai import OpenAI
3
- from os import getenv
4
- from audiorecorder import audiorecorder
5
- import tempfile
6
  import base64
7
- from pydub import AudioSegment
8
- import os
9
  import io
10
- import time
11
- import re
12
- from typing import Union, Optional, Any
13
  import json
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  def load_lang_ui(filepath: Optional[str] = "ui_lang_support.json") -> dict:
16
  try:
@@ -20,7 +23,9 @@ def load_lang_ui(filepath: Optional[str] = "ui_lang_support.json") -> dict:
20
  print(_("erreur_fichier_non_trouve").format(filepath))
21
  return {}
22
  except json.JSONDecodeError:
23
- print(_("erreur_lecture_fichier").format("Erreur de décodage JSON"))
 
 
24
  return {}
25
  except Exception as e:
26
  print(_("erreur_lecture_fichier").format(str(e)))
@@ -51,8 +56,11 @@ def lire_fichier(nom_fichier):
51
  def split_audio(audio_file, max_size_mb=25):
52
  audio = AudioSegment.from_wav(audio_file)
53
  duration_ms = len(audio)
54
- segment_duration_ms = int((max_size_mb * 1024 * 1024 * 8) / (audio.frame_rate * audio.sample_width * audio.channels))
55
-
 
 
 
56
  segments = []
57
  for start in range(0, duration_ms, segment_duration_ms):
58
  end = min(start + segment_duration_ms, duration_ms)
@@ -60,7 +68,7 @@ def split_audio(audio_file, max_size_mb=25):
60
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_segment:
61
  segment.export(temp_segment.name, format="wav")
62
  segments.append(temp_segment.name)
63
-
64
  return segments
65
 
66
  # Fonction modifiée pour transcrire l'audio en texte
@@ -74,7 +82,7 @@ def transcribe_audio(audio_file, language=None):
74
  for segment in segments:
75
  with open(segment, "rb") as audio_segment:
76
  transcript = client.audio.transcriptions.create(
77
- model="whisper-1",
78
  file=audio_segment,
79
  language=language
80
  )
@@ -84,7 +92,7 @@ def transcribe_audio(audio_file, language=None):
84
  else:
85
  with open(audio_file.name, "rb") as audio_file:
86
  transcript = client.audio.transcriptions.create(
87
- model="whisper-1",
88
  file=audio_file,
89
  language=language
90
  )
@@ -94,10 +102,13 @@ def transcribe_audio(audio_file, language=None):
94
  def language_detection(input_text, temperature=0.01):
95
  system_prompt = "".join([
96
  "Je souhaite que vous agissiez en tant que fonction linguistique.",
97
- "Je m'exprimerai dans n'importe quelle langue, et vous en détecterez la langue.",
 
98
  "Vous fournirez le résultat de votre détection au format ISO-639-1.",
99
- "Votre réponse doit représenter l'argument `language` et contenir seulement sa valeur de type chaîne de caractères.",
100
- "La langue de l'audio d'entrée. Fournir la langue d'entrée au format ISO-639-1 améliorera la précision et la latence."
 
 
101
  ])
102
  response = client.chat.completions.create(
103
  model="gpt-4o-mini",
@@ -119,6 +130,7 @@ def get_duration_pydub(audio_file):
119
  audio = AudioSegment.from_file(audio_file)
120
  return audio.duration_seconds
121
 
 
122
  # Fonction pour convertir du texte en parole
123
  def text_to_speech(text):
124
  response = client.audio.speech.create(
@@ -145,8 +157,12 @@ def concatenate_audio_files(audio_list):
145
  final_audio = AudioSegment.empty()
146
 
147
  # Charger les effets sonores
148
- begin_sound = AudioSegment.from_mp3("sound-effects/voice-message-play-begin/voice-message-play-begin-1.mp3")
149
- end_sound = AudioSegment.from_mp3("sound-effects/voice-message-play-ending/voice-message-play-ending-1.mp3")
 
 
 
 
150
 
151
  # Silence de 5 secondes
152
  silence = AudioSegment.silent(duration=5000) # 5000 ms = 5 secondes
@@ -155,7 +171,7 @@ def concatenate_audio_files(audio_list):
155
  # Convertir les bytes en un segment audio
156
  segment = AudioSegment.from_mp3(io.BytesIO(audio_bytes))
157
 
158
- # Ajouter le son de début, le segment TTS, le son de fin, et le silence au final_audio
159
  final_audio += begin_sound + segment + end_sound + silence
160
 
161
  # Convertir le segment audio final en bytes
@@ -164,10 +180,8 @@ def concatenate_audio_files(audio_list):
164
  return buffer.getvalue()
165
 
166
  # Fonction pour traiter les messages de l'utilisateur et générer une réponse
167
- def process_message(message,
168
- operation_prompt="",
169
- tts_enabled=False):
170
- payload_content = f'{operation_prompt} :\n\"\"\"\n{message}\n\"\"\"'
171
 
172
  st.session_state.messages.append({"role": "user", "content": payload_content})
173
  with st.chat_message("user"):
@@ -177,18 +191,20 @@ def process_message(message,
177
  message_placeholder = st.empty()
178
  full_response = ""
179
  for response in client.chat.completions.create(
180
- model="gpt-4o-mini",
181
- messages=st.session_state.messages,
182
- stream=True,
183
- temperature=0.1,
184
- ):
185
  full_response += (response.choices[0].delta.content or "")
186
  message_placeholder.markdown(full_response + "▌")
187
- # Utiliser un regex pour retirer les trois premières et dernières doubles quotes
 
188
  full_response = re.sub(r'^"{3}|"{3}$', '', full_response.strip())
189
  message_placeholder.markdown(full_response)
190
 
191
- st.session_state.messages.append({"role": "assistant", "content": full_response})
 
 
192
 
193
  if tts_enabled:
194
  tts_audio, tts_duration = text_to_speech(full_response)
@@ -202,19 +218,32 @@ class GlobalSystemPrompts:
202
  SYSTEM_PROMPT = f"{lire_fichier('linguascribe.prompt')}"
203
  return SYSTEM_PROMPT
204
 
 
205
  # Variables globales pour les prompts
206
- SYSTEM_PROMPT=""
207
- OP_PROMPT=""
 
208
 
209
  # Fonction pour configurer le mode de traduction
210
  def set_mode_translation(from_lang, dest_lang):
211
  global SYSTEM_PROMPT
212
  global OP_PROMPT
213
- SYSTEM_PROMPT=GlobalSystemPrompts.linguascribe()
214
  OP_PROMPT = f"Translate({from_lang} to {dest_lang})"
215
 
 
216
  # Liste des langues supportées par l'application
217
- SUPPORTED_LANGUAGES=["Afrikaans", "Arabic", "Armenian", "Azerbaijani", "Belarusian", "Bosnian", "Bulgarian", "Catalan", "Chinese", "Croatian", "Czech", "Danish", "Dutch", "English", "Estonian", "Finnish", "French", "Galician", "German", "Greek", "Hebrew", "Hindi", "Hungarian", "Icelandic", "Indonesian", "Italian", "Japanese", "Kannada", "Kazakh", "Korean", "Latvian", "Lithuanian", "Macedonian", "Malay", "Marathi", "Maori", "Nepali", "Norwegian", "Persian", "Polish", "Portuguese", "Romanian", "Russian", "Serbian", "Slovak", "Slovenian", "Spanish", "Swahili", "Swedish", "Tagalog", "Tamil", "Thai", "Turkish", "Ukrainian", "Urdu", "Vietnamese", "Welsh"]
 
 
 
 
 
 
 
 
 
 
218
 
219
  # Fonction pour convertir le nom d'une langue en code ISO 639-1
220
  def convert_language_name_to_iso6391(language_data):
@@ -261,7 +290,9 @@ def main():
261
  st.session_state.target_language = "en"
262
 
263
  if "selected_languages" not in st.session_state:
264
- st.session_state.selected_languages = [{"language": "English", "iso-639-1": "en"}]
 
 
265
 
266
  if "enable_tts_for_input_from_text_field" not in st.session_state:
267
  st.session_state["enable_tts_for_input_from_text_field"] = True
@@ -272,12 +303,13 @@ def main():
272
  if "interface_language" not in st.session_state:
273
  st.session_state.interface_language = "French" # Langue par défaut
274
 
275
-
276
  def init_process_mode():
277
  # Configuration du mode de traduction si nécessaire
278
  if "translation" == st.session_state["process_mode"]:
279
- set_mode_translation(from_lang=st.session_state.language_detected, dest_lang=st.session_state.target_language)
280
-
 
 
281
 
282
  init_process_mode()
283
 
@@ -293,8 +325,10 @@ def main():
293
  if user_input := st.chat_input(_("entrez_message")):
294
  # Traitement du message textuel de l'utilisateur
295
  if None == st.session_state.language_detected:
296
- st.session_state.language_detected = language_detection(input_text=user_input, temperature=0.01)
297
-
 
 
298
  audio_list = []
299
  for cursor_selected_lang in st.session_state.selected_languages:
300
  st.session_state.target_language = cursor_selected_lang["iso-639-1"]
@@ -303,32 +337,29 @@ def main():
303
  init_process_mode()
304
 
305
  # Traitement du message de l'utilisateur pour la langue cible actuelle
306
- tts_audio, tts_duration = process_message(
307
- user_input,
308
- operation_prompt=f"{OP_PROMPT}",
309
- tts_enabled=st.session_state.enable_tts_for_input_from_text_field
310
- )
311
  if tts_audio is not None:
312
  audio_list.append((tts_audio, tts_duration))
313
-
314
  if audio_list:
315
  final_audio = concatenate_audio_files(audio_list)
316
- st.audio(final_audio,
317
- format="audio/mp3",
318
- autoplay=True)
319
-
320
 
321
  with st.container(border=True):
322
  # Interface utilisateur pour l'enregistrement audio
323
  st.write(_("enregistrez_message"))
324
- audio = audiorecorder(start_prompt=_("cliquez_enregistrer"),
325
- stop_prompt=_("cliquez_arreter"),
326
- pause_prompt=_("cliquez_pause"),
327
- show_visualizer=True,
328
- key="vocal_chat_input"
 
329
  )
330
 
331
-
332
  # Traitement de l'entrée audio de l'utilisateur
333
  if len(audio) > 0:
334
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_audio:
@@ -336,7 +367,9 @@ def main():
336
  transcription = transcribe_audio(temp_audio, language=st.session_state.language_detected)
337
  os.unlink(temp_audio.name) # Supprimer le fichier temporaire
338
  if None == st.session_state.language_detected:
339
- st.session_state.language_detected = language_detection(input_text=transcription, temperature=0.01)
 
 
340
  st.write(_("langue_detectee").format(st.session_state.language_detected))
341
 
342
  st.write(_("transcription").format(transcription))
@@ -349,18 +382,16 @@ def main():
349
  init_process_mode()
350
 
351
  # Traitement du message de l'utilisateur pour la langue cible actuelle
352
- tts_audio, tts_duration = process_message(
353
- transcription,
354
- operation_prompt=f"{OP_PROMPT}",
355
- tts_enabled=st.session_state.enable_tts_for_input_from_audio_record
356
- )
357
  if tts_audio is not None:
358
  audio_list.append((tts_audio, tts_duration))
359
  if audio_list:
360
  final_audio = concatenate_audio_files(audio_list)
361
- st.audio(final_audio,
362
- format="audio/mp3",
363
- autoplay=True)
364
 
365
  # Configuration de la barre latérale
366
  with st.sidebar:
@@ -370,7 +401,6 @@ def main():
370
 
371
  # Fonction de rappel pour le changement de(s) langue(s) de destination selectionnée(s)
372
  def on_languages_change():
373
-
374
  selected_language_names = st.session_state.language_selector
375
  st.session_state.selected_languages = [
376
  {"language": lang, "iso-639-1": convert_language_name_to_iso6391(lang)}
@@ -384,13 +414,17 @@ def main():
384
  label=_("choix_langue_interface"),
385
  options=list(traductions.keys()),
386
  key="interface_language",
387
- index=list(traductions.keys()).index("French") if "interface_language" not in st.session_state else list(traductions.keys()).index(st.session_state.interface_language)
 
 
 
 
388
  )
389
 
390
  with st.container(border=True):
391
  # Conteneur pour la sélection de la langue
392
  st.subheader(_("selection_langue"))
393
-
394
  # Sélection multiple des langues de destination
395
  st.multiselect(
396
  label=_("langues_destination"),
@@ -417,7 +451,7 @@ def main():
417
  st.checkbox(
418
  _("activer_tts_audio"),
419
  key="enable_tts_for_input_from_audio_record"
420
- )
421
 
422
  # Point d'entrée de l'application
423
  if __name__ == "__main__":
 
1
+ # Bibliothèques standard
 
 
 
 
2
  import base64
 
 
3
  import io
 
 
 
4
  import json
5
+ import os
6
+ import re
7
+ import tempfile
8
+ import time
9
+ from os import getenv
10
+ from typing import Any, Optional, Union
11
+
12
+ # Bibliothèques tierces
13
+ import streamlit as st
14
+ from audiorecorder import audiorecorder
15
+ from openai import OpenAI
16
+ from pydub import AudioSegment
17
 
18
  def load_lang_ui(filepath: Optional[str] = "ui_lang_support.json") -> dict:
19
  try:
 
23
  print(_("erreur_fichier_non_trouve").format(filepath))
24
  return {}
25
  except json.JSONDecodeError:
26
+ print(_("erreur_lecture_fichier").format(
27
+ "Erreur de décodage JSON"
28
+ ))
29
  return {}
30
  except Exception as e:
31
  print(_("erreur_lecture_fichier").format(str(e)))
 
56
  def split_audio(audio_file, max_size_mb=25):
57
  audio = AudioSegment.from_wav(audio_file)
58
  duration_ms = len(audio)
59
+ segment_duration_ms = int(
60
+ (max_size_mb * 1024 * 1024 * 8) /
61
+ (audio.frame_rate * audio.sample_width * audio.channels)
62
+ )
63
+
64
  segments = []
65
  for start in range(0, duration_ms, segment_duration_ms):
66
  end = min(start + segment_duration_ms, duration_ms)
 
68
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_segment:
69
  segment.export(temp_segment.name, format="wav")
70
  segments.append(temp_segment.name)
71
+
72
  return segments
73
 
74
  # Fonction modifiée pour transcrire l'audio en texte
 
82
  for segment in segments:
83
  with open(segment, "rb") as audio_segment:
84
  transcript = client.audio.transcriptions.create(
85
+ model="whisper-1",
86
  file=audio_segment,
87
  language=language
88
  )
 
92
  else:
93
  with open(audio_file.name, "rb") as audio_file:
94
  transcript = client.audio.transcriptions.create(
95
+ model="whisper-1",
96
  file=audio_file,
97
  language=language
98
  )
 
102
  def language_detection(input_text, temperature=0.01):
103
  system_prompt = "".join([
104
  "Je souhaite que vous agissiez en tant que fonction linguistique.",
105
+ "Je m'exprimerai dans n'importe quelle langue, et vous en détecterez ",
106
+ "la langue.",
107
  "Vous fournirez le résultat de votre détection au format ISO-639-1.",
108
+ "Votre réponse doit représenter l'argument `language` et contenir ",
109
+ "seulement sa valeur de type chaîne de caractères.",
110
+ "La langue de l'audio d'entrée. Fournir la langue d'entrée au format ",
111
+ "ISO-639-1 améliorera la précision et la latence."
112
  ])
113
  response = client.chat.completions.create(
114
  model="gpt-4o-mini",
 
130
  audio = AudioSegment.from_file(audio_file)
131
  return audio.duration_seconds
132
 
133
+
134
  # Fonction pour convertir du texte en parole
135
  def text_to_speech(text):
136
  response = client.audio.speech.create(
 
157
  final_audio = AudioSegment.empty()
158
 
159
  # Charger les effets sonores
160
+ begin_sound = AudioSegment.from_mp3(
161
+ "sound-effects/voice-message-play-begin/voice-message-play-begin-1.mp3"
162
+ )
163
+ end_sound = AudioSegment.from_mp3(
164
+ "sound-effects/voice-message-play-ending/voice-message-play-ending-1.mp3"
165
+ )
166
 
167
  # Silence de 5 secondes
168
  silence = AudioSegment.silent(duration=5000) # 5000 ms = 5 secondes
 
171
  # Convertir les bytes en un segment audio
172
  segment = AudioSegment.from_mp3(io.BytesIO(audio_bytes))
173
 
174
+ # Ajouter le son de début, le segment TTS, le son de fin, et le silence
175
  final_audio += begin_sound + segment + end_sound + silence
176
 
177
  # Convertir le segment audio final en bytes
 
180
  return buffer.getvalue()
181
 
182
  # Fonction pour traiter les messages de l'utilisateur et générer une réponse
183
+ def process_message(message, operation_prompt="", tts_enabled=False):
184
+ payload_content = f'{operation_prompt} :\n"""\n{message}\n"""'
 
 
185
 
186
  st.session_state.messages.append({"role": "user", "content": payload_content})
187
  with st.chat_message("user"):
 
191
  message_placeholder = st.empty()
192
  full_response = ""
193
  for response in client.chat.completions.create(
194
+ model="gpt-4o-mini",
195
+ messages=st.session_state.messages,
196
+ stream=True,
197
+ temperature=0.1):
 
198
  full_response += (response.choices[0].delta.content or "")
199
  message_placeholder.markdown(full_response + "▌")
200
+ # Utiliser un regex pour retirer les trois premières et dernières
201
+ # doubles quotes
202
  full_response = re.sub(r'^"{3}|"{3}$', '', full_response.strip())
203
  message_placeholder.markdown(full_response)
204
 
205
+ st.session_state.messages.append(
206
+ {"role": "assistant", "content": full_response}
207
+ )
208
 
209
  if tts_enabled:
210
  tts_audio, tts_duration = text_to_speech(full_response)
 
218
  SYSTEM_PROMPT = f"{lire_fichier('linguascribe.prompt')}"
219
  return SYSTEM_PROMPT
220
 
221
+
222
  # Variables globales pour les prompts
223
+ SYSTEM_PROMPT = ""
224
+ OP_PROMPT = ""
225
+
226
 
227
  # Fonction pour configurer le mode de traduction
228
  def set_mode_translation(from_lang, dest_lang):
229
  global SYSTEM_PROMPT
230
  global OP_PROMPT
231
+ SYSTEM_PROMPT = GlobalSystemPrompts.linguascribe()
232
  OP_PROMPT = f"Translate({from_lang} to {dest_lang})"
233
 
234
+
235
  # Liste des langues supportées par l'application
236
+ SUPPORTED_LANGUAGES = [
237
+ "Afrikaans", "Arabic", "Armenian", "Azerbaijani", "Belarusian", "Bosnian",
238
+ "Bulgarian", "Catalan", "Chinese", "Croatian", "Czech", "Danish", "Dutch",
239
+ "English", "Estonian", "Finnish", "French", "Galician", "German", "Greek",
240
+ "Hebrew", "Hindi", "Hungarian", "Icelandic", "Indonesian", "Italian",
241
+ "Japanese", "Kannada", "Kazakh", "Korean", "Latvian", "Lithuanian",
242
+ "Macedonian", "Malay", "Marathi", "Maori", "Nepali", "Norwegian", "Persian",
243
+ "Polish", "Portuguese", "Romanian", "Russian", "Serbian", "Slovak",
244
+ "Slovenian", "Spanish", "Swahili", "Swedish", "Tagalog", "Tamil", "Thai",
245
+ "Turkish", "Ukrainian", "Urdu", "Vietnamese", "Welsh"
246
+ ]
247
 
248
  # Fonction pour convertir le nom d'une langue en code ISO 639-1
249
  def convert_language_name_to_iso6391(language_data):
 
290
  st.session_state.target_language = "en"
291
 
292
  if "selected_languages" not in st.session_state:
293
+ st.session_state.selected_languages = [
294
+ {"language": "English", "iso-639-1": "en"}
295
+ ]
296
 
297
  if "enable_tts_for_input_from_text_field" not in st.session_state:
298
  st.session_state["enable_tts_for_input_from_text_field"] = True
 
303
  if "interface_language" not in st.session_state:
304
  st.session_state.interface_language = "French" # Langue par défaut
305
 
 
306
  def init_process_mode():
307
  # Configuration du mode de traduction si nécessaire
308
  if "translation" == st.session_state["process_mode"]:
309
+ set_mode_translation(
310
+ from_lang=st.session_state.language_detected,
311
+ dest_lang=st.session_state.target_language
312
+ )
313
 
314
  init_process_mode()
315
 
 
325
  if user_input := st.chat_input(_("entrez_message")):
326
  # Traitement du message textuel de l'utilisateur
327
  if None == st.session_state.language_detected:
328
+ st.session_state.language_detected = language_detection(
329
+ input_text=user_input, temperature=0.01
330
+ )
331
+
332
  audio_list = []
333
  for cursor_selected_lang in st.session_state.selected_languages:
334
  st.session_state.target_language = cursor_selected_lang["iso-639-1"]
 
337
  init_process_mode()
338
 
339
  # Traitement du message de l'utilisateur pour la langue cible actuelle
340
+ tts_audio, tts_duration = process_message(
341
+ user_input,
342
+ operation_prompt=f"{OP_PROMPT}",
343
+ tts_enabled=st.session_state.enable_tts_for_input_from_text_field
344
+ )
345
  if tts_audio is not None:
346
  audio_list.append((tts_audio, tts_duration))
347
+
348
  if audio_list:
349
  final_audio = concatenate_audio_files(audio_list)
350
+ st.audio(final_audio, format="audio/mp3", autoplay=True)
 
 
 
351
 
352
  with st.container(border=True):
353
  # Interface utilisateur pour l'enregistrement audio
354
  st.write(_("enregistrez_message"))
355
+ audio = audiorecorder(
356
+ start_prompt=_("cliquez_enregistrer"),
357
+ stop_prompt=_("cliquez_arreter"),
358
+ pause_prompt=_("cliquez_pause"),
359
+ show_visualizer=True,
360
+ key="vocal_chat_input"
361
  )
362
 
 
363
  # Traitement de l'entrée audio de l'utilisateur
364
  if len(audio) > 0:
365
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_audio:
 
367
  transcription = transcribe_audio(temp_audio, language=st.session_state.language_detected)
368
  os.unlink(temp_audio.name) # Supprimer le fichier temporaire
369
  if None == st.session_state.language_detected:
370
+ st.session_state.language_detected = language_detection(
371
+ input_text=transcription, temperature=0.01
372
+ )
373
  st.write(_("langue_detectee").format(st.session_state.language_detected))
374
 
375
  st.write(_("transcription").format(transcription))
 
382
  init_process_mode()
383
 
384
  # Traitement du message de l'utilisateur pour la langue cible actuelle
385
+ tts_audio, tts_duration = process_message(
386
+ transcription,
387
+ operation_prompt=f"{OP_PROMPT}",
388
+ tts_enabled=st.session_state.enable_tts_for_input_from_audio_record
389
+ )
390
  if tts_audio is not None:
391
  audio_list.append((tts_audio, tts_duration))
392
  if audio_list:
393
  final_audio = concatenate_audio_files(audio_list)
394
+ st.audio(final_audio, format="audio/mp3", autoplay=True)
 
 
395
 
396
  # Configuration de la barre latérale
397
  with st.sidebar:
 
401
 
402
  # Fonction de rappel pour le changement de(s) langue(s) de destination selectionnée(s)
403
  def on_languages_change():
 
404
  selected_language_names = st.session_state.language_selector
405
  st.session_state.selected_languages = [
406
  {"language": lang, "iso-639-1": convert_language_name_to_iso6391(lang)}
 
414
  label=_("choix_langue_interface"),
415
  options=list(traductions.keys()),
416
  key="interface_language",
417
+ index=(
418
+ list(traductions.keys()).index("French")
419
+ if "interface_language" not in st.session_state
420
+ else list(traductions.keys()).index(st.session_state.interface_language)
421
+ )
422
  )
423
 
424
  with st.container(border=True):
425
  # Conteneur pour la sélection de la langue
426
  st.subheader(_("selection_langue"))
427
+
428
  # Sélection multiple des langues de destination
429
  st.multiselect(
430
  label=_("langues_destination"),
 
451
  st.checkbox(
452
  _("activer_tts_audio"),
453
  key="enable_tts_for_input_from_audio_record"
454
+ )
455
 
456
  # Point d'entrée de l'application
457
  if __name__ == "__main__":