File size: 3,089 Bytes
a20b9cf
20bfe49
a20b9cf
 
 
f123d01
20bfe49
a20b9cf
20bfe49
 
a20b9cf
20bfe49
a20b9cf
 
20bfe49
a20b9cf
20bfe49
 
a20b9cf
11c328a
20bfe49
a20b9cf
20bfe49
 
 
 
 
 
a20b9cf
 
20bfe49
a20b9cf
20bfe49
 
 
a20b9cf
20bfe49
 
a20b9cf
20bfe49
 
 
 
 
a20b9cf
20bfe49
 
a20b9cf
20bfe49
a20b9cf
20bfe49
 
 
a20b9cf
 
20bfe49
 
 
a20b9cf
 
20bfe49
a20b9cf
20bfe49
 
 
 
 
a20b9cf
20bfe49
 
 
 
 
 
a20b9cf
20bfe49
 
a20b9cf
20bfe49
a20b9cf
20bfe49
 
 
 
 
 
 
a20b9cf
20bfe49
 
a20b9cf
20bfe49
a20b9cf
20bfe49
 
 
 
a20b9cf
 
20bfe49
a20b9cf
 
20bfe49
 
 
a20b9cf
 
20bfe49
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import os
import tempfile
import subprocess
import gradio as gr
import logging
import sys
from pathlib import Path

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("demucs")

DEFAULT_MODEL = "htdemucs"


def run_demucs(audio_path, selected_stems, model_name=DEFAULT_MODEL):
    try:
        logger.info(f"Running Demucs on {audio_path}")
        output_dir = tempfile.mkdtemp()

        cmd = f"{sys.executable} -m demucs -n {model_name} -o {output_dir} \"{audio_path}\""
        logger.info(f"Executing command: {cmd}")

        process = subprocess.Popen(
            cmd,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )

        stdout, stderr = process.communicate()

        if process.returncode != 0:
            logger.error(f"Demucs error: {stderr}")
            raise gr.Error(f"Demucs failed: {stderr}")

        track_name = Path(audio_path).stem
        stem_dir = Path(output_dir) / model_name / track_name

        output_files = []
        for stem in selected_stems:
            stem_path = stem_dir / f"{stem}.wav"
            if stem_path.exists():
                output_files.append(str(stem_path))

        if not output_files:
            raise gr.Error("No stems were generated")

        return output_files

    except Exception as e:
        logger.error(f"Error: {str(e)}")
        raise gr.Error(f"Process failed: {str(e)}")


def create_interface():
    with gr.Blocks() as interface:
        gr.Markdown("# 🎚️ Demucs Stem Splitter")

        with gr.Row():
            audio_input = gr.Audio(type="filepath", label="Upload Audio File")

        with gr.Row():
            vocals = gr.Checkbox(label="Vocals", value=True)
            drums = gr.Checkbox(label="Drums", value=True)
            bass = gr.Checkbox(label="Bass", value=True)
            other = gr.Checkbox(label="Other", value=True)

        with gr.Row():
            model_selector = gr.Dropdown(
                label="Model",
                choices=["htdemucs", "mdx_extra", "mdx_extra_q"],
                value="htdemucs"
            )

        with gr.Row():
            submit_btn = gr.Button("Split Stems")

        output = gr.File(label="Output Stems", file_count="multiple")

        def process(audio_file, vocals_enabled, drums_enabled, bass_enabled, other_enabled, model):
            selected = [stem for stem, enabled in [
                ("vocals", vocals_enabled),
                ("drums", drums_enabled),
                ("bass", bass_enabled),
                ("other", other_enabled),
            ] if enabled]

            if not selected:
                raise gr.Error("Please select at least one stem")

            return run_demucs(audio_file, selected, model)

        submit_btn.click(
            fn=process,
            inputs=[audio_input, vocals, drums, bass, other, model_selector],
            outputs=output
        )

    return interface


def main():
    interface = create_interface()
    interface.launch()


if __name__ == '__main__':
    main()