tee342 commited on
Commit
aa87123
Β·
verified Β·
1 Parent(s): 5653c9c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -52
app.py CHANGED
@@ -15,6 +15,8 @@ from io import BytesIO
15
  from PIL import Image
16
  import zipfile
17
  import datetime
 
 
18
 
19
  # === Helper Functions ===
20
  def audiosegment_to_array(audio):
@@ -95,7 +97,7 @@ def apply_vocal_isolation(audio_path):
95
  sources = apply_model(model, wav[None])[0]
96
  wav += ref[:, None]
97
 
98
- vocal_track = sources[3].cpu() # index 3 = vocals
99
  out_path = os.path.join(tempfile.gettempdir(), "vocals.wav")
100
  save_track(out_path, vocal_track, model.samplerate)
101
  return out_path
@@ -112,7 +114,7 @@ def stem_split(audio_path):
112
  for i, name in enumerate(['drums', 'bass', 'other', 'vocals']):
113
  path = os.path.join(output_dir, f"{name}.wav")
114
  save_track(path, sources[i].cpu(), model.samplerate)
115
- stem_paths.append((path, name))
116
 
117
  return stem_paths
118
 
@@ -146,21 +148,33 @@ if not preset_choices:
146
 
147
  preset_names = list(preset_choices.keys())
148
 
149
- # === Waveform Generator ===
150
  def show_waveform(audio_file):
151
- try:
152
- audio = AudioSegment.from_file(audio_file)
153
- samples = np.array(audio.get_array_of_samples())
154
- plt.figure(figsize=(10, 2))
155
- plt.plot(samples[:10000], color="blue")
156
- plt.axis("off")
157
- buf = BytesIO()
158
- plt.savefig(buf, format="png", bbox_inches="tight", dpi=100)
159
- plt.close()
160
- buf.seek(0)
161
- return Image.open(buf)
162
- except Exception as e:
163
- return None
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
  # === Session Info Export ===
166
  def generate_session_log(audio_path, effects, isolate_vocals, export_format):
