ComfyUI Node

MiniMax Safe Audio Decode

One Node Between Your Song and a Blank AssertionError

By jplenio·Created 14 days ago·Updated a day ago· 33
MiniMax Safe Audio Decode
  • samples
  • vae
  • AUDIO
tile_size512
overlap64
tiledtrue

Here's the worst way to lose an hour: MiniMax Music 3 finishes sampling a four-minute track, the cover renders, everything looks done - and the export dies on soundfile.py: assert written == len(data). No message about the song. Just an assertion with nothing in it. The cause is NaN or Infinity in the decoded audio, and the reason the traceback is useless is that NaN slides straight past a normal peak check and then breaks the encoder.

MiniMax Safe Audio Decode exists to move that failure earlier and make it say something. It's a checked replacement for ComfyUI's own VAEDecodeAudio and VAEDecodeAudioTiled, sitting inside the MiniMax Music Production Toolkit's music subgraph. Same job, same wiring, same output type - just with validation and one bounded retry.

What it actually does

It's a VAE audio decode with four checks bolted on, and the order matters.

First it looks at the incoming latents. It walks the tensor in chunks (about 262k elements at a time, so a long song doesn't spike memory) and checks for non-finite values. If your sampler latents are already NaN, it stops immediately rather than decoding garbage: "Decoding cannot recover invalid sampler output. Rerun music sampling." That's the honest answer. In the toolkit's own troubleshooting, non-finite sampler output on this model traces back to ComfyUI's compiler/CUDA graph path interacting with MiniMax Music 3's dynamic layer loading - real sample-level corruption that decoding cannot undo.

If the latents are clean, it decodes and then validates the result: right rank, at least two samples, finite waveform, finite normalization divisor. Then it applies ComfyUI's own audio gain rule - divide by std * 5, with the divisor floored at 1.0 - so swapping this node in does not change your levels. If the decode produced NaNs while the latents were fine, it logs a warning and retries once, tiled, with conservative settings. The music is never re-sampled and bad samples are never quietly replaced with silence; the toolkit is explicit about that. If the retry also fails, the error points at the audio VAE or the decoder backend instead of blaming your sampler.

Inputs and outputs worth touching

  • samples (LATENT) - from the music sampler. vae (VAE) - your MiniMax Music 3 audio VAE (the example uses minimax_music3_dav.safetensors from models/vae/). The sample rate is read from the latent dict first, then from the VAE, so you don't set it here.
  • tiled (default true) - the one switch that matters. false decodes the whole thing in one pass, matching plain VAEDecodeAudio; true uses ComfyUI's tiled decoder, matching VAEDecodeAudioTiled. The bundled production workflow wires both variants side by side behind a tiled_decode switch, the tiled one at tile_size = 1536.
  • tile_size (default 512) / overlap (default 64) - latent frames per tile and the blend between them. Smaller tiles mean less working memory. The author's tooltip is blunt: overlap must be smaller than tile_size, and it isn't kidding - tile_size under 32, or overlap ≥ tile_size while tiled, is a straight error, not a clamp.

There's one output: AUDIO, which goes wherever the decode node used to feed - restoration, FlashSR, mastering, a saver. Note the retry is tiled even when you set tiled = false, so if you cared about a bit-exact single-pass decode, check the console for that warning.

Installing

The node ships with the pack; there's no separate install. Via Manager, search MiniMax Music Production Toolkit, or:

cd ComfyUI/custom_nodes
git clone https://github.com/jplenio/ComfyUI-MiniMax-Music-Production-Toolkit.git
cd ComfyUI-MiniMax-Music-Production-Toolkit
python -m pip install -r requirements.txt   # use the Python that runs ComfyUI

The requirements are numpy, scipy, soundfile, imageio-ffmpeg, mutagen, Pillow - SoundFile is the one you'll meet in the error above. Restart ComfyUI and refresh the browser. The bundled production example already uses this node in both decoder branches, so nothing extra to do if you're starting from it.

Where people get burned

Updating the pack doesn't rewrite your saved workflow. If you have a personal workflow from before 2.5.2, it still calls the stock decoders. Replace VAEDecodeAudio with this node keeping tiled = false, and VAEDecodeAudioTiled keeping tiled = true plus your tile size and overlap. Then restart - the save nodes' new sample checking only exists in the updated code.

The two error messages mean different things. "Music sampler latents" is upstream: rerun sampling, and if it keeps happening look at the diffusion model precision and the toolkit's runtime safety options (--fp32-unet, MINIMAX_MUSIC3_RUNTIME_SAFETY=auto). "Retry also failed / incoming latents were finite" is downstream - suspect the VAE file or the decode backend. Fixing the wrong end wastes an afternoon.

Decode isn't the only gate. The toolkit's savers check the whole batch too, so a later processing node can still hand the export NaN. This node tells you the decode was clean, not that everything after it was.

CategoryMiniMax Music Production Toolkit/audio

Inputs (5)

NameTypeDefaultDescription
samplesLATENTConfiguration input 'samples'. This value is passed directly to the node's processing logic; keep it at the workflow default unless you intentionally want to change that part of the production chain.
vaeVAEConfiguration input 'vae'. This value is passed directly to the node's processing logic; keep it at the workflow default unless you intentionally want to change that part of the production chain.
tile_sizeoptINT51232–8192Configuration input 'tile size'. This value is passed directly to the node's processing logic; keep it at the workflow default unless you intentionally want to change that part of the production chain.
overlapoptINT640–1024Configuration input 'overlap'. This value is passed directly to the node's processing logic; keep it at the workflow default unless you intentionally want to change that part of the production chain.
tiledoptBOOLEANtrueConfiguration input 'tiled'. This value is passed directly to the node's processing logic; keep it at the workflow default unless you intentionally want to change that part of the production chain.

Outputs (1)

NameTypeDescription
AUDIOAUDIO