ManuelZafra commited on
Commit
cc9f9e3
·
verified ·
1 Parent(s): 1f71c1c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +241 -479
app.py CHANGED
@@ -9,14 +9,13 @@ from tools.final_answer import FinalAnswerTool
9
  import logging
10
 
11
  # Configurar logging para depuración
12
- logging.basicConfig(level=logging.INFO,
13
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
14
  logger = logging.getLogger('music_recognition_app')
15
 
16
  # File to save the history of recognized songs
17
  HISTORY_FILE = "song_history.json"
18
 
19
- # Supported languages - removed German
20
  LANGUAGES = {
21
  "English": "en",
22
  "Español": "es",
@@ -27,16 +26,14 @@ LANGUAGES = {
27
  UI_MESSAGES = {
28
  "en": {
29
  "title": "Music Recognition & Fun Facts",
30
- "subtitle": "Record a song and get interesting facts about the artist",
31
  "choose_language": "Choose your language",
32
- "rec_button": "🎙 REC AND IDENTIFY SONG",
33
- "please_record": "Please click REC to record a song or upload an audio file",
34
  "recording": "Recording... Click Stop when done",
35
- "audio_loaded": " Audio loaded! Identifying song...",
36
- "loading_audio": "Please wait while processing the audio",
37
- "searching_song": "Searching for your song in the sound multiverse, please wait...",
38
- "identified_song": "🎵 Identified Song: \"{song}\" by {artist}",
39
- "loading_artist_info": "Now loading interesting facts about {artist}...",
40
  "song_recognized": "Song successfully recognized! Ask questions about the artist in the chat below",
41
  "about_artist": "About",
42
  "ask_more": "Ask me more about this artist or music in general",
@@ -45,7 +42,7 @@ UI_MESSAGES = {
45
  "history_tab": "Song History",
46
  "history_title": "History of recognized songs",
47
  "songs_to_show": "Number of songs to show",
48
- "view_history": "📋 View History",
49
  "recognized_song": "Recognized Song",
50
  "artist": "Artist",
51
  "album": "Album",
@@ -56,16 +53,14 @@ UI_MESSAGES = {
56
  },
57
  "es": {
58
  "title": "Reconocimiento de Música y Datos Curiosos",
59
- "subtitle": "Graba una canción y obtén datos interesantes sobre el artista",
60
  "choose_language": "Elige tu idioma",
61
- "rec_button": "🎙 GRABAR E IDENTIFICAR CANCIÓN",
62
- "please_record": "Haz clic en GRABAR para grabar una canción o sube un archivo de audio",
63
  "recording": "Grabando... Haz clic en Detener cuando termines",
64
- "audio_loaded": " ¡Audio cargado! Identificando canción...",
65
- "loading_audio": "Por favor espere mientras se procesa el audio",
66
- "searching_song": "Buscando tu canción en el multiverso sonoro, por favor espera...",
67
- "identified_song": "🎵 Canción identificada: \"{song}\" por {artist}",
68
- "loading_artist_info": "Ahora cargando datos interesantes sobre {artist}...",
69
  "song_recognized": "¡Canción reconocida con éxito! Haz preguntas sobre el artista en el chat de abajo",
70
  "about_artist": "Sobre",
71
  "ask_more": "Pregúntame más sobre este artista o música en general",
@@ -74,7 +69,7 @@ UI_MESSAGES = {
74
  "history_tab": "Historial de Canciones",
75
  "history_title": "Historial de canciones reconocidas",
76
  "songs_to_show": "Número de canciones para mostrar",
77
- "view_history": "📋 Ver Historial",
78
  "recognized_song": "Canción Reconocida",
79
  "artist": "Artista",
80
  "album": "Álbum",
@@ -85,16 +80,14 @@ UI_MESSAGES = {
85
  },
86
  "fr": {
87
  "title": "Reconnaissance de Musique et Anecdotes",
88
- "subtitle": "Enregistrez une chanson et découvrez des faits intéressants sur l'artiste",
89
  "choose_language": "Choisissez votre langue",
90
- "rec_button": "🎙 ENREGISTRER ET IDENTIFIER LA CHANSON",
91
- "please_record": "Cliquez sur ENREGISTRER pour enregistrer une chanson ou téléchargez un fichier audio",
92
  "recording": "Enregistrement... Cliquez sur Arrêter quand vous avez terminé",
93
- "audio_loaded": " Audio chargé ! Identification de la chanson...",
94
- "loading_audio": "Veuillez patienter pendant le traitement de l'audio",
95
- "searching_song": "Recherche de votre chanson dans le multivers sonore, veuillez patienter...",
96
- "identified_song": "🎵 Chanson identifiée: \"{song}\" par {artist}",
97
- "loading_artist_info": "Chargement de faits intéressants sur {artist}...",
98
  "song_recognized": "Chanson reconnue avec succès ! Posez des questions sur l'artiste dans le chat ci-dessous",
99
  "about_artist": "À propos de",
100
  "ask_more": "Demandez-moi plus d'informations sur cet artiste ou sur la musique en général",
@@ -103,7 +96,7 @@ UI_MESSAGES = {
103
  "history_tab": "Historique des Chansons",
104
  "history_title": "Historique des chansons reconnues",
105
  "songs_to_show": "Nombre de chansons à afficher",
106
- "view_history": "📋 Voir l'historique",
107
  "recognized_song": "Chanson Reconnue",
108
  "artist": "Artiste",
109
  "album": "Album",
@@ -122,35 +115,24 @@ def recognize_song(audio_path: str) -> dict:
122
  audio_path: path to the audio file to recognize
123
  """
124
  AUDD_API_TOKEN = os.getenv("AUDD_API_TOKEN")
125
-
126
  if not os.path.exists(audio_path):
127
  return {"error": "The audio file does not exist"}
128
-
129
  try:
130
  with open(audio_path, 'rb') as file:
131
  data = {
132
  'api_token': AUDD_API_TOKEN,
133
  'return': 'spotify,apple_music'
134
  }
135
- files = {
136
- 'file': file
137
- }
138
  response = requests.post('https://api.audd.io/', data=data, files=files)
139
-
140
  if response.status_code != 200:
141
  return {"error": f"API Error: {response.status_code}"}
142
-
143
  result = response.json()
144
-
145
  if result['status'] == 'error':
146
  return {"error": result['error']['error_message']}
147
-
148
  if not result.get('result'):
149
  return {"error": "Could not recognize the song"}
150
-
151
  song_info = result['result']
152
-
153
- # Create object with song information
154
  song_data = {
155
  "Song": song_info.get('title', 'Unknown'),
156
  "Artist": song_info.get('artist', 'Unknown'),
@@ -159,12 +141,8 @@ def recognize_song(audio_path: str) -> dict:
159
  "Apple Music": song_info.get('apple_music', {}).get('url', 'Not available'),
160
  "Recognition Date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
161
  }
162
-
163
- # Save to history
164
  save_to_history(song_data)
165
-
166
  return song_data
167
-
168
  except Exception as e:
169
  return {"error": f"Error processing audio: {str(e)}"}
170
 
@@ -172,7 +150,6 @@ def recognize_song(audio_path: str) -> dict:
172
  def save_to_history(song_data):
173
  """Saves a song to the history"""
174
  try:
175
- # Load existing history or create new
176
  if os.path.exists(HISTORY_FILE):
177
  with open(HISTORY_FILE, 'r') as f:
178
  try:
@@ -181,18 +158,11 @@ def save_to_history(song_data):
181
  history = []
182
  else:
183
  history = []
184
-
185
- # Add song to the beginning of history (most recent first)
186
  history.insert(0, song_data)
187
-
188
- # Limit history to the 50 most recent songs
189
  if len(history) > 50:
190
  history = history[:50]
191
-
192
- # Save updated history
193
  with open(HISTORY_FILE, 'w') as f:
194
  json.dump(history, f, indent=2)
195
-
196
  except Exception as e:
197
  print(f"Error saving to history: {str(e)}")
198
 
@@ -205,37 +175,25 @@ def view_song_history(limit: int = 10) -> str:
205
  """
206
  try:
207
  if not os.path.exists(HISTORY_FILE):
208
- return "📋 No song recognition history yet."
209
-
210
  with open(HISTORY_FILE, 'r') as f:
211
  try:
212
  history = json.load(f)
213
  except json.JSONDecodeError:
214
  return "📋 Error loading song history."
215
-
216
  if not history:
217
  return "📋 Song history is empty."
218
-
219
- # Limit the number of songs to display
220
  history = history[:min(limit, len(history))]
221
-
222
- # Format output
223
  result = "📋 **Song Recognition History:**\n\n"
224
-
225
  for i, song in enumerate(history, 1):
226
  result += f"{i}. **{song.get('Song', 'Unknown')}** - *{song.get('Artist', 'Unknown')}*\n"
227
  result += f" 📀 Album: {song.get('Album', 'Unknown')}\n"
228
-
229
  if song.get('Spotify', 'Not available') != 'Not available':
230
  result += f" 🎧 [Spotify]({song.get('Spotify')})\n"
231
-
232
  if song.get('Apple Music', 'Not available') != 'Not available':
233
  result += f" 🍏 [Apple Music]({song.get('Apple Music')})\n"
234
-
235
  result += f" 🕒 Recognized on: {song.get('Recognition Date', 'Unknown date')}\n\n"
236
-
237
  return result
238
-
239
  except Exception as e:
240
  return f"❌ Error getting history: {str(e)}"
241
 
@@ -243,32 +201,20 @@ def view_song_history(limit: int = 10) -> str:
243
  @tool
244
  def get_artist_info(artist_name: str, song_name: str = "", language: str = "en") -> str:
245
  """Gets detailed background information, fun facts about a music artist and the specific song in the specified language
246
-
247
  Args:
248
  artist_name: name of the artist to get information about
249
  song_name: name of the song (if available)
250
  language: language code (en, es, fr)
251
  """
252
- # Language-specific prompts
253
  prompts = {
254
  "en": f"Provide a comprehensive overview about the music artist '{artist_name}'. Include the following sections clearly marked with headers:\n\n1. General Biography: Brief overview of their career and significance in music.\n\n2. Fun Facts: 4-5 surprising or interesting facts about the artist or group that fans would find fascinating.\n\n3. Behind-the-scenes Anecdotes: 2-3 memorable stories about the artist's career, performances, or personal life that showcase their character or impact.\n\n" + (f'4. About the Song "{song_name}": If you know anything specific about how this song was created, its meaning, its impact, or interesting trivia related to it, please share those details.' if song_name else '') + "\n\nKeep the tone engaging and enthusiastic, highlighting what makes this artist unique and beloved by fans. Limit your response to around 500 words total.",
255
-
256
  "es": f"Proporciona una visión completa sobre el artista musical '{artist_name}'. Incluye las siguientes secciones claramente marcadas con encabezados:\n\n1. Biografía General: Breve resumen de su carrera y significado en la música.\n\n2. Datos Curiosos: 4-5 hechos sorprendentes o interesantes sobre el artista o grupo que los fans encontrarían fascinantes.\n\n3. Anécdotas entre bastidores: 2-3 historias memorables sobre la carrera del artista, actuaciones o vida personal que muestren su carácter o impacto.\n\n" + (f'4. Sobre la canción "{song_name}": Si conoces algo específico sobre cómo se creó esta canción, su significado, su impacto o curiosidades interesantes relacionadas con ella, por favor comparte esos detalles.' if song_name else '') + "\n\nMantén un tono atractivo y entusiasta, destacando lo que hace que este artista sea único y querido por los fans. Limita tu respuesta a alrededor de 500 palabras en total.",
257
-
258
  "fr": f"Fournissez un aperçu complet de l'artiste musical '{artist_name}'. Incluez les sections suivantes clairement marquées avec des en-têtes:\n\n1. Biographie générale: Bref aperçu de sa carrière et de son importance dans la musique.\n\n2. Anecdotes intéressantes: 4-5 faits surprenants ou intéressants sur l'artiste ou le groupe que les fans trouveraient fascinants.\n\n3. Anecdotes en coulisses: 2-3 histoires mémorables sur la carrière de l'artiste, ses performances ou sa vie personnelle qui mettent en valeur son caractère ou son impact.\n\n" + (f'4. À propos de la chanson "{song_name}": Si vous connaissez quelque chose de spécifique sur la façon dont cette chanson a été créée, sa signification, son impact ou des anecdotes intéressantes liées à elle, veuillez partager ces détails.' if song_name else '') + "\n\nGardez un ton engageant et enthousiaste, mettant en évidence ce qui rend cet artiste unique et apprécié des fans. Limitez votre réponse à environ 500 mots au total."
259
  }
260
-
261
- # Default to English if language not supported
262
  if language not in prompts:
263
  language = "en"
264
-
265
- # Create messages for the model
266
- messages = [
267
- {"role": "user", "content": prompts[language]}
268
- ]
269
-
270
  try:
271
- # Using the same model that powers our agent
272
  response = model(messages)
273
  return response.content
274
  except Exception as e:
@@ -283,30 +229,19 @@ def chat_with_assistant(query: str, artist_info: str = "", language: str = "en")
283
  artist_info: previous artist info to provide context
284
  language: language code (en, es, fr)
285
  """
286
- # Language-specific system messages
287
  system_messages = {
288
  "en": "You are a music expert assistant who specializes in providing engaging information about artists, songs, and music history. Focus on sharing interesting, fun facts that highlight the artist's unique contributions and stories.",
289
  "es": "Eres un asistente experto en música que se especializa en proporcionar información interesante sobre artistas, canciones e historia musical. Céntrate en compartir datos curiosos e interesantes que destaquen las contribuciones únicas y las historias del artista.",
290
  "fr": "Vous êtes un assistant expert en musique qui se spécialise dans la fourniture d'informations intéressantes sur les artistes, les chansons et l'histoire de la musique. Concentrez-vous sur le partage de faits intéressants et amusants qui mettent en évidence les contributions uniques et les histoires de l'artiste."
291
  }
292
-
293
- # Default to English if language not supported
294
  if language not in system_messages:
295
  language = "en"
296
-
297
- # Create context
298
- context = ""
299
- if artist_info:
300
- context = f"Previous context about the artist: {artist_info}\n\n"
301
-
302
- # Create messages for the model
303
  messages = [
304
  {"role": "system", "content": system_messages[language]},
305
  {"role": "user", "content": context + query}
306
  ]
307
-
308
  try:
309
- # Using the model to generate a response
310
  response = model(messages)
311
  return response.content
312
  except Exception as e:
@@ -320,20 +255,12 @@ model = HfApiModel(
320
  model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
321
  custom_role_conversions=None,
322
  )
323
-
324
  with open("prompts.yaml", 'r') as stream:
325
  prompt_templates = yaml.safe_load(stream)
326
 
327
- # Agent definition
328
  agent = CodeAgent(
329
  model=model,
330
- tools=[
331
- final_answer,
332
- recognize_song,
333
- view_song_history,
334
- get_artist_info,
335
- chat_with_assistant
336
- ],
337
  max_steps=8,
338
  verbosity_level=1,
339
  grammar=None,
@@ -345,58 +272,14 @@ agent = CodeAgent(
345
 
346
  # Gradio user interface con CSS personalizado para mejor experiencia móvil
347
  with gr.Blocks(title="Music Recognition & Fun Facts", css="""
348
- .large-button {
349
- min-height: 60px !important;
350
- font-size: 18px !important;
351
- padding: 15px !important;
352
- }
353
  @media (max-width: 600px) {
354
- .large-button {
355
- width: 100% !important;
356
- margin-bottom: 10px !important;
357
- }
358
- #audio-input {
359
- width: 100% !important;
360
- margin-top: 10px !important;
361
- margin-bottom: 10px !important;
362
- }
363
- /* Hacer el botón de grabar y parar más grande */
364
- button.record, button.stop {
365
- width: 60px !important;
366
- height: 60px !important;
367
- border-radius: 50% !important;
368
- }
369
- /* Hacer el texto de error más visible */
370
- .error-text {
371
- color: red !important;
372
- font-weight: bold !important;
373
- font-size: 16px !important;
374
- }
375
- /* Destacar el título de la canción identificada */
376
- .identified-song {
377
- font-size: 1.3em !important;
378
- margin: 15px 0 !important;
379
- padding: 10px !important;
380
- border-radius: 5px !important;
381
- background-color: rgba(0, 123, 255, 0.1) !important;
382
- border-left: 4px solid #007bff !important;
383
- }
384
- }
385
- /* Estilos para el indicador de micrófono */
386
- #mic-status {
387
- margin-top: 5px;
388
- margin-bottom: 15px;
389
- font-style: italic;
390
- }
391
- /* Destacar el título de la canción identificada */
392
- .identified-song {
393
- font-size: 1.2em;
394
- margin: 10px 0;
395
- padding: 8px;
396
- border-radius: 5px;
397
- background-color: rgba(0, 123, 255, 0.1);
398
- border-left: 4px solid #007bff;
399
  }
 
400
  """) as demo:
401
  # State variables
402
  selected_language = gr.State("en")
@@ -404,19 +287,19 @@ with gr.Blocks(title="Music Recognition & Fun Facts", css="""
404
  song_info_state = gr.State(None)
405
  artist_info_state = gr.State("")
406
  song_name_state = gr.State("")
407
- audio_status = gr.State("no_audio") # States: no_audio, loading, ready, processing
408
-
409
  # Function to get UI messages based on language
410
  def get_ui_message(message_key, language_code="en"):
411
  return UI_MESSAGES.get(language_code, UI_MESSAGES["en"]).get(message_key, UI_MESSAGES["en"][message_key])
412
-
413
  # Initial UI language is English
414
  current_lang = "en"
415
-
416
  # Title and intro
417
  title_component = gr.Markdown(f"# 🎵 {get_ui_message('title', current_lang)}")
418
  subtitle_component = gr.Markdown(get_ui_message('subtitle', current_lang))
419
-
420
  # Language selection
421
  with gr.Row():
422
  language_dropdown = gr.Dropdown(
@@ -424,23 +307,17 @@ with gr.Blocks(title="Music Recognition & Fun Facts", css="""
424
  value="English",
425
  label=get_ui_message('choose_language', current_lang)
426
  )
427
-
428
  # Combined recognition and chat interface
429
  with gr.Tab("Song Recognition & Chat"):
430
- # Audio status message
431
  audio_status_msg = gr.Markdown(f"*{get_ui_message('please_record', current_lang)}*")
432
 
433
- # Componente para mostrar inmediatamente la canción identificada
434
- song_identification = gr.Markdown("", elem_classes="identified-song")
435
-
436
- # Song recognition section
437
  with gr.Row():
438
  with gr.Column(scale=1):
439
- # Audio input siempre visible
440
  audio_input = gr.Audio(
441
  label="Audio Recording",
442
- type="filepath",
443
- visible=True,
444
  sources=["microphone", "upload"],
445
  streaming=False,
446
  elem_id="audio-input",
@@ -449,9 +326,7 @@ with gr.Blocks(title="Music Recognition & Fun Facts", css="""
449
  show_download_button=False,
450
  interactive=True
451
  )
452
-
453
- # Solo un botón que abre el audio y después identifica
454
- rec_btn = gr.Button(
455
  get_ui_message('rec_button', current_lang),
456
  size="lg",
457
  variant="primary",
@@ -459,21 +334,22 @@ with gr.Blocks(title="Music Recognition & Fun Facts", css="""
459
  elem_id="record-button",
460
  elem_classes="large-button"
461
  )
462
-
463
- # Indicador de estado del micrófono/proceso
464
- microphone_status = gr.Markdown("", elem_id="mic-status")
465
 
 
 
 
466
  # Processing indicator
467
  with gr.Row():
468
  processing_indicator = gr.Markdown("")
469
 
470
- # Artist info section
471
  with gr.Row():
472
- artist_facts = gr.Markdown("")
473
 
474
- # Recognition results section with links
475
  with gr.Row():
476
- recognition_results = gr.Markdown("")
477
 
478
  # Chat section
479
  with gr.Row():
@@ -490,321 +366,212 @@ with gr.Blocks(title="Music Recognition & Fun Facts", css="""
490
  get_ui_message('send_button', current_lang),
491
  variant="primary"
492
  )
493
-
494
- # Function to handle language changes
495
- def update_ui_language(language_name):
496
- lang_code = LANGUAGES.get(language_name, "en")
497
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
  return (
499
- f"# 🎵 {get_ui_message('title', lang_code)}",
500
- get_ui_message('subtitle', lang_code),
501
- gr.update(label=get_ui_message('choose_language', lang_code)),
502
- gr.update(value=get_ui_message('rec_button', lang_code)),
503
- f"*{get_ui_message('please_record', lang_code)}*",
504
- gr.update(value=get_ui_message('send_button', lang_code)),
505
- f"### {get_ui_message('ask_more', lang_code)}",
506
- gr.update(placeholder=get_ui_message('chat_placeholder', lang_code)),
507
- lang_code
508
  )
509
-
510
- # Function to handle audio recording with automatic recognition
511
- def toggle_audio_widget(lang_code):
512
- # Mensaje detallado con instrucciones para solucionar problemas de micrófono
513
- mobile_guidance = ""
514
-
515
- if lang_code == "en":
516
- mobile_guidance = """
517
- *Recording... Click Stop when done. The song will be identified automatically.*
518
-
519
- **If you're having trouble with the microphone:**
520
- - Make sure your browser has permission to access your microphone
521
- - Make sure you're using a secure connection (HTTPS)
522
- - Your microphone might be in use by another application
523
- - Try refreshing the page and allow microphone access when prompted
524
- - If using a mobile device, try using Chrome or Safari
525
- """
526
- elif lang_code == "es":
527
- mobile_guidance = """
528
- *Grabando... Haz clic en Detener cuando termines. La canción se identificará automáticamente.*
529
-
530
- **Si tienes problemas con el micrófono:**
531
- - Asegúrate de que tu navegador tiene permiso para acceder a tu micrófono
532
- - Asegúrate de que estás usando una conexión segura (HTTPS)
533
- - Tu micrófono podría estar siendo usado por otra aplicación
534
- - Intenta refrescar la página y permitir el acceso al micrófono cuando se te solicite
535
- - Si usas un dispositivo móvil, intenta usar Chrome o Safari
536
- """
537
- else: # French
538
- mobile_guidance = """
539
- *Enregistrement... Cliquez sur Arrêter quand vous avez terminé. La chanson sera identifiée automatiquement.*
540
-
541
- **Si vous avez des problèmes avec le microphone:**
542
- - Assurez-vous que votre navigateur a l'autorisation d'accéder à votre microphone
543
- - Assurez-vous que vous utilisez une connexion sécurisée (HTTPS)
544
- - Votre microphone pourrait être utilisé par une autre application
545
- - Essayez d'actualiser la page et d'autoriser l'accès au microphone lorsque vous y êtes invité
546
- - Si vous utilisez un appareil mobile, essayez d'utiliser Chrome ou Safari
547
- """
548
-
549
- # Hacer visible el componente de audio
550
  return (
551
- gr.update(visible=True),
552
- "loading",
553
- mobile_guidance,
554
- "", # Clear processing indicator
555
- "" # Clear song identification
556
  )
557
-
558
- # Function to update status when audio is uploaded/recorded and trigger automatic recognition
559
- def update_audio_status(audio_path, lang_code):
560
- if audio_path:
561
- audio_loaded_msg = f"*{get_ui_message('audio_loaded', lang_code)}*"
562
- # Activar automáticamente el reconocimiento
 
 
 
 
 
 
 
 
 
 
 
 
563
  return (
564
- "ready",
565
- audio_loaded_msg,
566
- f"*{get_ui_message('searching_song', lang_code)}*",
567
  "",
568
- audio_path,
569
- lang_code
570
- )
571
- else:
572
- # Si no hay audio, probable problema con el micrófono
573
- troubleshooting = ""
574
-
575
- if lang_code == "en":
576
- troubleshooting = """
577
- *No audio was recorded. Please try again.*
578
-
579
- **Microphone troubleshooting:**
580
- - Check if your browser shows a microphone permission dialog
581
- - Make sure microphone permissions are granted in your browser settings
582
- - Try using a different browser (Chrome or Safari recommended)
583
- - Check if your microphone is working in other applications
584
- """
585
- elif lang_code == "es":
586
- troubleshooting = """
587
- *No se grabó audio. Por favor, inténtalo de nuevo.*
588
-
589
- **Solución de problemas de micrófono:**
590
- - Verifica si tu navegador muestra un diálogo de permiso de micrófono
591
- - Asegúrate de que los permisos de micrófono estén concedidos en la configuración de tu navegador
592
- - Intenta usar un navegador diferente (se recomienda Chrome o Safari)
593
- - Comprueba si tu micrófono funciona en otras aplicaciones
594
- """
595
- else: # French
596
- troubleshooting = """
597
- *Aucun audio n'a été enregistré. Veuillez réessayer.*
598
-
599
- **Dépannage du microphone:**
600
- - Vérifiez si votre navigateur affiche une boîte de dialogue d'autorisation de microphone
601
- - Assurez-vous que les autorisations de microphone sont accordées dans les paramètres de votre navigateur
602
- - Essayez d'utiliser un navigateur différent (Chrome ou Safari recommandé)
603
- - Vérifiez si votre microphone fonctionne dans d'autres applications
604
- """
605
-
606
- return (
607
- "no_audio",
608
- troubleshooting,
609
- "", # Clear processing indicator
610
- "", # Clear song identification
611
- None, # No audio path
612
- lang_code
613
- )
614
-
615
- # Initial song recognition (just identifies the song)
616
- def initial_song_recognition(audio_path, lang_code):
617
- if not audio_path:
618
- return "", ""
619
-
620
- try:
621
- # Reconocer la canción
622
- result = recognize_song(audio_path)
623
-
624
- if "error" in result:
625
- return f"Error recognizing the song: {result['error']}", ""
626
-
627
- # Obtener datos básicos
628
- song_name = result['Song']
629
- artist_name = result['Artist']
630
-
631
- # Mensaje de identificación rápida
632
- identified_song_msg = get_ui_message('identified_song', lang_code).format(
633
- song=song_name,
634
- artist=artist_name
635
- )
636
-
637
- # Mensaje de carga de info del artista
638
- loading_artist_info_msg = get_ui_message('loading_artist_info', lang_code).format(
639
- artist=artist_name
640
- )
641
-
642
- # Devolver solo el mensaje de identificación y el resultado
643
- return identified_song_msg, json.dumps(result)
644
-
645
- except Exception as e:
646
- error_msg = f"❌ {get_ui_message('processing_error', lang_code)}: {str(e)}"
647
- return error_msg, ""
648
-
649
- # Load detailed artist information
650
- def load_artist_info(song_result_json, lang_code):
651
- if not song_result_json:
652
- return "", "", "", "", ""
653
-
654
- try:
655
- # Convertir el JSON a dict
656
- result = json.loads(song_result_json)
657
-
658
- # Obtener datos básicos
659
- song_name = result['Song']
660
- artist_name = result['Artist']
661
-
662
- # Obtener información detallada del artista
663
- artist_info = get_artist_info(artist_name, song_name, lang_code)
664
-
665
- # Format recognition result based on language (links y detalles)
666
- recognition_msg = f"### 🎵 {get_ui_message('recognized_song', lang_code)}: {result['Song']}\n\n"
667
- recognition_msg += f"**🎤 {get_ui_message('artist', lang_code)}:** {result['Artist']}\n"
668
- recognition_msg += f"**📀 {get_ui_message('album', lang_code)}:** {result['Album']}\n\n"
669
-
670
- if result['Spotify'] != "Not available":
671
- recognition_msg += f"**🎧 [{get_ui_message('listen_spotify', lang_code)}]({result['Spotify']})**\n"
672
- if result['Apple Music'] != "Not available":
673
- recognition_msg += f"**🍏 [{get_ui_message('listen_apple', lang_code)}]({result['Apple Music']})**\n"
674
-
675
- # Artist info section title based on language
676
- artist_facts_title = f"### 🌟 {get_ui_message('about_artist', lang_code)} {result['Artist']}\n\n"
677
-
678
- # Format the artist info with a title
679
- artist_facts_content = artist_facts_title + artist_info
680
-
681
- # Update status message
682
- status_msg = f"*{get_ui_message('song_recognized', lang_code)}*"
683
-
684
- return (
685
- recognition_msg, # Recognition result with links
686
- artist_facts_content, # Artist info
687
- status_msg, # Status message
688
- song_name, # Song name for state
689
- artist_name # Artist name for state
690
  )
691
-
692
- except Exception as e:
693
- error_msg = f" Error loading artist information: {str(e)}"
694
- return error_msg, "", "", "", ""
695
-
696
- # Chat function
697
- def process_chat(query, language_name, song_info, artist_info, lang_code):
698
- if not query:
699
- return []
700
-
701
- try:
702
- # Get response
703
- response = chat_with_assistant(query, artist_info, lang_code)
704
-
705
- return [{"role": "user", "content": query}, {"role": "assistant", "content": response}]
706
- except Exception as e:
707
- return [{"role": "user", "content": query}, {"role": "assistant", "content": f"Sorry, I couldn't process your request: {str(e)}"}]
708
-
709
- # Language selection event handler
710
- language_dropdown.change(
711
- fn=update_ui_language,
712
- inputs=[language_dropdown],
713
- outputs=[
714
- title_component,
715
- subtitle_component,
716
- language_dropdown,
717
- rec_btn,
718
- audio_status_msg,
719
- chat_btn,
720
- chat_section_title,
721
- chat_input,
722
- lang_code
723
- ]
724
- )
725
-
726
- # Event handlers - Mostrar componente de audio al hacer clic en REC
727
- rec_btn.click(
728
- fn=toggle_audio_widget,
729
- inputs=[lang_code],
730
- outputs=[
731
- audio_input,
732
- audio_status,
733
- audio_status_msg,
734
- processing_indicator,
735
- song_identification
736
- ]
737
- ).then(
738
- # Actualizar el estado del micrófono
739
- fn=lambda: "Microphone activated. The song will be identified automatically when you stop recording.",
740
- inputs=[],
741
- outputs=[microphone_status]
742
- )
743
-
744
- # Reconocer automáticamente cuando se sube o graba audio
745
- audio_input.change(
746
- fn=update_audio_status,
747
- inputs=[audio_input, lang_code],
748
- outputs=[
749
- audio_status,
750
- audio_status_msg,
751
- processing_indicator,
752
- song_identification,
753
- # Pasamos estos dos para activar el reconocimiento automático
754
- audio_input, # Audio path
755
- lang_code # Language code
756
- ]
757
- ).then(
758
- # Etapa 1: Identificación rápida de la canción
759
- fn=initial_song_recognition,
760
- inputs=[audio_input, lang_code],
761
- outputs=[
762
- song_identification, # Mostrar inmediatamente el título identificado
763
- song_info_state # Guardar resultado para siguiente etapa
764
- ]
765
- ).then(
766
- # Etapa 2: Cargar información detallada del artista
767
- fn=load_artist_info,
768
- inputs=[song_info_state, lang_code],
769
- outputs=[
770
- recognition_results, # Resultado con links
771
- artist_facts, # Información del artista
772
- audio_status_msg, # Mensaje de estado
773
- song_name_state, # Guardar nombre de canción
774
- artist_info_state # Guardar nombre de artista
775
- ]
776
- )
777
-
778
- # Botón de chat
779
- chat_btn.click(
780
- fn=process_chat,
781
- inputs=[chat_input, language_dropdown, song_info_state, artist_info_state, lang_code],
782
- outputs=[chat_history]
783
- ).then(
784
- fn=lambda: "", # Clear input after sending
785
- inputs=[],
786
- outputs=[chat_input]
787
- )
788
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
789
  with gr.Tab("Song History"):
790
  history_tab_title = gr.Markdown(f"### {get_ui_message('history_title', current_lang)}")
791
-
792
  with gr.Row():
793
  history_limit = gr.Slider(minimum=5, maximum=50, value=10, step=5, label=get_ui_message('songs_to_show', current_lang))
794
  view_history_btn = gr.Button(get_ui_message('view_history', current_lang))
795
-
796
  history_output = gr.Markdown()
797
-
798
  def view_history_process(limit):
799
  return view_song_history(int(limit))
800
-
801
  view_history_btn.click(
802
  fn=view_history_process,
803
  inputs=[history_limit],
804
  outputs=[history_output]
805
  )
806
-
807
- # Update history tab language
808
  def update_history_tab_language(lang_name):
809
  lang_code = LANGUAGES.get(lang_name, 'en')
810
  return (
@@ -812,23 +579,18 @@ with gr.Blocks(title="Music Recognition & Fun Facts", css="""
812
  gr.update(label=get_ui_message('songs_to_show', lang_code)),
813
  gr.update(value=get_ui_message('view_history', lang_code))
814
  )
815
-
816
  language_dropdown.change(
817
  fn=update_history_tab_language,
818
  inputs=[language_dropdown],
819
- outputs=[
820
- history_tab_title,
821
- history_limit,
822
- view_history_btn
823
- ]
824
  )
825
 
826
- # Set the configuration for mobile compatibility
827
  demo.launch(
828
- show_error=True,
829
  share=True,
830
  inbrowser=True,
831
  debug=True,
832
  allowed_paths=[],
833
- server_name="0.0.0.0" # Esto permite conexiones desde cualquier dirección
834
  )
 
9
  import logging
10
 
11
  # Configurar logging para depuración
12
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 
13
  logger = logging.getLogger('music_recognition_app')
14
 
15
  # File to save the history of recognized songs
16
  HISTORY_FILE = "song_history.json"
17
 
18
+ # Supported languages
19
  LANGUAGES = {
20
  "English": "en",
21
  "Español": "es",
 
26
  UI_MESSAGES = {
27
  "en": {
28
  "title": "Music Recognition & Fun Facts",
29
+ "subtitle": "Identify songs, learn interesting facts about artists, and chat about music",
30
  "choose_language": "Choose your language",
31
+ "rec_button": " REC MUSIC",
32
+ "please_record": "Please record or upload an audio clip",
33
  "recording": "Recording... Click Stop when done",
34
+ "audio_loaded": " Audio loaded! Processing song recognition...",
35
+ "loading_audio": "Please wait while the audio is loading",
36
+ "searching_song": "Searching for your song in the sound multiverse, please wait to discover incredible facts about your artist.",
 
 
37
  "song_recognized": "Song successfully recognized! Ask questions about the artist in the chat below",
38
  "about_artist": "About",
39
  "ask_more": "Ask me more about this artist or music in general",
 
42
  "history_tab": "Song History",
43
  "history_title": "History of recognized songs",
44
  "songs_to_show": "Number of songs to show",
45
+ "view_history": " View History",
46
  "recognized_song": "Recognized Song",
47
  "artist": "Artist",
48
  "album": "Album",
 
53
  },
54
  "es": {
55
  "title": "Reconocimiento de Música y Datos Curiosos",
56
+ "subtitle": "Identifica canciones, aprende datos interesantes sobre artistas y chatea sobre música",
57
  "choose_language": "Elige tu idioma",
58
+ "rec_button": " GRABAR MÚSICA",
59
+ "please_record": "Por favor graba o sube un clip de audio",
60
  "recording": "Grabando... Haz clic en Detener cuando termines",
61
+ "audio_loaded": " ¡Audio cargado! Procesando el reconocimiento de la canción...",
62
+ "loading_audio": "Por favor espera mientras se carga el audio",
63
+ "searching_song": "Buscando tu canción en el multiverso sonoro, espera para descubrir datos increíbles sobre tu artista.",
 
 
64
  "song_recognized": "¡Canción reconocida con éxito! Haz preguntas sobre el artista en el chat de abajo",
65
  "about_artist": "Sobre",
66
  "ask_more": "Pregúntame más sobre este artista o música en general",
 
69
  "history_tab": "Historial de Canciones",
70
  "history_title": "Historial de canciones reconocidas",
71
  "songs_to_show": "Número de canciones para mostrar",
72
+ "view_history": " Ver Historial",
73
  "recognized_song": "Canción Reconocida",
74
  "artist": "Artista",
75
  "album": "Álbum",
 
80
  },
81
  "fr": {
82
  "title": "Reconnaissance de Musique et Anecdotes",
83
+ "subtitle": "Identifiez des chansons, découvrez des faits intéressants sur les artistes et discutez de musique",
84
  "choose_language": "Choisissez votre langue",
85
+ "rec_button": " ENREGISTRER MUSIQUE",
86
+ "please_record": "Veuillez enregistrer ou télécharger un clip audio",
87
  "recording": "Enregistrement... Cliquez sur Arrêter quand vous avez terminé",
88
+ "audio_loaded": " Audio chargé ! Traitement de la reconnaissance de la chanson...",
89
+ "loading_audio": "Veuillez patienter pendant le chargement de l'audio",
90
+ "searching_song": "Recherche de votre chanson dans le multivers sonore, patientez pour découvrir des faits incroyables sur votre artiste.",
 
 
91
  "song_recognized": "Chanson reconnue avec succès ! Posez des questions sur l'artiste dans le chat ci-dessous",
92
  "about_artist": "À propos de",
93
  "ask_more": "Demandez-moi plus d'informations sur cet artiste ou sur la musique en général",
 
96
  "history_tab": "Historique des Chansons",
97
  "history_title": "Historique des chansons reconnues",
98
  "songs_to_show": "Nombre de chansons à afficher",
99
+ "view_history": " Voir l'historique",
100
  "recognized_song": "Chanson Reconnue",
101
  "artist": "Artiste",
102
  "album": "Album",
 
115
  audio_path: path to the audio file to recognize
116
  """
117
  AUDD_API_TOKEN = os.getenv("AUDD_API_TOKEN")
 
118
  if not os.path.exists(audio_path):
119
  return {"error": "The audio file does not exist"}
 
120
  try:
121
  with open(audio_path, 'rb') as file:
122
  data = {
123
  'api_token': AUDD_API_TOKEN,
124
  'return': 'spotify,apple_music'
125
  }
126
+ files = {'file': file}
 
 
127
  response = requests.post('https://api.audd.io/', data=data, files=files)
 
128
  if response.status_code != 200:
129
  return {"error": f"API Error: {response.status_code}"}
 
130
  result = response.json()
 
131
  if result['status'] == 'error':
132
  return {"error": result['error']['error_message']}
 
133
  if not result.get('result'):
134
  return {"error": "Could not recognize the song"}
 
135
  song_info = result['result']
 
 
136
  song_data = {
137
  "Song": song_info.get('title', 'Unknown'),
138
  "Artist": song_info.get('artist', 'Unknown'),
 
141
  "Apple Music": song_info.get('apple_music', {}).get('url', 'Not available'),
142
  "Recognition Date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
143
  }
 
 
144
  save_to_history(song_data)
 
145
  return song_data
 
146
  except Exception as e:
147
  return {"error": f"Error processing audio: {str(e)}"}
148
 
 
150
  def save_to_history(song_data):
151
  """Saves a song to the history"""
152
  try:
 
153
  if os.path.exists(HISTORY_FILE):
154
  with open(HISTORY_FILE, 'r') as f:
155
  try:
 
158
  history = []
159
  else:
160
  history = []
 
 
161
  history.insert(0, song_data)
 
 
162
  if len(history) > 50:
163
  history = history[:50]
 
 
164
  with open(HISTORY_FILE, 'w') as f:
165
  json.dump(history, f, indent=2)
 
166
  except Exception as e:
167
  print(f"Error saving to history: {str(e)}")
168
 
 
175
  """
176
  try:
177
  if not os.path.exists(HISTORY_FILE):
178
+ return " No song recognition history yet."
 
179
  with open(HISTORY_FILE, 'r') as f:
180
  try:
181
  history = json.load(f)
182
  except json.JSONDecodeError:
183
  return "📋 Error loading song history."
 
184
  if not history:
185
  return "📋 Song history is empty."
 
 
186
  history = history[:min(limit, len(history))]
 
 
187
  result = "📋 **Song Recognition History:**\n\n"
 
188
  for i, song in enumerate(history, 1):
189
  result += f"{i}. **{song.get('Song', 'Unknown')}** - *{song.get('Artist', 'Unknown')}*\n"
190
  result += f" 📀 Album: {song.get('Album', 'Unknown')}\n"
 
191
  if song.get('Spotify', 'Not available') != 'Not available':
192
  result += f" 🎧 [Spotify]({song.get('Spotify')})\n"
 
193
  if song.get('Apple Music', 'Not available') != 'Not available':
194
  result += f" 🍏 [Apple Music]({song.get('Apple Music')})\n"
 
195
  result += f" 🕒 Recognized on: {song.get('Recognition Date', 'Unknown date')}\n\n"
 
196
  return result
 
197
  except Exception as e:
198
  return f"❌ Error getting history: {str(e)}"
199
 
 
201
  @tool
202
  def get_artist_info(artist_name: str, song_name: str = "", language: str = "en") -> str:
203
  """Gets detailed background information, fun facts about a music artist and the specific song in the specified language
 
204
  Args:
205
  artist_name: name of the artist to get information about
206
  song_name: name of the song (if available)
207
  language: language code (en, es, fr)
208
  """
 
209
  prompts = {
210
  "en": f"Provide a comprehensive overview about the music artist '{artist_name}'. Include the following sections clearly marked with headers:\n\n1. General Biography: Brief overview of their career and significance in music.\n\n2. Fun Facts: 4-5 surprising or interesting facts about the artist or group that fans would find fascinating.\n\n3. Behind-the-scenes Anecdotes: 2-3 memorable stories about the artist's career, performances, or personal life that showcase their character or impact.\n\n" + (f'4. About the Song "{song_name}": If you know anything specific about how this song was created, its meaning, its impact, or interesting trivia related to it, please share those details.' if song_name else '') + "\n\nKeep the tone engaging and enthusiastic, highlighting what makes this artist unique and beloved by fans. Limit your response to around 500 words total.",
 
211
  "es": f"Proporciona una visión completa sobre el artista musical '{artist_name}'. Incluye las siguientes secciones claramente marcadas con encabezados:\n\n1. Biografía General: Breve resumen de su carrera y significado en la música.\n\n2. Datos Curiosos: 4-5 hechos sorprendentes o interesantes sobre el artista o grupo que los fans encontrarían fascinantes.\n\n3. Anécdotas entre bastidores: 2-3 historias memorables sobre la carrera del artista, actuaciones o vida personal que muestren su carácter o impacto.\n\n" + (f'4. Sobre la canción "{song_name}": Si conoces algo específico sobre cómo se creó esta canción, su significado, su impacto o curiosidades interesantes relacionadas con ella, por favor comparte esos detalles.' if song_name else '') + "\n\nMantén un tono atractivo y entusiasta, destacando lo que hace que este artista sea único y querido por los fans. Limita tu respuesta a alrededor de 500 palabras en total.",
 
212
  "fr": f"Fournissez un aperçu complet de l'artiste musical '{artist_name}'. Incluez les sections suivantes clairement marquées avec des en-têtes:\n\n1. Biographie générale: Bref aperçu de sa carrière et de son importance dans la musique.\n\n2. Anecdotes intéressantes: 4-5 faits surprenants ou intéressants sur l'artiste ou le groupe que les fans trouveraient fascinants.\n\n3. Anecdotes en coulisses: 2-3 histoires mémorables sur la carrière de l'artiste, ses performances ou sa vie personnelle qui mettent en valeur son caractère ou son impact.\n\n" + (f'4. À propos de la chanson "{song_name}": Si vous connaissez quelque chose de spécifique sur la façon dont cette chanson a été créée, sa signification, son impact ou des anecdotes intéressantes liées à elle, veuillez partager ces détails.' if song_name else '') + "\n\nGardez un ton engageant et enthousiaste, mettant en évidence ce qui rend cet artiste unique et apprécié des fans. Limitez votre réponse à environ 500 mots au total."
213
  }
 
 
214
  if language not in prompts:
215
  language = "en"
216
+ messages = [{"role": "user", "content": prompts[language]}]
 
 
 
 
 
217
  try:
 
218
  response = model(messages)
219
  return response.content
220
  except Exception as e:
 
229
  artist_info: previous artist info to provide context
230
  language: language code (en, es, fr)
231
  """
 
232
  system_messages = {
233
  "en": "You are a music expert assistant who specializes in providing engaging information about artists, songs, and music history. Focus on sharing interesting, fun facts that highlight the artist's unique contributions and stories.",
234
  "es": "Eres un asistente experto en música que se especializa en proporcionar información interesante sobre artistas, canciones e historia musical. Céntrate en compartir datos curiosos e interesantes que destaquen las contribuciones únicas y las historias del artista.",
235
  "fr": "Vous êtes un assistant expert en musique qui se spécialise dans la fourniture d'informations intéressantes sur les artistes, les chansons et l'histoire de la musique. Concentrez-vous sur le partage de faits intéressants et amusants qui mettent en évidence les contributions uniques et les histoires de l'artiste."
236
  }
 
 
237
  if language not in system_messages:
238
  language = "en"
239
+ context = f"Previous context about the artist: {artist_info}\n\n" if artist_info else ""
 
 
 
 
 
 
240
  messages = [
241
  {"role": "system", "content": system_messages[language]},
242
  {"role": "user", "content": context + query}
243
  ]
 
244
  try:
 
245
  response = model(messages)
246
  return response.content
247
  except Exception as e:
 
255
  model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
256
  custom_role_conversions=None,
257
  )
 
258
  with open("prompts.yaml", 'r') as stream:
259
  prompt_templates = yaml.safe_load(stream)
260
 
 
261
  agent = CodeAgent(
262
  model=model,
263
+ tools=[final_answer, recognize_song, view_song_history, get_artist_info, chat_with_assistant],
 
 
 
 
 
 
264
  max_steps=8,
265
  verbosity_level=1,
266
  grammar=None,
 
272
 
273
  # Gradio user interface con CSS personalizado para mejor experiencia móvil
274
  with gr.Blocks(title="Music Recognition & Fun Facts", css="""
275
+ .large-button {min-height: 60px !important; font-size: 18px !important; padding: 15px !important;}
 
 
 
 
276
  @media (max-width: 600px) {
277
+ .large-button {width: 100% !important; margin-bottom: 10px !important;}
278
+ #audio-input {width: 100% !important; margin-top: 10px !important; margin-bottom: 10px !important;}
279
+ button.record, button.stop {width: 60px !important; height: 60px !important; border-radius: 50% !important;}
280
+ .error-text {color: red !important; font-weight: bold !important; font-size: 16px !important;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  }
282
+ #mic-status {margin-top: 5px; margin-bottom: 15px; font-style: italic;}
283
  """) as demo:
284
  # State variables
285
  selected_language = gr.State("en")
 
287
  song_info_state = gr.State(None)
288
  artist_info_state = gr.State("")
289
  song_name_state = gr.State("")
290
+ audio_status = gr.State("no_audio")
291
+
292
  # Function to get UI messages based on language
293
  def get_ui_message(message_key, language_code="en"):
294
  return UI_MESSAGES.get(language_code, UI_MESSAGES["en"]).get(message_key, UI_MESSAGES["en"][message_key])
295
+
296
  # Initial UI language is English
297
  current_lang = "en"
298
+
299
  # Title and intro
300
  title_component = gr.Markdown(f"# 🎵 {get_ui_message('title', current_lang)}")
301
  subtitle_component = gr.Markdown(get_ui_message('subtitle', current_lang))
302
+
303
  # Language selection
304
  with gr.Row():
305
  language_dropdown = gr.Dropdown(
 
307
  value="English",
308
  label=get_ui_message('choose_language', current_lang)
309
  )
310
+
311
  # Combined recognition and chat interface
312
  with gr.Tab("Song Recognition & Chat"):
 
313
  audio_status_msg = gr.Markdown(f"*{get_ui_message('please_record', current_lang)}*")
314
 
 
 
 
 
315
  with gr.Row():
316
  with gr.Column(scale=1):
 
317
  audio_input = gr.Audio(
318
  label="Audio Recording",
319
+ type="filepath",
320
+ visible=False,
321
  sources=["microphone", "upload"],
322
  streaming=False,
323
  elem_id="audio-input",
 
326
  show_download_button=False,
327
  interactive=True
328
  )
329
+ record_btn = gr.Button(
 
 
330
  get_ui_message('rec_button', current_lang),
331
  size="lg",
332
  variant="primary",
 
334
  elem_id="record-button",
335
  elem_classes="large-button"
336
  )
337
+ microphone_status = gr.Markdown("Please click 'REC MUSIC' to start recording.", elem_id="mic-status")
 
 
338
 
339
+ # Song title display (nuevo componente para mostrar el título inmediatamente)
340
+ song_title_display = gr.Markdown("")
341
+
342
  # Processing indicator
343
  with gr.Row():
344
  processing_indicator = gr.Markdown("")
345
 
346
+ # Recognition results section
347
  with gr.Row():
348
+ recognition_results = gr.Markdown("")
349
 
350
+ # Artist info section
351
  with gr.Row():
352
+ artist_facts = gr.Markdown("")
353
 
354
  # Chat section
355
  with gr.Row():
 
366
  get_ui_message('send_button', current_lang),
367
  variant="primary"
368
  )
369
+
370
+ # Function to handle language changes
371
+ def update_ui_language(language_name):
372
+ lang_code = LANGUAGES.get(language_name, "en")
373
+ return (
374
+ f"# 🎵 {get_ui_message('title', lang_code)}",
375
+ get_ui_message('subtitle', lang_code),
376
+ gr.update(label=get_ui_message('choose_language', lang_code)),
377
+ gr.update(value=get_ui_message('rec_button', lang_code)),
378
+ f"*{get_ui_message('please_record', lang_code)}*",
379
+ gr.update(value=get_ui_message('send_button', lang_code)),
380
+ f"### {get_ui_message('ask_more', lang_code)}",
381
+ gr.update(placeholder=get_ui_message('chat_placeholder', lang_code)),
382
+ lang_code
383
+ )
384
+
385
+ # Function to handle audio recording
386
+ def toggle_audio_widget(lang_code):
387
+ mobile_guidance = {
388
+ "en": "Recording... Click Stop when done\n\nIf you're having trouble with the microphone:\n- Ensure your browser has microphone permission\n- Use a secure connection (HTTPS)\n- Check if another app is using the microphone\n- Refresh the page and allow microphone access\n- On mobile, use Chrome or Safari",
389
+ "es": "Grabando... Haz clic en Detener cuando termines\n\nSi tienes problemas con el micrófono:\n- Asegúrate de que tu navegador tenga permiso para el micrófono\n- Usa una conexión segura (HTTPS)\n- Verifica si otra app está usando el micrófono\n- Refresca la página y permite el acceso\n- En móviles, usa Chrome o Safari",
390
+ "fr": "Enregistrement... Cliquez sur Arrêter quand vous avez terminé\n\nSi vous avez des problèmes avec le microphone:\n- Assurez-vous que votre navigateur a l'autorisation\n- Utilisez une connexion sécurisée (HTTPS)\n- Vérifiez si une autre application utilise le micro\n- Rafraîchissez la page et autorisez l'accès\n- Sur mobile, utilisez Chrome ou Safari"
391
+ }
392
+ return (
393
+ gr.update(visible=True),
394
+ "loading",
395
+ mobile_guidance.get(lang_code, mobile_guidance["en"]),
396
+ "" # Clear processing indicator
397
+ )
398
+
399
+ # Function to update status and trigger recognition
400
+ def update_audio_status(audio_path, lang_code):
401
+ if audio_path:
402
  return (
403
+ "ready",
404
+ f"{get_ui_message('audio_loaded', lang_code)}",
405
+ "" # Clear processing indicator
 
 
 
 
 
 
406
  )
407
+ else:
408
+ troubleshooting = {
409
+ "en": "No audio recorded. Please try again.\n\nMicrophone troubleshooting:\n- Check browser microphone permissions\n- Use Chrome or Safari\n- Ensure no other app is using the microphone",
410
+ "es": "No se grabó audio. Intenta de nuevo.\n\nSolución de problemas:\n- Verifica los permisos del micrófono en el navegador\n- Usa Chrome o Safari\n- Asegúrate de que ninguna otra app use el micrófono",
411
+ "fr": "Aucun audio enregistré. Réessayez.\n\nDépannage:\n- Vérifiez les autorisations du microphone\n- Utilisez Chrome ou Safari\n- Assurez-vous qu'aucune autre app n'utilise le micro"
412
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
  return (
414
+ "no_audio",
415
+ troubleshooting.get(lang_code, troubleshooting["en"]),
416
+ "" # Clear processing indicator
 
 
417
  )
418
+
419
+ # Recognition function with immediate song title display
420
+ def process_audio(audio_path, language_name, status, lang_code):
421
+ if not audio_path or status != "ready":
422
+ return (
423
+ None,
424
+ "",
425
+ "",
426
+ "",
427
+ f"{get_ui_message('no_audio_error', lang_code)}",
428
+ "",
429
+ "",
430
+ ""
431
+ )
432
+ try:
433
+ # First step: Recognize the song and show the title immediately
434
+ result = recognize_song(audio_path)
435
+ if "error" in result:
436
  return (
437
+ None,
 
 
438
  "",
439
+ "",
440
+ "",
441
+ f"Error recognizing the song: {result['error']}",
442
+ "",
443
+ "",
444
+ ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  )
446
+ song_name = result['Song']
447
+ artist_name = result['Artist']
448
+ song_title_msg = f"🎵 **{song_name}** by {artist_name}"
449
+
450
+ # Second step: Prepare detailed recognition info
451
+ recognition_msg = f"### {get_ui_message('recognized_song', lang_code)}: {song_name}\n\n"
452
+ recognition_msg += f"{get_ui_message('artist', lang_code)}: {artist_name}\n"
453
+ recognition_msg += f"{get_ui_message('album', lang_code)}: {result['Album']}\n\n"
454
+ if result['Spotify'] != "Not available":
455
+ recognition_msg += f"{get_ui_message('listen_spotify', lang_code)} ([Spotify]({result['Spotify']}))\n"
456
+ if result['Apple Music'] != "Not available":
457
+ recognition_msg += f"[{get_ui_message('listen_apple', lang_code)}]({result['Apple Music']})\n"
458
+
459
+ # Third step: Get artist info
460
+ artist_info = get_artist_info(artist_name, song_name, lang_code)
461
+ artist_facts_title = f"### {get_ui_message('about_artist', lang_code)} {artist_name}\n\n"
462
+ artist_facts_content = artist_facts_title + artist_info
463
+
464
+ status_msg = f"{get_ui_message('song_recognized', lang_code)}"
465
+ return (
466
+ result,
467
+ song_name,
468
+ song_title_msg,
469
+ recognition_msg,
470
+ artist_facts_content,
471
+ status_msg,
472
+ "",
473
+ artist_name
474
+ )
475
+ except Exception as e:
476
+ return (
477
+ None,
478
+ "",
479
+ "",
480
+ "",
481
+ f"{get_ui_message('processing_error', lang_code)}: {str(e)}",
482
+ "",
483
+ "",
484
+ ""
485
+ )
486
+
487
+ # Chat function
488
+ def process_chat(query, language_name, song_info, artist_info, lang_code):
489
+ if not query:
490
+ return []
491
+ try:
492
+ response = chat_with_assistant(query, artist_info, lang_code)
493
+ return [{"role": "user", "content": query}, {"role": "assistant", "content": response}]
494
+ except Exception as e:
495
+ return [{"role": "user", "content": query}, {"role": "assistant", "content": f"Sorry, I couldn't process your request: {str(e)}"}]
496
+
497
+ # Language selection event handler
498
+ language_dropdown.change(
499
+ fn=update_ui_language,
500
+ inputs=[language_dropdown],
501
+ outputs=[
502
+ title_component,
503
+ subtitle_component,
504
+ language_dropdown,
505
+ record_btn,
506
+ audio_status_msg,
507
+ chat_btn,
508
+ chat_section_title,
509
+ chat_input,
510
+ lang_code
511
+ ]
512
+ )
513
+
514
+ # Event handlers
515
+ record_btn.click(
516
+ fn=toggle_audio_widget,
517
+ inputs=[lang_code],
518
+ outputs=[
519
+ audio_input,
520
+ audio_status,
521
+ audio_status_msg,
522
+ processing_indicator
523
+ ]
524
+ ).then(
525
+ fn=lambda: "Microphone activated. Please speak or sing the song you want to recognize.",
526
+ inputs=[],
527
+ outputs=[microphone_status]
528
+ )
529
+
530
+ audio_input.change(
531
+ fn=update_audio_status,
532
+ inputs=[audio_input, lang_code],
533
+ outputs=[audio_status, audio_status_msg, processing_indicator]
534
+ ).then(
535
+ fn=process_audio,
536
+ inputs=[audio_input, language_dropdown, audio_status, lang_code],
537
+ outputs=[
538
+ song_info_state,
539
+ song_name_state,
540
+ song_title_display,
541
+ recognition_results,
542
+ artist_facts,
543
+ audio_status_msg,
544
+ processing_indicator,
545
+ artist_info_state
546
+ ]
547
+ )
548
+
549
+ chat_btn.click(
550
+ fn=process_chat,
551
+ inputs=[chat_input, language_dropdown, song_info_state, artist_info_state, lang_code],
552
+ outputs=[chat_history]
553
+ ).then(
554
+ fn=lambda: "",
555
+ inputs=[],
556
+ outputs=[chat_input]
557
+ )
558
+
559
  with gr.Tab("Song History"):
560
  history_tab_title = gr.Markdown(f"### {get_ui_message('history_title', current_lang)}")
 
561
  with gr.Row():
562
  history_limit = gr.Slider(minimum=5, maximum=50, value=10, step=5, label=get_ui_message('songs_to_show', current_lang))
563
  view_history_btn = gr.Button(get_ui_message('view_history', current_lang))
 
564
  history_output = gr.Markdown()
565
+
566
  def view_history_process(limit):
567
  return view_song_history(int(limit))
568
+
569
  view_history_btn.click(
570
  fn=view_history_process,
571
  inputs=[history_limit],
572
  outputs=[history_output]
573
  )
574
+
 
575
  def update_history_tab_language(lang_name):
576
  lang_code = LANGUAGES.get(lang_name, 'en')
577
  return (
 
579
  gr.update(label=get_ui_message('songs_to_show', lang_code)),
580
  gr.update(value=get_ui_message('view_history', lang_code))
581
  )
582
+
583
  language_dropdown.change(
584
  fn=update_history_tab_language,
585
  inputs=[language_dropdown],
586
+ outputs=[history_tab_title, history_limit, view_history_btn]
 
 
 
 
587
  )
588
 
 
589
  demo.launch(
590
+ show_error=True,
591
  share=True,
592
  inbrowser=True,
593
  debug=True,
594
  allowed_paths=[],
595
+ server_name="0.0.0.0"
596
  )