Nodes/ComfyTV/Video Transform
ComfyUI Node

Video Transform

Pan, zoom, rotate — with keyframes and real motion blur

By jtydhr88·Created 3 months ago·Updated about 15 hours ago· 725
Video Transform
  • video
  • track
  • video
force_run_token0
project_id
parent_output_id0
pos_x0
pos_y0
scale1.00
rotation0.0
skew_x0.00
motion_blur0.00
shutter0.50
shutter_typecentered
shutter_offset0.00
keyframes

A static shot is fine until you want it to move. Video Transform is ComfyTV's 2D motion node: translate, scale, rotate, skew - and crucially, animate all of it with keyframes, plus shutter-based motion blur so fast moves smear the way they should. It's the difference between a clip and a push-in.

What it does

It applies a 2D geometric transform to a COMFYTV_VIDEO and renders on ▶ Run (or defers into an FX Chain - more on that below). The controls:

  • pos_x / pos_y - translation in pixels (−8192 to 8192). Positive x right, positive y down.
  • scale - uniform scale, 0.01–10.0, default 1.0.
  • rotation - degrees, −360 to 360, step 0.5.
  • skew_x - horizontal shear, −2.0 to 2.0.
  • motion_blur - 0–4, default 0 (off); higher takes more shutter samples across the move for smoother smear. Only matters when the transform is actually moving.
  • shutter - 0–4, default 0.5; the shutter angle/open duration. Wider = longer smear. shutter_type (centered/start/end/custom) and shutter_offset shape where the shutter opens.
  • keyframes - a JSON array [{t, x, y, scale, rotation, interp}] animating the transform. Normally set through the node's keyframe UI, not typed by hand.

There's also a track input (COMFYTV_TEXT): when you connect a motion track, its keyframes drive the transform and the node bakes and renders on its own. That's how a tracked layer sticks to movement.

How it plays with the FX Chain

Here's the interesting bit: when the transform is not identity (something is actually changing), and it's feeding an FX Chain, the node doesn't render immediately - it emits an FX spec that renders with the rest of the chain in a single pass. That's the pack's "stack effects, render once" design. When a track is connected it bakes directly instead. And if nothing is set - no transform, no keyframes - it's a clean pass-through that does nothing, which is documented behavior, not a bug.

Use it to reframe a shot, straighten a horizon, push in on a subject with keyframes, or run a Ken Burns-style drift. For free-form four-corner warps, that's Corner Pin; for per-pixel warps, UV Remap. This one is the pan/zoom/rotate workhorse.

Install and troubleshooting

Pack-standard: git clone https://github.com/jtydhr88/ComfyTV into ComfyUI/custom_nodes, restart, under ComfyTV → VideoFX. No models, no GPU.

  • Motion blur does nothing - the transform is static; blur only appears when keyframes or a track actually move the frame.
  • Nothing changes on Run - identity transform = documented pass-through. Set something.
  • Jumpy keyframe animation - check the interp field in your keyframes JSON; the UI writes it for you, but hand-edited JSON can drop it.

Output is a COMFYTV_VIDEO snapshot; cross to native nodes with a ← ComfyTV Video Bridge.

CategoryComfyTV/VideoFX

Inputs (15)

NameTypeDefaultDescription
force_run_tokenINT00–2147483647Internal — bumped on Run to invalidate ComfyUI's input cache.
project_idSTRINGInternal — populated by the projectStore on the frontend.
parent_output_idINT00–2147483647Internal — lineage parent set by spawn handlers on the frontend.
pos_xFLOAT0-8192–8192
pos_yFLOAT0-8192–8192
scaleFLOAT1.000.01–10
rotationFLOAT0.0-360–360
skew_xFLOAT0.00-2–2
motion_blurFLOAT0.000–40 = off; higher = more shutter samples
shutterFLOAT0.500–4
shutter_typeCOMBOcentered4 options: centered, start, end, custom
shutter_offsetFLOAT0.00-4–4
keyframesSTRINGJSON [{t,x,y,scale,rotation,interp}]
videooptCOMFYTV_VIDEO
trackoptCOMFYTV_TEXT

Outputs (1)

NameTypeDescription
videoCOMFYTV_VIDEO