Mastering Compressor – LUFS / True Peak
−14 LUFS on your CPU, with a true-peak ceiling that holds
- audio
- audio
- mastering_json
- info
The last thing between you and a release
Generated songs come out at inconsistent levels and unpredictable peaks. Before you upload anything you want a target loudness, a real true-peak ceiling with headroom for lossy encoding, and no pumping. That's what this node is: a stereo-linked compressor, a lookahead limiter and a measured loudness stage in one, on the CPU, with no extra VRAM.
That's the whole reason this pack's 2.5 release matters, by the way. The tooling conversation around local music generation is all about the model (ACE-Step, and the same "vocals are the weak spot" complaint every Suno user already knows), and almost nothing about the boring end of the chain - until you try to post a track. In-comfyui audio suites with real EQ, compression and LUFS targeting were the gap; this is one of the few attempts to close it with defaults that aren't arbitrary.
How it works under the hood
Each batch item is processed independently, and the loudness loop is iterative rather than a single gain guess. For each item: resample first (if you asked for it), compress, measure, then work out the makeup gain as "target minus measured", clamped to max_makeup_db. That gain drives a lookahead limiter. If the limiter had to reduce more than your max_limiter_reduction_db budget, the node backs the gain off and renders again from the un-limited compressed signal - three passes maximum. After each pass it re-measures and applies a small safety correction if the true peak landed above the ceiling, and if it still can't verify the ceiling it fails loudly instead of writing a file that claims compliance.
Resampling deliberately happens before dynamics, so the limiter and the meter are looking at the same sample rate you're actually exporting. Output is fixed at the length you gave it - the limiter's latency is compensated.
The mastering_json output explains every case. target_reached means you got your loudness. The interesting ones are when you didn't: limiter_reduction_budget and makeup_budget mean the node chose to protect peaks over hitting your number, and silence_or_unmeasurable_loudness means there was nothing to measure. Peak and gain-reduction limits take priority over the LUFS target, always - that's a design decision, not a bug.
The inputs that matter
audio is a normal stereo AUDIO. target_lufs is your integrated loudness goal, not a compressor threshold - −14 is the streaming-ish default, and you should think twice before going much hotter. ceiling_dbtp is the final measured true peak; −1 dBTP is the sane default, and the tooltip's advice is the right one: leave headroom for later lossy encoding, because the encoder's peaks will land above yours. target_sample_rate is keep / 44100 / 48000 and converts before dynamics.
Then the compressor itself, which is off-able: compressor_enabled lets you keep input gain, loudness targeting and limiting while skipping compression entirely - useful when the source is already squashed and you just need level and peaks sorted. threshold_db and ratio (1.5:1 default) are the gentle pair to start from; knee_db smooths the corner. sidechain_hz is a highpass in the detector only - at 80 Hz it stops bass from triggering gain reduction, and your low end is not filtered, it's just not being listened to. detector picks RMS (energy) or Peak (max across channels); both link stereo gain, so nothing wanders sideways. input_gain_db changes how hard the compressor works, max_makeup_db and max_limiter_reduction_db are the two budgets that decide whether the target gets hit, and lookahead_ms / limiter_release_ms tune the limiter rather than the compressor.
bypass returns the audio untouched, with no resampling and no metering - the honest A/B switch. The outputs are audio, mastering_json, and info, which is the one-liner you'll read constantly: something like Item 1: -14.0 LUFS / -1.0 dBTP (target_reached).
Install and the usual traps
It comes with the pack - Manager → MiniMax Music Production Toolkit, or clone and python -m pip install -r requirements.txt with ComfyUI's interpreter, then restart and hard-refresh the browser.
The dependency to remember here is FFmpeg: loudness and true-peak measurement run through it. The pack looks for a system ffmpeg first and falls back to the binary that ships with imageio-ffmpeg, so a "FFmpeg/loudness error" almost always means the requirements didn't install into the right environment. And because this is CPU DSP on full-length buffers, it's system RAM you'll feel on long tracks, not VRAM.
Finally, don't stack nodes. The pack's own troubleshooting notes the classic symptom of two loudness stages fighting each other - quiet tracks changing level unexpectedly, i.e. pumping - and points at a second compressor/limiter/loudness node elsewhere in the graph. If you disable compression here, make sure you're not just handing the job to a node you forgot about.
Inputs (18)
| Name | Type | Default | Description |
|---|---|---|---|
| audio | AUDIO | Mono/stereo AUDIO; each batch item gets independent dynamics and loudness analysis. | |
| bypass | BOOLEAN | false | Return the original audio without resampling or FFmpeg metering. |
| target_lufs | FLOAT | -14.0-30–-5 | Integrated loudness goal, not compressor threshold. The report explains when limits prevent reaching it. |
| ceiling_dbtp | FLOAT | -1.0-12–-0.1 | Final measured true-peak ceiling. Leave headroom for later lossy encoding. |
| target_sample_rate | COMBO | keep | Resample before dynamics so limiting and final measurement use the actual output rate. |
| compressor_enabled | BOOLEAN | true | Disable compression while keeping input gain, loudness targeting and limiting active. |
| threshold_db | FLOAT | -18.0-60–0 | Detector level above which compression begins; adjust to the source level. |
| ratio | FLOAT | 1.51–10 | Compression ratio. 1 is unity compression; 1.5–2 is a gentle starting point. |
| knee_db | FLOAT | 6.00–24 | Width of the smooth transition around threshold; zero is a hard knee. |
| attack_ms | FLOAT | 20.001–200 | Gain-reduction attack time constant. The detector uses 1 ms control cells. |
| release_ms | FLOAT | 150.0010–2000 | Compressor recovery time constant, independent of limiter release. |
| sidechain_hz | FLOAT | 80.000–500 | Highpass in the detector only. Zero disables it; the audible bass is not filtered. |
| detector | COMBO | RMS | RMS detects energy; Peak detects the maximum across channels. Both link stereo gain. |
| input_gain_db | FLOAT | 0.0-24–24 | Explicit gain before the compressor. This changes how strongly it compresses. |
| max_makeup_db | FLOAT | 18.000–24 | Maximum positive gain allowed to approach the LUFS target; prevents boosting near-silence excessively. |
| max_limiter_reduction_db | FLOAT | 6.001–18 | Maximum intended limiter reduction. If more is needed, loudness is reduced instead of forcing the target. |
| lookahead_ms | FLOAT | 3.01–5 | Limiter anticipation window; output latency is compensated and length preserved. |
| limiter_release_ms | FLOAT | 100.0010–1000 | Time for a 12 dB linear recovery in the limiter. This is not compressor release. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |
| mastering_json | STRING | — |
| info | STRING | — |