π Image Motion
The Deforum zoom-and-pan node that keeps your animation alive
- image
- frame_counter
- noise
- image
- mask1
- mask2
- mask3
If you've ever watched a Deforum video and wondered how the camera keeps drifting forward through a scene that doesn't actually move - this node is that trick. Image Motion [Dream] takes your last rendered frame, zooms and pans it by a per-frame amount, and hands you the result plus masks marking the areas where the previous frame is now missing. Those masks are the repaint zones: you feed the shifted image and the mask back into a sampler, regenerate just the exposed region, and the animation crawls forward one convincing step at a time.
It's the beating heart of the Dream Project pack. The author's example workflow starts with this node, and the whole point of the pack's frame counter is to drive this node's parameters over time - zooming in on the beat, drifting sideways on a curve.
How it works
Each frame, the node takes your image and scales it by 2^(zoom / fps) - so zoom is a per-second rate, not per-frame. Same for x_translation and y_translation: they're divided by frames-per-second and clamped to [-1, 1], meaning the values are fractions of the image width/height per second. The resized image gets pasted onto a black canvas (or your optional noise image, if you want color coherence instead of pure black bars), and the node computes three masks - mask1, mask2, mask3 - each with its own feather and overlap settings. Different masks let you control how aggressively you repaint the moving edge: a heavily feathered mask repaints softly; a tight one keeps more of the original pixels.
The inputs that matter
- image - your last rendered frame.
- zoom, x_translation, y_translation - the motion, in per-second units. Small values (0.01β0.05) give the subtle crawl that looks cinematic; big ones create fast push-ins that outrun the sampler's ability to fill in.
- mask_1/2/3_feather and mask_1/2/3_overlap - the three mask settings. Start with the defaults (0/10/15 feather, 0/5/5 overlap) and tweak when you see tearing at the edges.
- frame_counter - the pack's standard input, telling the node which frame it's on. Drive
zoomfrom a curve and the motion itself becomes animated. - Optional noise - plug in a
Noise from Palette [Dream]output here to keep colors consistent across frames (the pack's whole palette system exists to solve exactly this).
Outputs
image is the shifted frame (feed to your KSampler), and mask1/mask2/mask3 are the repaint masks (feed to the sampler's mask input, or to an inpaint/denoise stage). That's the classic loop: motion β repaint masked region β repeat.
Installing it
Ships with Dream Project Animation Nodes - ComfyUI Manager (search Dream Project Animation) or clone https://github.com/alt-key-project/comfyui-dream-project into custom_nodes + pip install -r requirements.txt, restart. No model downloads.
Common issues
The two traps are scale and masks. First: because values are per-second, a zoom of 0.1 at 30fps is a slow, pleasant drift - crank it to 1.0 and the sampler will be chasing an ever-expanding hole and the video will wobble. Start small. Second, beginners wire the node's image output straight to a preview and skip the masks entirely, which gives a picture with black edges instead of an animation. The masks aren't decoration - they're the repaint instructions, and the loop doesn't work without them.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | β | |
| zoom | FLOAT | 0.00-10β10 | β |
| mask_1_feather | INT | 0 | β |
| mask_1_overlap | INT | 0 | β |
| mask_2_feather | INT | 10 | β |
| mask_2_overlap | INT | 5 | β |
| mask_3_feather | INT | 15 | β |
| mask_3_overlap | INT | 5 | β |
| x_translation | FLOAT | 0.00-10β10 | β |
| y_translation | FLOAT | 0.00-10β10 | β |
| frame_counter | FRAME_COUNTER | β | |
| noiseopt | IMAGE | β | |
| output_resize_widthopt | INT | 0 | β |
| output_resize_heightopt | INT | 0 | β |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | β |
| mask1 | MASK | β |
| mask2 | MASK | β |
| mask3 | MASK | β |