CleanSong commited on
Commit
d1a97be
Β·
verified Β·
1 Parent(s): 10b4eff

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -0
app.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import subprocess
4
+ import tempfile
5
+ from pathlib import Path
6
+
7
+ import gradio as gr
8
+ import torchaudio
9
+ import torch
10
+
11
+
12
+ # ================================
13
+ # CONFIG
14
+ # ================================
15
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
16
+ MODEL = "htdemucs" # best quality vocal separation
17
+
18
+
19
+ # ================================
20
+ # SPLIT FUNCTION
21
+ # ================================
22
+ def split_vocals(audio_file):
23
+ if audio_file is None:
24
+ return None, None, "❌ Please upload an audio file."
25
+
26
+ work_dir = tempfile.mkdtemp(prefix="demucs_")
27
+
28
+ try:
29
+ print(f"[Demucs] Input: {audio_file}")
30
+ print(f"[Demucs] Device: {DEVICE}")
31
+
32
+ # Run Demucs
33
+ result = subprocess.run(
34
+ [
35
+ "python", "-m", "demucs",
36
+ "--two-stems", "vocals", # only split vocals vs everything else
37
+ "-n", MODEL,
38
+ "-o", work_dir,
39
+ audio_file,
40
+ ],
41
+ capture_output=True,
42
+ text=True,
43
+ )
44
+
45
+ if result.returncode != 0:
46
+ error = result.stderr[-1000:] # last 1000 chars to avoid huge dumps
47
+ print(f"[Demucs] Error:\n{error}")
48
+ return None, None, f"❌ Demucs failed:\n{error}"
49
+
50
+ # Find output files
51
+ track_name = Path(audio_file).stem
52
+ demucs_out = Path(work_dir) / MODEL / track_name
53
+
54
+ vocals_src = demucs_out / "vocals.wav"
55
+ background_src = demucs_out / "no_vocals.wav"
56
+
57
+ if not vocals_src.exists() or not background_src.exists():
58
+ return None, None, "❌ Demucs ran but output files not found."
59
+
60
+ # Copy to stable paths
61
+ vocals_dst = str(Path(work_dir) / "vocals.wav")
62
+ background_dst = str(Path(work_dir) / "background.wav")
63
+
64
+ shutil.copy2(vocals_src, vocals_dst)
65
+ shutil.copy2(background_src, background_dst)
66
+
67
+ print(f"[Demucs] βœ… Done. Vocals: {vocals_dst}")
68
+ return vocals_dst, background_dst, "βœ… Split complete!"
69
+
70
+ except Exception as e:
71
+ return None, None, f"❌ Exception: {str(e)}"
72
+
73
+
74
+ # ================================
75
+ # GRADIO UI
76
+ # ================================
77
+ with gr.Blocks(title="CleanSong AI β€” Demucs Splitter") as demo:
78
+
79
+ gr.Markdown("# 🎸 CleanSong AI β€” Vocal Splitter")
80
+ gr.Markdown(
81
+ "Upload a song β†’ get the isolated **vocals** and **background** tracks back separately. "
82
+ "Powered by Demucs `htdemucs` model."
83
+ )
84
+
85
+ with gr.Row():
86
+ with gr.Column():
87
+ audio_input = gr.Audio(
88
+ label="Upload Song",
89
+ type="filepath",
90
+ sources=["upload"],
91
+ )
92
+ split_btn = gr.Button("🎸 Split Vocals", variant="primary", size="lg")
93
+
94
+ with gr.Column():
95
+ status = gr.Textbox(label="Status", interactive=False)
96
+ vocals_out = gr.Audio(label="Vocals Only", type="filepath")
97
+ background_out = gr.Audio(label="Background / Instrumental", type="filepath")
98
+
99
+ split_btn.click(
100
+ fn=split_vocals,
101
+ inputs=[audio_input],
102
+ outputs=[vocals_out, background_out, status],
103
+ )
104
+
105
+ gr.Markdown(
106
+ """
107
+ ---
108
+ **Part of the CleanSong AI pipeline.**
109
+ - Upload your song here first to get isolated vocals
110
+ - Feed the vocals into the Whisper Transcriber Space
111
+ - The background track is kept intact for the final remix
112
+ """
113
+ )
114
+
115
+ if __name__ == "__main__":
116
+ demo.launch()