tee342 commited on
Commit
3af2469
Β·
verified Β·
1 Parent(s): 7f358cd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +100 -25
app.py CHANGED
@@ -13,6 +13,8 @@ from pathlib import Path
13
  import matplotlib.pyplot as plt
14
  from io import BytesIO
15
  from PIL import Image
 
 
16
 
17
  # === Helper Functions ===
18
  def audiosegment_to_array(audio):
@@ -98,6 +100,22 @@ def apply_vocal_isolation(audio_path):
98
  save_track(out_path, vocal_track, model.samplerate)
99
  return out_path
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  # === Preset Loader with Fallback ===
102
  def load_presets():
103
  try:
@@ -110,10 +128,8 @@ def load_presets():
110
  data = json.load(infile)
111
  if "name" in data and "effects" in data:
112
  presets[data["name"]] = data["effects"]
113
- else:
114
- print(f"Invalid format in {f}")
115
  except json.JSONDecodeError:
116
- print(f"Failed to parse {f} β€” invalid JSON")
117
  return presets
118
  except FileNotFoundError:
119
  print("Presets folder not found")
@@ -146,6 +162,17 @@ def show_waveform(audio_file):
146
  except Exception as e:
147
  return None
148
 
 
 
 
 
 
 
 
 
 
 
 
149
  # === Main Processing Function ===
150
  def process_audio(audio_file, selected_effects, isolate_vocals, preset_name, export_format):
151
  audio = AudioSegment.from_file(audio_file)
@@ -178,27 +205,46 @@ def process_audio(audio_file, selected_effects, isolate_vocals, preset_name, exp
178
 
179
  output_path = f.name
180
  final_audio.export(output_path, format=export_format.lower())
181
- return output_path, show_waveform(output_path)
182
 
183
- # === Batch Processing Function ===
184
- import zipfile
 
 
185
 
 
186
  def batch_process_audio(files, selected_effects, isolate_vocals, preset_name, export_format):
187
  output_dir = tempfile.mkdtemp()
188
  results = []
 
189
 
190
  for file in files:
191
- processed_path = process_audio(file.name, selected_effects, isolate_vocals, preset_name, export_format)
192
- results.append(processed_path[0]) # Take just the file path
 
193
 
194
  zip_path = os.path.join(output_dir, "batch_output.zip")
195
  with zipfile.ZipFile(zip_path, 'w') as zipf:
196
  for i, res in enumerate(results):
197
- zipf.write(res, f"processed_{i}.{export_format.lower()}")
 
 
198
 
199
  return zip_path
200
 
201
- # === Effect List ===
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  effect_options = [
203
  "Noise Reduction",
204
  "Compress Dynamic Range",
@@ -215,6 +261,27 @@ effect_options = [
215
  with gr.Blocks(title="AI Audio Studio") as demo:
216
  gr.Markdown("## 🎧 AI Audio Studio\nUpload, edit, export β€” all powered by AI")
217
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  # ----- Batch Processing Tab -----
219
  with gr.Tab("πŸ”Š Batch Processing"):
220
  gr.Interface(
@@ -234,24 +301,32 @@ with gr.Blocks(title="AI Audio Studio") as demo:
234
  clear_btn=False
235
  )
236
 
237
- # ----- Single File Studio Tab -----
238
- with gr.Tab("🎡 Single File Studio"):
 
 
 
 
 
239
  gr.Interface(
240
- fn=process_audio,
241
- inputs=[
242
- gr.Audio(label="Upload Audio", type="filepath"),
243
- gr.CheckboxGroup(choices=effect_options, label="Apply Effects in Order"),
244
- gr.Checkbox(label="Isolate Vocals After Effects"),
245
- gr.Dropdown(choices=preset_names, label="Select Preset", value=preset_names[0] if preset_names else None),
246
- gr.Dropdown(choices=["MP3", "WAV"], label="Export Format", value="MP3")
247
- ],
248
  outputs=[
249
- gr.Audio(label="Processed Audio", type="filepath"),
250
- gr.Image(label="Waveform Preview")
251
  ],
252
- title="Edit One File at a Time",
253
- description="Apply effects, preview waveform, and export as MP3 or WAV",
254
- allow_flagging="never"
 
 
 
 
 
 
 
 
 
255
  )
256
 
257
  demo.launch()
 
13
  import matplotlib.pyplot as plt
14
  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):
 
100
  save_track(out_path, vocal_track, model.samplerate)
101
  return out_path
102
 
103
+ # === Stem Splitting (Drums, Bass, Other, Vocals) ===
104
+ def stem_split(audio_path):
105
+ model = pretrained.get_model(name='htdemucs')
106
+ wav = load_track_local(audio_path, model.samplerate, channels=2)
107
+ sources = apply_model(model, wav[None])[0]
108
+
109
+ output_dir = tempfile.mkdtemp()
110
+ stem_paths = []
111
+
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
+
119
  # === Preset Loader with Fallback ===
120
  def load_presets():
121
  try:
 
128
  data = json.load(infile)
129
  if "name" in data and "effects" in data:
130
  presets[data["name"]] = data["effects"]
 
 
131
  except json.JSONDecodeError:
132
+ print(f"Invalid JSON: {f}")
133
  return presets
134
  except FileNotFoundError:
135
  print("Presets folder not found")
 
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):
167
+ log = {
168
+ "timestamp": str(datetime.datetime.now()),
169
+ "filename": os.path.basename(audio_path),
170
+ "effects_applied": effects,
171
+ "isolate_vocals": isolate_vocals,
172
+ "export_format": export_format
173
+ }
174
+ return json.dumps(log, indent=2)
175
+
176
  # === Main Processing Function ===
177
  def process_audio(audio_file, selected_effects, isolate_vocals, preset_name, export_format):
178
  audio = AudioSegment.from_file(audio_file)
 
205
 
206
  output_path = f.name
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):
216
  output_dir = tempfile.mkdtemp()
217
  results = []
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
 
225
  zip_path = os.path.join(output_dir, "batch_output.zip")
226
  with zipfile.ZipFile(zip_path, 'w') as zipf:
227
  for i, res in enumerate(results):
228
+ filename = f"processed_{i}.{export_format.lower()}"
229
+ zipf.write(res, filename)
230
+ zipf.writestr(f"session_info_{i}.json", session_logs[i])
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",
 
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"):
266
+ gr.Interface(
267
+ fn=process_audio,
268
+ inputs=[
269
+ gr.Audio(label="Upload Audio", type="filepath"),
270
+ gr.CheckboxGroup(choices=effect_options, label="Apply Effects in Order"),
271
+ gr.Checkbox(label="Isolate Vocals After Effects"),
272
+ gr.Dropdown(choices=preset_names, label="Select Preset", value=preset_names[0] if preset_names else None),
273
+ gr.Dropdown(choices=["MP3", "WAV"], label="Export Format", value="MP3")
274
+ ],
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 -----
286
  with gr.Tab("πŸ”Š Batch Processing"):
287
  gr.Interface(
 
301
  clear_btn=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()