Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -3,8 +3,8 @@ 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
|
@@ -29,20 +29,18 @@ def generate_video(audio_file, image_file):
|
|
29 |
|
30 |
# 3. Analizar audio
|
31 |
audio_envelope = np.abs(y) / np.max(np.abs(y)) # Normalizar
|
32 |
-
audio_envelope_zoom = audio_envelope * 0.2 + 0.9 #
|
33 |
-
audio_envelope_wave = audio_envelope * (img_h // 6) # Para
|
34 |
|
35 |
-
# 4. Generar frames
|
36 |
def make_frame(t):
|
37 |
-
#
|
38 |
time_idx = int(t * sr)
|
39 |
-
|
40 |
-
# --- Efecto de Zoom ---
|
41 |
zoom_factor = audio_envelope_zoom[time_idx] if time_idx < len(audio_envelope_zoom) else 1.0
|
42 |
new_size = (int(img_w * zoom_factor), int(img_h * zoom_factor))
|
43 |
zoomed_img = img.resize(new_size, Image.LANCZOS)
|
44 |
|
45 |
-
#
|
46 |
x_offset = (new_size[0] - img_w) // 2
|
47 |
y_offset = (new_size[1] - img_h) // 2
|
48 |
cropped_img = zoomed_img.crop((
|
@@ -52,11 +50,9 @@ def generate_video(audio_file, image_file):
|
|
52 |
y_offset + img_h
|
53 |
))
|
54 |
|
55 |
-
# ---
|
56 |
frame = ImageDraw.Draw(cropped_img)
|
57 |
-
|
58 |
-
# Posici贸n vertical del waveform (abajo)
|
59 |
-
start_y = int(img_h * 0.75) # 75% hacia abajo
|
60 |
|
61 |
# Extraer slice de audio
|
62 |
start = max(0, time_idx - sr//10)
|
@@ -72,7 +68,7 @@ def generate_video(audio_file, image_file):
|
|
72 |
points.extend([(x, y_pos), (x, y_neg)])
|
73 |
|
74 |
if len(points) > 2:
|
75 |
-
frame.polygon(points, fill=(255, 0, 0, 150))
|
76 |
|
77 |
return np.array(cropped_img)
|
78 |
|
@@ -82,21 +78,23 @@ def generate_video(audio_file, image_file):
|
|
82 |
video = video.set_audio(mp.AudioFileClip(audio_file))
|
83 |
|
84 |
# 6. Guardar video
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
|
|
|
|
96 |
|
97 |
except Exception as e:
|
98 |
logger.error(f"Error cr铆tico: {str(e)}")
|
99 |
-
return
|
100 |
|
101 |
# Interfaz Gradio
|
102 |
iface = gr.Interface(
|
@@ -105,7 +103,7 @@ iface = gr.Interface(
|
|
105 |
gr.Audio(type="filepath", label="Audio (WAV/MP3)"),
|
106 |
gr.Image(type="filepath", label="Imagen de Fondo")
|
107 |
],
|
108 |
-
outputs=gr.File(label="Descargar Video"),
|
109 |
title="Generador de Video Musical",
|
110 |
description="Crea videos con zoom autom谩tico y efectos de audio sincronizados"
|
111 |
)
|
|
|
3 |
import numpy as np
|
4 |
import librosa
|
5 |
from PIL import Image, ImageDraw
|
|
|
6 |
import os
|
7 |
+
import tempfile
|
8 |
import logging
|
9 |
|
10 |
# Configuraci贸n de logging
|
|
|
29 |
|
30 |
# 3. Analizar audio
|
31 |
audio_envelope = np.abs(y) / np.max(np.abs(y)) # Normalizar
|
32 |
+
audio_envelope_zoom = audio_envelope * 0.2 + 0.9 # Para zoom
|
33 |
+
audio_envelope_wave = audio_envelope * (img_h // 6) # Para waveform
|
34 |
|
35 |
+
# 4. Generar frames
|
36 |
def make_frame(t):
|
37 |
+
# --- Zoom autom谩tico ---
|
38 |
time_idx = int(t * sr)
|
|
|
|
|
39 |
zoom_factor = audio_envelope_zoom[time_idx] if time_idx < len(audio_envelope_zoom) else 1.0
|
40 |
new_size = (int(img_w * zoom_factor), int(img_h * zoom_factor))
|
41 |
zoomed_img = img.resize(new_size, Image.LANCZOS)
|
42 |
|
43 |
+
# Recortar al tama帽o original
|
44 |
x_offset = (new_size[0] - img_w) // 2
|
45 |
y_offset = (new_size[1] - img_h) // 2
|
46 |
cropped_img = zoomed_img.crop((
|
|
|
50 |
y_offset + img_h
|
51 |
))
|
52 |
|
53 |
+
# --- Waveform ---
|
54 |
frame = ImageDraw.Draw(cropped_img)
|
55 |
+
start_y = int(img_h * 0.8) # 80% hacia abajo
|
|
|
|
|
56 |
|
57 |
# Extraer slice de audio
|
58 |
start = max(0, time_idx - sr//10)
|
|
|
68 |
points.extend([(x, y_pos), (x, y_neg)])
|
69 |
|
70 |
if len(points) > 2:
|
71 |
+
frame.polygon(points, fill=(255, 0, 0, 150))
|
72 |
|
73 |
return np.array(cropped_img)
|
74 |
|
|
|
78 |
video = video.set_audio(mp.AudioFileClip(audio_file))
|
79 |
|
80 |
# 6. Guardar video
|
81 |
+
temp_dir = tempfile.mkdtemp()
|
82 |
+
output_path = os.path.join(temp_dir, "output.mp4")
|
83 |
+
|
84 |
+
video.write_videofile(
|
85 |
+
output_path,
|
86 |
+
codec="libx264",
|
87 |
+
audio_codec="aac",
|
88 |
+
fps=24,
|
89 |
+
logger=None
|
90 |
+
)
|
91 |
+
|
92 |
+
logger.info(f"Video guardado en: {output_path}")
|
93 |
+
return output_path # Retornar la ruta completa
|
94 |
|
95 |
except Exception as e:
|
96 |
logger.error(f"Error cr铆tico: {str(e)}")
|
97 |
+
return None # Retornar None en caso de error
|
98 |
|
99 |
# Interfaz Gradio
|
100 |
iface = gr.Interface(
|
|
|
103 |
gr.Audio(type="filepath", label="Audio (WAV/MP3)"),
|
104 |
gr.Image(type="filepath", label="Imagen de Fondo")
|
105 |
],
|
106 |
+
outputs=gr.File(label="Descargar Video"), # Muestra el enlace de descarga
|
107 |
title="Generador de Video Musical",
|
108 |
description="Crea videos con zoom autom谩tico y efectos de audio sincronizados"
|
109 |
)
|