ahkd commited on
Commit
36badcc
Β·
1 Parent(s): 10d4684
Files changed (3) hide show
  1. README.md +73 -5
  2. app.py +203 -38
  3. requirements.txt +3 -1
README.md CHANGED
@@ -1,12 +1,80 @@
1
  ---
2
- title: HT Demucs Stem Separation 2025
3
- emoji: πŸ‘
4
- colorFrom: gray
5
- colorTo: gray
6
  sdk: gradio
7
  sdk_version: 5.39.0
8
  app_file: app.py
9
  pinned: false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: HT-Demucs Spleeter Music Stem Separation - AI Audio Source Separation 2025
3
+ emoji: 🎡
4
+ colorFrom: blue
5
+ colorTo: purple
6
  sdk: gradio
7
  sdk_version: 5.39.0
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
11
+ short_description: HT-Demucs and Spleeter AI music stem separation - separate vocals, drums, bass, piano, other instruments
12
+ tags:
13
+ - music
14
+ - audio
15
+ - stem-separation
16
+ - htdemucs
17
+ - spleeter
18
+ - ai
19
+ - machine-learning
20
+ - vocals
21
+ - drums
22
+ - bass
23
+ - piano
24
+ - audio-processing
25
  ---
26
 
27
+ # 🎡 HT-Demucs Spleeter Music Stem Separation - AI Audio Source Separation
28
+
29
+ A powerful AI-powered music stem separation tool that runs both **HT-Demucs** and **Spleeter** models. Choose which models to run or compare both simultaneously to get the best quality stems for vocals, drums, bass, piano, and other instruments.
30
+
31
+ ## πŸš€ Features
32
+
33
+ ### HT-Demucs Model
34
+ - **Drums** - High-quality drum separation
35
+ - **Bass** - Clean bass line extraction
36
+ - **Other** - All other instruments
37
+ - **Vocals** - Vocal track isolation
38
+
39
+ ### Spleeter Model
40
+ - **Vocals** - Vocal track isolation
41
+ - **Drums** - Drum track separation
42
+ - **Bass** - Bass line extraction
43
+ - **Other** - Other instruments
44
+ - **Piano** - 🎹 **Piano separation (unique to Spleeter!)**
45
+
46
+ ## 🎯 Why Use Both Models?
47
+
48
+ - **HT-Demucs**: Excellent for general stem separation with high quality
49
+ - **Spleeter**: Provides piano separation that HT-Demucs doesn't offer
50
+ - **Comparison**: Side-by-side results help you choose the best quality stems
51
+ - **Flexibility**: Get the best of both worlds!
52
+
53
+ ## πŸ› οΈ How to Use
54
+
55
+ 1. Upload your audio file (MP3, WAV, etc.)
56
+ 2. **Choose your models**: Select HT-Demucs, Spleeter, or both (default: both)
57
+ 3. Click "Separate Music"
58
+ 4. Compare the results and download the best stems for your project
59
+
60
+ ## πŸ“Š Model Comparison
61
+
62
+ | Feature | HT-Demucs | Spleeter |
63
+ |---------|-----------|----------|
64
+ | Vocals | βœ… High Quality | βœ… High Quality |
65
+ | Drums | βœ… High Quality | βœ… High Quality |
66
+ | Bass | βœ… High Quality | βœ… High Quality |
67
+ | Other | βœ… High Quality | βœ… High Quality |
68
+ | Piano | ❌ Not Available | βœ… **Available** |
69
+ | Speed | ⚑ Fast | ⚑ Fast |
70
+
71
+ ## 🎼 Perfect For
72
+
73
+ - Music producers comparing stem quality
74
+ - Remix artists needing piano separation
75
+ - Audio engineers testing different models
76
+ - Anyone who wants the best possible stem separation
77
+
78
+ ---
79
+
80
+ *Powered by HT-Demucs and Spleeter - Choose your best stems!*
app.py CHANGED
@@ -6,28 +6,42 @@ import torchaudio
6
  from demucs.pretrained import get_model
7
  from demucs.apply import apply_model
8
  import os
9
-
10
- # --- Setup the model ---
11
- print("Setting up the model...")
 
 
 
 
 
 
12
  device = 'cuda' if torch.cuda.is_available() else 'cpu'
13
  print(f"Using device: {device}")
14
 
15
- model = get_model(name="htdemucs")
16
- model = model.to(device)
17
- model.eval()
18
- print("Model loaded successfully.")
19
-
20
- # --- Separation function ---
21
- def separate_stems(audio_path):
 
 
 
 
 
 
 
 
22
  """
23
- Separates an audio file into drums, bass, other, and vocals.
24
- Returns FILE PATHS (not base64).
25
  """
26
  if audio_path is None:
27
  return None, None, None, None, "Please upload an audio file."
28
 
29
  try:
