Mpi Audio Range
Cut video frames without silently desyncing the soundtrack
- audio
- audio
The problem this node solves is one you won't see coming. You trim a handful of frames off a clip - to make the expensive video-model pass cheaper, say - and the soundtrack is now glued to the wrong moments. Nothing errors. Nothing warns you. Every tensor downstream is still valid, so the model just gets conditioned on the wrong slice of audio while it cheerfully generates video that never quite lines up with what's playing.
MpiAudioRange is the fix, and it's boring in the best way: give it the same two frame numbers you already used to cut the picture, and it cuts the sound to match.
Why this exists at all
It's part of a pattern called windowed video work, and it matters most with audio-video models like MiniMax H3, which generate the soundtrack jointly with the picture rather than bolting an audio pass on afterwards. Here's the trap that pattern walks into: masking a few frames of a video model doesn't make sampling cheaper - the sampler denoises the whole latent every step no matter what your mask says. The only real lever is feeding the model a shorter clip and splicing the result back afterwards. Cut the clip with something like MpiListRange, cut the frames out of the graph, and suddenly the model is being handed a soundtrack that doesn't match the picture anymore. And as the pack's own description puts it, nothing downstream can notice: the result is just conditioned on the wrong moment.
So MpiAudioRange exists so one pair of numbers windows the picture and the sound together. The start and end inputs use the same inclusive, negative-counts-from-the-end convention as MpiListRange, which is the point: you shouldn't need two different maths for picture and audio.
The inputs that matter
Only four, and really only two you'll touch:
start/end- frames, inclusive.end = -1means the last frame; negative numbers count from the end, exactly like MpiListRange. One pair of numbers does both jobs.fps- this is the one to get right. Wire the loader's ownfpsoutput into it. A guessed rate doesn't fail, it slides the audio against the picture - the tooltip is explicit about it, and it's the node's sneakiest failure mode.audio- the clip's full, uncut soundtrack as a standard ComfyUIAUDIO.
One output: the trimmed audio, which you feed straight into the downstream encode - in this pack, MpiH3EncodeAV's audio input if you're windowing an H3 clip.
How it actually works
Under the hood it's a clean slice, not a resample. It takes the AUDIO dict's waveform and sample_rate, works out how many frames the clip contains (round(total_samples / rate * fps)), converts your inclusive frame range to sample indices, and returns the cut waveform. Two details are worth knowing. End is inclusive, so end = start keeps one frame's worth of audio - no off-by-one. And it clamps rather than trusts, because the frame count is derived from the waveform length, so the last frame's boundary can round a few samples past the real tail; it won't let that produce garbage or crash.
Install
This ships in ComfyUi-MpiNodes by Mad Pony Interactive, a pack of 100+ utility nodes that also powers the Cubric Vision desktop app. Install via ComfyUI Manager: search ComfyUi-MpiNodes and hit install, then restart ComfyUI. Or the manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/MadPonyInteractive/ComfyUi-MpiNodes
Then restart ComfyUI. That's the whole install - it's pure Python with no pip dependencies and no model files to download. The node needs nothing but your already-loaded audio.
Troubleshooting
- Sound drifts but never errors. You guessed the fps instead of wiring it. Pull the loader's own fps value off and connect it.
- Silence where audio should be. Your
start/endwindow is inverted (endbeforestart) - the node deliberately returns empty audio in that case instead of guessing. - It "does nothing." You fed it already-trimmed audio. It expects the full soundtrack and does the windowing itself; give it the original file.
One aside, because it's the whole reason the node is worth having: desynced audio doesn't look like a graph bug, it looks like the model underperformed. That's exactly why a node this simple earns its place.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| audio | AUDIO | The clip's full soundtrack. | |
| fps | FLOAT | 24.000.01–1000 | Frame rate the start/end indices are counted in. Wire the loader's own fps - a guessed rate slides the audio against the picture instead of failing. |
| start | INT | 0-18446744073709550000–18446744073709550000 | Start FRAME (inclusive). Negative counts from the end. Same convention as MpiListRange, so both nodes take the same two numbers. |
| end | INT | -1-18446744073709550000–18446744073709550000 | End FRAME (inclusive). -1 is the last frame. Same convention as MpiListRange. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |