Sections

Guide/Part two

Chapters 05–07 · Installation & configuration

Setup & configuration

The repository, the commands that drive it, and the YAML that tunes it. This is the part you will come back to constantly — bookmark the argument tables.

Ch 05 RepositoryCh 06 CommandsCh 07 YAML~14 min read

The training repository

One repository does the work: ZFTurbo/Music-Source-Separation-Training, usually shortened to MSST. It trains, validates and runs inference on the same architectures that UVR and the separation web apps use.

Get the code

  1. Download the repository

    Open the repository page, press the green Code button and choose Download as ZIP, then extract it anywhere convenient.

  2. Pick the model you want to train

    Scroll to the Pre-trained models section, open the List of Pre-trained models, and grab the Config and the Weights for your chosen architecture — for example a Mel-Band Roformer, or Kimberley Jensen's Roformer as a base.

  3. Place the two files correctly

    The checkpoint goes into a folder named results; the YAML goes at the repository root, next to train.py, valid.py and inference.py.

Repository layout after step 3
Music-Source-Separation-Training/
├── train.py
├── valid.py
├── inference.py
├── requirements.txt
├── config_vocals_mel_band_roformer.yaml   ← the config, at the root
└── results/
    └── model_mel_band_roformer.ckpt          ← the weights

Config vs. checkpoint

Config → .yamleditable

Everything about the model and how it trains: architecture dimensions, chunk size, learning rate, epochs, which instruments to target.

  • Where most of your tuning happens.
  • Lives at the repo root, next to train.py.
Weights → .ckptmillions of numbers

The model itself. You never edit it — you load it, train further, and let the trainer write new checkpoints.

  • Lives in results/.
  • One file, plus its matching config.

If you have used UVR before, you already know these two files: this is exactly the pairing it ships with.

Two practical notes
  • Some browsers display a config file instead of downloading it. If that happens, open it in a text editor (Notepad++ works fine), copy the contents, and save the file yourself with a .yaml extension.
  • Every model published with the repository is open-source. Check the licence of the specific checkpoint before you build anything commercial on top of it.
Rofomers have their own loss

Mel-Band and BS Roformers train with an additional spectrogram loss rather than a pure waveform loss. That is why you never need to add one manually unless you are deliberately training for fullness — see Chapter 10.

Commands & arguments

Everything runs through Python scripts, so everything is a command with arguments. Copy the templates, replace the placeholders, and keep them somewhere you can paste from.

Local runs: use an administrator shell

On Windows, run these commands in a Command Prompt or PowerShell opened as administrator. Package installs and some file operations will fail silently or half-way without it.

Installation

powershell · one-time setup
# 1. Install PyTorch — pick the command for your CUDA version
# https://pytorch.org/get-started/locally/
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124

# 2. Install the repository requirements (from the repo folder)
cd C:\path\to\Music-Source-Separation-Training
pip install -r requirements.txt

# 3. Install anything the previous step skipped
pip install name-of-missing-package

The training command

This is the command you will run the most. Every highlighted value has to be replaced with your own paths and choices.

powershell · start training
python train.py
  --model_type mel_band_roformer
  --config_path config_vocals.yaml
  --results_path results/
  --data_path C:\path\to\dataset
  --dataset_type 2
  --num_workers 4
  --device_ids 0
  --start_check_point results/model.ckpt
  --valid_path C:\path\to\validation
  --metric_for_scheduler sdr
  --metrics sdr fullness bleedless

The valid options for --metrics and --metric_for_scheduler are listed in the argument tables below; what each one measures is explained in Appendix B.

Make it a two-click run

Paste the command into Notepad, edit the values there, and save it as run.bat in the repository root. From then on you double-click it, or type .\run.bat in the shell. No more re-typing the argument list every time — and no more typos in paths.

Inference: using the model

Once you have a checkpoint you are happy with, inference separates files with it.

powershell · inference
python inference.py
  --model_type mel_band_roformer
  --config_path config_vocals.yaml
  --start_check_point results/model.ckpt
  --input_folder input
  --store_dir separation_results

Create two folders first: input, where you drop the files you want separated, and separation_results, where the script writes the stems.

Cloud only · OpenBLAS

On rented instances you may hit an OpenBLAS threading error during training. Fix it for the current session with:

bash · cloud
export OPENBLAS_NUM_THREADS=1

