- model
- motion_brush
- brush_mask
- MotionBrush
BrushMotion is the node that makes this pack's "motion brush" concept actually feel like painting. You hand it a motion brush and a mask, and it takes the motion that exists in the brush and confines it to the region you painted - scaling it to fit that region's bounding box. It's the difference between "the whole image slides left" and "just the part I outlined slides left, and it slides relative to how big that part is."
The mechanism is worth understanding because it explains the node's quirks. First it measures the mask's bounding box and computes a scale factor: the mask's bbox size over the motion brush's full size. It multiplies the brush's x/y displacement by that ratio - so a small masked region gets a proportionally smaller absolute motion, which is the right instinct for keeping motion believable. Then it takes the scaled brush, resizes it to exactly the bbox dimensions with bilinear interpolation, and pastes those flow values back into a full-size output tensor - but only where the mask is set. Everywhere outside the mask, flow is zero. Dead still.
Inputs
- model - the
DragNUWAobject, needed because this node builds its output at the model'smodel_lengthand resolution. - motion_brush - the source brush, e.g. from InstantCameraMotionBrush or a tracking-points loader. Its motion is what gets "painted through."
- brush_mask - a
MASK. The region where motion survives. Everything else is frozen.
Output
A MotionBrush with motion only inside the mask. Standard wiring: out to DragNUWA Run MotionBrush, often after a CompositeMotionBrush pass to layer it over another brush.
How people actually use it
The classic move is in the repo's workflow_motionbrush.json: build a camera or object brush, then mask it down to a region so only part of the frame animates. Think water in a pond - full-frame pan, masked to the water, everything else holds. Because BrushMotion needs a model loaded to know the output size, it's heavier to iterate than the "Without Model" nodes, but the output is properly sized for the checkpoint, which is a real convenience.
The gotchas
Mask quality is everything, same as InstantObjectMotionBrush - a mask with holes leaves unbrushed gaps inside your region, and a mask that's tiny relative to the brush produces nearly invisible motion because of that bbox scaling. If your masked region barely moves, that's usually the scale ratio working as designed, not a bug - increase speed on the source brush.
The model dependency is a trap in disguise. Since this node needs a DragNUWA model just to know the dimensions, you can't build masked brushes in a light "planning" workflow without loading the 9.5 GB checkpoint first. If that annoys you, the "Without Model" variants in the pack exist precisely so you can prototype brushes without the weight. This node is for the final pass.
It's still SVD-era. Expect the pack's usual output quirks - soft warping on complex motion, and a "stuck pixels" look if you mask something the model clearly wants to move. And as ever: hardcoded cuda:0 at model load, heavyweight requirements, slow inference. The brush pipeline is the most interesting thing this pack does; just know what you're signing up for.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| model | DragNUWA | — | |
| motion_brush | MotionBrush | — | |
| brush_mask | MASK | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MotionBrush | MotionBrush | — |