teszenofficial commited on
Commit
072eb0c
·
verified ·
1 Parent(s): daea37c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -0
app.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from pydub import AudioSegment
3
+ import uuid
4
+ import os
5
+
6
+ UPLOAD_DIR = "uploads"
7
+ OUTPUT_DIR = "outputs"
8
+ CROSSFADE_MS = 20_000 # 20 segundos reales
9
+
10
+ os.makedirs(UPLOAD_DIR, exist_ok=True)
11
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
12
+
13
+ # -------------------------
14
+ # MOTOR DE MEZCLA REAL
15
+ # -------------------------
16
+
17
+ def create_mix(files, progress=gr.Progress()):
18
+ if not files or len(files) < 2 or len(files) > 4:
19
+ raise gr.Error("Sube entre 2 y 4 canciones")
20
+
21
+ progress(0, desc="Validando archivos…")
22
+
23
+ paths = []
24
+ for f in files:
25
+ ext = f.name.split(".")[-1].lower()
26
+ if ext not in ["mp3", "wav", "flac", "m4a"]:
27
+ raise gr.Error("Formato no soportado")
28
+
29
+ name = f"{uuid.uuid4().hex}.{ext}"
30
+ path = os.path.join(UPLOAD_DIR, name)
31
+
32
+ # Copia segura (NO rename, esto arregla bugs en HF)
33
+ with open(f.name, "rb") as src, open(path, "wb") as dst:
34
+ dst.write(src.read())
35
+
36
+ paths.append(path)
37
+
38
+ progress(10, desc="Cargando primera canción…")
39
+
40
+ current = AudioSegment.from_file(paths[0])
41
+ step = 80 // (len(paths) - 1)
42
+
43
+ for i, p in enumerate(paths[1:], start=1):
44
+ progress(10 + step * (i - 1), desc=f"Mezclando canción {i + 1}")
45
+ next_track = AudioSegment.from_file(p)
46
+ current = current.append(next_track, crossfade=CROSSFADE_MS)
47
+
48
+ progress(95, desc="Exportando mix…")
49
+
50
+ out_name = f"monx_ai_mix_{uuid.uuid4().hex}.wav"
51
+ out_path = os.path.join(OUTPUT_DIR, out_name)
52
+ current.export(out_path, format="wav")
53
+
54
+ progress(100, desc="Mix listo 🎶")
55
+
56
+ return out_path
57
+
58
+ # -------------------------
59
+ # INTERFAZ GRADIO
60
+ # -------------------------
61
+
62
+ with gr.Blocks(title="MONX AI") as demo:
63
+ gr.Markdown(
64
+ """
65
+ <div style="text-align:center">
66
+ <h1>🎵 MONX AI</h1>
67
+ <p>Fusión de audio inteligente con crossfade</p>
68
+ </div>
69
+ """
70
+ )
71
+
72
+ with gr.Column():
73
+ files = gr.File(
74
+ label="Sube de 2 a 4 canciones",
75
+ file_count="multiple",
76
+ file_types=[".mp3", ".wav", ".flac", ".m4a"]
77
+ )
78
+
79
+ btn = gr.Button("✨ Crear Mix", variant="primary")
80
+
81
+ output = gr.Audio(
82
+ label="Resultado",
83
+ type="filepath"
84
+ )
85
+
86
+ btn.click(
87
+ fn=create_mix,
88
+ inputs=files,
89
+ outputs=output
90
+ )
91
+
92
+ # -------------------------
93
+ # HF ENTRYPOINT
94
+ # -------------------------
95
+
96
+ if __name__ == "__main__":
97
+ demo.launch()