gnosticdev commited on
Commit
68930cd
verified
1 Parent(s): a474c04

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -76
app.py CHANGED
@@ -2,111 +2,82 @@ import gradio as gr
2
  import moviepy.editor as mp
3
  import numpy as np
4
  import librosa
5
- import matplotlib.pyplot as plt
6
- from PIL import Image
7
  import tempfile
8
  import os
9
- import io
10
  import logging
11
 
12
  # Configuraci贸n de logging
13
- logging.basicConfig(
14
- level=logging.INFO,
15
- format='%(asctime)s - %(levelname)s - %(message)s',
16
- handlers=[
17
- logging.FileHandler("app.log"), # Guardar logs en archivo
18
- logging.StreamHandler() # Mostrar logs en consola
19
- ]
20
- )
21
- logger = logging.getLogger("audio_to_video")
22
 
23
- def generate_waveform_video(audio_file, image_file):
24
  try:
25
- logger.info("------ Nueva solicitud de generaci贸n ------")
26
- logger.info(f"Archivo de audio recibido: {audio_file}")
27
- logger.info(f"Archivo de imagen recibido: {image_file}")
28
-
29
  # 1. Cargar audio
30
- logger.info("Cargando archivo de audio...")
31
- y, sr = librosa.load(audio_file)
32
  duration = librosa.get_duration(y=y, sr=sr)
33
- logger.info(f"Duraci贸n del audio: {duration:.2f} segundos")
34
 
35
- # 2. Procesar imagen
36
- logger.info("Cargando imagen y preparando formato...")
37
- img = Image.open(image_file).convert('RGB')
38
- img_array = np.array(img)
39
- img_clip = mp.ImageClip(img_array).set_duration(duration)
40
- img_w, img_h = img_clip.size
41
- logger.info(f"Resoluci贸n de imagen: {img_w}x{img_h}")
42
 
