Nodes/ComfyUI-CustomNodePacks/Spline Mask — Edit/Track/Flow-Path
ComfyUI Node

Spline Mask — Edit/Track/Flow-Path

One spline node for edit, track, and flow-path masks

By Code2Collapse·Created 6 months ago·Updated a day ago· 52
Spline Mask — Edit/Track/Flow-Path
  • image
  • mask
  • coords_json
  • spline_data_out
  • info_json
  • bbox
modeedit
spline_data[]
spline_typecatmull_rom
closedtrue
samples_per_segment20
feather_radius0.0
invertfalse
smoothingtrue
centripetal_alpha0.50
width0
height0
mask_color#ff00ff
mask_opacity0.40
tracking_weight0.70
klt_window21
stroke_width3
patternribbon
thickness12.0
amplitude8.0
frequency2.0
turbulence0.00
turbulence_scale1.00
edge_softness1.0
taper_start0.00
taper_end0.00
frames1
animation_speed0.050
flow_directionforward
mod_decay0.00
seed0
use_embedded_editortrue

Most mask nodes in ComfyUI are one-trick ponies: draw a shape, get a mask. SplineMaskMEC is the pack's unified spline node, and it packs three different jobs behind a single mode dropdown - a canvas-based spline editor, a video tracker, and a procedural "flow path" pattern generator. The pitch from the author is that one control-point canvas drives all three, so the JSON you draw in edit mode is the same shape of data the tracker and the flow generator consume.

It's a replacement too. The pack's __init__.py is explicit: SplineMaskMEC replaces three legacy nodes (SplineMaskEditorMEC, SplineMaskTrackerMEC, SplinePathFlowMaskMEC), which are gone from the registry. If you see old workflows referencing those, this is their home now.

How it works - the three modes

  • edit - rasterize a single closed or open spline to a mask. The spline_type dropdown is where the flavor lives: catmull_rom (passes through points), bezier (tangent handles), polyline (straight), plus b_spline / nurbs / natural_cubic / cardinal for smooth approximating curves. Control resolution with samples_per_segment.
  • track - Lucas-Kanade optical-flow tracking across a video. You pin keyframes (a list of {frame, points} in spline_data) and the node tracks the spline's control points through the footage, blending with simple lerp according to tracking_weight (1 = pure LK, 0 = pure lerp). klt_window sizes the LK window; stroke_width handles open splines.
  • flow_path - forget masking; this generates an animated procedural pattern along the spline path - ribbon, wave, dust, river, smoke, sawtooth, fbm, curl noise, lightning, and more (13 patterns). frames controls the animation length, amplitude/frequency/turbulence shape the modulation, flow_direction (forward/reverse/bidirectional/oscillate) sets how it moves, and seed makes it reproducible.

There are a lot of knobs, but the tooltips tell you which mode each applies to ([edit], [track], [flow_path], [all]), and irrelevant ones are ignored - the author is careful about that.

The inputs and outputs that matter

For a first workflow you'll touch maybe five:

  • mode - edit / track / flow_path.
  • spline_data (STRING) - the payload from the JS canvas; keyframe list in track mode.
  • spline_type, closed, samples_per_segment - curve shape and resolution.
  • feather_radius - edge softness in edit/track.
  • In track mode: tracking_weight and klt_window. In flow_path mode: pattern, frames, seed.

The outputs are the interesting part, because this node feeds the rest of the graph, not just a preview:

  • mask (MASK) - the rasterized result.
  • coords_json (STRING) - SAM-compatible point coordinates from edit mode, so your drawn spline can seed a SAM prompt instead of only a mask.
  • spline_data_out (SPLINE_DATA) - structured spline data, for feeding trackers.
  • info_json (STRING) - mode diagnostics.
  • bbox (BBOX) - the axis-aligned bounding box of your control points, which feeds the pack's bbox pipeline.

That coords_json output is worth highlighting: draw a rough spline, then hand the points to SAM for a clean mask. Model-free authoring, model-assisted finishing.

