⬡ Polyhedron Audio Stretch
Keep the soundtrack in step when you slow the picture down
- audio
- video
- frames
- audio
- info
Slow a video down and the audio drifts out of step with it - unless you retime the soundtrack to match. ⬡ Polyhedron Audio Stretch is the node that does that, and it's built to measure the target itself: point it at the video (or the frames) and it works out how long the audio needs to be, no manual arithmetic.
The workflow it's made for is the "interpret a clip" pipeline: you slow-mo a piece of footage (with ⬡ Polyhedron Interpolate, or any frame-rate change), and you want the sound to follow. mode decides where the target duration comes from. match video reads a wired VIDEO's frame count over its frame rate. frames x fps counts a wired IMAGE batch at the fps widget (default 16). Or skip the wires entirely: target seconds and factor let you type the answer, with factor being a length factor - 2.0 makes the audio twice as long (2× slow motion), 0.5 half as long.
The pitch choice is the whole creative decision
pitch is where you pick which kind of slow-motion sound you want:
- preserve - ffmpeg
atempo: the tempo changes, the pitch doesn't, so speech stays intelligible at its natural register. This is the lip-sync mode, for dialogue or anything where a voice must still sound like a voice. - follow speed - sinc resample: the pitch scales with the tempo, the classic deep slow-motion sound - an octave down at 2× slow. That's the "cinematic drowning" tone for music and ambience, not for words.
Speech survives the stretch far better in preserve mode than a naive resample, because the tempo change is done without moving the pitch. And the node shares its machinery with the Interpolate node's audio_mode - one implementation, two ways to reach it, so the two can't drift apart.
The rest of the inputs
trim_to_target (default on) cuts the result to exactly the target duration - stretching lands within a filter window of the target, and this removes the remainder. It never pads, so a short source just stays short. There's a hard sanity envelope: the node refuses loudly outside 1/16×..16×. That's a wiring mistake, not a slow-motion request - a 40-second clip at 50× isn't "slower," it's a bug, and the node treats it as one.
What comes out
audio(AUDIO) - the retimed soundtrack, into any audio consumer or a save node.info(STRING) - what was measured and what was done; wire it into a ⬡ Polyhedron Note and the node documents itself.
Installing it
Part of the ⬡ Polyhedron Suite pack. ComfyUI Manager → "Polyhedron Suite", or:
cd ComfyUI/custom_nodes
git clone https://github.com/PolyhedronAI/ComfyUI-PolyhedronLoRAStack.git
# restart ComfyUI
The preserve path shells out to ffmpeg's atempo filter, so you'll want ffmpeg available the way ComfyUI already expects it. No extra Python dependencies beyond that.
Gotchas
The classic mistake is wiring a still into match video and expecting a duration - a still has no frame rate to measure, so you'd get nonsense; use target seconds or factor for anything that isn't a real video or a frames-with-fps batch. And remember factor is a length factor, not a speed percentage: 2.0 is half speed, which is the direction that trips people. If the node looks blank under ComfyUI's Nodes 2.0 (Modern Node Design) renderer, disable it in Settings.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| audio | AUDIO | — | |
| mode | COMBO | match video | Where the target duration comes from. 'match video' measures a wired VIDEO; 'frames x fps' counts a wired IMAGE batch at the fps below; 'target seconds' and 'factor' are typed in. |
| pitch | COMBO | preserve | preserve: ffmpeg atempo - speech stays intelligible at its own pitch (the lip-sync mode). follow speed: sinc resample - pitch scales with tempo, the classic slow-motion sound (an octave down at 2x slow). |
| fps | FLOAT | 16.00.1–480 | Only read in 'frames x fps' mode: the rate the wired frames will play at. |
| target_seconds | FLOAT | 5.000.05–36000 | Only read in 'target seconds' mode. |
| factor | FLOAT | 1.0000.0625–16 | Only read in 'factor' mode. LENGTH factor: 2.0 makes the audio twice as long (2x slow motion), 0.5 half as long. |
| trim_to_target | BOOLEAN | true | Cut the result to exactly the target duration. Stretching lands within a filter window of the target; this removes the remainder. Never pads. |
| videoopt | VIDEO | 'match video': the target duration is this video's frame count over its frame rate. | |
| framesopt | IMAGE | 'frames x fps': the target duration is this batch's frame count over the fps widget. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | The retimed soundtrack. |
| info | STRING | What was measured and what was done - wire it into a Note. |