Install
$ agentstack add skill-artokun-comfyui-mcp-video-extend ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ● Dynamic code execution Used
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Video Extension (Pusa 2.2 — temporal flowmatching)
Overview
Pusa extends a video temporally — it continues / lengthens an existing clip rather than regenerating it from scratch. It does this on the ComfyUI-WanVideoWrapper stack (kijai) using the WAN 2.2 T2V A14B dual HIGH/LOW models you already have for wan-t2v-video, plus the small Pusa V1 LoRAs and a Pusa-specific sampling path: the flowmatch_pusa scheduler and the WanVideoAddPusaNoise node. The input clip is encoded with WanVideoEncode and injected as the first latents of the generation — that is what carries the existing motion/content into the continuation.
The official reference graph is kijai's wanvideo_2_2_14B_Pusa_extension_example_01.json (in ComfyUI-WanVideoWrapper/example_workflows/). This skill is built directly from that workflow plus the live node schemas.
> Relationship to wan-t2v-video: Pusa rides on the exact same WanVideoWrapper > stack — same T2V A14B HIGH/LOW fp8 models, same UMT5 text encoder, same WAN > VAE, same block-swap/torch-compile machinery. The only new downloads are the > two Pusa V1 LoRAs (~1.9 GB total). Read wan-t2v-video first for the base > stack; this skill is the temporal-extension delta on top of it.
> ⚠️ Verification note: every node, model, LoRA filename and setting below was > confirmed against the live ComfyUI /object_info (WanVideoWrapper installed) > and against kijai's example workflow JSON + HF repo (June 2026). Where a value > is a starting recommendation rather than a hard requirement it's flagged. Don't > substitute a node you can't confirm with list_installed_nodes / > get_node_info.
What "temporal flowmatching" means here (why it extends, not regenerates)
WAN is a flow-matching video model: sampling integrates a velocity field from noise to a clean latent, and every frame normally shares the same denoising timestep. Pusa's contribution (Vectorized Timestep Adaptation) is to make the timestep per-frame: the frames you already have can be held at (or near) t = 0 (clean) while the new frames start from t = 1 (noise), and the model flow-matches the noisy tail conditioned on the clean head.
Concretely in the graph:
WanVideoEncodeturns the tail of your loaded clip into a clean latent.- That latent is placed at the front of an otherwise-empty embed
(WanVideoEmptyEmbeds + WanVideoAddExtraLatent), so the generation's first latents are your real footage.
WanVideoAddPusaNoiseassigns **small, ramping per-latent noise
multipliers** to those conditioning latents (so they stay mostly clean) and full noise to the new latents — this per-frame noise schedule is the "vectorized timestep."
flowmatch_pusaonWanVideoSamplerintegrates that mixed-timestep field.
Because the conditioning latents are real (not just a single start image like I2V), the continuation inherits the existing motion, subject, camera and color, then keeps going. That's the difference from plain T2V (no memory of any clip) and from I2V (conditions on one still frame only).
⭐ Recommended pipeline (the kijai extension graph)
VHS_LoadVideo (your clip)
│ IMAGE (all frames)
▼
ImageResizeKJv2 ◄── resize to 832×480 (divisible by 16), get W/H
│
├─► GetImageRangeFromBatch (tail N frames) ─► WanVideoEncode (vae, image)
│ │ LATENT = clean
│ ▼ conditioning latents
│ GetLatentSizeAndCount ─► count
│ │
WanVideoEmptyEmbeds (W,H, total_frames=81) ▼
│ WANVIDIMAGE_EMBEDS CreateScheduleFloatList
└────────► WanVideoAddExtraLatent ◄────────┘ (per-latent noise multipliers,
│ (encoded clip latent at front) ramp e.g. 0→0.2)
▼ WANVIDIMAGE_EMBEDS
WanVideoAddPusaNoise ◄── noise_multipliers (list), noisy_steps
│
┌──────────────┴───────────────┐
▼ (pass 1, HIGH) ▼ (pass 2, LOW)
WanVideoSampler (HIGH model WanVideoSampler (LOW model
+ Pusa HIGH LoRA + distill, + Pusa LOW LoRA + distill,
flowmatch_pusa, steps 6, cfg 1, flowmatch_pusa, steps 6, cfg 1,
shift 5, start 0 / end 3) shift 5, start 3 / end -1)
└──────────────┬───────────────┘
▼ LATENT
WanVideoDecode (WAN VAE)
│ IMAGE
▼
VHS_VideoCombine ─► MP4 (16 fps)
VHS_LoadVideo/VHS_VideoCombinecome from ComfyUI-VideoHelperSuite
(installed). VHS_VideoCombine is preferred for the encode (audio passthrough).
- Everything
WanVideo*is ComfyUI-WanVideoWrapper (installed). ImageResizeKJv2,GetImageRangeFromBatch,GetLatentSizeAndCount,
CreateScheduleFloatList are ComfyUI-KJNodes (installed alongside the wrapper). They're convenience nodes — see "Minimal wiring" if you want fewer.
The two load-bearing nodes (confirmed schemas)
WanVideoAddPusaNoise — "Adds latent and timestep noise multipliers when using flowmatch_pusa."
| Input | Type | Meaning | |---|---|---| | embeds | WANVIDIMAGE_EMBEDS | the embeds carrying your encoded clip latents | | noise_multipliers | FLOAT (list) | per-input-latent noise; 0 = keep that latent fully clean, higher = let the model change it. In the example this is a ramp [0.0, 0.07, 0.13, 0.17, 0.19, 0.2] fed from CreateScheduleFloatList (one value per conditioning latent), so the oldest conditioning frame stays cleanest and the seam frame gets a touch of noise for smooth blending. | | noisy_steps | INT (default −1) | how many sampling steps the extra noise is applied for; the example uses 0 on the HIGH pass and 2 on the LOW pass. −1 = all steps. |
It outputs WANVIDIMAGE_EMBEDS straight into WanVideoSampler's image_embeds.
flowmatch_pusa — a value in WanVideoSampler.scheduler (confirmed present in the dropdown: ...flowmatch_distill, flowmatch_pusa, multitalk...). It must be selected on the sampler(s) for the Pusa noise schedule to be interpreted correctly. The example also wires explicit WanVideoScheduler nodes set to flowmatch_pusa, steps 6, shift 5 (one per pass, split 0–3 / 3–end).
How the input clip conditions the extension (the key wire)
WanVideoEncode(vae, image=) → LATENT → WanVideoAddExtraLatent (or WanVideoEmptyEmbeds.extra_latents, tooltip: "First latent to use for the Pusa -model"). This places the real clip's latents at the head of the embed window. The sampler then only has to generate the tail, flow-matched onto that clean head — that is the entire trick. No CLIPVision, no WanFirstLastFrameToVideo.
In practice: load → strip → re-point (DON'T hand-build) ⭐ preferred
The kijai wanvideo_2_2_14B_Pusa_extension_example_01.json is a 56-node graph thick with GetNode/SetNode buses, Reroutes, and an alternate (dead) text branch. Hand-wiring the Pusa noise / extra-latent / frame-stitch path is slow and error-prone. The reliable flow is load the real graph, then adapt ~7 widgets:
- Stage the example anywhere on disk (e.g. copy into the ComfyUI workflows
folder).
panel_load_workflow(path: …)— drops it on the canvas server-side (no
150KB JSON through chat).
panel_strip_workflow(path: …)— returns the resolved API graph
(Get/Set/Reroute/bypass collapsed to real links). This is how you SEE what is actually wired — it exposes both the dead text branch and the silently-reset dropdowns below. (Raw UI JSON hides them.)
⚠️ TRAP 1 — the example's model paths reset to the WRONG file on load
The example references models by subfolder (WanVideo\2_2\…, WanVideo\Lightx2v\…, wanvideo\Wan2_1_VAE_bf16…). On a flat local models/ layout those don't resolve, so ComfyUI silently falls each dropdown back to the first entry in the list — e.g. both WanVideoModelLoaders land on Qwen_Image_Edit-Q8_0.gguf and the WanVideoVAELoader on LTX23_audio_vae_bf16. It looks wired but errors (wrong arch) or renders garbage. After loading, set each explicitly:
| Node | Set to (local) | |---|---| | WanVideoModelLoader HIGH | Wan2_2-T2V-A14B_HIGH_fp8_e4m3fn_scaled_KJ.safetensors — note underscore before HIGH | | WanVideoModelLoader LOW | Wan2_2-T2V-A14B-LOW_fp8_e4m3fn_scaled_KJ.safetensors — note dash before LOW | | WanVideoVAELoader | wan_2.1_vae.safetensors | | WanVideoLoraSelectMulti ×2, slot lora_0 | Pusa HIGH/LOW — these DO resolve if you downloaded to loras/WanVideo/Pusa/ | | WanVideoLoraSelectMulti ×2, slot lora_1 | lightx2v_T2V_14B_cfg_step_distill_v2_lora_rank128_bf16.safetensors @ 1.0 | | VHS_LoadVideo | your clip | | WanVideoTextEncodeCached positive_prompt | your continuation prompt |
> The official HIGH-underscore / LOW-dash filename inconsistency is a real > trap — verify each one rather than copy-pasting.
⚠️ TRAP 2 — the distill LoRA silently drops to none
The example's lightx2v path is WanVideo\Lightx2v\…rank64_bf16_.safetensors (note the trailing _). Locally you usually have rank128 (…rank128_bf16), so the slot resets to none on load — which removes the speed LoRA, and 6-step / cfg-1 sampling then produces mush. Re-add it to lora_1 (strength 1.0) on both WanVideoLoraSelectMulti nodes. Keep merge_loras=false on both (fp8 gotcha above).
⚠️ TRAP 3 — the active prompt is on WanVideoTextEncodeCached, not CLIPTextEncode
The example also contains a CLIPLoader → CLIPTextEncode → WanVideoTextEmbedBridge branch (the "red panda" prompt). It is NOT wired to the samplers — both WanVideoSampler.text_embeds come from WanVideoTextEncodeCached (umt5-xxl-enc-bf16). Edit the prompt THERE; the CLIPTextEncode pair is a decoy that strip_workflow will show dangling.
⚠️ TRAP 4 — match the conditioning fps to WAN-native (16)
If your source clip was frame-interpolated (e.g. RIFE'd to 32/50 fps), set VHS_LoadVideo.force_rate = 16 so the conditioning frames carry motion at WAN's native cadence. Otherwise the encoded "past" runs at 2–3× the model's pace and you get a velocity jump at the seam — the exact artifact Pusa exists to avoid. Best practice: extend the pre-interpolation 16fps master, then interpolate/upscale the combined result afterwards, not before.
⚠️ TRAP 5 — the example assumes SageAttention + torch.compile (triton)
WanVideoModelLoader in the example sets attention_mode: sageattn and wires a WanVideoTorchCompileSettings (inductor) into compile_args. Both are optional accelerators with extra deps that a stock Windows ComfyUI usually lacks:
sageattn→ needs thesageattentionpackage. Missing → the model loader
hard-fails with ValueError: Can't import SageAttention: No module named 'sageattention' before any sampling. Fix: set attention_mode → sdpa on both WanVideoModelLoaders (always available; a bit slower).
- inductor
torch.compile→ needs triton (no official Windows build).
Missing → compile errors later. Fix: disconnect WanVideoTorchCompileSettings from each model loader's compile_args (or don't load it). Only re-enable these two if you've actually installed sageattention / triton-windows.
Check first with the ComfyUI startup log (it prints Could not load sageattention… and triton: unavailable) or list_installed_nodes.
Preferred end-to-end order
generate (or Krea2→WAN/LTX i2v) → Pusa-extend at 832×480/16fps → THEN upscale+interpolate (hand the extended clip to the video-upscale block / a saved Upscale4x-RIFE-1080p subgraph). Upscaling/interpolating before extending wastes the work and feeds Pusa an off-cadence, harder-to-match conditioning clip.
Models, LoRAs & where to get them
UNET — WAN 2.2 T2V A14B (already installed for wan-t2v-video)
| Model | Loader | Notes | |---|---|---| | Wan2_2-T2V-A14B-HIGH_fp8_e4m3fn_scaled_KJ.safetensors | WanVideoModelLoader | HighNoise expert, fp8. Quantization fp8_e4m3fn_scaled. | | Wan2_2-T2V-A14B-LOW_fp8_e4m3fn_scaled_KJ.safetensors | WanVideoModelLoader | LowNoise expert, fp8. |
Text encoder + VAE: same as wan-t2v-video — UMT5 (umt5_xxl_fp8_e4m3fn_scaled / umt5_xxl_fp16) via the wrapper's text-embed path, and the WAN VAE (wan_2.1_vae) via WanVideoVAELoader. The example uses WanVideoTinyVAELoader + taew2_1.safetensors for fast preview decode; use the full WAN VAE for final-quality decode.
Pusa V1 LoRAs — the ONLY new download (~1.9 GB)
From kijai's HF repo Kijai/WanVideo_comfy, folder Pusa/ → place in models/loras/ (the example expects them under loras/WanVideo/Pusa/):
| LoRA file | ~Size | Applies to | Strength (example) | |---|---|---|---| | Wan22_PusaV1_lora_HIGH_resized_dynamic_avg_rank_98_bf16.safetensors | ~956 MB | HIGH T2V model | 1.5 | | Wan22_PusaV1_lora_LOW_resized_dynamic_avg_rank_98_bf16.safetensors | ~968 MB | LOW T2V model | 1.4 |
> There is also a single-file Wan21_PusaV1_LoRA_14B_rank512_bf16.safetensors > (~4.9 GB) in the same folder — that's the Wan 2.1 single-model Pusa LoRA. > For the 2.2 dual HIGH/LOW extension graph, use the two Wan22_...rank_98 > files above, matched to the correct expert. Upstream weights / paper: > RaphaelLiu/PusaV1 on HF.
Speed LoRA (paired with Pusa in the example)
The example also stacks the lightx2v T2V distill LoRA on each model via WanVideoLoraSelectMulti, so 6-step low-CFG sampling works:
| LoRA | Strength | From | |---|---|---| | lightx2v_T2V_14B_cfg_step_distill_v2_lora_rank64_bf16_.safetensors | 1.0 | Kijai/WanVideo_comfy/Lightx2v/ |
LoRAs are selected with WanVideoLoraSelectMulti (multi-slot) and fed into each WanVideoModelLoader's lora input — one select feeds HIGH (Pusa HIGH + distill), one feeds LOW (Pusa LOW + distill).
⚠️ CRITICAL — merge_loras=false on fp8 models (same gotcha as wan-t2v-video)
Pusa loads LoRAs onto the fp8-quantized T2V A14B models (quantization=fp8_e4m3fn_scaled). As documented in wan-t2v-video: when a LoRA is applied to an fp8 model via the wrapper's LoRA select, set merge_loras to false. The default merge_loras=true tries to bake the LoRA into the already-quantized fp8 weights and hard-crashes ComfyUI during LoRA loading with no Python traceback (looks like an unexplained restart/OOM). false applies the LoRA as a runtime patch, which is fp8-safe. This applies to both the Pusa LoRAs and the lightx2v distill LoRA. Use merge_loras=true only on non-quantized bf16/fp16 models.
Settings
Sampler (from the example — distilled 6-step, two-pass HIGH→LOW)
| Param | HIGH pass | LOW pass | Notes | |---|---|---|---| | model | HIGH + Pusa HIGH (1.5) + distill (1.0) | LOW + Pusa LOW (1.4) + distill (1.0) | | | scheduler | flowmatch_pusa | flowmatch_pusa | required for Pusa | | steps | 6 | 6 | distilled; raise to ~20–30 for the non-distill path | | cfg | 1.0 | 1.0 | distilled low-CFG; ~5–6 without distill | | shift | 5.0 | 5.0 | flow-matching shift | | startstep / endstep | 0 / 3 | 3 / −1 | HIGH does early steps, LOW finishes | | noisy_steps (on AddPusaNoise) | 0 | 2 | extra-noise duration per pass |
If you drop the distill LoRA: use steps ~20–30, cfg ~5–6, keep flowmatch_pusa and shift 5, single-pass unipc-style splitting still works HIGH→LOW.
Pusa noise (WanVideoAddPusaNoise.noise_multipliers)
This is the dial that controls how strictly the continuation honors the input clip vs. how free it is to diverge:
- **Lower mu
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: artokun
- Source: artokun/comfyui-mcp
- License: MIT
- Homepage: https://comfyui-mcp.artokun.io/docs
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.