Installing it

Standard pack install:

cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git

restart ComfyUI or use Manager → "CustomNodePacks", confirm [MEC] Loading MaskEditControl node pack … in the console. CPU + small VRAM, no models required - this node is pure geometry and OpenCV, so no downloads.

Where people get burned

Expect to set tracking_weight deliberately. Pure LK (1.0) can wander on texture-less plates; pure lerp (0.0) ignores the footage entirely; the sweet spot is usually 0.6–0.8. And remember flow_path isn't a mask of your spline - it's an animation along it, so don't wire it where you wanted a plain filled region. Read which mode a knob belongs to before turning it; there are a lot of knobs, but each one is scoped.

CategoryC2C/Spline

Inputs (32)

NameTypeDefaultDescription
modeCOMBOeditedit: rasterize a single spline (closed/open) to a mask. track: Lucas-Kanade multi-keyframe tracker across a video. flow_path: procedural pattern along the spline (waves/dust/lightning…).
spline_dataSTRING[]Spline payload from the JS canvas. edit/flow_path: single shape list. track: keyframes list [{frame:int, points:[[x,y],…]}, …].
spline_typeCOMBOcatmull_rom[edit/flow_path] interpolation method. catmull_rom/natural_cubic/cardinal pass through the points; b_spline/nurbs are smooth approximating curves; bezier uses tangent handles; polyline = straight.
closedBOOLEANtrue[all] closed loop vs open path
samples_per_segmentINT202–128[all] curve resolution per segment
feather_radiusFLOAT0.00–64[edit/track] gaussian edge feather
invertBOOLEANfalse[edit/flow_path] invert mask
smoothingBOOLEANtrue[edit] enable spline smoothing
centripetal_alphaFLOAT0.500–1[edit] Catmull-Rom alpha (0.5 = centripetal)
widthINT00–16384[edit/flow_path] output width (0 = inherit image)
heightINT00–16384[edit/flow_path] output height (0 = inherit image)
mask_colorSTRING#ff00ff[edit] preview overlay color (hex)
mask_opacityFLOAT0.400–1[edit] preview overlay opacity
tracking_weightFLOAT0.700–1[track] lerp/tracker blend (1=pure LK, 0=pure lerp)
klt_windowINT215–51[track] Lucas-Kanade window size
stroke_widthINT31–64[track] stroke width for open splines
patternCOMBOribbon[flow_path] procedural pattern
thicknessFLOAT12.00–1024[flow_path] base stroke thickness
amplitudeFLOAT8.00–1024[flow_path] modulation amplitude
frequencyFLOAT2.00–64[flow_path] modulation frequency
turbulenceFLOAT0.000–4[flow_path] noise turbulence strength
turbulence_scaleFLOAT1.000.01–32[flow_path] noise spatial scale
edge_softnessFLOAT1.00–32[flow_path] edge softness in pixels
taper_startFLOAT0.000–1[flow_path] start-end taper amount
taper_endFLOAT0.000–1[flow_path] tail-end taper amount
framesINT11–4096[flow_path] number of animation frames
animation_speedFLOAT0.0500–4[flow_path] phase advance per frame
flow_directionCOMBOforward[flow_path] flow direction
mod_decayFLOAT0.000–4[flow_path] modulation falloff over time
seedINT00–4294967295[flow_path] noise seed
use_embedded_editorBOOLEANtrue[flow_path] show embedded spline preview
imageoptIMAGE[edit/track/flow_path] reference / source video frames

Outputs (5)

NameTypeDescription
maskMASKRasterized mask (B,H,W).
coords_jsonSTRINGSAM-compatible point coords (edit mode); '[]' otherwise.
spline_data_outSPLINE_DATAStructured spline data (edit mode); pass-through input otherwise.
info_jsonSTRINGMode diagnostics: edit→bbox_json, track→info, flow_path→params.
bboxBBOXAABB of control points as [x,y,w,h]; [0,0,0,0] when N/A.