Nodes/Link Comfy Nodes/Shift Pose Frames
ComfyUI Node

Shift Pose Frames

Move the seam to the middle and let the model paint over it

By Mister-Link·Created 10 months ago·Updated 6 days ago· 0
Shift Pose Frames
  • frames
  • frames
  • total_frames
  • shift
  • blank_frames
  • is_loop
blank_frames5

Seamless loops are the eternal pain of local video generation. The model knows nothing about looping, so when your last frame wraps back to the first, you get a visible pop. The standard workaround is to stop fighting it: generate a transition between the end and the start and let it be the seam. Shift Pose Frames automates the tedious half of that for WAN pose workflows - it takes your frame sequence, rotates it so the loop seam sits right in the middle, drops a run of black frames in there, and reorders everything so the transition gets generated over a gap instead of a hard cut.

If you've ever wanted a looping WAN video that doesn't click at the wrap, this is the node you didn't know you needed. It's a utility that pairs with Unshift Pose Frames - one shifts, one restores.

How it works

Given a batch of frames, it splits the sequence in half:

[start_portion | end_portion]  →  [end_portion | blank | start_portion]

The original wrap (frame N → frame 1) is now dead center, separated by blank_frames black frames. When blank_frames is greater than 0 it also tacks two overlap frames onto each end - the last two frames of the start half and the first two of the end half - so the generator has context on both sides of the gap, and the node only validates the final frame count. You generate over that black gap (masked inpainting at low denoise, or whatever your pose pipeline does), then Unshift trims the overlap and rotates back.

Two details matter. First, the node enforces a WAN-valid frame count: 1 + 4k, because WAN 2.x models are temporally downsampled by 4 and expect n = 1 + 4k frames. If your math doesn't land there, it raises an error rather than feeding the model garbage. Second, the shift value it returns is exactly how much to rotate the overlap-trimmed sequence to restore the original order - you don't have to think about it, you just wire it into Unshift.

Inputs and outputs

  • frames (IMAGE) - your batch, ideally already in loop order.
  • blank_frames (INT, default 5) - black frames to place at the seam. 0 means plain rotation with no gap and no overlap.

Outputs, and they're designed to be piped straight into Unshift Pose Frames: frames, total_frames, shift, blank_frames, is_loop. The last three are bookkeeping that the restore node consumes; keep them wired.

Installing it

Part of Link Comfy Nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/Mister-Link/link-comfy-nodes
cd link-comfy-nodes
pip install -r requirements.txt

or ComfyUI Manager → "Link Comfy Nodes", restart. This one is pure tensor math - torch only, no models, no downloads.

Common issues

  • "requires at least 2 frames on both sides of the split" - with blank_frames > 0 you need a minimum of 2 frames in each half, because the overlap frames come from both ends. Feed it a longer batch.
  • "Could not construct a WAN-valid output frame count" - your total didn't land on 1 + 4k. Adjust blank_frames (or the input frame count) until it does. WAN is unforgiving about this.
  • Blank frames are black, not transparent - that's deliberate; they're inpaint targets, and black is the neutral fill your mask-and-denoise step replaces.
  • Pinned workflows stop reproducing after an update - the pack's README warns the author changes behavior without warning. If your loop math suddenly breaks, suspect the pack version before your workflow.

The node won't do the actual inpaint for you - that's your sampler's job. What it does is make the geometry of the loop trick automatic and, critically, guaranteed WAN-legal. Then Unshift puts everything back.

Categoryanimation/utils

Inputs (2)

NameTypeDefaultDescription
framesIMAGE
blank_framesINT50–9999Number of black inpaint frames placed in the middle of the shifted loop. When this is greater than 0, the node also adds 2 overlap frames at each end and only validates the final total frame count. Set to 0 to pass the frames through untouched, with no shift and no blanks.

Outputs (5)

NameTypeDescription
framesIMAGEFrame sequence shifted so the original seam sits near the middle, with loop blanks and overlap added, when blank_frames is greater than 0. Passed through unchanged when blank_frames is 0.
total_framesINTActual total frame count of the shifted output sequence.
shiftINTAmount to rotate the overlap-trimmed sequence left by to restore original frame order. 0 when blank_frames is 0.
blank_framesINTNumber of blank frames inserted into the shifted loop, for reference.
is_loopBOOLEANWhether loop blanks and overlap were added. Feed this into Unshift Pose Frames.