30
- print(f"Loading audio from: {audio_path}")
31
  wav, sr = torchaudio.load(audio_path)
32
 
33
  if wav.shape[0] == 1:
@@ -36,14 +50,14 @@ def separate_stems(audio_path):
36
 
37
  wav = wav.to(device)
38
 
39
- print("Applying the separation model...")
40
  with torch.no_grad():
41
- sources = apply_model(model, wav[None], device=device, progress=True)[0]
42
- print("Separation complete.")
43
 
44
  # Save stems temporarily
45
  stem_names = ["drums", "bass", "other", "vocals"]
46
- output_dir = "separated_stems"
47
  os.makedirs(output_dir, exist_ok=True)
48
 
49
  output_paths = []
@@ -51,38 +65,189 @@ def separate_stems(audio_path):
51
  out_path = os.path.join(output_dir, f"{name}.wav")
52
  torchaudio.save(out_path, sources[i].cpu(), sr)
53
  output_paths.append(out_path)
54
- print(f"βœ… Saved {name} to {out_path}")
55
 
56
- return output_paths[0], output_paths[1], output_paths[2], output_paths[3], "βœ… Separation successful!"
57
 
58
  except Exception as e:
59
- print(f"Error: {e}")
60
- return None, None, None, None, f"❌ Error: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
  # --- Gradio UI ---
63
  print("Creating Gradio interface...")
64
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
65
- gr.Markdown("# 🎡 Music Stem Separator with HT Demucs")
 
 
 
 
 
 
 
 
 
66
 
67
  with gr.Row():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  with gr.Column():
69
- audio_input = gr.Audio(type="filepath", label="Upload Your Song")
70
- separate_button = gr.Button("Separate Music", variant="primary")
71
- status_output = gr.Textbox(label="Status", interactive=False)
72
-
 
 
 
 
 
73
  with gr.Column():
74
- gr.Markdown("### 🎧 Separated Stems")
75
- drums_output = gr.Audio(label="Drums", type="filepath")
76
- bass_output = gr.Audio(label="Bass", type="filepath")
77
- other_output = gr.Audio(label="Other", type="filepath")
78
- vocals_output = gr.Audio(label="Vocals", type="filepath")
79
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  separate_button.click(
81
- fn=separate_stems,
82
- inputs=audio_input,
83
- outputs=[drums_output, bass_output, other_output, vocals_output, status_output]
 
 
 
 
84
  )
85
 
86
- gr.Markdown("---\n<p style='text-align: center; font-size: small;'>Powered by HT Demucs</p>")
 
 
 
 
 
 
87
 
88
- demo.launch(share=True)
 
 
6
  from demucs.pretrained import get_model
7
  from demucs.apply import apply_model
8
  import os
9
+ import tempfile
10
+ import numpy as np
11
+ from spleeter.separator import Separator
12
+ from spleeter.audio.adapter import AudioAdapter
13
+ import warnings
14
+ warnings.filterwarnings("ignore")
15
+
16
+ # --- Setup the models ---
17
+ print("Setting up models...")
18
  device = 'cuda' if torch.cuda.is_available() else 'cpu'
19
  print(f"Using device: {device}")
20
 
21
+ # Load HT-Demucs model
22
+ print("Loading HT-Demucs model...")
23
+ htdemucs_model = get_model(name="htdemucs")
24
+ htdemucs_model = htdemucs_model.to(device)
25
+ htdemucs_model.eval()
26
+ print("HT-Demucs model loaded successfully.")
27
+
28
+ # Load Spleeter model (5stems-16kHz)
29
+ print("Loading Spleeter model...")
30
+ spleeter_separator = Separator('spleeter:5stems-16kHz')
31
+ spleeter_audio_adapter = AudioAdapter.default()
32
+ print("Spleeter model loaded successfully.")
33
+
34
+ # --- HT-Demucs separation function ---
35
+ def separate_with_htdemucs(audio_path):
36
  """
37
+ Separates an audio file using HT-Demucs into drums, bass, other, and vocals.
38
+ Returns FILE PATHS.
39
  """
40
  if audio_path is None:
41
  return None, None, None, None, "Please upload an audio file."
42
 
43
  try:
44
+ print(f"HT-Demucs: Loading audio from: {audio_path}")
45
  wav, sr = torchaudio.load(audio_path)
46
 
47
  if wav.shape[0] == 1:
 
50
 
51
  wav = wav.to(device)
52
 
53
+ print("HT-Demucs: Applying the separation model...")
54
  with torch.no_grad():
55
+ sources = apply_model(htdemucs_model, wav[None], device=device, progress=True)[0]
56
+ print("HT-Demucs: Separation complete.")
57
 
58
  # Save stems temporarily
59
  stem_names = ["drums", "bass", "other", "vocals"]