@@ -207,9 +221,10 @@ def process_audio(audio_file, selected_effects, isolate_vocals, preset_name, exp
207
  final_audio.export(output_path, format=export_format.lower())
208
 
209
  waveform_image = show_waveform(output_path)
 
210
  session_log = generate_session_log(audio_file, effects_to_apply, isolate_vocals, export_format)
211
 
212
- return output_path, waveform_image, session_log
213
 
214
  # === Batch Processing Function ===
215
  def batch_process_audio(files, selected_effects, isolate_vocals, preset_name, export_format):
@@ -218,7 +233,7 @@ def batch_process_audio(files, selected_effects, isolate_vocals, preset_name, ex
218
  session_logs = []
219
 
220
  for file in files:
221
- processed_path, _, log = process_audio(file.name, selected_effects, isolate_vocals, preset_name, export_format)
222
  results.append(processed_path)
223
  session_logs.append(log)
224
 
@@ -231,20 +246,7 @@ def batch_process_audio(files, selected_effects, isolate_vocals, preset_name, ex
231
 
232
  return zip_path
233
 
234
- # === Custom Preset Upload Handler ===
235
- def upload_preset(preset_file):
236
- try:
237
- with open(preset_file.name, "r") as f:
238
- data = json.load(f)
239
- if "name" in data and "effects" in data:
240
- preset_choices[data["name"]] = data["effects"]
241
- return f"βœ… Loaded custom preset: {data['name']}"
242
- else:
243
- return "❌ Invalid preset file"
244
- except Exception as e:
245
- return f"⚠️ Error loading preset: {str(e)}"
246
-
247
- # === Gradio Interface ===
248
  effect_options = [
249
  "Noise Reduction",
250
  "Compress Dynamic Range",
@@ -258,8 +260,11 @@ effect_options = [
258
  ]
259
 
260
  # === Multi-Tab UI ===
261
- with gr.Blocks(title="AI Audio Studio") as demo:
262
- gr.Markdown("## 🎧 AI Audio Studio\nUpload, edit, export β€” all powered by AI")
 
 
 
263
 
264
  # ----- Single File Studio Tab -----
265
  with gr.Tab("🎡 Single File Studio"):
@@ -275,11 +280,14 @@ with gr.Blocks(title="AI Audio Studio") as demo:
275
  outputs=[
276
  gr.Audio(label="Processed Audio", type="filepath"),
277
  gr.Image(label="Waveform Preview"),
 
278
  gr.Textbox(label="Session Log (JSON)", lines=5)
279
  ],
280
  title="Edit One File at a Time",
281
- description="Apply effects, preview waveform, and export as MP3 or WAV",
282
- allow_flagging="never"
 
 
283
  )
284
 
285
  # ----- Batch Processing Tab -----
@@ -296,37 +304,51 @@ with gr.Blocks(title="AI Audio Studio") as demo:
296
  outputs=gr.File(label="Download ZIP of All Processed Files"),
297
  title="Batch Audio Processor",
298
  description="Upload multiple files, apply effects in bulk, and download all results in a single ZIP.",
299
- flagging_mode="never", # βœ… New way to disable flagging
300
  submit_btn="Process All Files",
301
- clear_btn=None # βœ… Instead of False
302
  )
303
 
304
  # ----- Remix Mode Tab -----
305
  with gr.Tab("πŸŽ› Remix Mode (Split Stems)"):
306
  def remix_mode(audio_file):
307
- stem_paths = stem_split(audio_file.name)
308
- return [path for path, _ in stem_paths], \
309
- [name for _, name in stem_paths]
310
 
311
  gr.Interface(
312
  fn=remix_mode,
313
  inputs=gr.Audio(label="Upload Music Track", type="filepath"),
314
  outputs=[
315
- gr.File(label="Stem Files (Vocals, Drums, etc.)"),
316
- gr.Textbox(label="Stem Names")
 
 
317
  ],
318
- title="Split Into Drums, Bass, Vocals",
319
- description="Use AI to separate musical elements like vocals, drums, and bass."
 
 
320
  )
321
 
322
- # ----- Preset Manager Tab -----
323
- with gr.Tab("βš™οΈ Preset Manager"):
 
 
 
324
  gr.Interface(
325
- fn=upload_preset,
326
- inputs=gr.File(label="Upload Your Own Preset (.json)"),
327
- outputs=gr.Textbox(label="Preset Status"),
328
- title="Load Custom Presets",
329
- description="Upload your own `.json` preset to customize effect chains."
 
 
 
 
 
 
 
 
330
  )
331
 
332
  demo.launch()
 
15
  from PIL import Image
16
  import zipfile
17
  import datetime
18
+ import librosa
19
+ import librosa.display
20
 
21
  # === Helper Functions ===
22
  def audiosegment_to_array(audio):
 
97
  sources = apply_model(model, wav[None])[0]
98
  wav += ref[:, None]
99
 
100
+ vocal_track = sources[3].cpu()
101
  out_path = os.path.join(tempfile.gettempdir(), "vocals.wav")
102
  save_track(out_path, vocal_track, model.samplerate)
103
  return out_path
 
114
  for i, name in enumerate(['drums', 'bass', 'other', 'vocals']):
115
  path = os.path.join(output_dir, f"{name}.wav")
116
  save_track(path, sources[i].cpu(), model.samplerate)
117
+ stem_paths.append(path)
118
 
119
  return stem_paths
120
 
 
148
 
149
  preset_names = list(preset_choices.keys())
150
 
151
+ # === Waveform + Spectrogram Generator ===
152
  def show_waveform(audio_file):
153
+ audio = AudioSegment.from_file(audio_file)
154
+ samples = np.array(audio.get_array_of_samples())
155
+ plt.figure(figsize=(10, 2))
156
+ plt.plot(samples[:10000], color="blue")
157
+ plt.axis("off")
158
+ buf = BytesIO()
159
+ plt.savefig(buf, format="png", bbox_inches="tight", dpi=100)
160
+ plt.close()
161
+ buf.seek(0)
162
+ return Image.open(buf)
163
+
164
+ def show_spectrogram(audio_file):
165
+ y, sr = torchaudio.load(audio_file)
166
+ y_np = y.numpy().flatten()
167
+ S = librosa.feature.melspectrogram(y=y_np, sr=sr)
168
+ plt.figure(figsize=(10, 2))
169
+ librosa.display.specshow(librosa.power_to_db(S, ref=np.max), sr=sr, x_axis='time', y_axis='mel')
170
+ plt.colorbar(format='%+2.0f dB')
171
+ plt.title('Spectrogram')
172
+ plt.tight_layout()
173
+ buf = BytesIO()
174
+ plt.savefig(buf, format="png", bbox_inches="tight", dpi=100)
175
+ plt.close()
176
+ buf.seek(0)
177
+ return Image.open(buf)
178
 
179
  # === Session Info Export ===
180
  def generate_session_log(audio_path, effects, isolate_vocals, export_format):
 
221
  final_audio.export(output_path, format=export_format.lower())
222
 
223
  waveform_image = show_waveform(output_path)
224
+ spectrogram_image = show_spectrogram(output_path)
225
  session_log = generate_session_log(audio_file, effects_to_apply, isolate_vocals, export_format)
226
 
227
+ return output_path, waveform_image, spectrogram_image, session_log
228
 
229
  # === Batch Processing Function ===
230
  def batch_process_audio(files, selected_effects, isolate_vocals, preset_name, export_format):
 
233
  session_logs = []
234
 
235
  for file in files:
236
+ processed_path, _, _, log = process_audio(file.name, selected_effects, isolate_vocals, preset_name, export_format)
237
  results.append(processed_path)
238
  session_logs.append(log)
239
 
 
246
 
247
  return zip_path
248
 
249
+ # === Gradio Interface Setup ===
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  effect_options = [
251
  "Noise Reduction",
252
  "Compress Dynamic Range",
 
260
  ]
261
 
262
  # === Multi-Tab UI ===
263
+ with gr.Blocks(title="AI Audio Studio", css="style.css") as demo:
264
+ gr.Markdown("""
265
+ # 🎧 AI Audio Studio – Powered by Hugging Face & Demucs
266
+ Upload, edit, and export audio with AI-powered tools.
267
+ """)
268
 
269
  # ----- Single File Studio Tab -----
270
  with gr.Tab("🎡 Single File Studio"):
 
280
  outputs=[
281
  gr.Audio(label="Processed Audio", type="filepath"),
282
  gr.Image(label="Waveform Preview"),
283
+ gr.Image(label="Spectrogram View"),
284
  gr.Textbox(label="Session Log (JSON)", lines=5)
285
  ],
286
  title="Edit One File at a Time",
287
+ description="Apply effects, preview waveform and spectrogram, and get full session log.",
288
+ flagging_mode="never",
289
+ submit_btn="Process Audio",
290
+ clear_btn=None
291
  )
292
 
293
  # ----- Batch Processing Tab -----
 
304
  outputs=gr.File(label="Download ZIP of All Processed Files"),
305
  title="Batch Audio Processor",
306
  description="Upload multiple files, apply effects in bulk, and download all results in a single ZIP.",
307
+ flagging_mode="never",
308
  submit_btn="Process All Files",
309
+ clear_btn=None
310
  )
