toobusy Wan SCAIL Extend Sampler
The whole SCAIL-2 motion-transfer + extend chain, one node
- model
- clip
- vae
- reference_image
- pose_video
- clip_vision
- pose_video_mask
- reference_image_mask
- continue_video
- images
- frame_count
SCAIL-2 is Z.ai's Apache 2.0 motion-transfer model on a Wan 2.1 base - the one that dropped the stick-figure pose skeleton entirely, which is what lets you drive animals and multiple characters from a single reference. It ships in ComfyUI core, but the workflow around it is a monster: base generation, extend chunks, overlap trimming, color correction. toobusy Wan SCAIL Extend Sampler is the pack's flagship video node for a reason - it folds SCAIL-2 generation plus the entire extend chain into one node, and the README's before/after table credits it with collapsing "SCAIL-2 generation + extend + overlap trim + color-correction chain" into a single node.
The mechanism: the first chunk is generated from your reference image and pose video at base_frames (Wan wants 4k+1 lengths - 65, 81, and so on). Each extend chunk then re-anchors on the tail frames of the previous chunk - previous_frame_count, default 5, which is what SCAIL-2 was trained on - renders a fresh segment, and the overlap is trimmed from the output. Every extend chunk gets seed + chunk index.
The inputs that matter
Like the Animate 2 sampler, this takes finished sockets: model, clip, vae from your loaders, plus reference_image, pose_video, and plain-text positive/negative (it encodes them internally). The few you'll actually tune:
frame_mode-target total(default) ormanual segments. In target-total mode you type a goal intarget_total_framesand the node auto-splits it intobase_frames-sized chunks, trimming the last one to fit. Manual mode hands you the eightextend_N_framesslots to drive yourself.base_frames- the first chunk, and the auto-mode extend size. 81 is a solid start.color_match- on by default, and this is where the pack's attention went. It's a Reinhard LAB color transfer applied to every extend chunk.color_anchor-first chunk(every chunk matches the first, stopping cumulative fade) orprevious chunk(each matches its neighbor; smoothest seams, but it follows drift).color_sample- whether the anchor chunk's color target comes from the whole chunk or its last frame.whole chunkprevents a color-atypical tail (a blue close-up right before a zoom-out) from dragging the next chunk's color.color_match_strength- how hard the transfer pulls. Drop it below 1 when a scene legitimately changes color and full matching tints it.shift- the ModelSamplingSD3 sigma shift (5 default; 0 keeps the model's own sampling).
Outputs: images and frame_count - the latter reads the actual landed total, which on the 4k+1 grid may differ from your target by a few frames.
What it needs
A current ComfyUI with SCAIL-2 extension inputs on the core WanSCAILToVideo node, plus SCAIL-2 model files. The README's example workflow (docs/workflows/wan21_scail2.json) also pulls in SAM3, KJNodes and VHS for pre-processing and video saving - you don't strictly need them to use the sampler, but you'll want them to reproduce the demo.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/nicekriss/toobusy.git toobusy
or search "toobusy" in ComfyUI Manager, then restart. No extra Python deps for this node.
One feature to know about before you're surprised by it: continue_video. Feed it frames from a previous run you liked and the node skips the base chunk, walks the same pose video from that point, and continues - so you can rescue a good opening instead of re-rolling. Just keep the same pose video and settings as the original run. Between the chunk planner, the color-drift controls and continue-video, this is the node you reach for when SCAIL-2 stops being a demo and becomes a production pipeline.
Inputs (42)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| clip | CLIP | — | |
| vae | VAE | — | |
| reference_image | IMAGE | — | |
| pose_video | IMAGE | — | |
| positive | STRING | — | |
| negative | STRING | — | |
| width | INT | 51264–8192 | — |
| height | INT | 89664–8192 | — |
| base_frames | INT | 815–1024 | Frames of the first chunk, and the per-chunk size auto mode extends with. Wan wants 4k+1 lengths (65, 81, ...). |
| extend_segments | INT | 00–8 | — |
| seed | INT | 10–18446744073709550000 | Base noise seed. Each extend chunk uses seed + chunk index. |
| steps | INT | 61–100 | — |
| cfg | FLOAT | 1.00–30 | — |
| sampler_name | COMBO | euler | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 |
| scheduler | COMBO | simple | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 |
| shift | FLOAT | 5.000–100 | ModelSamplingSD3 sigma shift. 0 keeps the model's own sampling. |
| previous_frame_count | INT | 51–33 | Tail frames of the previous chunk each extend re-anchors on (SCAIL-2 is trained at 5). The overlap is trimmed from the extend output. |
| color_match | BOOLEAN | true | Reinhard LAB color transfer of every extend chunk so the colors stay consistent down the video. |
| color_anchor | COMBO | first chunk | Which chunk color_match aims at. 'first chunk' anchors every chunk to the first chunk, stopping the cumulative fade that chunk-by-chunk VAE round-trips cause. 'previous chunk' matches each chunk to the one before it (smoothest seams, but follows the drift). See color_sample for which frames set the target. |
| replacement_mode | BOOLEAN | false | — |
| pose_strength | FLOAT | 1.000–10 | — |
| pose_start | FLOAT | 0.000–1 | — |
| pose_end | FLOAT | 1.000–1 | — |
| clip_vision_crop | COMBO | none | 2 options: none, center |
| extend_1_frames | INT | 819–1024 | Frames rendered for this extend chunk; the first previous_frame_count of them are the overlap and get trimmed. |
| extend_2_frames | INT | 819–1024 | Frames rendered for this extend chunk; the first previous_frame_count of them are the overlap and get trimmed. |
| extend_3_frames | INT | 819–1024 | Frames rendered for this extend chunk; the first previous_frame_count of them are the overlap and get trimmed. |
| extend_4_frames | INT | 819–1024 | Frames rendered for this extend chunk; the first previous_frame_count of them are the overlap and get trimmed. |
| extend_5_frames | INT | 819–1024 | Frames rendered for this extend chunk; the first previous_frame_count of them are the overlap and get trimmed. |
| extend_6_frames | INT | 819–1024 | Frames rendered for this extend chunk; the first previous_frame_count of them are the overlap and get trimmed. |
| extend_7_frames | INT | 819–1024 | Frames rendered for this extend chunk; the first previous_frame_count of them are the overlap and get trimmed. |
| extend_8_frames | INT | 819–1024 | Frames rendered for this extend chunk; the first previous_frame_count of them are the overlap and get trimmed. |
| frame_mode | COMBO | target total | target total: enter a goal frame count; the node auto-splits it into base_frames-sized chunks and extends as needed (last chunk trims to fit). manual segments: drive each extend chunk yourself with the +/- slots. |
| target_total_frames | INT | 1575–100000 | Goal output frames in 'target total' mode. The readout shows the actual landed total (4k+1 grid means it may differ by a few frames). |
| color_sample | COMBO | whole chunk | Which frames of the anchor chunk set the color target. 'whole chunk' averages the chunk's color so a color-atypical tail (e.g. a blue close-up right before a zoom-out) can't drag the next chunk's color. 'last frame' matches the seam frame exactly (tightest seam, but vulnerable to that tail). |
| color_match_strength | FLOAT | 1.000–1 | How hard color_match pulls each chunk toward the target color. 1.0 = full transfer, 0.0 = none (same as turning color_match off). Lower it when scenes legitimately change color and full matching tints them. |
| clip_visionopt | CLIP_VISION | — | |
| pose_video_maskopt | IMAGE | — | |
| reference_image_maskopt | IMAGE | — | |
| continue_videoopt | IMAGE | Frames of an already-generated video to continue from (load the good part of a previous run and trim it to the last frame you want to keep). When connected the base chunk is skipped: these frames open the output, their tail anchors the first new chunk, and the pose video is walked from that point on automatically — so keep the SAME pose_video and settings as the original run. In 'target total' mode these frames count toward the target. | |
| target_total_frames_inputopt | INT | Optional linked override for target_total_frames. Use this when driving the target with a frame counter or other INT output; when connected it wins over the widget value. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| frame_count | INT | — |