60
+ output_dir = "htdemucs_stems"
61
  os.makedirs(output_dir, exist_ok=True)
62
 
63
  output_paths = []
 
65
  out_path = os.path.join(output_dir, f"{name}.wav")
66
  torchaudio.save(out_path, sources[i].cpu(), sr)
67
  output_paths.append(out_path)
68
+ print(f"βœ… HT-Demucs saved {name} to {out_path}")
69
 
70
+ return output_paths[0], output_paths[1], output_paths[2], output_paths[3], "βœ… HT-Demucs separation successful!"
71
 
72
  except Exception as e:
73
+ print(f"HT-Demucs Error: {e}")
74
+ return None, None, None, None, f"❌ HT-Demucs Error: {str(e)}"
75
+
76
+ # --- Spleeter separation function ---
77
+ def separate_with_spleeter(audio_path):
78
+ """
79
+ Separates an audio file using Spleeter into vocals, drums, bass, other, and piano.
80
+ Returns FILE PATHS.
81
+ """
82
+ if audio_path is None:
83
+ return None, None, None, None, None, "Please upload an audio file."
84
+
85
+ try:
86
+ print(f"Spleeter: Loading audio from: {audio_path}")
87
+
88
+ # Load audio with Spleeter
89
+ waveform, _ = spleeter_audio_adapter.load(audio_path)
90
+
91
+ print("Spleeter: Applying the separation model...")
92
+ prediction = spleeter_separator.separate(waveform)
93
+ print("Spleeter: Separation complete.")
94
+
95
+ # Save stems temporarily
96
+ stem_names = ["vocals", "drums", "bass", "other", "piano"]
97
+ output_dir = "spleeter_stems"
98
+ os.makedirs(output_dir, exist_ok=True)
99
+
100
+ output_paths = []
101
+ for name in stem_names:
102
+ out_path = os.path.join(output_dir, f"{name}.wav")
103
+ # Convert to the right format and save
104
+ stem_audio = prediction[name]
105
+ spleeter_audio_adapter.save(out_path, stem_audio, 44100, 'wav', '16')
106
+ output_paths.append(out_path)
107
+ print(f"βœ… Spleeter saved {name} to {out_path}")
108
+
109
+ return output_paths[0], output_paths[1], output_paths[2], output_paths[3], output_paths[4], "βœ… Spleeter separation successful!"
110
+
111
+ except Exception as e:
112
+ print(f"Spleeter Error: {e}")
113
+ return None, None, None, None, None, f"❌ Spleeter Error: {str(e)}"
114
+
115
+ # --- Combined separation function ---
116
+ def separate_selected_models(audio_path, run_htdemucs, run_spleeter):
117
+ """
118
+ Separates an audio file using selected models (HT-Demucs, Spleeter, or both).
119
+ Returns stems from selected models.
120
+ """
121
+ if audio_path is None:
122
+ return [None] * 13, "Please upload an audio file."
123
+
124
+ if not run_htdemucs and not run_spleeter:
125
+ return [None] * 13, "❌ Please select at least one model to run."
126
+
127
+ try:
128
+ htdemucs_results = [None] * 5 # 4 stems + 1 status
129
+ spleeter_results = [None] * 6 # 5 stems + 1 status
130
+ status_messages = []
131
+
132
+ # Run HT-Demucs if selected
133
+ if run_htdemucs:
134
+ print("Running HT-Demucs...")
135
+ htdemucs_results = separate_with_htdemucs(audio_path)
136
+ status_messages.append(htdemucs_results[-1])
137
+
138
+ # Run Spleeter if selected
139
+ if run_spleeter:
140
+ print("Running Spleeter...")
141
+ spleeter_results = separate_with_spleeter(audio_path)
142
+ status_messages.append(spleeter_results[-1])
143
+
144
+ # Combine results: HT-Demucs (4 stems) + Spleeter (5 stems) + status messages
145
+ all_results = list(htdemucs_results[:-1]) + list(spleeter_results[:-1]) + status_messages
146
+
147
+ # Create combined status message
148
+ models_used = []
149
+ if run_htdemucs:
150
+ models_used.append("HT-Demucs")
151
+ if run_spleeter:
152
+ models_used.append("Spleeter")
153
+
154
+ combined_status = f"🎡 {' + '.join(models_used)} completed!\n\n" + "\n".join(status_messages)
155
+
156
+ return all_results + [combined_status]
157
+
158
+ except Exception as e:
159
+ print(f"Combined Error: {e}")
160
+ return [None] * 13, f"❌ Error: {str(e)}"
161
 
162
  # --- Gradio UI ---
163
  print("Creating Gradio interface...")