It only applies to the terminal session you run it in — see Chapter 12 for where it fits in the cloud sequence.

Argument reference — training

ArgumentWhat it does
--model_typeArchitecture to train: mdx23c, htdemucs, segm_models, mel_band_roformer, bs_roformer, swin_upernet, bandit.
--config_pathPath to the YAML config for that model.
--start_check_pointInitial checkpoint to start from (fine-tuning). Omit it to train from scratch.
--results_pathFolder for outputs — both .ckpt files and run metadata.
--data_pathPath to your dataset folder.
--dataset_type1, 2, 3 or 4 — which layout your data follows. See the dataset types documentation.
--valid_pathPath to the validation dataset folder.
--num_workersHow many CPU workers load and pre-process audio in parallel.
--pin_memoryKeeps host memory page-locked so transfers to the GPU are faster; worth enabling with several workers.
--seedSeeds the randomness in the run — experiment with values for reproducibility.
--device_idsList of GPU IDs to use; normally just 0.
--use_multistft_lossMulti-STFT loss (spectrogram based) — the setting behind fullness models.
--use_mse_lossDefault MSE loss, waveform based.
--use_l1_lossL1 loss, waveform based.
--wandb_keyWeights & Biases API key, for live run dashboards.
--pre_validRuns a validation pass before training begins.
--metricsMetrics to compute each validation pass: sdr, l1_freq, si_sdr, neg_log_wmse, aura_stft, aura_mrstft, bleedless, fullness.
--metric_for_schedulerWhich metric the learning-rate scheduler watches (same options as above).
--train_loraTrain with LoRA (Low-Rank Adaptation) instead of full weights.
--lora_checkpointStarting checkpoint for LoRA weights.

Argument reference — inference

ArgumentWhat it does
--model_typeArchitecture, matching the checkpoint you loaded.
--config_pathPath to the config file.
--start_check_pointThe checkpoint to run.
--input_folderFolder holding the mixtures you want separated.
--store_dirWhere the resulting stems are written.
--draw_spectroAlso renders spectrogram images of the results; the value sets how many seconds of the track to draw (default 0, off).
--device_idsList of GPU IDs to use.
--extract_instrumentalInverts the vocal output to produce an instrumental (and vice versa).
--disable_detailed_pbarTurns off the detailed progress bar.
--force_cpuForces CPU inference even when CUDA is available.
--flac_fileWrite FLAC instead of WAV.
--pcm_typeBit depth for FLAC output: PCM_16 or PCM_24.
--use_ttaTest-time augmentation (polarity and channel inversion). Roughly triples runtime, reduces noise and slightly improves quality.
--lora_checkpointStarting checkpoint for LoRA weights.

Configuring the YAML

The config is where the run is actually shaped. Its defaults are sane, but the training block is the part worth understanding — and the part worth experimenting with.

A config has four sections: audio, model, training and inference. You rarely touch the first two, with one exception: the audio chunk size. Which block owns the rest of the spectrum settings — n_fft, hop_length, dim_f — depends on the architecture, and there is a table of who owns what below the calculator.

chunk_size — the one audio setting you will change

The trainer reads the window itself from audio.chunk_size, in samples — that key is the one every architecture family reads. Configs also describe the same window in frames (dim_t), and because every STFT here runs with center=True the two are one value in two units:

The formula

chunk_size = (dim_t − 1) × hop_length

dim_tchunk_size (samples)Audio window
2561124552.55 s
8013528008.00 s
110148510011.00 s
133358741213.32 s

The conversions above assume hop_length: 441 — the step every published Roformer in this guide uses. A different hop gives a different sample count for the same dim_t, because the frame count is what follows from the window: floor(chunk_size ÷ hop_length) + 1. So the hop decides both the window and the memory, and it belongs to the model rather than to you — the hop_length section below the calculator has the details. Smaller chunks train faster and use less VRAM; larger chunks teach the model longer musical context. This is the main dial you change when a run will not fit.

Schematic · chunk windows drawn to scale
ONE TRACK · FIRST 16 SECONDS SHOWN TO SCALE whole track dim_t 256 1124552.55 s dim_t 801 3528008.00 s dim_t 1101 48510011.00 s dim_t 1333 58741213.32 s chunk_size = (dim_t − 1) × hop_length — the same track, seen through four different window lengths.
The one audio setting worth changing. Roformer and MDX-Net configs describe their window in frames (dim_t); the trainer reads samples (chunk_size). Bars are scaled to a 16-second excerpt, so what you are looking at is how much musical context each setting sees.
Chunk size & VRAM calculator