43
- # 3. Crear efecto de waveform
44
- logger.info("Generando efecto de onda de audio...")
45
- audio_envelope = np.abs(y)
46
- audio_envelope = (audio_envelope / np.max(audio_envelope)) * (img_h // 3)
47
 
 
48
  def make_frame(t):
49
- fig, ax = plt.subplots(figsize=(img_w/100, img_h/100), dpi=100)
50
- fig.patch.set_facecolor('black')
51
- ax.set_facecolor('black')
52
- ax.set_xlim(0, duration)
53
- ax.set_ylim(-img_h//2, img_h//2)
54
- ax.axis('off')
55
-
56
  time_idx = int(t * sr)
57
  start = max(0, time_idx - sr//10)
58
  end = min(len(audio_envelope), time_idx + sr//10)
59
  wave_slice = audio_envelope[start:end]
60
-
61
- x = np.linspace(t-0.1, t+0.1, len(wave_slice))
62
- ax.fill_between(x, wave_slice - img_h//4, -wave_slice + img_h//4,
63
- facecolor='red', alpha=0.7)
64
-
65
- # Convertir a RGB sin transparencia
66
- buf = io.BytesIO()
67
- plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0,
68
- transparent=False, facecolor='black')
69
- plt.close(fig)
70
 
71
- img_frame = Image.open(buf).convert('RGB')
72
- return np.array(img_frame)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
- # 4. Componer video
75
- logger.info("Creando clip de video...")
76
- effect_clip = mp.VideoClip(make_frame, duration=duration).set_fps(24)
77
- final_clip = mp.CompositeVideoClip([img_clip, effect_clip.set_pos("center")])
78
- final_clip = final_clip.set_audio(mp.AudioFileClip(audio_file))
79
- logger.info("Video compuesto exitosamente")
80
 
81
- # 5. Guardar video
82
- logger.info("Exportando video final...")
83
- with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmpfile:
84
- final_clip.write_videofile(
85
- tmpfile.name,
86
- fps=24,
87
- codec="libx264",
88
- audio_codec="aac",
89
- logger=None
90
- )
91
- logger.info(f"Video guardado temporalmente en: {tmpfile.name}")
92
- return tmpfile.name
93
 
94
  except Exception as e:
95
- logger.error(f"Error cr铆tico durante la generaci贸n: {str(e)}", exc_info=True)
96
- raise Exception(f"Error: {str(e)} - Consulta el archivo app.log para m谩s detalles")
97
 
98
  # Interfaz Gradio
99
  iface = gr.Interface(
100
- fn=generate_waveform_video,
101
  inputs=[
102
- gr.Audio(type="filepath", label="Audio (WAV/MP3)"),
103
- gr.Image(type="filepath", label="Imagen de Fondo"),
104
  ],
105
- outputs=gr.Video(label="Video Resultante", format="mp4"),
106
  title="Generador de Video Musical",
107
- description="Crea videos con efectos de onda de audio sincronizados. Usa im谩genes JPG/PNG y audio WAV/MP3."
108
  )
109
 
110
  if __name__ == "__main__":
111
- logger.info("Iniciando aplicaci贸n Gradio...")
112
  iface.queue().launch()
 
2
  import moviepy.editor as mp
3
  import numpy as np
4
  import librosa
5
+ from PIL import Image, ImageDraw
 
6
  import tempfile
7
  import os
 
8
  import logging
9
 
10
  # Configuraci贸n de logging
11
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
 
 
 
 
 
 
 
 
12
 
13
+ def generate_video(audio_path, image_path):
14
  try:
 
 
 
 
15
  # 1. Cargar audio
16
+ y, sr = librosa.load(audio_path, sr=None)
 
17
  duration = librosa.get_duration(y=y, sr=sr)
18
+ logging.info(f"Audio cargado ({duration:.1f} segundos)")
19
 
20
+ # 2. Cargar imagen
21
+ img = Image.open(image_path).convert('RGB')
22
+ img_w, img_h = img.size
23
+ logging.info(f"Imagen cargada ({img_w}x{img_h})")
 
 
 
24
 
25
+ # 3. Crear efecto de onda
26
+ audio_envelope = np.abs(y) / np.max(np.abs(y)) # Normalizar
27
+ audio_envelope *= img_h // 4 # Escalar al 25% de la altura
 
28
 
29
+ # 4. Generar frames
30
  def make_frame(t):
31
+ frame = img.copy()
32
+ draw = ImageDraw.Draw(frame)
33
+
34
+ # Calcular posici贸n en el audio
 
 
 
35
  time_idx = int(t * sr)
36
  start = max(0, time_idx - sr//10)
37
  end = min(len(audio_envelope), time_idx + sr//10)
38
  wave_slice = audio_envelope[start:end]
 
 
 
 
 
 
 
 
 
 
39
 
40
+ # Dibujar onda
41
+ points = []
42
+ for i, val in enumerate(wave_slice):
43
+ x = int((i / len(wave_slice)) * img_w)
44
+ y_pos = img_h//2 - int(val)
45
+ y_neg = img_h//2 + int(val)
46
+ points.extend([(x, y_pos), (x, y_neg)])
47
+
48
+ if len(points) > 2:
49
+ draw.polygon(points, fill=(255, 0, 0, 128)) # Rojo semitransparente
50
+
51
+ return np.array(frame)
52
+
53
+ # 5. Crear video
54
+ video = mp.VideoClip(make_frame, duration=duration)
55
+ video.fps = 24
56
+ video = video.set_audio(mp.AudioFileClip(audio_path))
57
 
58
+ # 6. Guardar video temporalmente
59
+ temp_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
60
+ video.write_videofile(temp_file.name, codec="libx264", audio_codec="aac", fps=24, logger=None)
61
+ logging.info(f"Video guardado temporalmente en: {temp_file.name}")
 
 
62
 
63
+ # Retornar el archivo como descargable
64
+ return temp_file.name
 
 
 
 
 
 
 
 
 
 
65
 
66
  except Exception as e:
67
+ logging.error(f"Error: {str(e)}")
68
+ return f"Error: {str(e)}"
69
 
70
  # Interfaz Gradio
71
  iface = gr.Interface(
72
+ fn=generate_video,
73
  inputs=[
74
+ gr.Audio(type="filepath", label="Subir Audio (WAV/MP3)"),
75
+ gr.Image(type="filepath", label="Subir Imagen de Fondo")
76
  ],
77
+ outputs=gr.File(label="Descargar Video"), # Cambiado a gr.File para descargar
78
  title="Generador de Video Musical",
79
+ description="Crea videos con efectos de audio sincronizados. Sube un audio y una imagen."
80
  )
81
 
82
  if __name__ == "__main__":
 
83
  iface.queue().launch()