164
+ with gr.Blocks(theme=gr.themes.Soft(), title="Music Stem Separator - HT-Demucs & Spleeter") as demo:
165
+ gr.Markdown("""
166
+ # 🎡 Music Stem Separator - HT-Demucs & Spleeter Comparison
167
+
168
+ Upload your music and get stems from both **HT-Demucs** and **Spleeter** models!
169
+
170
+ **HT-Demucs** provides: Drums, Bass, Other, Vocals
171
+ **Spleeter** provides: Vocals, Drums, Bass, Other, **Piano** 🎹
172
+
173
+ Compare the quality and choose the best stems for your needs!
174
+ """)
175
 
176
  with gr.Row():
177
+ with gr.Column(scale=1):
178
+ audio_input = gr.Audio(type="filepath", label="🎡 Upload Your Song")
179
+
180
+ # Model selection toggles
181
+ gr.Markdown("### πŸŽ›οΈ Select Models to Run")
182
+ with gr.Row():
183
+ htdemucs_toggle = gr.Checkbox(label="🎯 HT-Demucs", value=True, info="Drums, Bass, Other, Vocals")
184
+ spleeter_toggle = gr.Checkbox(label="🎡 Spleeter", value=True, info="Vocals, Drums, Bass, Other, Piano")
185
+
186
+ separate_button = gr.Button("πŸš€ Separate Music", variant="primary", size="lg")
187
+ status_output = gr.Textbox(label="πŸ“Š Status", interactive=False, lines=4)
188
+
189
+ gr.Markdown("---")
190
+
191
+ with gr.Row():
192
+ # HT-Demucs Results
193
  with gr.Column():
194
+ gr.Markdown("### 🎯 HT-Demucs Results")
195
+ with gr.Row():
196
+ htdemucs_drums = gr.Audio(label="πŸ₯ Drums", type="filepath")
197
+ htdemucs_bass = gr.Audio(label="🎸 Bass", type="filepath")
198
+ with gr.Row():
199
+ htdemucs_other = gr.Audio(label="🎼 Other", type="filepath")
200
+ htdemucs_vocals = gr.Audio(label="🎀 Vocals", type="filepath")
201
+
202
+ # Spleeter Results
203
  with gr.Column():
204
+ gr.Markdown("### 🎡 Spleeter Results")
205
+ with gr.Row():
206
+ spleeter_vocals = gr.Audio(label="🎀 Vocals", type="filepath")
207
+ spleeter_drums = gr.Audio(label="πŸ₯ Drums", type="filepath")
208
+ with gr.Row():
209
+ spleeter_bass = gr.Audio(label="🎸 Bass", type="filepath")
210
+ spleeter_other = gr.Audio(label="🎼 Other", type="filepath")
211
+ with gr.Row():
212
+ spleeter_piano = gr.Audio(label="🎹 Piano", type="filepath")
213
+
214
+ gr.Markdown("---")
215
+
216
+ with gr.Row():
217
+ gr.Markdown("""
218
+ ### πŸ“‹ Model Comparison
219
+
220
+ | Feature | HT-Demucs | Spleeter |
221
+ |---------|-----------|----------|
222
+ | **Vocals** | βœ… High Quality | βœ… High Quality |
223
+ | **Drums** | βœ… High Quality | βœ… High Quality |
224
+ | **Bass** | βœ… High Quality | βœ… High Quality |
225
+ | **Other** | βœ… High Quality | βœ… High Quality |
226
+ | **Piano** | ❌ Not Available | βœ… **Available** |
227
+ | **Speed** | ⚑ Fast | ⚑ Fast |
228
+ | **Quality** | πŸ† Excellent | πŸ† Excellent |
229
+
230
+ **πŸ’‘ Tip:** Use Spleeter when you need piano separation, HT-Demucs for other instruments!
231
+ """)
232
+
233
+ # Connect the button to the combined function
234
  separate_button.click(
235
+ fn=separate_selected_models,
236
+ inputs=[audio_input, htdemucs_toggle, spleeter_toggle],
237
+ outputs=[
238
+ htdemucs_drums, htdemucs_bass, htdemucs_other, htdemucs_vocals, # HT-Demucs outputs
239
+ spleeter_vocals, spleeter_drums, spleeter_bass, spleeter_other, spleeter_piano, # Spleeter outputs
240
+ status_output # Status output
241
+ ]
242
  )
243
 
244
+ gr.Markdown("""
245
+ ---
246
+ <p style='text-align: center; font-size: small;'>
247
+ πŸš€ Powered by <strong>HT-Demucs</strong> & <strong>Spleeter</strong> |
248
+ 🎡 Compare and choose your best stems!
249
+ </p>
250
+ """)
251
 
252
+ if __name__ == "__main__":
253
+ demo.launch(share=True)
requirements.txt CHANGED
@@ -1 +1,3 @@
1
- git+https://github.com/adefossez/demucs
 
 
 
1
+ git+https://github.com/adefossez/demucs
2
+ spleeter==2.3.2
3
+ tensorflow==2.13.0