Type in your numbers and see what window you are actually asking for, and whether your card can hold it. Nothing is sent anywhere — the arithmetic runs in the page.

target preset
chunk_size (samples)audio.chunk_size
dim_t preset (frames)
hop_lengthmodel.stft_hop_length
n_fftmodel.stft_n_fft
sample rate

where these settings live · Roformer—

chunk_size—
frames (dim_t)—
window—
frame step—
frames per second—
bandwidth kept—
effective batch—
estimated VRAM—
—

—

How this is derived. The window is chunk_size — the number the YAML holds and the one key every architecture family reads. Every STFT in this ecosystem runs with center=True, so a window of chunk_size samples becomes floor(chunk_size ÷ hop_length) + 1 frames, and across it a whole number of frames is chunk_size = (dim_t − 1) × hop_length. The frame count is what the model is asked to attend over, and the memory figure is anchored on frames and batch size — one data point, a stereo Roformer at batch_size: 4 and dim_t: 1333 (13.32 s at hop_length: 441) filling a 140 GB H200. That is why the hop moves this number and dim_t follows it: at a fixed window, half the hop is twice the frames. The sample rate reaches the estimate only through frames — frames per second = rate ÷ hop_length — so under the rate ÷ 100 rule, where the hop halves with the rate, 100 frames per second stays 100 frames per second and halving the rate changes nothing; under a fixed hop it halves the frames, and the window it covers doubles until chunk_size is halved to match. The anchor is a Roformer, so pick a different architecture and the figure is that measurement extrapolated — the guide has no mdx23c, DTTNet or SCNet run to check it against. Real attention cost also grows faster than the frame count does, so wide windows land worse than this predicts; use_amp and use_torch_checkpoint move it the other way, and dim_f — the number of mel bands — is a second lever this tool does not model. Choosing Mono (1 ch) halves the sequence the transformer attends over and the tool halves its figure with it, the least certain step here. Use it to decide what to try first, not to predict an exact number.

hop_length and n_fft — which block of the config owns them

hop_length is the step between STFT frames, and it is not a free preference: it is baked into the spectrogram the weights were trained on, so change it and the checkpoint you are fine-tuning no longer matches its own input. Where you change it, though, depends on the architecture — and this is the mistake that costs people an afternoon, because a Roformer config and an mdx23c config both have an n_fft and a hop_length, in different blocks, and only one of the two counts in each.

Architecturen_fft / hop_lengthSpectrogram widthWindow
Roformer
bs_roformer,
mel_band_roformer,
bs_conformer,
bs_mamba2
model.stft_n_fft
model.stft_hop_length (and stft_win_length)
model.freqs_per_bands or model.num_bands, at model.sample_rateaudio.chunk_size
mdx23c · DTTNetaudio.n_fft
audio.hop_length
audio.dim_f
(the model crops to it)
audio.chunk_size
audio.dim_t
SCNetmodel.nfft
model.hop_size (and win_size)
derived from model.nfftaudio.chunk_size

The mechanism is plain in the source. mel_band_roformer and bs_roformer are constructed as MelBandRoformer(**config.model), and SCNet as SCNet(**config.model) — the model block is the only thing they see, and their STFT parameters are named there. mdx23c and DTTNet go the other way and are handed the whole audio block (STFT(config.audio)), so for them audio.n_fft, audio.hop_length and audio.dim_f are the real ones. What every family reads from audio is chunk_size, num_channels, sample_rate and min_mean_abs.

Two rules account for every config in this ecosystem, and which one is right depends entirely on where your config came from:

Real confign_ffthop_lengthFrameRule
Kimberley Jensen · vocals mel-band204844110.0 msrate ÷ 100
viperx · mel-band ep 3005204844110.0 msrate ÷ 100
pcunwa · Mel-Band-Roformer-small204844110.0 msrate ÷ 100
MSST template · mel-band / BS Roformer204851211.6 msn_fft ÷ 4
MSST template · DTTNet4096102423.2 msn_fft ÷ 4
MSST template · mdx23c8192102423.2 msn_fft ÷ 8

