Nodes/Video XY Plot/Video XY Plot Sampler
ComfyUI Node

Video XY Plot Sampler

Compare Wan CFG and shift without babysitting a dozen renders

By markuryy·Created about a year ago·Updated about a year ago· 3
Video XY Plot Sampler
  • model
  • vae
  • positive
  • negative
  • latent_image
  • IMAGE
cfg_min1.0
cfg_max8.0
cfg_steps4
shift_min1.0
shift_max5.0
shift_steps4
steps20
sampler_name
scheduler
seed0
denoise1.00
add_labelsenable

Wan video has two knobs everybody ends up tuning blind: CFG and the sigma shift. Set them wrong and you get mush or burn, and because each run costs you a full video render, dialing them in one at a time eats an afternoon. VideoXYPlotSampler is the fix: it renders a whole CFG-by-shift grid in one go and tiles the results into a single image or video, straight out of markuryy/ComfyUI-Simple-Video-XY-Plot.

This is the video descendant of the XY plot script from the A1111 era - the same idea people have asked about for Wan on r/comfyui since 2025 ("how do I build an XY plot for video?"). The author's own description is the honest one: the node is "very basic," basically a ModelSamplingSD3 patch, a KSampler, and a VAE decode wrapped in a loop. It does one thing, but it does the thing you'll otherwise hand-roll.

How it works

Pick a CFG range and a shift range. The node builds cfg_steps CFG values and shift_steps shift values with np.linspace (endpoints included), then, for each combination: patches the model with the SD3-style shift via ModelSamplingSD3, samples your latent with comfy.sample.sample (same guts as a KSampler), and decodes through the VAE. Columns are CFG, rows are shift. If add_labels is on, it stamps "CFG: 5.00" across the top and "Shift: 6.00" down the left so you don't have to guess which cell is which.

The shift here is the SD3/Flux-family sigma shift - the same parameter Wan 2.x workflows set to ~8 in ComfyUI templates. The defaults (shift_min 1, shift_max 5) run low for Wan, so expect to raise shift_max toward 8 before the sweep tells you anything useful.

The inputs that matter

Five wires and a few numbers. The wires are the boring part: model, vae, positive, negative, and latent_image - feed it what you'd feed any KSampler, where the latent is an empty image or video latent. The numbers:

  • cfg_min / cfg_max / cfg_steps and shift_min / shift_max / shift_steps - the sweep. cfg_steps and shift_steps are capped at 10 and are counts, not step sizes: 4 means four values including both endpoints.
  • steps, sampler_name, scheduler, seed, denoise - the KSampler settings every cell shares.
  • add_labels - keep it enabled; the labels are the whole point.

Output is one IMAGE: the full grid. For video latents each frame of that tensor is the entire grid, so wire it into SaveWEBM or Video Helper Suite to get an actual movie out - the demo workflow that ships with the pack ends in SaveWEBM.

Installing it

Search "Video XY Plot" in ComfyUI Manager, or clone it manually:

cd ComfyUI/custom_nodes
git clone https://github.com/markuryy/ComfyUI-Simple-Video-XY-Plot

Then restart ComfyUI. No model downloads, no runtime pip dependencies - pyproject.toml lists an empty dependency set and it's MIT licensed, so it's about as light a pack as exists.

Where people get burned

The trap is compute. Every cell is a full sampling run, so a 4×4 grid is 16 renders - and a multi-frame video latent multiplies that again. A 3×3 sweep of an 81-frame Wan clip is nine video generations. Keep cfg_steps and shift_steps low while you're testing; there's no VRAM saving here, each cell runs sequentially, and there's no way to cancel a single cell.

The second gotcha is video handling. The node decides "video" by the latent's batch dimension (shape[0] > 1), and it only outputs the tiled grid - individual per-setting videos are never produced. The still-image path is solid; the video path is where the node gets rough, so if your grid comes out scrambled, check what shape your video latent actually is before debugging anything else.

None of that makes it less useful - this is the node you reach for when you want to know what CFG and shift your Wan checkpoint actually wants, in one run, and then delete from the graph.

Categoryvideo_xy_plot

Inputs (17)

NameTypeDefaultDescription
modelMODEL
vaeVAE
positiveCONDITIONING
negativeCONDITIONING
latent_imageLATENT
cfg_minFLOAT1.00–100
cfg_maxFLOAT8.00–100
cfg_stepsINT42–10
shift_minFLOAT1.00–100
shift_maxFLOAT5.00–100
shift_stepsINT42–10
stepsINT201–10000
sampler_nameCOMBO34 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +28
schedulerCOMBO9 options: normal, karras, exponential, sgm_uniform, simple, ddim_uniform, +3
seedINT00–18446744073709550000
denoiseFLOAT1.000–1
add_labelsCOMBOenable2 options: enable, disable

Outputs (1)

NameTypeDescription
IMAGEIMAGE