Nodes/ComfyTV/Lens Distort
ComfyUI Node

Lens Distort

ComfyTV's Lens Distort

By jtydhr88·Created 3 months ago·Updated about 15 hours ago· 725
Lens Distort
  • video
  • video
force_run_token0
project_id
parent_output_id0
modelnuke_k1k2
directionundistort
k10.000
k20.000
fov140
center_x0.00
center_y0.00
squeeze1.00
lens_scale1.00
cx_curv0.000
cy_curv0.000
tang_u0.000
tang_v0.000
pt_c0.000
edgeclamp

Lens Distort is the "that GoPro look has to go" node. Any wide-angle clip has barrel distortion - straight lines bow outward, and it's the fastest tell that footage came from an action camera or a cheap wide lens. This stage either corrects that (undistort) or applies it (distort) using real lens models, not a dumb bulge slider, so you can actually match footage shot on a known lens or make a normal clip look like it was shot wide.

ComfyTV is the canvas-style app layer on ComfyUI where every operation is its own node and results flow downstream. Lens Distort is one of the VideoFX stages, and it's a proper Nuke-adjacent tool - the default model is literally nuke_k1k2, Nuke's radial distortion convention.

How it works. Distortion is modeled per-pixel: a radial polynomial maps each output pixel back to its source position, with coefficients that come from the lens model you pick. The node supports several conventions - nuke_k1k2 (radial k1/k2), pf_barrel (PFTrack-style), 3de_classic / 3de_radial (the 3DE lens-distortion standard used for VFX camera tracking). You supply fov to define the lens, and it remaps the image accordingly, with an edge policy for what happens past the frame (clamp, mirror or blank). Like other ComfyTV video FX, it rides the FX chain as a deferred torch op and previews live in the node body - you dial it until the horizon line is straight, then bake.

The inputs that matter. The force_run_token, project_id and parent_output_id inputs are internal plumbing. The ones you'll actually touch:

  • model - which lens convention to use. nuke_k1k2 is the sane default; switch to 3de_radial if you're round-tripping with a VFX track.
  • direction - undistort (straighten the barrel, the usual fix) or distort (apply it, for matching or stylizing).
  • k1 / k2 - the radial coefficients that drive the whole thing. k1 is the main knob: negative for barrel-outward correction, positive to bow inward. k2 refines the edge.
  • fov - field of view in degrees (20–180). Get this roughly right or the correction overshoots at the edges.
  • squeeze / lens_scale / center_x / center_y - anamorphic squeeze, overall scale, and where the optical center sits. If it's not centering right, nudge center.
  • edge - clamp (stretch edge pixels), mirror, or blank (empty border).

The video input is the upstream clip; the output is a video you keep feeding down the chain.

Install. Install the pack once:

cd ComfyUI/custom_nodes
git clone https://github.com/jtydhr88/ComfyTV

Restart ComfyUI (full restart, not a browser refresh) and the stage appears under ComfyTV → VideoFX. ComfyUI Manager - search "ComfyTV" - works too. Zero Python dependencies (empty dependencies in pyproject.toml) and no model downloads - this is pure per-frame math. Desktop/multi-install users: clone into the running instance's absolute path from the startup log, or the node never shows up.

Where people get burned. Cranking k1 without setting fov - the two fight each other, and you'll chase a correction that never settles. Watch the frame edges: the standard symptom of over-correction is the image pulling in at the corners with big empty triangles (raise lens_scale a touch to crop past them). And remember edge: clamp will stretch edge pixels into smears if you correct too far; mirror hides it better on organic footage. The other classic mistake is applying distort when you meant undistort - the direction default is undistort, which is what 90% of people want, but it's worth confirming when a clip suddenly gets more bowed.

CategoryComfyTV/VideoFX

Inputs (19)

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.
modelCOMBOnuke_k1k29 options: nuke_k1k2, pf_barrel, 3de_classic, 3de_radial, panotools, fisheye_equidistant, +3
directionCOMBOundistort2 options: undistort, distort
k1FLOAT0.000-1–1
k2FLOAT0.000-1–1
fovFLOAT14020–180
center_xFLOAT0.00-0.5–0.5
center_yFLOAT0.00-0.5–0.5
squeezeFLOAT1.000.5–2
lens_scaleFLOAT1.000.25–4
cx_curvFLOAT0.000-0.5–0.5
cy_curvFLOAT0.000-0.5–0.5
tang_uFLOAT0.000-0.5–0.5
tang_vFLOAT0.000-0.5–0.5
pt_cFLOAT0.000-1–1
edgeCOMBOclamp3 options: blank, clamp, mirror
videooptCOMFYTV_VIDEO

Outputs (1)

NameTypeDescription
videoCOMFYTV_VIDEO