NoiseWarperNode
Flicker-Free Video by Warping Noise, Not Training Temporal Modules
- flow_image
- LATENT
- IMAGE
The trick behind "GoWithTheFlow" - the technique that blew up as "Netflix go-with-the-flow" in early 2025 - is that you don't need a temporal model to keep video frames coherent. You need the right noise. This node is a faithful ComfyUI port of that research code (Eyeline Research's Go-with-the-Flow, which draws on Ryan Burgert's noise_warp.py), and its entire job is to warp a persistent noise field according to an optical-flow map, frame after frame.
Here's why anyone bothers. Every diffusion sample starts from noise. Give every video frame fresh random noise and you get flicker - the sampler sees a different starting point each time. Give every frame the same noise and you get the frozen-snowglobe look where nothing moves. The middle path: warp one noise field by the scene's motion, so the grain flows with the camera instead of fighting it. It's a different answer to the same problem AnimateDiff's motion modules solve - no fine-tuning, just geometry.
How it works
The node keeps a private noise state in a module-level dict, keyed to the node instance - that's the "loopback" in the pack name, and the README's promise that it "preserves the noise state and only updates it each time the workflow is invoked." Each queue run you feed it a flow image and it:
- decodes the image as an optical-flow colorwheel (hue = direction, brightness = distance, scaled to a hardcoded 20px max displacement),
- warps the persistent noise by those offsets - shrinking where the flow lands in-bounds, expanding and re-gaussianizing where new areas appear,
- downsamples to latent resolution (⅛ of the flow image's size) and returns a LATENT plus an IMAGE preview of the warped noise.
Because the state outlives any single run, frame 40 is still the same noise field as frame 1, just pushed around by whatever motion you supplied.
The inputs that matter
- flow_image - the one real input. The node does not compute optical flow for you; you supply it, either from a flow estimator or from your own math, rendered as a colorwheel image.
- noise_channels - default 4, which is right for SD/SDXL (4 latent channels). The README suggests 3; the node auto-pads 3→4 with fresh noise, so it won't crash either way. Leave it at 4.
- width / height - leave both at 0 and the node takes the flow image's size ÷ 8 as the latent size. Set them explicitly only if your flow and target resolutions disagree.
- scale_factor - renders the warp at higher internal resolution (default 1). Bigger means smoother warping at the cost of VRAM and time; start at 1.
- noise_scale - per the tooltip, "the amount of noise added to the latent image." 1 is standard; drop it to soften the grain.
Outputs: LATENT (the warped noise, ready for a sampler) and IMAGE (a normalized visualization - wire it to a preview node so you can see what you're about to denoise).
Wiring it up
Feed the LATENT into a sampler that won't add its own noise - the pack ships KSamplerNoiseless for exactly this, because a normal KSampler would overwrite your hard-won warped noise with fresh random noise and undo everything. The pattern: update the flow image for the next frame, run the queue, and the noise warps one step further each time. Add your conditioning, denoise, done - continuous grain across the whole clip.
Installing it
Via ComfyUI Manager (search "ComfyUI-gowiththeflow"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/oxysoft/ComfyUI-gowiththeflow-loopback
# restart ComfyUI
No model downloads, which is a relief. The catch is the dependency list: it pulls rp (Ryan Burgert's "Ryan's Python" library) plus opencv, einops, and tqdm. rp is a heavyweight meta-package, so expect pip to install a lot of transitive deps. If an install ever feels bloated, this is why.
Reality check
Honest take: this is a single-commit port of research code, not a polished workflow kit. If your actual goal is making video in ComfyUI, most people end up on kijai's ComfyUI-VideoNoiseWarp, which wraps the same idea with real documentation and a flow-estimation path. Reach for this node when you want the literal original algorithm or a minimal, learnable version.
Watch the BGR footgun: ComfyUI images are RGB, but the node reads the channels as BGR before converting to HSV (the README literally says "Pass a BGR flow map"). Feed a flow image built for this pipeline, or your warps come out rotated or mirrored. And flow direction matters - flip the image and your "motion" runs backwards.
Finally: if the noise keeps resetting mid-sequence, you changed width, height, or noise_channels - any of those re-initializes the warper with a fresh random seed. Keep them fixed across the whole run and the noise will evolve, not jump.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| flow_image | IMAGE | — | |
| width | INT | 00–4096 | — |
| height | INT | 00–4096 | — |
| noise_channels | INT | 41–8 | — |
| scale_factor | INT | 11–8 | — |
| noise_scale | FLOAT | 1.000–10 | The amount of noise added to the latent image. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | — |
| IMAGE | IMAGE | — |