ASesYusuf1 commited on
Commit
6a76931
·
verified ·
1 Parent(s): 003791d

Update gui.py

Browse files
Files changed (1) hide show
  1. gui.py +245 -169
gui.py CHANGED
@@ -9,7 +9,8 @@ from audio_separator.separator import Separator
9
  import numpy as np
10
  import librosa
11
  import soundfile as sf
12
- from ensemble import ensemble_files # ensemble.py'dan import
 
13
 
14
  device = "cuda" if torch.cuda.is_available() else "cpu"
15
  use_autocast = device == "cuda"
@@ -21,7 +22,9 @@ logger = logging.getLogger(__name__)
21
  # Model dictionaries organized by category
22
  ROFORMER_MODELS = {
23
  "Vocals": {
 
24
  'MelBand Roformer | Vocals by Kimberley Jensen': 'vocals_mel_band_roformer.ckpt',
 
25
  'MelBand Roformer | Vocals by becruily': 'mel_band_roformer_vocals_becruily.ckpt',
26
  'MelBand Roformer | Vocals Fullness by Aname': 'mel_band_roformer_vocal_fullness_aname.ckpt',
27
  'BS Roformer | Vocals by Gabox': 'bs_roformer_vocals_gabox.ckpt',
@@ -34,6 +37,13 @@ ROFORMER_MODELS = {
34
  'BS Roformer | Male-Female by aufr33': 'bs_roformer_male_female_by_aufr33_sdr_7.2889.ckpt',
35
  },
36
  "Instrumentals": {
 
 
 
 
 
 
 
37
  'MelBand Roformer Kim | Inst V1 by Unwa': 'melband_roformer_inst_v1.ckpt',
38
  'MelBand Roformer Kim | Inst V1 (E) by Unwa': 'melband_roformer_inst_v1e.ckpt',
39
  'MelBand Roformer Kim | Inst V2 by Unwa': 'melband_roformer_inst_v2.ckpt',
@@ -76,6 +86,7 @@ ROFORMER_MODELS = {
76
  "Karaoke": {
77
  'Mel-Roformer-Karaoke-Aufr33-Viperx': 'mel_band_roformer_karaoke_aufr33_viperx_sdr_10.1956.ckpt',
78
  'MelBand Roformer | Karaoke by Gabox': 'mel_band_roformer_karaoke_gabox.ckpt',
 
79
  },
80
  "General Purpose": {
81
  'BS-Roformer-Viperx-1297': 'model_bs_roformer_ep_317_sdr_12.9755.ckpt',
@@ -102,29 +113,30 @@ ROFORMER_MODELS = {
102
 
103
  OUTPUT_FORMATS = ['wav', 'flac', 'mp3', 'ogg', 'opus', 'm4a', 'aiff', 'ac3']
104
 
105
- # CSS
106
  CSS = """
107
- /* İnce ve Ortalanmış Tema */
108
  #app-container {
109
- max-width: 600px;
110
  width: 100%;
111
  margin: 0 auto;
112
- padding: 0.2rem;
113
  box-sizing: border-box;
114
  display: flex;
115
  flex-direction: column;
116
  align-items: center;
117
  min-height: 100vh;
118
- background-color: #2d0b0b;
119
  position: relative;
 
120
  }
121
  body {
122
  background: url('/content/logo.jpg') no-repeat center center fixed;
123
  background-size: cover;
124
  margin: 0;
125
  padding: 0;
126
- font-family: 'Poppins', sans-serif;
127
- color: #C0C0C0;
128
  display: flex;
129
  justify-content: center;
130
  }
@@ -135,163 +147,180 @@ body::after {
135
  left: 0;
136
  width: 100%;
137
  height: 100%;
138
- background: rgba(45, 11, 11, 0.85);
139
  z-index: -1;
140
  }
141
  .logo-container {
142
  position: fixed;
143
- top: 0.2rem;
144
  left: 50%;
145
  transform: translateX(-50%);
146
  z-index: 2000;
147
  }
148
  .logo-img {
149
- width: 60px;
150
  height: auto;
 
 
 
 
151
  }
152
  .header-text {
153
  text-align: center;
154
- padding: 2rem 0.3rem 0.3rem;
155
- color: #ff4040;
156
- font-size: 1.4rem;
157
- font-weight: 700;
158
- text-shadow: 0 0 5px rgba(255, 64, 64, 0.4);
159
- z-index: 1500;
 
 
 
 
160
  }
161
  .dubbing-theme {
162
- background: linear-gradient(to bottom, #800000, #2d0b0b);
163
- border-radius: 6px;
164
- padding: 0.4rem;
165
- box-shadow: 0 3px 10px rgba(255, 64, 64, 0.2);
166
  width: 100%;
 
 
 
 
167
  }
168
  .footer {
169
  text-align: center;
170
- padding: 0.2rem;
171
- color: #ff4040;
172
- font-size: 10px;
173
  position: fixed;
174
  bottom: 0;
175
  width: 100%;
176
- max-width: 600px;
177
- background: rgba(45, 11, 11, 0.7);
178
  z-index: 1001;
179
  left: 50%;
180
  transform: translateX(-50%);
181
  }
182
  button {
183
- background: #800000 !important;
184
- border: 1px solid #ff4040 !important;
185
- color: #C0C0C0 !important;
186
- border-radius: 4px !important;
187
- padding: 4px 8px !important;
188
- font-size: 0.75rem !important;
189
- transition: all 0.2s ease !important;
 
 
190
  }
191
  button:hover {
192
- transform: scale(1.03) !important;
193
- background: #ff4040 !important;
194
- box-shadow: 0 3px 12px rgba(255, 64, 64, 0.5) !important;
195
  }
196
  .compact-upload.horizontal {
197
- display: inline-flex !important;
198
  align-items: center !important;
199
- gap: 4px !important;
200
- max-width: 200px !important;
201
- height: 28px !important;
202
- padding: 0 5px !important;
203
- border: 1px solid #ff4040 !important;
204
- background: rgba(128, 0, 0, 0.5) !important;
205
- border-radius: 4px !important;
206
- color: #C0C0C0 !important;
207
  }
208
  .compact-upload.horizontal:hover {
209
- border-color: #ff6b6b !important;
210
- background: rgba(128, 0, 0, 0.7) !important;
211
  }
212
  .compact-upload.horizontal button {
213
- padding: 2px 6px !important;
214
- font-size: 0.6rem !important;
215
- height: 20px !important;
216
- min-width: 40px !important;
217
  }
218
  .gr-tab {
219
- background: rgba(128, 0, 0, 0.5) !important;
220
- border-radius: 5px 5px 0 0 !important;
221
- padding: 0.3rem 0.6rem !important;
222
- margin: 0 1px !important;
223
- color: #C0C0C0 !important;
224
- border: 1px solid #ff4040 !important;
225
- z-index: 1500;
226
- font-size: 0.8rem !important;
227
  }
228
  .gr-tab-selected {
229
- background: #800000 !important;
230
- color: #ffffff !important;
231
- border: 1px solid #ff6b6b !important;
232
- box-shadow: 0 2px 5px rgba(255, 64, 64, 0.5) !important;
233
  }
234
  .compact-grid {
235
- gap: 0.15rem !important;
236
- max-height: 30vh;
237
  overflow-y: auto;
238
- padding: 0.3rem;
239
- background: rgba(128, 0, 0, 0.3) !important;
240
- border-radius: 5px;
241
- border: 1px solid #ff4040 !important;
242
  width: 100%;
243
  }
244
  .compact-dropdown {
245
- padding: 4px 6px !important;
246
- border-radius: 5px !important;
247
- border: 1px solid #ff4040 !important;
248
- background: rgba(128, 0, 0, 0.5) !important;
249
- color: #C0C0C0 !important;
250
  width: 100%;
251
- font-size: 0.8rem !important;
 
 
 
 
252
  }
253
  .gr-slider input[type="range"] {
254
  -webkit-appearance: none !important;
255
  width: 100% !important;
256
- height: 5px !important;
257
- background: #ff4040 !important;
258
- border-radius: 2px !important;
259
  outline: none !important;
260
  }
261
  .gr-slider input[type="range"]::-webkit-slider-thumb {
262
  -webkit-appearance: none !important;
263
- width: 12px !important;
264
- height: 12px !important;
265
- background: #800000 !important;
266
- border: 1px solid #ff6b6b !important;
267
  border-radius: 50% !important;
268
  cursor: pointer !important;
 
269
  }
270
  .gr-slider input[type="range"]::-moz-range-thumb {
271
- width: 12px !important;
272
- height: 12px !important;
273
- background: #800000 !important;
274
- border: 1px solid #ff6b6b !important;
275
  border-radius: 50% !important;
276
  cursor: pointer !important;
 
277
  }
278
  @media (max-width: 768px) {
279
  #app-container {
280
  max-width: 100%;
281
- padding: 0.1rem;
282
  }
283
  .header-text {
284
- font-size: 1.2rem;
285
- padding: 1.5rem 0.3rem 0.2rem;
286
  }
287
  .logo-img {
288
- width: 40px;
289
  }
290
  .compact-upload.horizontal {
291
  max-width: 100% !important;
292
  }
293
  .compact-grid {
294
- max-height: 25vh;
295
  }
296
  .footer {
297
  max-width: 100%;
@@ -300,14 +329,19 @@ button:hover {
300
  """
301
 
302
  # Fonksiyonlar
303
- def download_audio(url, output_dir="ytdl"):
304
  if not url:
305
  raise ValueError("No URL provided.")
306
- os.makedirs(output_dir, exist_ok=True)
 
 
 
 
 
307
  ydl_opts = {
308
  'format': 'bestaudio/best',
309
  'postprocessors': [{'key': 'FFmpegExtractAudio', 'preferredcodec': 'wav', 'preferredquality': '192'}],
310
- 'outtmpl': os.path.join(output_dir, '%(title)s.%(ext)s'),
311
  }
312
  try:
313
  with YoutubeDL(ydl_opts) as ydl:
@@ -317,9 +351,15 @@ def download_audio(url, output_dir="ytdl"):
317
  except Exception as e:
318
  raise RuntimeError(f"Download failed: {e}")
319
 
320
- def roformer_separator(audio, model_key, seg_size, override_seg_size, overlap, pitch_shift, model_dir, out_dir, out_format, norm_thresh, amp_thresh, batch_size, single_stem="", progress=gr.Progress(track_tqdm=True)):
321
  if not audio:
322
  raise ValueError("No audio file provided.")
 
 
 
 
 
 
323
  base_name = os.path.splitext(os.path.basename(audio))[0]
324
  for category, models in ROFORMER_MODELS.items():
325
  if model_key in models:
@@ -333,32 +373,45 @@ def roformer_separator(audio, model_key, seg_size, override_seg_size, overlap, p
333
  separator = Separator(
334
  log_level=logging.INFO,
335
  model_file_dir=model_dir,
336
- output_dir=out_dir,
337
  output_format=out_format,
338
  normalization_threshold=norm_thresh,
339
  amplification_threshold=amp_thresh,
340
  use_autocast=use_autocast,
341
- output_single_stem=single_stem if single_stem.strip() else None,
342
  mdxc_params={"segment_size": seg_size, "override_model_segment_size": override_seg_size, "batch_size": batch_size, "overlap": overlap, "pitch_shift": pitch_shift}
343
  )
344
  progress(0.2, desc="Loading model...")
345
  separator.load_model(model_filename=model)
346
  progress(0.7, desc="Separating audio...")
347
  separation = separator.separate(audio)
348
- stems = [os.path.join(out_dir, file_name) for file_name in separation]
349
- return stems[0], stems[1] if len(stems) > 1 and not single_stem.strip() else None
 
 
 
 
 
 
350
  except Exception as e:
351
  logger.error(f"Separation failed: {e}")
352
  raise RuntimeError(f"Separation failed: {e}")
353
 
354
- def auto_ensemble_process(audio, model_keys, seg_size, overlap, out_format, use_tta, model_dir, out_dir, norm_thresh, amp_thresh, batch_size, ensemble_method, only_instrumental, progress=gr.Progress()):
355
  if not audio or not model_keys:
356
  raise ValueError("Audio or models missing.")
 
 
 
 
 
 
357
  base_name = os.path.splitext(os.path.basename(audio))[0]
358
  logger.info(f"Ensemble for {base_name} with {model_keys}")
359
 
360
- all_stems = []
361
  total_models = len(model_keys)
 
 
362
  for i, model_key in enumerate(model_keys):
363
  for category, models in ROFORMER_MODELS.items():
364
  if model_key in models:
@@ -366,10 +419,11 @@ def auto_ensemble_process(audio, model_keys, seg_size, overlap, out_format, use_
366
  break
367
  else:
368
  continue
 
369
  separator = Separator(
370
  log_level=logging.INFO,
371
  model_file_dir=model_dir,
372
- output_dir=out_dir,
373
  output_format=out_format,
374
  normalization_threshold=norm_thresh,
375
  amplification_threshold=amp_thresh,
@@ -380,22 +434,36 @@ def auto_ensemble_process(audio, model_keys, seg_size, overlap, out_format, use_
380
  separator.load_model(model_filename=model)
381
  progress(0.5 + (0.4 / total_models) * i, desc=f"Separating with {model_key}")
382
  separation = separator.separate(audio)
383
- stems = [os.path.join(out_dir, file_name) for file_name in separation]
384
- if only_instrumental:
385
- instrumental_stem = next((stem for stem in stems if "instrumental" in stem.lower()), None)
386
- if instrumental_stem:
387
- all_stems.append(instrumental_stem)
 
 
388
  else:
389
- all_stems.append(stems[0])
390
 
391
  if not all_stems:
392
- raise ValueError("No valid stems for ensemble.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
 
394
- output_file = os.path.join(out_dir, f"{base_name}_ensemble_{'instrumental_' if only_instrumental else ''}{ensemble_method}.{out_format}")
395
- with open(output_file, 'w') as f:
396
- f.write("Simulated ensemble output")
397
  progress(1.0, desc="Ensemble complete")
398
- return output_file, f"Ensemble completed with {ensemble_method}"
399
 
400
  def update_roformer_models(category):
401
  return gr.update(choices=list(ROFORMER_MODELS[category].keys()))
@@ -405,70 +473,84 @@ def update_ensemble_models(category):
405
 
406
  # Arayüzü bir fonksiyon olarak tanımla
407
  def create_interface():
408
- with gr.Blocks(title="🎵 Audio-Separator 🎵", css=CSS, elem_id="app-container") as app:
409
- gr.Markdown("<h1 class='header-text'>🎵 Audio-Separator 🎵</h1>")
410
 
411
  with gr.Tabs():
 
412
  with gr.Tab("⚙️ Settings"):
413
- model_file_dir = gr.Textbox(value="/tmp/audio-separator-models/", label="📂 Model Cache", placeholder="/tmp/audio-separator-models/")
414
- output_dir = gr.Textbox(value="output", label="📤 Output Dir", placeholder="output")
415
- output_format = gr.Dropdown(value="wav", choices=OUTPUT_FORMATS, label="🎶 Format")
416
- norm_threshold = gr.Slider(0.1, 1, value=0.9, step=0.1, label="🔊 Norm Thresh")
417
- amp_threshold = gr.Slider(0.1, 1, value=0.6, step=0.1, label="📈 Amp Thresh")
418
- batch_size = gr.Slider(1, 16, value=1, step=1, label=" Batch Size")
 
 
419
 
 
420
  with gr.Tab("🎤 Roformer"):
421
- roformer_audio = gr.Audio(label="🎧 Input Audio", type="filepath")
422
- roformer_single_stem = gr.Textbox(label="🎼 Single Stem", placeholder="e.g., Instrumental")
423
- roformer_category = gr.Dropdown(label="📚 Category", choices=list(ROFORMER_MODELS.keys()), value="General Purpose")
424
- roformer_model = gr.Dropdown(label="🛠️ Model", choices=list(ROFORMER_MODELS["General Purpose"].keys()))
425
- with gr.Row():
426
- roformer_seg_size = gr.Slider(32, 4000, value=256, step=32, label="📏 Seg Size")
427
- roformer_overlap = gr.Slider(2, 10, value=8, step=1, label="🔄 Overlap")
428
- with gr.Row():
429
- roformer_pitch_shift = gr.Slider(-12, 12, value=0, step=1, label="🎵 Pitch")
430
- roformer_override_seg_size = gr.Checkbox(value=False, label="🔧 Override Seg")
431
- with gr.Row():
432
- url_ro = gr.Textbox(label="🔗 URL", placeholder="Audio/Video URL")
433
- download_roformer = gr.Button("⬇️ Download")
434
- roformer_button = gr.Button("✂️ Separate!", variant="primary")
435
- with gr.Row():
436
- roformer_stem1 = gr.Audio(label="🎸 Stem 1", type="filepath", interactive=False)
437
- roformer_stem2 = gr.Audio(label="🥁 Stem 2", type="filepath", interactive=False)
 
 
 
438
 
 
439
  with gr.Tab("🎚️ Auto Ensemble"):
440
- ensemble_audio = gr.Audio(label="🎧 Input Audio", type="filepath")
441
- ensemble_category = gr.Dropdown(label="📚 Category", choices=list(ROFORMER_MODELS.keys()), value="Instrumentals")
442
- ensemble_models = gr.Dropdown(label="🛠️ Models", choices=list(ROFORMER_MODELS["Instrumentals"].keys()), multiselect=True)
443
- with gr.Row():
444
- ensemble_seg_size = gr.Slider(32, 4000, value=256, step=32, label="📏 Seg Size")
445
- ensemble_overlap = gr.Slider(0.1, 0.9, value=0.2, step=0.1, label="🔄 Overlap")
446
- with gr.Row():
447
- ensemble_use_tta = gr.Checkbox(value=False, label="🔍 TTA")
448
- only_instrumental = gr.Checkbox(value=False, label="🎸 Only Instr")
449
- ensemble_method = gr.Dropdown(label="Method", choices=['avg_wave', 'median_wave', 'max_wave', 'min_wave'], value='avg_wave')
450
- with gr.Row():
451
- url_ensemble = gr.Textbox(label="🔗 URL", placeholder="Audio/Video URL")
452
- download_ensemble = gr.Button("⬇️ Download")
453
- ensemble_button = gr.Button("🎛️ Run Ensemble!", variant="primary")
454
- ensemble_output = gr.Audio(label="🎶 Output", type="filepath", interactive=False)
455
- ensemble_status = gr.Textbox(label="📢 Status", interactive=False)
 
 
 
456
 
457
- gr.HTML("<div class='footer'>Powered by Audio-Separator 🌟🎶</div>")
458
 
459
- # Event Handlers
460
  roformer_category.change(update_roformer_models, inputs=[roformer_category], outputs=[roformer_model])
461
  download_roformer.click(fn=download_audio, inputs=[url_ro], outputs=[roformer_audio])
462
  roformer_button.click(
463
  roformer_separator,
464
- inputs=[roformer_audio, roformer_model, roformer_seg_size, roformer_override_seg_size, roformer_overlap, roformer_pitch_shift, model_file_dir, output_dir, output_format, norm_threshold, amp_threshold, batch_size, roformer_single_stem],
465
  outputs=[roformer_stem1, roformer_stem2]
466
  )
467
  ensemble_category.change(update_ensemble_models, inputs=[ensemble_category], outputs=[ensemble_models])
468
  download_ensemble.click(fn=download_audio, inputs=[url_ensemble], outputs=[ensemble_audio])
469
  ensemble_button.click(
470
- auto_ensemble_process,
471
- inputs=[ensemble_audio, ensemble_models, ensemble_seg_size, ensemble_overlap, output_format, ensemble_use_tta, model_file_dir, output_dir, norm_threshold, amp_threshold, batch_size, ensemble_method, only_instrumental],
 
 
 
472
  outputs=[ensemble_output, ensemble_status]
473
  )
474
 
@@ -480,13 +562,7 @@ if __name__ == "__main__":
480
  parser.add_argument("--ngrok-token", type=str, default=None, help="Ngrok token for tunneling")
481
  args = parser.parse_args()
482
 
483
- app = create_interface() # app değişkenini burada tanımlıyoruz
484
-
485
- if args.ngrok_token:
486
- from pyngrok import ngrok
487
- ngrok.set_auth_token(args.ngrok_token)
488
- public_url = ngrok.connect(args.port, "http")
489
- print(f"Ngrok URL: {public_url}")
490
- app.launch(server_name="0.0.0.0", server_port=args.port)
491
- else:
492
- app.launch(server_name="0.0.0.0", server_port=args.port, share=True)
 
9
  import numpy as np
10
  import librosa
11
  import soundfile as sf
12
+ from ensemble import ensemble_files
13
+ import shutil
14
 
15
  device = "cuda" if torch.cuda.is_available() else "cpu"
16
  use_autocast = device == "cuda"
 
22
  # Model dictionaries organized by category
23
  ROFORMER_MODELS = {
24
  "Vocals": {
25
+ 'MelBand Roformer | Big Beta 6X by unwa': 'melband_roformer_big_beta6x.ckpt',
26
  'MelBand Roformer | Vocals by Kimberley Jensen': 'vocals_mel_band_roformer.ckpt',
27
+ 'MelBand Roformer Kim | FT 3 by unwa': 'mel_band_roformer_kim_ft3_unwa.ckpt',
28
  'MelBand Roformer | Vocals by becruily': 'mel_band_roformer_vocals_becruily.ckpt',
29
  'MelBand Roformer | Vocals Fullness by Aname': 'mel_band_roformer_vocal_fullness_aname.ckpt',
30
  'BS Roformer | Vocals by Gabox': 'bs_roformer_vocals_gabox.ckpt',
 
37
  'BS Roformer | Male-Female by aufr33': 'bs_roformer_male_female_by_aufr33_sdr_7.2889.ckpt',
38
  },
39
  "Instrumentals": {
40
+ 'MelBand Roformer | FVX by Gabox': 'mel_band_roformer_instrumental_fvx_gabox.ckpt',
41
+ 'MelBand Roformer | INSTV8N by Gabox': 'mel_band_roformer_instrumental_instv8n_gabox.ckpt',
42
+ 'MelBand Roformer | INSTV8 by Gabox': 'mel_band_roformer_instrumental_instv8_gabox.ckpt',
43
+ 'MelBand Roformer | INSTV7N by Gabox': 'mel_band_roformer_instrumental_instv7n_gabox.ckpt',
44
+ 'MelBand Roformer | Instrumental Bleedless V3 by Gabox': 'mel_band_roformer_instrumental_bleedless_v3_gabox.ckpt',
45
+ 'MelBand Roformer Kim | Inst V1 (E) Plus by Unwa': 'melband_roformer_inst_v1e_plus.ckpt',
46
+ 'MelBand Roformer Kim | Inst V1 Plus by Unwa': 'melband_roformer_inst_v1_plus.ckpt',
47
  'MelBand Roformer Kim | Inst V1 by Unwa': 'melband_roformer_inst_v1.ckpt',
48
  'MelBand Roformer Kim | Inst V1 (E) by Unwa': 'melband_roformer_inst_v1e.ckpt',
49
  'MelBand Roformer Kim | Inst V2 by Unwa': 'melband_roformer_inst_v2.ckpt',
 
86
  "Karaoke": {
87
  'Mel-Roformer-Karaoke-Aufr33-Viperx': 'mel_band_roformer_karaoke_aufr33_viperx_sdr_10.1956.ckpt',
88
  'MelBand Roformer | Karaoke by Gabox': 'mel_band_roformer_karaoke_gabox.ckpt',
89
+ "MelBand Roformer | Karaoke by becruily": 'mel_band_roformer_karaoke_becruily.ckpt',
90
  },
91
  "General Purpose": {
92
  'BS-Roformer-Viperx-1297': 'model_bs_roformer_ep_317_sdr_12.9755.ckpt',
 
113
 
114
  OUTPUT_FORMATS = ['wav', 'flac', 'mp3', 'ogg', 'opus', 'm4a', 'aiff', 'ac3']
115
 
116
+ # CSS (değişmedi, aynı kalıyor)
117
  CSS = """
118
+ /* Modern ve Etkileşimli Tema */
119
  #app-container {
120
+ max-width: 900px;
121
  width: 100%;
122
  margin: 0 auto;
123
+ padding: 1rem;
124
  box-sizing: border-box;
125
  display: flex;
126
  flex-direction: column;
127
  align-items: center;
128
  min-height: 100vh;
129
+ background: linear-gradient(135deg, #1a0b2e, #2e1a47);
130
  position: relative;
131
+ overflow: hidden;
132
  }
133
  body {
134
  background: url('/content/logo.jpg') no-repeat center center fixed;
135
  background-size: cover;
136
  margin: 0;
137
  padding: 0;
138
+ font-family: 'Roboto', sans-serif;
139
+ color: #e0e0e0;
140
  display: flex;
141
  justify-content: center;
142
  }
 
147
  left: 0;
148
  width: 100%;
149
  height: 100%;
150
+ background: rgba(26, 11, 46, 0.8);
151
  z-index: -1;
152
  }
153
  .logo-container {
154
  position: fixed;
155
+ top: 1rem;
156
  left: 50%;
157
  transform: translateX(-50%);
158
  z-index: 2000;
159
  }
160
  .logo-img {
161
+ width: 80px;
162
  height: auto;
163
+ transition: transform 0.3s ease;
164
+ }
165
+ .logo-img:hover {
166
+ transform: scale(1.1);
167
  }
168
  .header-text {
169
  text-align: center;
170
+ padding: 3rem 0 1rem;
171
+ color: #ff6b6b;
172
+ font-size: 2rem;
173
+ font-weight: 800;
174
+ text-shadow: 0 0 10px rgba(255, 107, 107, 0.7);
175
+ animation: glow 2s infinite alternate;
176
+ }
177
+ @keyframes glow {
178
+ 0% { text-shadow: 0 0 10px rgba(255, 107, 107, 0.7); }
179
+ 100% { text-shadow: 0 0 20px rgba(255, 107, 107, 1); }
180
  }
181
  .dubbing-theme {
182
+ background: rgba(46, 26, 71, 0.9);
183
+ border-radius: 12px;
184
+ padding: 1rem;
185
+ box-shadow: 0 5px 20px rgba(255, 107, 107, 0.3);
186
  width: 100%;
187
+ transition: transform 0.3s ease;
188
+ }
189
+ .dubbing-theme:hover {
190
+ transform: translateY(-5px);
191
  }
192
  .footer {
193
  text-align: center;
194
+ padding: 0.5rem;
195
+ color: #ff6b6b;
196
+ font-size: 12px;
197
  position: fixed;
198
  bottom: 0;
199
  width: 100%;
200
+ max-width: 900px;
201
+ background: rgba(26, 11, 46, 0.7);
202
  z-index: 1001;
203
  left: 50%;
204
  transform: translateX(-50%);
205
  }
206
  button {
207
+ background: #ff6b6b !important;
208
+ border: none !important;
209
+ color: #fff !important;
210
+ border-radius: 8px !important;
211
+ padding: 8px 16px !important;
212
+ font-size: 1rem !important;
213
+ font-weight: 600 !important;
214
+ transition: all 0.3s ease !important;
215
+ box-shadow: 0 2px 8px rgba(255, 107, 107, 0.4) !important;
216
  }
217
  button:hover {
218
+ transform: scale(1.05) !important;
219
+ background: #ff8787 !important;
220
+ box-shadow: 0 4px 12px rgba(255, 107, 107, 0.6) !important;
221
  }
222
  .compact-upload.horizontal {
223
+ display: flex !important;
224
  align-items: center !important;
225
+ gap: 8px !important;
226
+ max-width: 300px !important;
227
+ padding: 6px 10px !important;
228
+ border: 2px dashed #ff6b6b !important;
229
+ background: rgba(46, 26, 71, 0.7) !important;
230
+ border-radius: 8px !important;
231
+ color: #e0e0e0 !important;
232
+ transition: border-color 0.3s ease !important;
233
  }
234
  .compact-upload.horizontal:hover {
235
+ border-color: #ff8787 !important;
 
236
  }
237
  .compact-upload.horizontal button {
238
+ padding: 4px 10px !important;
239
+ font-size: 0.8rem !important;
 
 
240
  }
241
  .gr-tab {
242
+ background: rgba(46, 26, 71, 0.7) !important;
243
+ border-radius: 8px 8px 0 0 !important;
244
+ padding: 0.5rem 1rem !important;
245
+ margin: 0 2px !important;
246
+ color: #e0e0e0 !important;
247
+ border: 2px solid #ff6b6b !important;
248
+ font-size: 1rem !important;
249
+ transition: all 0.3s ease !important;
250
  }
251
  .gr-tab-selected {
252
+ background: #ff6b6b !important;
253
+ color: #fff !important;
254
+ border: 2px solid #ff8787 !important;
255
+ box-shadow: 0 2px 8px rgba(255, 107, 107, 0.5) !important;
256
  }
257
  .compact-grid {
258
+ gap: 0.5rem !important;
259
+ max-height: 40vh;
260
  overflow-y: auto;
261
+ padding: 1rem;
262
+ background: rgba(46, 26, 71, 0.7) !important;
263
+ border-radius: 10px;
264
+ border: 2px solid #ff6b6b !important;
265
  width: 100%;
266
  }
267
  .compact-dropdown {
268
+ padding: 8px 12px !important;
269
+ border-radius: 8px !important;
270
+ border: 2px solid #ff6b6b !important;
271
+ background: rgba(46, 26, 71, 0.7) !important;
272
+ color: #e0e0e0 !important;
273
  width: 100%;
274
+ font-size: 1rem !important;
275
+ transition: border-color 0.3s ease !important;
276
+ }
277
+ .compact-dropdown:hover {
278
+ border-color: #ff8787 !important;
279
  }
280
  .gr-slider input[type="range"] {
281
  -webkit-appearance: none !important;
282
  width: 100% !important;
283
+ height: 6px !important;
284
+ background: #ff6b6b !important;
285
+ border-radius: 3px !important;
286
  outline: none !important;
287
  }
288
  .gr-slider input[type="range"]::-webkit-slider-thumb {
289
  -webkit-appearance: none !important;
290
+ width: 16px !important;
291
+ height: 16px !important;
292
+ background: #fff !important;
293
+ border: 2px solid #ff6b6b !important;
294
  border-radius: 50% !important;
295
  cursor: pointer !important;
296
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2) !important;
297
  }
298
  .gr-slider input[type="range"]::-moz-range-thumb {
299
+ width: 16px !important;
300
+ height: 16px !important;
301
+ background: #fff !important;
302
+ border: 2px solid #ff6b6b !important;
303
  border-radius: 50% !important;
304
  cursor: pointer !important;
305
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2) !important;
306
  }
307
  @media (max-width: 768px) {
308
  #app-container {
309
  max-width: 100%;
310
+ padding: 0.5rem;
311
  }
312
  .header-text {
313
+ font-size: 1.5rem;
314
+ padding: 2rem 0 0.5rem;
315
  }
316
  .logo-img {
317
+ width: 60px;
318
  }
319
  .compact-upload.horizontal {
320
  max-width: 100% !important;
321
  }
322
  .compact-grid {
323
+ max-height: 30vh;
324
  }
325
  .footer {
326
  max-width: 100%;
 
329
  """
330
 
331
  # Fonksiyonlar
332
+ def download_audio(url, out_dir="ytdl"):
333
  if not url:
334
  raise ValueError("No URL provided.")
335
+
336
+ # ytdl klasörünü temizle
337
+ if os.path.exists(out_dir):
338
+ shutil.rmtree(out_dir)
339
+ os.makedirs(out_dir, exist_ok=True)
340
+
341
  ydl_opts = {
342
  'format': 'bestaudio/best',
343
  'postprocessors': [{'key': 'FFmpegExtractAudio', 'preferredcodec': 'wav', 'preferredquality': '192'}],
344
+ 'outtmpl': os.path.join(out_dir, '%(title)s.%(ext)s'),
345
  }
346
  try:
347
  with YoutubeDL(ydl_opts) as ydl:
 
351
  except Exception as e:
352
  raise RuntimeError(f"Download failed: {e}")
353
 
354
+ def roformer_separator(audio, model_key, seg_size, override_seg_size, overlap, pitch_shift, model_dir, output_dir, out_format, norm_thresh, amp_thresh, batch_size, exclude_stems="", progress=gr.Progress(track_tqdm=True)):
355
  if not audio:
356
  raise ValueError("No audio file provided.")
357
+
358
+ # output klasörünü temizle
359
+ if os.path.exists(output_dir):
360
+ shutil.rmtree(output_dir)
361
+ os.makedirs(output_dir, exist_ok=True)
362
+
363
  base_name = os.path.splitext(os.path.basename(audio))[0]
364
  for category, models in ROFORMER_MODELS.items():
365
  if model_key in models:
 
373
  separator = Separator(
374
  log_level=logging.INFO,
375
  model_file_dir=model_dir,
376
+ output_dir=output_dir,
377
  output_format=out_format,
378
  normalization_threshold=norm_thresh,
379
  amplification_threshold=amp_thresh,
380
  use_autocast=use_autocast,
 
381
  mdxc_params={"segment_size": seg_size, "override_model_segment_size": override_seg_size, "batch_size": batch_size, "overlap": overlap, "pitch_shift": pitch_shift}
382
  )
383
  progress(0.2, desc="Loading model...")
384
  separator.load_model(model_filename=model)
385
  progress(0.7, desc="Separating audio...")
386
  separation = separator.separate(audio)
387
+ stems = [os.path.join(output_dir, file_name) for file_name in separation]
388
+
389
+ # Exclude stems filtresi
390
+ if exclude_stems.strip():
391
+ excluded = [s.strip().lower() for s in exclude_stems.split(',')]
392
+ filtered_stems = [stem for stem in stems if not any(ex in os.path.basename(stem).lower() for ex in excluded)]
393
+ return filtered_stems[0] if filtered_stems else None, filtered_stems[1] if len(filtered_stems) > 1 else None
394
+ return stems[0], stems[1] if len(stems) > 1 else None
395
  except Exception as e:
396
  logger.error(f"Separation failed: {e}")
397
  raise RuntimeError(f"Separation failed: {e}")
398
 
399
+ def auto_ensemble_process(audio, model_keys, seg_size, overlap, out_format, use_tta, model_dir, output_dir, norm_thresh, amp_thresh, batch_size, ensemble_method, exclude_stems="", weights=None, progress=gr.Progress()):
400
  if not audio or not model_keys:
401
  raise ValueError("Audio or models missing.")
402
+
403
+ # output klasörünü temizle
404
+ if os.path.exists(output_dir):
405
+ shutil.rmtree(output_dir)
406
+ os.makedirs(output_dir, exist_ok=True)
407
+
408
  base_name = os.path.splitext(os.path.basename(audio))[0]
409
  logger.info(f"Ensemble for {base_name} with {model_keys}")
410
 
411
+ all_stems = [] # Tüm modellerden kalan stem'ler burada toplanacak
412
  total_models = len(model_keys)
413
+
414
+ # Her model için ayrıştırma yap
415
  for i, model_key in enumerate(model_keys):
416
  for category, models in ROFORMER_MODELS.items():
417
  if model_key in models:
 
419
  break
420
  else:
421
  continue
422
+
423
  separator = Separator(
424
  log_level=logging.INFO,
425
  model_file_dir=model_dir,
426
+ output_dir=output_dir,
427
  output_format=out_format,
428
  normalization_threshold=norm_thresh,
429
  amplification_threshold=amp_thresh,
 
434
  separator.load_model(model_filename=model)
435
  progress(0.5 + (0.4 / total_models) * i, desc=f"Separating with {model_key}")
436
  separation = separator.separate(audio)
437
+ stems = [os.path.join(output_dir, file_name) for file_name in separation]
438
+
439
+ # Exclude stems filtresi
440
+ if exclude_stems.strip():
441
+ excluded = [s.strip().lower() for s in exclude_stems.split(',')]
442
+ filtered_stems = [stem for stem in stems if not any(ex in os.path.basename(stem).lower() for ex in excluded)]
443
+ all_stems.extend(filtered_stems)
444
  else:
445
+ all_stems.extend(stems) # Eğer exclude_stems yoksa tüm stem'leri al
446
 
447
  if not all_stems:
448
+ raise ValueError("No valid stems for ensemble after exclusion.")
449
+
450
+ # Weights kontrolü
451
+ if weights is None or len(weights) != len(model_keys):
452
+ weights = [1.0] * len(model_keys)
453
+
454
+ # Tüm kalan stem'leri birleştir
455
+ output_file = os.path.join(output_dir, f"{base_name}_ensemble_{ensemble_method}.{out_format}")
456
+ ensemble_args = [
457
+ "--files", *all_stems,
458
+ "--type", ensemble_method,
459
+ "--weights", *[str(w) for w in weights[:len(all_stems)]], # Stem sayısına göre weights kes
460
+ "--output", output_file
461
+ ]
462
+ progress(0.9, desc="Running ensemble...")
463
+ ensemble_files(ensemble_args)
464
 
 
 
 
465
  progress(1.0, desc="Ensemble complete")
466
+ return output_file, f"Ensemble completed with {ensemble_method}, excluded: {exclude_stems if exclude_stems else 'None'}"
467
 
468
  def update_roformer_models(category):
469
  return gr.update(choices=list(ROFORMER_MODELS[category].keys()))
 
473
 
474
  # Arayüzü bir fonksiyon olarak tanımla
475
  def create_interface():
476
+ with gr.Blocks(title="🎵 SESA Fast Separation 🎵", css=CSS, elem_id="app-container") as app:
477
+ gr.Markdown("<h1 class='header-text'>🎵 SESA Fast Separation 🎵</h1>")
478
 
479
  with gr.Tabs():
480
+ # Settings Sekmesi
481
  with gr.Tab("⚙️ Settings"):
482
+ with gr.Group(elem_classes="dubbing-theme"):
483
+ gr.Markdown("### General Settings")
484
+ model_file_dir = gr.Textbox(value="/tmp/audio-separator-models/", label="📂 Model Cache", placeholder="Path to model directory", interactive=True)
485
+ output_dir = gr.Textbox(value="output", label="📤 Output Directory", placeholder="Where to save results", interactive=True)
486
+ output_format = gr.Dropdown(value="wav", choices=OUTPUT_FORMATS, label="🎶 Output Format", interactive=True)
487
+ norm_threshold = gr.Slider(0.1, 1, value=0.9, step=0.1, label="🔊 Normalization Threshold", interactive=True)
488
+ amp_threshold = gr.Slider(0.1, 1, value=0.3, step=0.1, label="📈 Amplification Threshold", interactive=True)
489
+ batch_size = gr.Slider(1, 16, value=4, step=1, label="⚡ Batch Size", interactive=True)
490
 
491
+ # Roformer Sekmesi
492
  with gr.Tab("🎤 Roformer"):
493
+ with gr.Group(elem_classes="dubbing-theme"):
494
+ gr.Markdown("### Audio Separation")
495
+ with gr.Row():
496
+ roformer_audio = gr.Audio(label="🎧 Upload Audio", type="filepath", interactive=True)
497
+ url_ro = gr.Textbox(label="🔗 Or Paste URL", placeholder="YouTube or audio URL", interactive=True)
498
+ download_roformer = gr.Button("⬇️ download", variant="secondary")
499
+ roformer_exclude_stems = gr.Textbox(label="🚫 Exclude Stems", placeholder="e.g., vocals, drums (comma-separated)", interactive=True)
500
+ with gr.Row():
501
+ roformer_category = gr.Dropdown(label="📚 Category", choices=list(ROFORMER_MODELS.keys()), value="General Purpose", interactive=True)
502
+ roformer_model = gr.Dropdown(label="🛠️ Model", choices=list(ROFORMER_MODELS["General Purpose"].keys()), interactive=True)
503
+ with gr.Row():
504
+ roformer_seg_size = gr.Slider(32, 4000, value=256, step=32, label="📏 Segment Size", interactive=True)
505
+ roformer_overlap = gr.Slider(2, 10, value=8, step=1, label="🔄 Overlap", interactive=True)
506
+ with gr.Row():
507
+ roformer_pitch_shift = gr.Slider(-12, 12, value=0, step=1, label="🎵 Pitch Shift", interactive=True)
508
+ roformer_override_seg_size = gr.Checkbox(value=False, label="🔧 Override Segment Size", interactive=True)
509
+ roformer_button = gr.Button("✂️ Separate Now!", variant="primary")
510
+ with gr.Row():
511
+ roformer_stem1 = gr.Audio(label="🎸 Stem 1", type="filepath", interactive=False)
512
+ roformer_stem2 = gr.Audio(label="🥁 Stem 2", type="filepath", interactive=False)
513
 
514
+ # Auto Ensemble Sekmesi
515
  with gr.Tab("🎚️ Auto Ensemble"):
516
+ with gr.Group(elem_classes="dubbing-theme"):
517
+ gr.Markdown("### Ensemble Processing")
518
+ with gr.Row():
519
+ ensemble_audio = gr.Audio(label="🎧 Upload Audio", type="filepath", interactive=True)
520
+ url_ensemble = gr.Textbox(label="🔗 Or Paste URL", placeholder="YouTube or audio URL", interactive=True)
521
+ download_ensemble = gr.Button("⬇️ download", variant="secondary")
522
+ ensemble_exclude_stems = gr.Textbox(label="🚫 Exclude Stems", placeholder="e.g., vocals, drums (comma-separated)", interactive=True)
523
+ with gr.Row():
524
+ ensemble_category = gr.Dropdown(label="📚 Category", choices=list(ROFORMER_MODELS.keys()), value="Instrumentals", interactive=True)
525
+ ensemble_models = gr.Dropdown(label="🛠Models", choices=list(ROFORMER_MODELS["Instrumentals"].keys()), multiselect=True, interactive=True)
526
+ with gr.Row():
527
+ ensemble_seg_size = gr.Slider(32, 4000, value=256, step=32, label="📏 Segment Size", interactive=True)
528
+ ensemble_overlap = gr.Slider(2, 10, value=8, step=1, label="🔄 Overlap", interactive=True)
529
+ ensemble_use_tta = gr.Checkbox(value=False, label="🔍 Use TTA", interactive=True)
530
+ ensemble_method = gr.Dropdown(label="⚙️ Ensemble Method", choices=['avg_wave', 'median_wave', 'max_wave', 'min_wave', 'avg_fft', 'median_fft', 'max_fft', 'min_fft'], value='avg_wave', interactive=True)
531
+ ensemble_weights = gr.Textbox(label="⚖️ Weights", placeholder="e.g., 1.0, 1.0 (comma-separated)", interactive=True)
532
+ ensemble_button = gr.Button("🎛️ Run Ensemble!", variant="primary")
533
+ ensemble_output = gr.Audio(label="🎶 Ensemble Result", type="filepath", interactive=False)
534
+ ensemble_status = gr.Textbox(label="📢 Status", interactive=False)
535
 
536
+ gr.HTML("<div class='footer'>Powered by Audio-Separator 🌟🎶 | Made with ❤️</div>")
537
 
538
+ # Event Handlers (Aynı kalıyor)
539
  roformer_category.change(update_roformer_models, inputs=[roformer_category], outputs=[roformer_model])
540
  download_roformer.click(fn=download_audio, inputs=[url_ro], outputs=[roformer_audio])
541
  roformer_button.click(
542
  roformer_separator,
543
+ inputs=[roformer_audio, roformer_model, roformer_seg_size, roformer_override_seg_size, roformer_overlap, roformer_pitch_shift, model_file_dir, output_dir, output_format, norm_threshold, amp_threshold, batch_size, roformer_exclude_stems],
544
  outputs=[roformer_stem1, roformer_stem2]
545
  )
546
  ensemble_category.change(update_ensemble_models, inputs=[ensemble_category], outputs=[ensemble_models])
547
  download_ensemble.click(fn=download_audio, inputs=[url_ensemble], outputs=[ensemble_audio])
548
  ensemble_button.click(
549
+ lambda *args: auto_ensemble_process(
550
+ *args[:-1],
551
+ weights=[float(w.strip()) for w in args[-1].split(',')] if args[-1] else None
552
+ ),
553
+ inputs=[ensemble_audio, ensemble_models, ensemble_seg_size, ensemble_overlap, output_format, ensemble_use_tta, model_file_dir, output_dir, norm_threshold, amp_threshold, batch_size, ensemble_method, ensemble_exclude_stems, ensemble_weights],
554
  outputs=[ensemble_output, ensemble_status]
555
  )
556
 
 
562
  parser.add_argument("--ngrok-token", type=str, default=None, help="Ngrok token for tunneling")
563
  args = parser.parse_args()
564
 
565
+ app = create_interface()
566
+ app.launch(server_name="0.0.0.0", server_port=args.port, share=True)
567
+
568
+ app.close()