KSampler Sequence (v2)
Sine-modulated denoise and seed keying for prompt progression
- model
- positive_seq
- negative_seq
- latent_image
- LATENT
This is the more elaborate sibling of KSampler Sequence (KSamplerSeq). Same core idea - loop a KSampler across multiple passes, evolving prompt and seed as you go - but v2 trades the v1 node's inline frameIndex:prompt scheduling for separate frame_count/cond_keyframes inputs (matching CLIPTextEncodeSequence2 upstream), and adds a handful of knobs v1 doesn't have: noise injection between loops, sine-modulated denoise, and periodic seed keying.
How it works
The base loop mechanic is the same as v1: denoise_start runs the first pass, denoise_seq covers the rest, seed evolves per seed_mode_seq, and you get the same conditioning-slerp (use_conditioning_slerp/cond_slerp_strength) and latent-interpolation (use_latent_interpolation/latent_interpolation_mode/latent_interp_strength) smoothing options plus unsample_latents for controlled variation.
Where v2 diverges is three added systems, all optional and all off some by default:
Noise injection. inject_noise (default true) adds random noise between loops at noise_strength - a different variation mechanism than unsample_latents, injecting fresh randomness rather than reversing existing steps.
Sine-modulated denoise. denoise_sine (default true) varies the effective denoise over the loop sequence using a sine wave up to denoise_max, instead of holding denoise_seq flat across every loop. The practical effect is a pulsing rhythm to how much each loop changes, rather than a constant nudge.
Seed keying. seed_keying (default true) modulates the seed on a schedule rather than simply incrementing or randomizing it - seed_keying_mode picks sine or modulo, and seed_divisor sets the period. This is for deliberately periodic patterns across the sequence rather than a monotonic drift.
All three default on, which means v2 behaves noticeably differently out of the box than v1 even at matching denoise_seq/seed_mode_seq settings - worth knowing before comparing the two side by side.
The inputs and outputs that matter
model,latent_image- usual sampler inputs.positive_seq/negative_seq(CONDITIONING) - note the type: plainCONDITIONING, notCONDITIONING_SEQ. This node pairs withCLIPTextEncodeSequence2, notCLIPTextEncodeList.frame_count/cond_keyframes(INT) - the schedule metadata thatCLIPTextEncodeSequence2outputs alongside its conditioning; wire all three across from that node, not just the conditioning.denoise_sine/denoise_max- if you want v1's flatter, predictabledenoise_seqbehavior instead, turndenoise_sineoff.inject_noise/noise_strength,seed_keying/seed_keying_mode/seed_divisor- the three extra systems above; all can be disabled individually if you want closer-to-v1 behavior with the rest of v2's wiring.
Single output: LATENT.
How to install it
Via ComfyUI Manager: search "WAS_Extras", install, restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/WAS_Extras
pip install -r WAS_Extras/requirements.txt
Same ksampler_sequence.py file as v1 and both CLIP Text Encode Sequence nodes - the requirements.txt install is needed for all four, whether you clone the repo or copy individual files.
Common issues & troubleshooting
Wired CLIPTextEncodeList's output in and it won't connect. That node outputs CONDITIONING_SEQ, which doesn't match this node's CONDITIONING-typed positive_seq/negative_seq. Use CLIPTextEncodeSequence2 upstream instead.
Only wired the conditioning and left frame_count/cond_keyframes disconnected. Both need to come from CLIPTextEncodeSequence2's matching outputs - this node's schedule awareness depends on them, not just the conditioning tensor.
Results feel wildly different from v1 at "the same" settings. That's the three defaulted-on systems - denoise_sine, inject_noise, and seed_keying are all active out of the box and none of them exist in v1. Turn them off one at a time if you're trying to reproduce v1-like, more predictable behavior.
Output has a visible pulsing or periodic quality you didn't ask for. Check denoise_sine and seed_keying - both introduce genuinely periodic effects by design (a sine wave and a modulo/sine seed schedule respectively). If you want steady, monotonic progression instead, disable both and set denoise_seq directly like v1 does.
Inputs (28)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | The diffusion model every frame in the run samples with. | |
| seed | INT | 00–18446744073709550000 | The seed the first frame runs on, and the base every later frame's seed is worked out from. The same seed replays the whole run. Any whole number; `0` is as good a seed as any. |
| seed_mode_seq | COMBO | How the seed moves from frame to frame, applied after any keying. 'increment' and 'decrement' step it by one, which keeps consecutive frames close; 'random' picks a fresh seed each frame, which makes every frame its own image; 'fixed' leaves the keyed seed alone. | |
| alternate_values | BOOLEAN | true | Whether every other loop runs on a second seed that drifts away from the first instead of on the scheduled one. It gives the run a slight back-and-forth flicker between two looks, which reads as movement in a short sequence. Off, seed_keying and seed_mode decide every frame's seed. |
| steps | INT | 201–10000 | Sampling steps per frame. Around 20 suits most models, and the whole run costs this many steps times the number of frames. |
| cfg | FLOAT | 8.00–100 | How closely each frame is held to its prompt. Around 7-8 suits most models; lower is looser and softer, much higher burns contrast and makes a sequence flicker. |
| sampler_name | COMBO | The sampling algorithm. 'euler' is the plain, predictable choice and the steadiest across a sequence; the 'ancestral' and 'sde' variants add fresh noise as they go, which adds detail and also adds flicker. The list is whatever this ComfyUI offers. | |
| scheduler | COMBO | How the noise level is stepped down within each frame. 'normal' and 'karras' are the usual choices. The list is whatever this ComfyUI offers. | |
| frame_count | INT | 00–1024 | How many frames to render. Wire it from CLIPTextEncodeSequence2's frame_count output. At 0, or with no keyframes connected, the run is one frame per prompt instead. |
| cond_keyframes | INT | 00–1024 | The frame numbers at which the run steps to the next prompt. Wire it from CLIPTextEncodeSequence2's cond_keyframes output, which builds the whole schedule; a single number here means one changeover at that frame. |
| positive_seq | CONDITIONING | The list of positive prompts to work through, from CLIPTextEncodeSequence2. One plain conditioning also works and is then used for every frame. | |
| negative_seq | CONDITIONING | The list of negative prompts, stepped through on the same keyframes as the positive ones. One plain conditioning is used for every frame. | |
| use_conditioning_slerp | BOOLEAN | false | Whether each frame's conditioning is rebuilt from its embedding and pooled output alone. Anything else the prompt carried, an area, a mask, a control hint, is dropped when this is on, so leave it off unless the prompts are plain text encodes. |
| cond_slerp_strength | FLOAT | 0.5000–1 | Interpolation factor for the rebuild above. The two ends of the interpolation are the same prompt here, so the value makes no difference to the result. Ignored while use_conditioning_slerp is off. |
| latent_image | LATENT | The latent the first frame starts from, which also sets the size of every frame. An empty latent generates from scratch; an encoded image starts the sequence on that picture. | |
| use_latent_interpolation | BOOLEAN | false | Whether each new latent is mixed back towards the previous frame before it is kept. It damps down how much can change between two frames, which is the main handle on how jumpy the finished sequence looks. |
| latent_interpolation_mode | COMBO | How the previous frame is mixed in. 'Blend' is a straight average; 'Slerp' travels along the arc between the two latents and holds contrast better; 'Cosine Interp' eases in and out. Ignored while use_latent_interpolation is off. | |
| latent_interp_strength | FLOAT | 0.5000–1 | How much of the newly sampled frame survives the mix. 1.0 keeps it whole and changes nothing, 0.5 is an even blend with the frame before, and low values nearly freeze the sequence. Ignored while use_latent_interpolation is off. |
| denoise_start | FLOAT | 1.000–1 | How much of the first frame is redrawn. 1.0 ignores latent_image's content and generates the opening frame from noise; around 0.5 keeps its composition and changes the detail. |
| denoise_seq | FLOAT | 0.500–1 | How much every frame after the first redraws, and the low end of the swing when denoise_sine is on. 0.5 lets a frame change noticeably, 0.2 barely moves, and near 1.0 each frame is a fresh image. |
| unsample_latents | BOOLEAN | false | Whether each frame first runs the sampler backwards over the previous one, pushing it back up the noise schedule before resampling. It gives the new prompt something to re-resolve rather than a finished image to leave alone, at roughly double the time per frame. |
| inject_noise | BOOLEAN | true | Whether fresh noise is stirred into each frame before it is sampled. It is what stops a long run settling on one image and holding it; turn it off for the steadiest possible sequence. |
| noise_strength | FLOAT | 0.1000.001–1 | How much noise is stirred in. 0.1 keeps the picture and adds movement; above about 0.3 the composition starts breaking up frame to frame. Ignored while inject_noise is off. |
| denoise_sine | BOOLEAN | true | Whether the denoise swings between denoise_seq and denoise_max over the length of the run rather than staying put. The run then breathes , settling for a stretch, opening up again, which suits a long sequence better than one fixed value. |
| denoise_max | FLOAT | 0.9000–1 | The far end of the denoise swing. 0.9 lets the picture change a great deal at the top of the wave; bring it closer to denoise_seq for a flatter run. Ignored while denoise_sine is off. |
| seed_keying | BOOLEAN | true | Whether the seed follows a pattern tied to the frame number instead of only stepping. A pattern that repeats brings back seeds the run has already used, which is how a sequence comes back round to a look rather than drifting away from it for good. |
| seed_keying_mode | COMBO | Which pattern the seed follows. `sine` swings it smoothly around the base seed once every seed_divisor frames; `modulo` leaves it alone and jumps it on every seed_divisor-th frame, which also skips the unsample pass on those frames. Ignored while seed_keying is off. | |
| seed_divisor | INT | 42–1024 | How many frames one cycle of the seed pattern takes. 4 gives a fast flutter, 24 a slow swing across a second of video. Ignored while seed_keying is off. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | Every frame's latent, stacked into one batch in order. Decode it with a VAE Decode to get the frames, then save them as an image sequence or a video. |