- stemroller/: PySide6/QML desktop app and player for separating music into stems - android/: Plex music player that plays per-stem mixes, with Android Auto support, a graphic + parametric (Equalizer APO-style) EQ, and offline downloads - server/: stemserve (serves stems to the app) and stemd (separates the library on the server's GPU, with "Stem Now" priority requests) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
2.0 KiB
Python
52 lines
2.0 KiB
Python
"""Model catalog and stem metadata shared by the UI and the worker.
|
|
|
|
Kept free of torch imports so the UI process stays light.
|
|
"""
|
|
|
|
DEMUCS_4 = ["drums", "bass", "other", "vocals"]
|
|
DEMUCS_6 = ["drums", "bass", "other", "vocals", "guitar", "piano"]
|
|
|
|
MODELS = [
|
|
{"id": "htdemucs", "label": "HT Demucs", "family": "demucs",
|
|
"stems": DEMUCS_4, "note": "Fast 4-stem"},
|
|
{"id": "htdemucs_ft", "label": "HT Demucs FT", "family": "demucs",
|
|
"stems": DEMUCS_4, "note": "Fine-tuned 4-stem, ~4x slower"},
|
|
{"id": "htdemucs_6s", "label": "HT Demucs 6-stem", "family": "demucs",
|
|
"stems": DEMUCS_6, "note": "Adds guitar and piano"},
|
|
{"id": "roformer_bs_vocals", "label": "BS-RoFormer Vocals", "family": "roformer",
|
|
"file": "model_bs_roformer_ep_317_sdr_12.9755.ckpt",
|
|
"stems": ["vocals", "instrumental"], "note": "Viperx 1297, vocals / instrumental"},
|
|
{"id": "roformer_mel_kim_ft", "label": "Mel-RoFormer Vocals FT", "family": "roformer",
|
|
"file": "mel_band_roformer_kim_ft_unwa.ckpt",
|
|
"stems": ["vocals", "instrumental"], "note": "Kim FT by unwa, cleanest vocals"},
|
|
{"id": "roformer_bs_sw", "label": "BS-RoFormer SW 6-stem", "family": "roformer",
|
|
"file": "BS-Roformer-SW.ckpt",
|
|
"stems": DEMUCS_6, "note": "jarredou, 6-stem RoFormer"},
|
|
]
|
|
|
|
MODELS_BY_ID = {m["id"]: m for m in MODELS}
|
|
|
|
STEM_COLORS = {
|
|
"vocals": "#FF7AB6",
|
|
"drums": "#FFB547",
|
|
"bass": "#7C8CFF",
|
|
"other": "#4CD07D",
|
|
"guitar": "#FF8A5C",
|
|
"piano": "#B48CFF",
|
|
"instrumental": "#3DD6C6",
|
|
}
|
|
|
|
# Lane order in the UI, regardless of the order a model emits stems in.
|
|
STEM_ORDER = ["vocals", "drums", "bass", "guitar", "piano", "other", "instrumental"]
|
|
|
|
|
|
def stems_for(model_id: str, two_stems: bool) -> list[str]:
|
|
stems = MODELS_BY_ID[model_id]["stems"]
|
|
if two_stems and "vocals" in stems:
|
|
return ["vocals", "instrumental"]
|
|
return stems
|
|
|
|
|
|
def sort_stems(names):
|
|
return sorted(names, key=lambda n: STEM_ORDER.index(n) if n in STEM_ORDER else 99)
|