Every published Roformer checkpoint this guide tells you to fine-tune uses 441 — a tenth of the sample rate, so a frame lands exactly on 10 ms of audio at any full-band rate. The blank templates that ship with MSST, and the DTTNet config, use n_fft ÷ 4 — the ordinary 75 % overlap you would pick for a fresh STFT — and mdx23c halves that again. So “keep hop_length = n_fft ÷ 4” is good advice for a config you are writing from scratch and the wrong advice for a checkpoint you are continuing: load Kimberley Jensen's model with hop_length: 512 and its learned features no longer line up with the input you feed them.

That is why the calculator's hop rule is a choice rather than a constant, and why it carries an n_fft field: both STFT rules are measured from the window, and dim_f — the width the transformer actually reads — is half of it, so n_fft: 2048 is dim_f: 1024, 4096 is 2048. A wider window is therefore also a wider spectrogram and a heavier model, which is the one part of the memory estimate the calculator still does not scale for.

Don't tune the copy that is ignored

A Roformer config carries hop_length twice — once under audio, once as model.stft_hop_length — and the shipped ones annotate the first copy # don't work (use in model). viperx's BS-Roformer config says exactly that about both audio.hop_length: 441 and audio.dim_t: 801. For mdx23c and DTTNet there is no second copy to get wrong: edit audio.hop_length or edit nothing. Setting both copies to the same number keeps a config readable either way.

Because the hop decides how many frames the window divides into, and the frame count is what the model attends over, the hop is a memory setting as much as a spectral one. At a fixed chunk_size the relationship is exact: frames = floor(chunk_size ÷ hop_length) + 1, so chunk_size: 587412 is 1333 frames at hop_length: 441 and 1148 frames at 512 — the same 13.3 seconds of audio, seen through far fewer, wider steps. That is the direction the calculator's hop rule moves in: it holds the window and lets the frame count follow. Run it the other way — hold dim_t and let the window grow — and dim_t: 801 is an 8.00 s window at 441 but a 9.29 s one at 512. Which of the two you want depends on what you are doing: keeping chunk_size is how you switch conventions without changing the music the model hears, and keeping dim_t is what a fine-tune does when it inherits the frames its checkpoint was trained on.

Sample rate — the band each choice keeps

The sample rate is not a memory dial, but it does decide something you cannot undo later: everything above half the rate — the Nyquist frequency — is gone before training starts. A rate of 22 050 Hz keeps 0–11 025 Hz and throws away cymbals, sibilance and guitar harmonics: free for a bass model, fatal for a drum model.

RateKeeps up toWhat it costsFair target
44 10022 050 HzNothing — and it is what every Roformer in this guide was trained atAnything
48 00024 000 HzNothing, but a 44.1 kHz checkpoint expects that rate's filterbankAnything, if you train from scratch
22 050
44 100 ÷ 2
11 025 HzCymbals, sibilance, synth harmonics — and the top of a guitar DI's pick scrapeBass, kick, a guitar DI — low-band targets only
24 000
48 000 ÷ 2
12 000 HzThe same, 975 Hz widerBass, kick, a guitar DI — low-band targets only

Halving the rate halves what the loader reads and what the STFT transforms, and whether it halves the memory depends entirely on the hop — because frames = chunk_size ÷ hop_length + 1. At a fixed chunk_size a halved rate makes the same chunk twice as long, so you get twice the frames and the estimate doubles; halve chunk_size at the same time and it comes straight back to where it started. That is exactly what hop_length = rate ÷ 100 arranges without you thinking about it: frames per second = rate ÷ hop_length is 100 at every full-band rate, so the frame count follows the seconds of audio and nothing else. Under a fixed hop it does not: at hop_length: 512 a halved rate halves the frames per second, so the same 13.3 s window arrives as 574 frames instead of 1148 — half the memory, and each frame now steps 23.2 ms instead of 11.6 ms. One arithmetic wrinkle, and only under the rate ÷ 100 rule: 22 050 ÷ 100 is not a whole number, so the hop lands on 221 rather than 220.5 — 10.02 ms per frame instead of 10, which moves the window by tens of milliseconds — while 24 000 ÷ 100 = 240 lands exactly. Switch the rule to n_fft ÷ 4 and the wrinkle disappears: 512 at any rate.

A halved rate is an experiment, not a setting

No model in this guide's ecosystem is published below 44.1 kHz, and the mel filterbank is built from the sample rate — change the rate and a checkpoint's learned features no longer line up with the input they are being fed. If you try it, change audio.sample_rate, audio.hop_length and the sample_rate in the loss_multistft block together, then judge the run on validation metrics against an untouched full-band baseline.

