Nodes/Comfy-MSS/Audio Ensemble
ComfyUI Node

Audio Ensemble

Average three models and the artefacts mostly cancel

By pymss-project·Created 4 months ago·Updated a day ago· 22
Audio Ensemble
  • audio_1
  • audio_2
  • audio_3
  • audio_4
  • audio_5
  • audio_6
  • audio_7
  • audio_8
  • audio_9
  • audio_10
  • audio
input_count2
ensemble_typeavg_wave
weight_11
weight_21
weight_31
weight_41
weight_51
weight_61
weight_71
weight_81
weight_91
weight_101

What it is, and the trick behind it

Ensembling is the oldest quality hack in source separation: run the same input through several models (or the same model with different settings) and combine the results. Each model makes different mistakes, so averaging their errors leaves the part they agree on - the actual signal - standing. It's how UVR's karaoke community has been squeezing the last dB out of their vocal removal for years, and Audio Ensemble is that idea as a node, with pymss's ensemble implementations underneath.

It's also the honest way to answer "which of these two models is better for my track": run both, listen to the average, and compare. And if you feed the same audio in twice with weights 1 and -0.999, you get a difference signal - near silence if they match, which is how you confirm a separation is a true null rather than just sounding clean. (Exactly 1 and -1 is refused: a zero weight sum raises an error, which is why you nudge one of them.)

Inputs

  • input_count - 2 to 10. This is a live control: the frontend adds and removes the matching audio inputs and weight widgets as you change it, so you only ever see the sockets you're using.
  • ensemble_type - eight algorithms, described below.
  • audio_1audio_10 - the audio inputs (the first input_count of them are the live ones). All must be connected; a missing one is a hard error naming the socket.
  • weight_1weight_10 - per-input weights, as strings, defaulting to "1". They're parsed as floats, an empty value counts as 1.0, and anything non-numeric raises weight_N must be a number. Weights only affect the avg_* algorithms.

Output: a single audio socket.

What the algorithms actually do

From pymss's own ensemble implementation:

  • avg_wave (default) - weighted average of the waveforms. Weights must not sum to zero - the underlying function raises rather than dividing by zero, so a 1 / -1 pair is rejected and 1 / -0.999 is the way to ask for a difference signal. This is the one you want most of the time, and it's where the weights earn their keep: give the model you trust 2 and the other 1.
  • median_wave - per-sample median across inputs. With three or more sources this is the artefact killer: a glitch that only one model produced gets voted out. Weights are ignored.
  • min_wave / max_wave - per-sample minimum/maximum magnitude. Blunt instruments: they don't blend, they select, so expect a harder sound. Useful as a diagnostic, rarely as a finish.
  • avg_fft, median_fft, min_fft, max_fft - the same operations in the STFT domain (2048-point window, 1024 hop), converted back with an inverse STFT. FFT averaging can be cleaner where models disagree on phase; the min/max FFT variants are the spectral equivalent of the blunt ones above.

Whatever you pick, inputs are aligned first: everything is resampled to the first input's sample rate, then truncated to the shortest length, with the channel and batch counts reduced to the smallest of the set. So mixing a 48kHz stem with a 44.1kHz one works, but you're silently downsampling the higher one, and a slightly different-length stem just loses its tail.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/pymss-project/comfy-mss
python -m pip install pymss   # into ComfyUI's Python env

ComfyUI Manager → Comfy-MSS is the same thing with fewer keystrokes. Restart. This node needs torchaudio for resampling, which ships with ComfyUI's standard torch stack; the ensemble maths itself is numpy inside pymss.

Gotchas

  • The first input sets the rules. Its sample rate wins and everything else conforms. If you're mixing rates, put your highest-rate source first.
  • Unconnected inputs error out loudly - Missing required audio inputs: audio_2. Set input_count to what you actually wired.
  • Weights do nothing for median/min/max. Not a bug; the docs on the underlying function say so explicitly.
  • Don't ensemble blind. Averaging a good model with a bad one drags the result toward the middle. Ensembling shines when you're combining models that are each decent and different - a roformer and an MDX23C, say.
  • This doesn't create anything. It combines audio you already separated; the separation itself is the expensive part, and you'll be paying for it once per model.
Categoryaudio/pymss

Inputs (22)

NameTypeDefaultDescription
input_countCOMBO29 options: 2, 3, 4, 5, 6, 7, +3
ensemble_typeCOMBOavg_wave8 options: avg_wave, median_wave, min_wave, max_wave, avg_fft, median_fft, +2
weight_1STRING1
weight_2STRING1
weight_3STRING1
weight_4STRING1
weight_5STRING1
weight_6STRING1
weight_7STRING1
weight_8STRING1
weight_9STRING1
weight_10STRING1
audio_1optAUDIO
audio_2optAUDIO
audio_3optAUDIO
audio_4optAUDIO
audio_5optAUDIO
audio_6optAUDIO
audio_7optAUDIO
audio_8optAUDIO
audio_9optAUDIO
audio_10optAUDIO

Outputs (1)

NameTypeDescription
audioAUDIO