carana08 commited on
Commit
a6ad5a8
·
verified ·
1 Parent(s): af53974

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -67
app.py CHANGED
@@ -1,11 +1,10 @@
1
- # app.py
2
-
3
  import subprocess
4
  import os
5
  import shutil
6
  from pathlib import Path
7
  from datasets import load_dataset, Audio
8
  import gradio as gr
 
9
 
10
  # ----------------------------------------------------------------------
11
  # 1. FUNCIONES DE DESCARGA Y PROCESAMIENTO
@@ -16,13 +15,12 @@ def download_clip(
16
  output_filename,
17
  start_time,
18
  end_time,
19
- num_attempts=5,
20
  url_base='https://www.youtube.com/watch?v='
21
  ):
22
- """Descarga un clip de YouTube usando yt-dlp."""
23
- status = False
24
 
25
- # Comando para descargar el clip
26
  command = [
27
  "yt-dlp",
28
  "--quiet",
@@ -30,28 +28,44 @@ def download_clip(
30
  "--no-warnings",
31
  "-x",
32
  "--audio-format", "wav",
33
- "-f", "bestaudio",
 
 
 
 
34
  "-o", output_filename,
35
  "--download-sections", f"*{start_time}-{end_time}",
36
  f"{url_base}{video_identifier}"
37
  ]
38
 
39
- attempts = 0
40
- while True:
41
  try:
42
- # Ejecutamos el comando
43
- subprocess.check_output(command, stderr=subprocess.STDOUT)
44
- except subprocess.CalledProcessError as err:
45
- attempts += 1
46
- if attempts == num_attempts:
47
- # Retornar error si se agotan los intentos
48
- return status, err.output.decode('utf-8')
49
- else:
50
- break
51
-
52
- # Verificar si el archivo se guardó
53
- status = os.path.exists(output_filename)
54
- return status, 'Downloaded'
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
 
57
  def main(
@@ -60,7 +74,6 @@ def main(
60
  limit: int = None,
61
  num_proc: int = 1,
62
  writer_batch_size: int = 1000,
63
- cast_audio: bool = True # Nuevo parámetro
64
  ):
65
  """
66
  Descarga los clips de MusicCaps, procesa el dataset y maneja la limpieza.
@@ -68,7 +81,7 @@ def main(
68
 
69
  data_dir_path = Path(data_dir)
70
 
71
- # 💥 CORRECCIÓN DE ESPACIO: LIMPIEZA DE DISCO (1 GB LIMIT)
72
  if data_dir_path.exists():
73
  shutil.rmtree(data_dir_path)
74
  print(f"Limpiando el directorio {data_dir} para liberar espacio.")
@@ -93,13 +106,17 @@ def main(
93
  example['start_s'],
94
  example['end_s'],
95
  )
 
 
 
 
 
96
 
97
- example['audio'] = outfile_path
98
  example['download_status'] = status
99
  return example
100
 
101
- # Usar ds.map para descargar y actualizar el dataset
102
- # En esta etapa, 'audio' es solo una cadena (str) de la ruta.
103
  ds = ds.map(
104
  process,
105
  num_proc=num_proc,
@@ -107,28 +124,53 @@ def main(
107
  keep_in_memory=False
108
  )
109
 
110
- # Aplicar cast_column SÓLO si se solicita. Ahora lo haremos fuera de main.
111
- if cast_audio:
112
- ds = ds.cast_column('audio', Audio(sampling_rate=sampling_rate))
113
-
114
  return ds
115
 
116
  # ----------------------------------------------------------------------
117
  # 2. CARGA DEL DATASET AL INICIO Y FILTRADO
118
  # ----------------------------------------------------------------------
119
 
120
- # 1. Llamar a main SIN aplicar cast_column inmediatamente.
121
- ds = main('./music_data', num_proc=1, limit=15, cast_audio=False)
 
 
 
 
122
  print(f"Dataset cargado. Total de ejemplos antes del filtro: {len(ds)}")
123
 
124
- # 2. FILTRAR: Esto ahora funciona porque 'audio' es una ruta (str), no un objeto Audio.
125
- # datasets no intenta decodificar archivos inexistentes.
126
  ds = ds.filter(lambda example: example['download_status'] == True)
127
- print(f"Ejemplos válidos después del filtro: {len(ds)}")
128
 
129
- # 3. ASIGNACIÓN DEL TIPO AUDIO: Aplicamos el tipo solo a los ejemplos válidos.
130
- ds = ds.cast_column('audio', Audio(sampling_rate=44100))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
 
 
 
 
132
 
133
  # ----------------------------------------------------------------------
134
  # 3. INTERFAZ GRADIO
@@ -136,36 +178,56 @@ ds = ds.cast_column('audio', Audio(sampling_rate=44100))
136
 
137
  def get_example(idx):
138
  """Función que Gradio llama al mover el slider."""
139
- # Convertir a entero es crucial
140
  idx = int(idx)
141
- ex = ds[idx]
 
142
 
143
- # Retornar la ruta del audio y el caption
144
  return ex['audio']['path'], ex['caption']
145
 
146
- # Definición de la interfaz
147
- demo = gr.Interface(
148
- get_example,
149
- inputs=gr.Slider(
150
- 0,
151
- len(ds) - 1,
152
- value=0,
153
- step=1,
154
- label=f"Índice del Ejemplo (0 a {len(ds) - 1})"
155
- ),
156
- outputs=[
157
- gr.Audio(label="Muestra de Audio"),
158
- gr.Textbox(label="Descripción (Caption)")
159
- ],
160
- title="Demo de MusicCaps (Muestras)",
161
- description="Selecciona un índice para escuchar el clip de audio y ver su descripción asociada.",
162
- live=True,
163
- )
164
-
165
- # En Hugging Face Spaces, solo necesitas llamar a launch()
166
- if __name__ == "__main__":
167
- # Si el dataset está vacío después del filtro, no tiene sentido lanzar la demo.
168
- if len(ds) == 0:
169
- print("¡ADVERTENCIA! No se pudo descargar ningún ejemplo válido. El dataset está vacío. No se lanzará la demo.")
170
- else:
171
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import subprocess
2
  import os
3
  import shutil
4
  from pathlib import Path
5
  from datasets import load_dataset, Audio
6
  import gradio as gr
7
+ import time
8
 
9
  # ----------------------------------------------------------------------
10
  # 1. FUNCIONES DE DESCARGA Y PROCESAMIENTO
 
15
  output_filename,
16
  start_time,
17
  end_time,
18
+ num_attempts=3,
19
  url_base='https://www.youtube.com/watch?v='
20
  ):
21
+ """Descarga un clip de YouTube usando yt-dlp con mejor manejo de errores."""
 
22
 
23
+ # Comando mejorado con más opciones de compatibilidad
24
  command = [
25
  "yt-dlp",
26
  "--quiet",
 
28
  "--no-warnings",
29
  "-x",
30
  "--audio-format", "wav",
31
+ "-f", "bestaudio/best",
32
+ "--no-check-certificate", # Evita problemas de SSL
33
+ "--prefer-insecure",
34
+ "--socket-timeout", "30",
35
+ "--retries", "3",
36
  "-o", output_filename,
37
  "--download-sections", f"*{start_time}-{end_time}",
38
  f"{url_base}{video_identifier}"
39
  ]
40
 
41
+ for attempt in range(num_attempts):
 
42
  try:
43
+ result = subprocess.run(
44
+ command,
45
+ capture_output=True,
46
+ text=True,
47
+ timeout=60 # Timeout de 60 segundos
48
+ )
49
+
50
+ # Verificar si el archivo existe y tiene tamaño > 0
51
+ if os.path.exists(output_filename) and os.path.getsize(output_filename) > 0:
52
+ return True, 'Downloaded successfully'
53
+
54
+ if attempt < num_attempts - 1:
55
+ time.sleep(2) # Esperar antes de reintentar
56
+
57
+ except subprocess.TimeoutExpired:
58
+ print(f"Timeout en intento {attempt + 1} para {video_identifier}")
59
+ if attempt < num_attempts - 1:
60
+ time.sleep(2)
61
+ except Exception as e:
62
+ print(f"Error en intento {attempt + 1} para {video_identifier}: {str(e)}")
63
+ if attempt < num_attempts - 1:
64
+ time.sleep(2)
65
+
66
+ # Si llegamos aquí, la descarga falló
67
+ error_msg = f"Failed after {num_attempts} attempts"
68
+ return False, error_msg
69
 
70
 
71
  def main(
 
74
  limit: int = None,
75
  num_proc: int = 1,
76
  writer_batch_size: int = 1000,
 
77
  ):
78
  """
79
  Descarga los clips de MusicCaps, procesa el dataset y maneja la limpieza.
 
81
 
82
  data_dir_path = Path(data_dir)
83
 
84
+ # Limpieza de disco
85
  if data_dir_path.exists():
86
  shutil.rmtree(data_dir_path)
87
  print(f"Limpiando el directorio {data_dir} para liberar espacio.")
 
106
  example['start_s'],
107
  example['end_s'],
108
  )
109
+ if not status:
110
+ print(f"❌ Falló descarga de {example['ytid']}: {log}")
111
+ else:
112
+ # Si el archivo existe, verificar que tenga contenido
113
+ status = os.path.getsize(outfile_path) > 0
114
 
115
+ example['audio'] = outfile_path if status else ""
116
  example['download_status'] = status
117
  return example
118
 
119
+ # Descargar y actualizar el dataset
 
120
  ds = ds.map(
121
  process,
122
  num_proc=num_proc,
 
124
  keep_in_memory=False
125
  )
126
 
 
 
 
 
127
  return ds
128
 
129
  # ----------------------------------------------------------------------
130
  # 2. CARGA DEL DATASET AL INICIO Y FILTRADO
131
  # ----------------------------------------------------------------------
132
 
133
+ print("=" * 60)
134
+ print("INICIANDO APLICACIÓN MUSICCAPS DEMO")
135
+ print("=" * 60)
136
+
137
+ # Intentar con más ejemplos para aumentar probabilidad de éxito
138
+ ds = main('./music_data', num_proc=1, limit=30) # Aumentado a 30
139
  print(f"Dataset cargado. Total de ejemplos antes del filtro: {len(ds)}")
140
 
141
+ # Filtrar ejemplos válidos
 
142
  ds = ds.filter(lambda example: example['download_status'] == True)
143
+ print(f"Ejemplos válidos después del filtro: {len(ds)}")
144
 
145
+ # Si no hay ejemplos válidos, intentar con otro rango
146
+ if len(ds) == 0:
147
+ print("⚠️ Primer intento falló. Intentando con ejemplos 100-130...")
148
+ full_ds = load_dataset('google/MusicCaps', split='train')
149
+ ds = full_ds.select(range(100, 130))
150
+
151
+ data_dir_path = Path('./music_data')
152
+ def process(example):
153
+ outfile_path = str(data_dir_path / f"{example['ytid']}.wav")
154
+ status = False
155
+ if not os.path.exists(outfile_path):
156
+ status, log = download_clip(
157
+ example['ytid'],
158
+ outfile_path,
159
+ example['start_s'],
160
+ example['end_s'],
161
+ )
162
+ example['audio'] = outfile_path if status else ""
163
+ example['download_status'] = status
164
+ return example
165
+
166
+ ds = ds.map(process, num_proc=1, keep_in_memory=False)
167
+ ds = ds.filter(lambda example: example['download_status'] == True)
168
+ print(f"✅ Ejemplos válidos en segundo intento: {len(ds)}")
169
 
170
+ # Aplicar tipo Audio solo si hay ejemplos válidos
171
+ if len(ds) > 0:
172
+ ds = ds.cast_column('audio', Audio(sampling_rate=44100))
173
+ print(f"🎵 Dataset preparado con {len(ds)} ejemplos")
174
 
175
  # ----------------------------------------------------------------------
176
  # 3. INTERFAZ GRADIO
 
178
 
179
  def get_example(idx):
180
  """Función que Gradio llama al mover el slider."""
 
181
  idx = int(idx)
182
+ if idx >= len(ds):
183
+ idx = len(ds) - 1
184
 
185
+ ex = ds[idx]
186
  return ex['audio']['path'], ex['caption']
187
 
188
+ # Crear interfaz solo si hay datos
189
+ if len(ds) > 0:
190
+ demo = gr.Interface(
191
+ get_example,
192
+ inputs=gr.Slider(
193
+ 0,
194
+ len(ds) - 1,
195
+ value=0,
196
+ step=1,
197
+ label=f"Índice del Ejemplo (0 a {len(ds) - 1})"
198
+ ),
199
+ outputs=[
200
+ gr.Audio(label="🎵 Muestra de Audio"),
201
+ gr.Textbox(label="📝 Descripción (Caption)", lines=3)
202
+ ],
203
+ title="🎵 MusicCaps Dataset Explorer",
204
+ description=f"Explora {len(ds)} clips de música con sus descripciones. Mueve el slider para cambiar de ejemplo.",
205
+ live=True,
206
+ )
207
+
208
+ print("🚀 Lanzando aplicación Gradio...")
209
+ demo.launch()
210
+ else:
211
+ print("=" * 60)
212
+ print("❌ ERROR CRÍTICO")
213
+ print("=" * 60)
214
+ print("No se pudo descargar ningún ejemplo válido del dataset.")
215
+ print("Posibles causas:")
216
+ print("1. Problemas de conectividad en Hugging Face Spaces")
217
+ print("2. YouTube bloqueando las descargas")
218
+ print("3. Videos no disponibles o privados")
219
+ print("\nSugerencias:")
220
+ print("- Verificar que yt-dlp esté actualizado")
221
+ print("- Intentar con un VPN o proxy")
222
+ print("- Usar un dataset pre-descargado")
223
+ print("=" * 60)
224
+
225
+ # Crear una interfaz mínima de error
226
+ demo = gr.Interface(
227
+ lambda: ("⚠️ No hay datos disponibles", "No se pudieron descargar clips de audio"),
228
+ inputs=None,
229
+ outputs=[gr.Textbox(label="Estado"), gr.Textbox(label="Mensaje")],
230
+ title="❌ MusicCaps Demo - Error",
231
+ description="No se pudieron descargar ejemplos del dataset. Verifica los logs para más detalles."
232
+ )
233
+ demo.launch()