import gradio as gr
import os
import glob
import subprocess
from pathlib import Path
from datetime import datetime
from helpers import update_model_dropdown, handle_file_upload, clear_old_output, save_uploaded_file, update_file_list
from download import download_callback
from model import get_model_config, MODEL_CONFIGS
from processing import process_audio, auto_ensemble_process, ensemble_audio_fn
# BASE_DIR tanımı (BASE_PATH yerine)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# Arayüz oluşturma fonksiyonu
def create_interface():
# Gelişmiş ve profesyonel CSS
css = """
/* Genel Tema */
body {
background: url('/content/studio_bg.jpg') no-repeat center center fixed;
background-size: cover;
background-color: #1a0d0d; /* Daha koyu ve sofistike kırmızı ton */
min-height: 100vh;
margin: 0;
padding: 2rem;
font-family: 'Montserrat', sans-serif; /* Daha modern ve profesyonel font */
color: #D4A017; /* Altın tonu metin, lüks hissi */
overflow-x: hidden;
}
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(26, 13, 13, 0.9), rgba(45, 11, 11, 0.85));
z-index: -1;
}
/* Logo Stilleri */
.logo-container {
position: fixed;
top: 1.5rem;
left: 2rem;
display: flex;
align-items: center;
z-index: 3000;
background: rgba(0, 0, 0, 0.7);
padding: 0.5rem 1rem;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(212, 160, 23, 0.3);
}
.logo-img {
width: 100px;
height: auto;
filter: drop-shadow(0 0 5px rgba(212, 160, 23, 0.5));
}
/* Başlık Stilleri */
.header-text {
text-align: center;
padding: 4rem 0 2rem;
color: #D4A017; /* Altın tonu, profesyonel ve dikkat çekici */
font-size: 3rem;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 2px;
text-shadow: 0 0 15px rgba(212, 160, 23, 0.7), 0 0 5px rgba(255, 64, 64, 0.5);
z-index: 1500;
animation: text-glow 4s infinite ease-in-out;
}
/* Profesyonel Panel Stili */
.dubbing-panel {
background: rgba(26, 13, 13, 0.95);
border: 1px solid #D4A017;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 8px 25px rgba(212, 160, 23, 0.2);
transition: transform 0.3s ease;
}
.dubbing-panel:hover {
transform: translateY(-5px);
}
/* Düğme Stilleri */
button {
background: linear-gradient(45deg, #800000, #A31818); /* Koyu kırmızıdan parlak kırmızıya */
border: 1px solid #D4A017 !important;
color: #FFF !important;
border-radius: 8px !important;
padding: 10px 20px !important;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
transition: all 0.3s ease !important;
box-shadow: 0 4px 15px rgba(212, 160, 23, 0.3);
}
button:hover {
background: linear-gradient(45deg, #A31818, #D42F2F) !important;
transform: scale(1.05) !important;
box-shadow: 0 6px 20px rgba(212, 160, 23, 0.5) !important;
}
/* Yükleme Alanı */
.compact-upload.horizontal {
background: rgba(26, 13, 13, 0.9);
border: 1px solid #D4A017;
border-radius: 8px;
padding: 0.5rem 1rem;
display: flex;
align-items: center;
gap: 10px;
max-width: 450px;
transition: all 0.3s ease;
}
.compact-upload.horizontal:hover {
border-color: #FFD700; /* Parlak altın hover efekti */
background: rgba(45, 11, 11, 0.95);
}
.compact-upload.horizontal button {
background: #800000;
border: 1px solid #D4A017;
padding: 6px 12px;
font-size: 0.8rem;
}
/* Sekme Stilleri */
.gr-tab {
background: rgba(26, 13, 13, 0.9);
border: 1px solid #D4A017;
border-radius: 12px 12px 0 0;
padding: 0.75rem 1.5rem;
color: #D4A017;
font-weight: 600;
text-transform: uppercase;
transition: all 0.3s ease;
}
.gr-tab-selected {
background: #800000;
color: #FFF;
border-bottom: none;
box-shadow: 0 4px 15px rgba(212, 160, 23, 0.4);
}
/* Altbilgi */
.footer {
text-align: center;
padding: 1rem;
color: #D4A017;
font-size: 1rem;
font-weight: 500;
text-shadow: 0 0 5px rgba(212, 160, 23, 0.3);
position: relative;
z-index: 1001;
}
/* Animasyonlar */
@keyframes text-glow {
0% { text-shadow: 0 0 5px rgba(212, 160, 23, 0.5); }
50% { text-shadow: 0 0 20px rgba(212, 160, 23, 1), 0 0 10px rgba(255, 64, 64, 0.7); }
100% { text-shadow: 0 0 5px rgba(212, 160, 23, 0.5); }
}
"""
# Arayüz tasarımı
with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
# Üst Panel: Logo ve Başlık
with gr.Row():
with gr.Column(scale=1, min_width=200):
gr.HTML("""
""")
with gr.Column(scale=4):
gr.HTML("""
""")
with gr.Tabs():
with gr.Tab("Audio Separation", elem_id="separation_tab"):
with gr.Row(equal_height=True):
# Sol Panel - Kontroller
with gr.Column(scale=1, min_width=380):
with gr.Accordion("📥 Input & Model", open=True):
with gr.Tabs():
with gr.Tab("🖥 Upload"):
input_audio_file = gr.File(
file_types=[".wav", ".mp3", ".m4a", ".mp4", ".mkv", ".flac"],
elem_classes=["compact-upload", "horizontal", "x-narrow"],
label=""
)
with gr.Tab("📂 Path"):
file_path_input = gr.Textbox(placeholder="/path/to/audio.wav")
with gr.Row():
model_category = gr.Dropdown(
label="Category",
choices=list(MODEL_CONFIGS.keys()),
value="Vocal Models"
)
model_dropdown = gr.Dropdown(
label="Model",
choices=list(MODEL_CONFIGS["Vocal Models"].keys())
)
with gr.Accordion("⚙ Settings", open=False):
with gr.Row():
export_format = gr.Dropdown(
label="Format",
choices=['wav FLOAT', 'flac PCM_16', 'flac PCM_24'],
value='wav FLOAT'
)
chunk_size = gr.Dropdown(
label="Chunk Size",
choices=[352800, 485100],
value=352800,
info="Don't change unless you have specific requirements"
)
with gr.Row():
overlap = gr.Slider(2, 50, step=1, label="Overlap", value=2)
gr.Markdown("Recommended: 2-10 (Higher values increase quality but require more VRAM)")
use_tta = gr.Checkbox(label="TTA Boost")
with gr.Row():
use_demud_phaseremix_inst = gr.Checkbox(label="Phase Fix")
gr.Markdown("Advanced phase correction for instrumental tracks")
extract_instrumental = gr.Checkbox(label="Instrumental")
with gr.Row():
process_btn = gr.Button("🚀 Process", variant="primary")
clear_old_output_btn = gr.Button("🧹 Reset", variant="secondary")
clear_old_output_status = gr.Textbox(label="Status", interactive=False)
# Sağ Panel - Sonuçlar
with gr.Column(scale=2, min_width=800):
with gr.Tabs():
with gr.Tab("🎧 Main"):
with gr.Column():
original_audio = gr.Audio(label="Original", interactive=False)
with gr.Row():
vocals_audio = gr.Audio(label="Vocals", show_download_button=True)
instrumental_audio = gr.Audio(label="Instrumental", show_download_button=True)
with gr.Tab("🔍 Details"):
with gr.Column():
with gr.Row():
male_audio = gr.Audio(label="Male")
female_audio = gr.Audio(label="Female")
speech_audio = gr.Audio(label="Speech")
with gr.Row():
drum_audio = gr.Audio(label="Drums")
bass_audio = gr.Audio(label="Bass")
with gr.Row():
other_audio = gr.Audio(label="Other")
effects_audio = gr.Audio(label="Effects")
with gr.Tab("⚙ Advanced"):
with gr.Column():
with gr.Row():
phaseremix_audio = gr.Audio(label="Phase Remix")
dry_audio = gr.Audio(label="Dry")
with gr.Row():
music_audio = gr.Audio(label="Music")
karaoke_audio = gr.Audio(label="Karaoke")
bleed_audio = gr.Audio(label="Bleed")
with gr.Row():
gr.Markdown("""
🔈 Processing Tip: For noisy results, use bleed_suppressor_v1
or denoisedebleed
models in the "Denoise & Effect Removal"
category to clean the output
""")
# Oto Ensemble Sekmesi
with gr.Tab("Auto Ensemble"):
with gr.Row():
with gr.Column():
with gr.Group():
auto_input_audio_file = gr.File(label="Upload file")
auto_file_path_input = gr.Textbox(
label="Or enter file path",
placeholder="Enter full path to audio file",
interactive=True
)
with gr.Accordion("⚙️ Advanced Settings", open=False):
with gr.Row():
auto_use_tta = gr.Checkbox(label="Use TTA", value=False)
auto_extract_instrumental = gr.Checkbox(label="Instrumental Only")
with gr.Row():
auto_overlap = gr.Slider(
label="Overlap",
minimum=2,
maximum=50,
value=2,
step=1
)
auto_chunk_size = gr.Dropdown(
label="Chunk Size",
choices=[352800, 485100],
value=352800
)
export_format2 = gr.Dropdown(
label="Output Format",
choices=['wav FLOAT', 'flac PCM_16', 'flac PCM_24'],
value='wav FLOAT'
)
# Model Seçim Bölümü
with gr.Group():
gr.Markdown("### 🧠 Model Selection")
with gr.Row():
auto_category_dropdown = gr.Dropdown(
label="Model Category",
choices=list(MODEL_CONFIGS.keys()),
value="Vocal Models"
)
# Model seçimi (tek seferde)
auto_model_dropdown = gr.Dropdown(
label="Select Models from Category",
choices=list(MODEL_CONFIGS["Vocal Models"].keys()),
multiselect=True,
max_choices=50,
interactive=True
)
# Seçilen modellerin listesi (ayrı kutucuk)
selected_models = gr.Dropdown(
label="Selected Models",
choices=[],
multiselect=True,
interactive=False
)
with gr.Row():
add_btn = gr.Button("➕ Add Selected", variant="secondary")
clear_btn = gr.Button("🗑️ Clear All", variant="stop")
# Ensemble Ayarları
with gr.Group():
gr.Markdown("### ⚡ Ensemble Settings")
with gr.Row():
auto_ensemble_type = gr.Dropdown(
label="Method",
choices=['avg_wave', 'median_wave', 'min_wave', 'max_wave',
'avg_fft', 'median_fft', 'min_fft', 'max_fft'],
value='avg_wave'
)
gr.Markdown("**Recommendation:** avg_wave and max_fft best results")
auto_process_btn = gr.Button("🚀 Start Processing", variant="primary")
with gr.Column():
with gr.Tabs():
with gr.Tab("🔊 Original Audio"):
original_audio2 = gr.Audio(
label="Original Audio",
interactive=False,
every=1,
elem_id="original_audio_player"
)
with gr.Tab("🎚️ Ensemble Result"):
auto_output_audio = gr.Audio(
label="Output Preview",
show_download_button=True,
interactive=False
)
auto_status = gr.Textbox(
label="Processing Status",
interactive=False,
placeholder="Waiting for processing...",
elem_classes="status-box"
)
gr.Markdown("""
⚠️
Model Selection Guidelines
- Avoid cross-category mixing: Combining vocal and instrumental models may create unwanted blends
- Special model notes:
- Duality models (v1/v2) - Output both stems
- MDX23C Separator - Hybrid results
- Best practice: Use 3-5 similar models from same category
💡 Pro Tip: Start with "VOCALS-MelBand-Roformer BigBeta5e" + "VOCALS-BS-Roformer_1297" combination
""")
# İndirme Sekmesi
with gr.Tab("Download Sources"):
with gr.Row():
with gr.Column():
gr.Markdown("### 🗂️ Cloud Storage")
drive_url_input = gr.Textbox(label="Google Drive Shareable Link")
drive_download_btn = gr.Button("⬇️ Download from Drive", variant="secondary")
drive_download_status = gr.Textbox(label="Download Status")
drive_download_output = gr.File(label="Downloaded File", interactive=False)
with gr.Column():
gr.Markdown("### 🌐 Direct Links")
direct_url_input = gr.Textbox(label="Audio File URL")
direct_download_btn = gr.Button("⬇️ Download from URL", variant="secondary")
direct_download_status = gr.Textbox(label="Download Status")
direct_download_output = gr.File(label="Downloaded File", interactive=False)
with gr.Column():
gr.Markdown("### 🍪 Cookie Management")
cookie_file = gr.File(
label="Upload Cookies.txt",
file_types=[".txt"],
interactive=True,
elem_id="cookie_upload"
)
gr.Markdown("""
**📌 Why Needed?**
- Access age-restricted content
- Download private/unlisted videos
- Bypass regional restrictions
- Avoid YouTube download limits
**⚠️ Important Notes**
- NEVER share your cookie files!
- Refresh cookies when:
• Getting "403 Forbidden" errors
• Downloads suddenly stop
• Seeing "Session expired" messages
**🔄 Renewal Steps**
1. Install this
Chrome extension
2. Login to YouTube in Chrome
3. Click extension icon → "Export"
4. Upload the downloaded file here
**⏳ Cookie Lifespan**
- Normal sessions: 24 hours
- Sensitive operations: 1 hour
- Password changes: Immediate invalidation
""")
# Manuel Ensemble Sekmesi
with gr.Tab("🎚️ Manuel Ensemble"):
with gr.Row(equal_height=True):
with gr.Column(scale=1, min_width=400):
with gr.Accordion("📂 Input Sources", open=True):
with gr.Row():
refresh_btn = gr.Button("🔄 Refresh", variant="secondary", size="sm")
ensemble_type = gr.Dropdown(
label="Ensemble Algorithm",
choices=['avg_wave', 'median_wave', 'min_wave', 'max_wave',
'avg_fft', 'median_fft', 'min_fft', 'max_fft'],
value='avg_wave'
)
# Dosya listesini belirli bir yoldan al
file_path = os.path.join(Path.home(), 'Music-Source-Separation', 'output')
initial_files = glob.glob(f"{file_path}/*.wav") + glob.glob(os.path.join(BASE_DIR, 'Music-Source-Separation-Training', 'old_output', '*.wav'))
gr.Markdown("### Select Audio Files")
file_dropdown = gr.Dropdown(
choices=initial_files,
label="Available Files",
multiselect=True,
interactive=True,
elem_id="file-dropdown"
)
weights_input = gr.Textbox(
label="Custom Weights (comma separated)",
placeholder="Example: 0.8, 1.2, 1.0, ...",
info="Leave empty for equal weights"
)
# Sağ Panel - Sonuçlar
with gr.Column(scale=2, min_width=800):
with gr.Tabs():
with gr.Tab("🎧 Result Preview"):
ensemble_output_audio = gr.Audio(
label="Ensembled Output",
interactive=False,
show_download_button=True,
elem_id="output-audio"
)
with gr.Tab("📋 Processing Log"):
ensemble_status = gr.Textbox(
label="Processing Details",
interactive=False,
elem_id="log-box"
)
with gr.Row():
ensemble_process_btn = gr.Button(
"⚡ Process Ensemble",
variant="primary",
size="sm",
elem_id="process-btn"
)
gr.HTML("""
""")
def update_models(category):
return gr.Dropdown(choices=list(MODEL_CONFIGS[category].keys()))
def add_models(new_models, existing_models):
updated = list(set(existing_models + new_models))
return gr.Dropdown(choices=updated, value=updated)
def clear_models():
return gr.Dropdown(choices=[], value=[])
# Event handlers
model_category.change(fn=update_model_dropdown, inputs=model_category, outputs=model_dropdown)
clear_old_output_btn.click(fn=clear_old_output, outputs=clear_old_output_status)
input_audio_file.upload(
fn=lambda x, y: handle_file_upload(x, y, is_auto_ensemble=False),
inputs=[input_audio_file, file_path_input],
outputs=[input_audio_file, original_audio]
)
file_path_input.change(
fn=lambda x, y: handle_file_upload(x, y, is_auto_ensemble=False),
inputs=[input_audio_file, file_path_input],
outputs=[input_audio_file, original_audio]
)
auto_input_audio_file.upload(
fn=lambda x, y: handle_file_upload(x, y, is_auto_ensemble=True),
inputs=[auto_input_audio_file, auto_file_path_input],
outputs=[auto_input_audio_file, original_audio2]
)
auto_file_path_input.change(
fn=lambda x, y: handle_file_upload(x, y, is_auto_ensemble=True),
inputs=[auto_input_audio_file, auto_file_path_input],
outputs=[auto_input_audio_file, original_audio2]
)
auto_category_dropdown.change(fn=update_models, inputs=auto_category_dropdown, outputs=auto_model_dropdown)
add_btn.click(fn=add_models, inputs=[auto_model_dropdown, selected_models], outputs=selected_models)
clear_btn.click(fn=clear_models, inputs=[], outputs=selected_models)
process_btn.click(
fn=process_audio,
inputs=[
input_audio_file, model_dropdown, chunk_size, overlap, export_format,
use_tta, use_demud_phaseremix_inst, extract_instrumental, gr.State(None), gr.State(None)
],
outputs=[
vocals_audio, instrumental_audio, phaseremix_audio, drum_audio, karaoke_audio,
bass_audio, other_audio, effects_audio, speech_audio, bleed_audio, music_audio,
dry_audio, male_audio, female_audio
]
)
auto_process_btn.click(
fn=auto_ensemble_process,
inputs=[
auto_input_audio_file, selected_models, auto_chunk_size, auto_overlap, export_format2,
auto_use_tta, auto_extract_instrumental, auto_ensemble_type, gr.State(None)
],
outputs=[auto_output_audio, auto_status]
)
drive_download_btn.click(
fn=download_callback,
inputs=[drive_url_input, gr.State('drive')],
outputs=[drive_download_output, drive_download_status, input_audio_file, auto_input_audio_file, original_audio, original_audio2]
)
direct_download_btn.click(
fn=download_callback,
inputs=[direct_url_input, gr.State('direct'), cookie_file],
outputs=[direct_download_output, direct_download_status, input_audio_file, auto_input_audio_file, original_audio, original_audio2]
)
refresh_btn.click(fn=update_file_list, outputs=file_dropdown)
ensemble_process_btn.click(fn=ensemble_audio_fn, inputs=[file_dropdown, ensemble_type, weights_input], outputs=[ensemble_output_audio, ensemble_status])
return demo