Channels — stereo is architecture, not file format

Every Roformer published for this ecosystem is stereo, and the config says so twice: audio.num_channels: 2 and model.stereo: true. Those lines describe the model, not your files. The band-split front end turns each mel band's two channels into one longer sequence for the transformer to attend over, which is why a stereo run costs more than a mono one — and why the calculator now asks which you are training.

The distinction matters in both directions. If your source material is mono, you have not made training any cheaper: a stereo model still expects two channels, so the mono file arrives duplicated. And if you genuinely want a mono model, you change the architecture — num_channels: 1 together with stereo: false, trained on mono mixtures and targets — which halves the sequence and so most of the activation memory.

Mono is a different model, not a smaller version of the same one

A checkpoint trained with stereo: true will not load into a stereo: false model — the shapes differ, so you are training from scratch, not fine-tuning. Mono suits material that is genuinely single-channel (a bass DI, a close-mic drum, a mono room recording) and is a bad deal wherever the stereo image carries information: wide guitars, spacious drums, reverb tails. Judge it on the same validation metrics as any other architecture change.

The training block

config.yaml · training section
training:
  batch_size: 1
  gradient_accumulation_steps: 1
  grad_clip: 0
  instruments:
    - vocals
    - other
  lr: 1.0e-05
  patience: 2
  reduce_factor: 0.95
  target_instrument: vocals
  num_epochs: 1000
  num_steps: 1000
  optimizer: adam
  ema_momentum: 0.999
  q: 0.95
  coarse_loss_clip: false
  other_fix: true
  use_amp: true
  use_torch_checkpoint: true
  augmentation: false
  augmentation_type: null
  use_mp3_compress: false
  augmentation_mix: false
  augmentation_loudness: false
  augmentation_loudness_type: 1
  augmentation_loudness_min: 0
  augmentation_loudness_max: 0
KeyMeaning
batch_sizeHow many audio samples are used to update the weights. Higher values need more VRAM.
gradient_accumulation_stepsSimulates a larger batch without the VRAM cost: effective batch becomes batch_size × steps. Weights are not updated on the in-between steps.
grad_clipGradient clipping threshold. 0 leaves it off.
instrumentsThe stems inside your dataset. Must match the folders you actually created.
lrLearning rate. 1.0e-05 is the common default; 5.0e-06 is the other frequent choice for fine-tuning.
patienceHow many epochs the scheduler waits without improvement before dropping the learning rate.
reduce_factorHow much the learning rate is multiplied by when it drops (0.95 = −5%).
target_instrumentThe stem the model focuses on. Set to null when you are declaring stems explicitly.
num_epochsHow many times the full num_steps cycle runs. Can be changed when resuming from a checkpoint.
num_stepsWeight updates per epoch (divided by gradient accumulation). Validation runs each time this count is reached. Also resumable.
optimizerOptimiser for training; adam is the default.
ema_momentumMomentum of the exponential moving average of the weights — a smoother, usually more stable copy of the model.
qQuantile-style parameter used by the loss weighting.
coarse_loss_clipClips extreme loss values early in training to avoid a first-epoch blow-up.
other_fixNeeded on multisong datasets to check that other really is an instrumental.
use_ampMixed-precision (float16) training. Usually should be true — it is a large speed and VRAM win.
use_torch_checkpointGradient checkpointing: trades a little speed for notably lower VRAM use. Enable when you hit out-of-memory errors.

Augmentation options

  • augmentation — master switch for audiomentations and pedalboard augmentations.
  • augmentation_type — which augmentation profile to use.
  • augmentation_mix — mixes several stems of the same type with some probability, useful when your dataset is small.
  • augmentation_loudness, _type, _min, _max — randomly change the loudness of each stem, with the range you specify.
  • use_mp3_compress — deprecated; leave it false.
Set inference overlap to 1 while training

num_overlap in the inference section of the config controls how many passes are averaged at inference time. During training it only costs time — always set it to 1 for the training run, and raise it later when you actually separate audio.

Optimal parameters take time

There is no magic config. Expect to find your numbers by iterating: change one thing, train, listen, compare metrics. Add use_torch_checkpoint if you genuinely need the VRAM saving — that is, when you are seeing CUDA_OutOfMemory errors.