311
 
312
  # ----- Remix Mode Tab -----
313
  with gr.Tab("πŸŽ› Remix Mode (Split Stems)"):
314
  def remix_mode(audio_file):
315
+ stems = stem_split(audio_file.name)
316
+ return [gr.File(value=stem) for stem in stems]
 
317
 
318
  gr.Interface(
319
  fn=remix_mode,
320
  inputs=gr.Audio(label="Upload Music Track", type="filepath"),
321
  outputs=[
322
+ gr.File(label="Vocals"),
323
+ gr.File(label="Drums"),
324
+ gr.File(label="Bass"),
325
+ gr.File(label="Other")
326
  ],
327
+ title="Split Into Drums, Bass, Vocals, and More",
328
+ description="Use AI to separate musical elements like vocals, drums, and bass.",
329
+ flagging_mode="never",
330
+ clear_btn=None
331
  )
332
 
333
+ # ----- Session Info Tab -----
334
+ with gr.Tab("πŸ“ Session Info"):
335
+ def get_session_info(audio_file, selected_effects, isolate_vocals, preset_name, export_format):
336
+ return generate_session_log(audio_file, selected_effects, isolate_vocals, export_format)
337
+
338
  gr.Interface(
339
+ fn=get_session_info,
340
+ inputs=[
341
+ gr.Audio(label="Upload Audio", type="filepath"),
342
+ gr.CheckboxGroup(choices=effect_options, label="Apply Effects in Order"),
343
+ gr.Checkbox(label="Isolate Vocals After Effects"),
344
+ gr.Dropdown(choices=preset_names, label="Select Preset", value=preset_names[0] if preset_names else None),
345
+ gr.Dropdown(choices=["MP3", "WAV"], label="Export Format", value="MP3")
346
+ ],
347
+ outputs=gr.Textbox(label="Your Session Info (Copy or Save This)", lines=10),
348
+ title="Save Your Session Settings",
349
+ description="Get a full log of what was done to your track.",
350
+ flagging_mode="never",
351
+ clear_btn=None
352
  )
353
 
354
  demo.launch()