Nodes/ComfyUI-WanMove-Adapter/Coords To WanMove Tracks
ComfyUI Node

Coords To WanMove Tracks

Feeding hand-authored tracks into Wan-Move

By danielvw·Created 8 months ago·Updated 8 months ago· 2
Coords To WanMove Tracks
    • TRACKS
    coords
    width720
    height720
    num_frames81
    normalizedfalse

    If you've watched the Wan-Move demo where an object gets dragged along a path and the video actually follows it, this node is the boring but necessary glue: it turns a JSON blob of coordinates into the TRACKS tensor that Wan-Move's ComfyUI nodes actually eat. No model weights, no VRAM, no dependencies beyond what ComfyUI already ships. It's a format converter, and honestly, that's its whole job.

    Why you'd ever hand-write tracks

    Wan-Move (Ali-VILab's latent trajectory guidance, built on top of Wan 2.1 I2V) gives Wan point-level motion control - think Kling's motion brush. In ComfyUI you normally reach it through Kijai's WanVideoWrapper, and the usual way to get tracks is to extract them from a driving video with CoTracker. That pipeline is where most of the Wan-Move work actually happens.

    So who needs this node? People whose tracks aren't coming from a video. Maybe you've got coordinates exported from a script, a motion-capture tool, or a keyframe animation you drew yourself. Maybe you want a clean geometric path - a circle, an arc, an object drifting diagonally - without hunting for a reference clip. That's the niche: you have the numbers, this converts them to the format the sampler wants.

    What it actually does

    The node is one function and it's easy to read in the source. It parses your JSON, treats every coordinate as pixels, divides by width and height to normalize to 0–1, linearly interpolates the path up or down to your frame count, then - here's the subtle bit - multiplies back into pixels if you leave normalized off. It also stamps an all-True visibility mask, meaning every track point is considered "seen" for every frame.

    The output TRACKS is a dict with two tensors:

    • track_path - shape (T, N, 2), time first, then number of tracks, then x/y. Float, in pixels (or 0–1).
    • track_visibility - shape (T, N), a bool mask saying each point is visible at each frame.

    That's exactly the format Kijai's Wan-Move nodes in WanVideoWrapper consume, so you wire the TRACKS output straight into them and let the motion guidance do the rest.

    The inputs that matter

    Four of them, all in the required set:

    • coords - the JSON. A list of tracks, each track a list of points with x and y keys, like [ [{"x":355,"y":148}, ...], ... ]. This is where all your authoring happens.
    • num_frames - default 81, which is Wan's native clip length. Set it to match the clip you're actually generating, or your motion gets stretched or squeezed to fit.
    • normalized - output units. Default off (pixels); flip it on if whatever you're feeding downstream wants 0–1.
    • width / height - used to normalize your input. Match them to your generation resolution.

    Installing it

    Clone into custom_nodes and restart ComfyUI:

    cd ComfyUI/custom_nodes
    git clone https://github.com/danielvw/ComfyUI-WanMove-Adapter
    

    It shows up under WanMove/Adapters. ComfyUI Manager can grab it too - search "ComfyUI-WanMove-Adapter". There are no model downloads and no extra Python deps; it only uses torch, numpy, and json, all of which your ComfyUI install already has.

    Where people get burned

    The one that'll bite you first: every track must have the same number of points. The node builds a numpy array straight from your list, so a ragged set of tracks throws an inhomogeneous-shape error. Pad short tracks to the same length first.

    Second: the coords input is always treated as pixels regardless of normalized - that flag only changes what comes out. Feed it 0–1 values by accident and you'll get tracks scaled by your width and height, which is a great way to generate a scene where nothing moves where you told it to.

    And third, a workflow sanity check rather than a crash: num_frames has to equal your generation's frame count. Wan's default 81 matches the node's default, so this only bites if you've changed one side and not the other.

    One honest take: if you're serious about motion transfer, the CoTracker-driven pipeline gives you far richer, more organic motion than anything you'll hand-type. This node is for the cases where you want precise, authored, repeatable paths - which is also, not coincidentally, the case where it's the fastest way to a working result.

    CategoryWanMove/Adapters

    Inputs (5)

    NameTypeDefaultDescription
    coordsSTRING
    widthINT720
    heightINT720
    num_framesINT81
    normalizedBOOLEANfalse

    Outputs (1)

    NameTypeDescription
    TRACKSTRACKS