WAN 2.2 First-Last-Frame (FLF) Video Workflows

Build WAN 2.2 First-Last-Frame video workflows.

How to install

How to install

  1. Setup differs for this server — follow the Installation part of the README below.
  2. Claude Code: claude mcp add <name> -- <command>.
  3. Claude Desktop / Cursor: add it under mcpServers in the MCP config file.
Claude Code — installs the whole folder, not just SKILL.md
npx degit artokun/comfyui-mcp/plugin/skills/wan-flf-video#main ~/.claude/skills/wan-flf-video

For one project only, change the path to .claude/skills/wan-flf-video. This skill also uses Advanced.json — copying SKILL.md alone won't be enough. See the folder on GitHub.

This one runs on your machine and can reach your files. Read the README below before you connect it.

Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Show the full text474 lines
wan-flf-video/SKILL.md474 lines20.2 KBpushed 27d agoRawView on GitHub

WAN 2.2 First-Last-Frame (FLF) Video Workflows

Overview

First-Last-Frame (FLF) video generation takes a start image and an end image and generates a smooth video transition between them. The WAN 2.2 I2V (Image-to-Video) 14B model is good at this.

CRITICAL: Dual Hi-Lo Architecture (REQUIRED)

WAN 2.2 I2V uses a split-noise architecture. Unlike WAN 2.1, the 2.2 model was trained with separate HighNoise and LowNoise components that handle different denoising ranges. You MUST use both models in a two-pass KSamplerAdvanced setup. Using a single model produces low-quality, broken output.

  • HighNoise model (pass 1, steps 0→N/2) establishes structure, motion, and composition
  • LowNoise model (pass 2, steps N/2→N) refines details and keeps fidelity to input frames
  • Both passes share the same conditioning from WanFirstLastFrameToVideo
  • Pass 1 returns noisy latent → Pass 2 continues from there

NEVER use a single KSampler with only one model for WAN 2.2 I2V.

Two native approaches are available:

  1. Native Dual Hi-Lo (Default): WanFirstLastFrameToVideo + dual KSamplerAdvanced two-pass
  2. WanVideoWrapper: WanVideoVACEStartToEndFrame + WanVideoVACEEncode + WanVideoSampler (VACE, caching, context windows)

Models

UNET Pairs (Always load BOTH Hi and Lo)

Remix NSFW (Recommended, built-in lightning, fp16):

Model Loader Notes
Wan2.2_Remix_NSFW_i2v_14b_high_lighting_fp16_v2.1.safetensors UNETLoader HighNoise, built-in lightning acceleration
Wan2.2_Remix_NSFW_i2v_14b_low_lighting_fp16_v2.1.safetensors UNETLoader LowNoise, built-in lightning acceleration

GGUF Q8 (Alternative, needs external lightning LoRAs):

Model Loader Notes
Wan2.2-I2V-A14B-HighNoise-Q8_0.gguf UnetLoaderGGUF HighNoise, quantized
Wan2.2-I2V-A14B-LowNoise-Q8_0.gguf UnetLoaderGGUF LowNoise, quantized

Official fp8:

Model Loader Notes
wan2.2_i2v_high_noise_14B_fp8_scaled.safetensors UNETLoader HighNoise, needs lightning LoRA
wan2.2_i2v_low_noise_14B_fp8_scaled.safetensors UNETLoader LowNoise, needs lightning LoRA

Text Encoder

Model Node Notes
nsfw_wan_umt5-xxl_bf16_fixed.safetensors CLIPLoaderGGUF (type=wan) NSFW-tuned, pair with Remix models
umt5_xxl_fp8_e4m3fn_scaled.safetensors CLIPLoader (type=wan) Standard UMT5-XXL fp8

CLIP Vision + VAE

Component Node Model
CLIP Vision CLIPVisionLoader clip_vision_h.safetensors
VAE VAELoader wan_2.1_vae.safetensors

ModelSamplingSD3 (REQUIRED)

WAN 2.2 uses flow matching and requires ModelSamplingSD3 applied to each UNET:

{"class_type": "ModelSamplingSD3", "inputs": {"model": ["<unet>", 0], "shift": 5}}

shift=5 for lightning/Remix models. shift=8 for standard (non-lightning) models.

Lightning LoRAs

Remix NSFW models have lightning baked in. No external LoRA needed.

For GGUF/fp8 models, use paired hi/lo lightning LoRAs:

  • wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors → HighNoise UNET
  • wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors → LowNoise UNET

LoRA Stacks (rgthree)

Each model path has two stacked loaders (Common + Specific), each supporting 4 LoRA slots:

Hi path: UNETLoader(HN) → ModelSamplingSD3(shift=5) → Hi Common Stack → Hi Lora Stack → MODEL_HI
Lo path: UNETLoader(LN) → ModelSamplingSD3(shift=5) → Lo Common Stack → Lo Lora Stack → MODEL_LO

Common stacks hold shared LoRAs (quality/style). Specific stacks hold model-variant LoRAs. Set slots to "None" when unused. Even with no LoRAs, include the stacks. They pass CLIP through for text encoding.

Image Resizing (ImageResizeKJv2)

Input frames MUST be resized to the target video resolution before FLF and CLIPVisionEncode. The end frame inherits width/height from the start frame's resize so the dimensions match.

{"class_type": "ImageResizeKJv2", "inputs": {
  "image": ["<load_image>", 0], "width": 480, "height": 720,
  "upscale_method": "nearest-exact", "keep_proportion": "crop",
  "pad_color": "0, 0, 0", "crop_position": "center", "divisible_by": 2
}}

KSamplerAdvanced Two-Pass Settings

Parameter Pass 1 (Hi) Pass 2 (Lo)
model Hi LoRA stack output Lo LoRA stack output
add_noise enable disable
steps 4 4
cfg 1 1
sampler_name uni_pc uni_pc
scheduler beta beta
start_at_step 0 2
end_at_step 2 4
return_with_leftover_noise enable disable
latent_image WanFLF output[2] Pass 1 output[0]

Both passes share the same positive/negative conditioning from WanFirstLastFrameToVideo outputs [0] and [1].

For standard (non-lightning) models: steps=20, split at step 10, cfg=4, sampler=euler, scheduler=simple, shift=8.

Negative Prompt (REQUIRED)

Always include a quality negative prompt:

The tones are vibrant, overexposed, static, details are unclear, subtitles, style, work, painting, image, still, overall grayish, worst quality, low quality, JPEG compression artifacts, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, distorted limbs, merged fingers, motionless image, cluttered background, three legs, many people in the background, walking backwards

Node: WanFirstLastFrameToVideo

Required Inputs:
  - positive: CONDITIONING (from CLIPTextEncode)
  - negative: CONDITIONING (from CLIPTextEncode with negative prompt)
  - vae: VAE
  - width: INT (from ImageResizeKJv2 end frame output[1])
  - height: INT (from ImageResizeKJv2 end frame output[2])
  - length: INT (default 81, step 4) — number of frames
  - batch_size: INT (default 1)

Optional Inputs:
  - clip_vision_start_image: CLIP_VISION_OUTPUT (from CLIPVisionEncode)
  - clip_vision_end_image: CLIP_VISION_OUTPUT (from CLIPVisionEncode)
  - start_image: IMAGE (resized start frame)
  - end_image: IMAGE (resized end frame)

Outputs:
  - [0] positive: CONDITIONING → feed to BOTH Hi and Lo KSamplerAdvanced
  - [1] negative: CONDITIONING → feed to BOTH Hi and Lo KSamplerAdvanced
  - [2] latent: LATENT → feed to Hi Pass only (Lo Pass gets Hi Pass output)

Pipeline Flow

UNETLoader (HighNoise) → ModelSamplingSD3 (shift=5) → Hi Common Stack → Hi Lora Stack → MODEL_HI
UNETLoader (LowNoise) → ModelSamplingSD3 (shift=5) → Lo Common Stack → Lo Lora Stack → MODEL_LO
CLIPLoaderGGUF (wan) → CLIP
  ├─ CLIPTextEncode (positive) → CONDITIONING
  └─ CLIPTextEncode (negative) → CONDITIONING
CLIPVisionLoader → CLIPVisionEncode (start) + CLIPVisionEncode (end)
VAELoader → VAE
LoadImage (start) → ImageResizeKJv2 (480x720) → resized start
LoadImage (end) → ImageResizeKJv2 (match dims) → resized end

WanFirstLastFrameToVideo (positive, negative, vae, clip_vision_start, clip_vision_end,
  start_image, end_image, width/height from resize)
  → modified positive [0], modified negative [1], latent [2]

KSamplerAdvanced (Hi: MODEL_HI, steps 0→2, add_noise=enable, return_leftover=enable)
  → noisy LATENT
KSamplerAdvanced (Lo: MODEL_LO, steps 2→4, add_noise=disable, return_leftover=disable)
  → final LATENT

VAEDecode → IMAGE → VHS_VideoCombine (raw output)
                   → VRAM_Debug → SeedVR2VideoUpscaler (1080p) → VHS_VideoCombine (upscaled)

Complete workflow (API JSON)

The full Native FLF (Remix NSFW + Lightning) graph is in references/workflows.md.

Optional: Video Upscaling with SeedVR2

Add after VAEDecode for AI-powered video upscaling to 1080p. Use VRAM_Debug to free VRAM between generation and upscaling:

{
  "25": { "class_type": "VRAM_Debug", "inputs": {
    "image_pass": ["23", 0], "empty_cache": true, "gc_collect": true, "unload_all_models": true
  }},
  "26": { "class_type": "SeedVR2LoadDiTModel", "inputs": {
    "model": "seedvr2_ema_3b_fp8_e4m3fn.safetensors", "device": "cuda:0",
    "blocks_to_swap": 0, "swap_io_components": false, "cache_model": false, "attention_mode": "sdpa"
  }},
  "27": { "class_type": "SeedVR2LoadVAEModel", "inputs": {
    "model": "ema_vae_fp16.safetensors", "device": "cuda:0",
    "encode_tiled": false, "decode_tiled": false, "cache_model": false
  }},
  "28": { "class_type": "SeedVR2VideoUpscaler", "inputs": {
    "image": ["25", 1], "dit": ["26", 0], "vae": ["27", 0],
    "seed": 0, "resolution": 1080, "max_resolution": 0,
    "batch_size": 5, "uniform_batch_size": false, "color_correction": "lab"
  }},
  "29": { "class_type": "VHS_VideoCombine", "inputs": {
    "images": ["28", 0], "frame_rate": 16, "loop_count": 0,
    "filename_prefix": "wan_flf_upscaled", "format": "video/h264-mp4",
    "pingpong": false, "save_output": true,
    "pix_fmt": "yuv420p", "crf": 19, "save_metadata": true, "trim_to_audio": false
  }}
}

Alternative: GGUF Models with Lightning LoRAs

When using GGUF Q8 models instead of Remix, add paired lightning LoRAs:

Hi path: UnetLoaderGGUF(HN Q8) → ModelSamplingSD3(shift=5) → LoraLoaderModelOnly(hi_noise_lightning) → Hi Common Stack → Hi Lora Stack
Lo path: UnetLoaderGGUF(LN Q8) → ModelSamplingSD3(shift=5) → LoraLoaderModelOnly(lo_noise_lightning) → Lo Common Stack → Lo Lora Stack

LoRA files:

  • Unknown\no tags\wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors
  • Unknown\no tags\wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors

Approach 2: WanVideoWrapper (Advanced Control)

Uses the WanVideoWrapper custom node pack for more control over conditioning, caching, context windows, and advanced features.

Key Differences from Native

  • Uses WANVIDEOMODEL type instead of generic MODEL
  • Uses WANVIDIMAGE_EMBEDS for conditioning instead of CONDITIONING
  • Has own sampler (WanVideoSampler) with shift parameter and scheduler options
  • Supports TeaCache, MagCache, EasyCache for speed optimization
  • Supports context windows for longer videos
  • VACE module provides more flexible frame conditioning

VACE-Based FLF Pipeline

WanVideoModelLoader → WANVIDEOMODEL
WanVideoVAELoader → WANVAE
WanVideoTextEncode → WANVIDEOTEXTEMBEDS
WanVideoClipVisionEncode (start + end images) → WANVIDIMAGE_CLIPEMBEDS

WanVideoVACEStartToEndFrame (start_image, end_image, num_frames=81)
  → images batch, masks

WanVideoVACEEncode (vae, input_frames, input_masks, width, height, num_frames)
  → WANVIDIMAGE_EMBEDS (vace_embeds)

WanVideoSampler (model, image_embeds, text_embeds, steps, cfg, shift, scheduler)
  → LATENT

WanVideoDecode (vae, samples) → IMAGE → VHS_VideoCombine → MP4

WanVideoSampler Settings

Parameter Standard Lightning Notes
steps 30 4
cfg 6.0 1.0
shift 5.0 5.0 Flow matching shift
scheduler unipc euler WanVideoWrapper has own schedulers
force_offload true true Move model to CPU after sampling

When to Use WanVideoWrapper vs Native

Feature Native WanVideoWrapper
Simplicity Simpler More complex
Dual Hi-Lo Manual two-pass May handle internally
LoRA loading Lora Loader Stack (rgthree) WanVideoLoraSelect → WanVideoModelLoader lora (see merge_loras caveat)
Caching (TeaCache) Not available Built-in
Context windows Not available WanVideoContextOptions
Block swap (VRAM) Not available WanVideoBlockSwap
VACE conditioning Not available Full VACE support
Long video (>81 frames) Limited InfiniteTalk / context windows

Recommendation: use Native dual hi-lo for standard FLF transitions. Use WanVideoWrapper when you need caching, context windows, VRAM management, or advanced conditioning.

⚠️ CRITICAL: merge_loras=false with fp8-scaled models

When loading a LoRA through WanVideoLoraSelectWanVideoModelLoader's lora input on an fp8-quantized model (quantization=fp8_e4m3fn_scaled, e.g. the official wan2.2_i2v_high/low_noise_14B_fp8_scaled weights), you MUST set the WanVideoLoraSelect widget merge_loras=false.

  • merge_loras=true (the node default) tries to bake the LoRA deltas into the already-quantized fp8 weights. That merge path hard-crashes ComfyUI during LoRA loading. The process dies with no Python traceback (so panel_get_errors / the frontend show nothing; only a process restart/OOM-style symptom). This is the #1 cause of a "crashed on lora loading" report with the wrapper.
  • merge_loras=false applies the LoRA as a runtime patch during the forward pass instead of merging. It is fp8-safe with negligible speed cost. This is the correct setting for the lightx2v 4-step lightning LoRAs (hi + lo) on the fp8 hi/lo I2V models.
  • It also pairs cleanly with block swap: WanVideoBlockSwap (e.g. 20 to 30 of 40 blocks → RAM) + merge_loras=false is the verified combo for fp8 14B I2V at 720p/81f on a 24GB card. (If you instead use a non-quantized bf16/fp16 model, merge_loras=true is fine.)

Separately, at 720p/81f enable enable_vae_tiling=true on WanVideoDecode. The full-frame decode is the other common uncaught-OOM crash point.

Resolution & Frame Count

Standard Resolutions

Aspect Resolution Megapixels
Portrait 2:3 480x720 0.35MP (recommended default)
Landscape 16:9 832x480 0.4MP
Portrait 9:16 480x832 0.4MP
Square 640x640 0.4MP

Width and height must be divisible by 16. Use ImageResizeKJv2 with divisible_by: 2 and keep_proportion: crop.

Frame Count

  • 81 frames at 16fps = ~5 seconds (default, recommended)
  • 49 frames at 16fps = ~3 seconds (faster, less motion)
  • 121 frames at 16fps = ~7.5 seconds (longer, more VRAM)
  • Frame count should be 4n + 1 (1, 5, 9, ..., 49, 81, 121)

Frame Rate

Standard: 16 fps for WAN 2.2 output.

Video Output

VHS_VideoCombine

{
  "class_type": "VHS_VideoCombine",
  "inputs": {
    "images": ["<vae_decode>", 0],
    "frame_rate": 16,
    "loop_count": 0,
    "filename_prefix": "wan_flf",
    "format": "video/h264-mp4",
    "pingpong": false,
    "save_output": true,
    "pix_fmt": "yuv420p",
    "crf": 19,
    "save_metadata": true,
    "trim_to_audio": false
  }
}

VRAM Considerations

Dual Hi-Lo with Remix fp16

  • Two UNETs loaded sequentially (ComfyUI offloads between passes): ~14GB each
  • NSFW UMT5-XXL bf16: ~8GB (offloaded after text encoding)
  • CLIP Vision H: ~1.5GB (offloaded after encoding)
  • VAE: ~200MB
  • Latent (81 frames at 480x720): ~1-2GB

ComfyUI manages VRAM by offloading models between passes. The Hi UNET is offloaded before the Lo UNET loads.

Tips

  1. Always clear_vram before switching to WAN from another model family
  2. Use VRAM_Debug node between generation and SeedVR2 upscaling to free all VRAM
  3. For 24GB GPUs, 81 frames at 480x720 is the practical maximum
  4. Remix NSFW models have lightning baked in. No separate LoRA needed, 4 steps total

Morph LoRAs (Smooth Metamorphosis)

By default, FLF produces a transition/dissolve between frames. For true morphing (one shape continuously reshaping into another), use a morph LoRA on both Hi and Lo paths.

Magical Morph (Recommended)

Variant File Strength Notes
HighNoise wan2.2_i2v_magical_morph_highnoise.safetensors 0.7-1.0 Apply to Hi Common stack
LowNoise wan2.2_i2v_magical_morph_lownoise.safetensors 0.7-1.0 Apply to Lo Common stack
  • Source: NikolaSigmoid/wan2.2-i2v-loras-magical-morph
  • No trigger word needed. The LoRA modifies the denoising behavior
  • Strength 1.0 can add visual sparkle/particle effects. Reduce to 0.7-0.8 for cleaner morphs
  • Works with Remix NSFW models (no conflict with built-in lightning)

SkinMorph Redmond (Alternative — Face/Body Focus)

For person-to-person morphs (identity, gender transforms):

  • Trigger word: Skin morph
  • Strength: 0.8-1.0
  • Source: CivitAI

Prompt Tips

Describe the transition motion in addition to the start/end states:

Good: "A small cat sitting on the ground smoothly transforms and grows into a woman standing tall, seamless transformation, cinematic"
Bad: "A cat and a girl"

IMPORTANT: prompt language affects visuals.

  • AVOID words like "magical", "enchanted", "mystical". They cause literal sparkle/particle effects
  • USE clean motion language: "smoothly transforms", "gradually reshapes", "seamlessly morphs", "transitions into"
  • The morph LoRA handles the morphing effect. The prompt should describe motion and form change, not style
  • Include scale/position cues when subjects differ in size: "grows into", "expands upward", "shrinks down"

Settings Quick Reference

Config Lightning (Remix) Standard
Models Remix NSFW Hi+Lo fp16 Official Hi+Lo fp8
CLIP nsfw_wan_umt5-xxl_bf16_fixed umt5_xxl_fp8_e4m3fn_scaled
ModelSamplingSD3 shift 5 8
Total steps 4 20
Hi pass end_at_step 2 10
CFG 1 4
Sampler uni_pc euler
Scheduler beta simple
External LoRA needed No (built-in) Yes (paired hi/lo)

Multi-Step Pipeline Pattern

Anchor Frame Strategy (Proportions)

When the start and end frames have different subject sizes (e.g., small cat → tall person), generate the "anchor" frame first (the one with the most complex composition), then use Qwen Edit to create the other frame from it. This gives you:

  • Consistent background/scene between frames
  • Correct relative proportions (the edit inherits the scene scale)
  • Better FLF results since both frames share the same visual context

Example, cat-to-girl morph:

  1. Generate girl standing in front of barn with Z-Image (she fills the frame)
  2. Qwen Edit: "Replace the woman with a small cat sitting at the bottom of the image"
  3. FLF: cat (start) → girl (end). Proportions are correct because the barn establishes scale

Anti-pattern: generating cat and girl independently produces mismatched scale.

Full Pipeline

  1. Generate anchor frame with Z-Image/SDXL/Flux (portrait orientation for standing subjects)
  2. Qwen Edit to create second frame. The edit preserves scene context
  3. Clear VRAM between model families
  4. Stage both frames as inputs. When the frames are ComfyUI OUTPUTS from a prior stage (the generated/edited frames above), use upload_image (action:"stage") with each output's { filename, subfolder?, type? } and feed the returned input filename into each LoadImage. (For a frame already on local disk, use upload_image (action:"image").) NEVER copy the output file into, or guess, a filesystem input/ path. ComfyUI's input/output dirs may be CUSTOM (--input-directory / --output-directory), so a guessed path makes LoadImage reject the file (Invalid image file) and wastes the render. upload_image (action:"stage") routes through the server API (/view/upload/image), which resolves the real dirs correctly.
  5. Run dual hi-lo FLF with morph LoRA if morphing is desired
  6. Optionally upscale with SeedVR2 to 1080p

Proven timing on RTX 4090: Z-Image (35s) → Qwen Edit (78s) → WAN FLF 81 frames (139s) = ~4 minutes total.

Working with Saved Workflows

Use get_workflow (action:"analyze") to understand any saved WAN FLF workflow before modifying or executing it. It returns a structured summary with sections, node IDs, key settings, and virtual wire connections. No raw JSON needed.

get_workflow(action="analyze", filename="Wan FirstLastFrame Advanced.json")                # summary view (default)
get_workflow(action="analyze", filename="Wan FirstLastFrame Advanced.json", view="flat")   # mermaid diagram

Only use get_workflow when you need the raw JSON for enqueue_workflow or create_workflow (action:"modify").

Sources

  • Official: none found.
  • Empirical: sampler values, wiring, and prompt notes from working graphs in packs/ and observed renders; not a vendor prompting guide.
1---
2name: wan-flf-video
3description: Build WAN 2.2 First-Last-Frame video workflows. Native dual hi-lo (required), and WanVideoWrapper VACE approaches
4globs:
5 - "**/*.json"
6---
7 
8# WAN 2.2 First-Last-Frame (FLF) Video Workflows
9 
10## Overview
11 
12First-Last-Frame (FLF) video generation takes a start image and an end image and generates a smooth video transition between them. The WAN 2.2 I2V (Image-to-Video) 14B model is good at this.
13 
14## CRITICAL: Dual Hi-Lo Architecture (REQUIRED)
15 
16**WAN 2.2 I2V uses a split-noise architecture.** Unlike WAN 2.1, the 2.2 model was trained with separate HighNoise and LowNoise components that handle different denoising ranges. **You MUST use both models in a two-pass KSamplerAdvanced setup.** Using a single model produces low-quality, broken output.
17 
18- HighNoise model (pass 1, steps 0→N/2) establishes structure, motion, and composition
19- LowNoise model (pass 2, steps N/2→N) refines details and keeps fidelity to input frames
20- Both passes share the same conditioning from `WanFirstLastFrameToVideo`
21- Pass 1 returns noisy latent → Pass 2 continues from there
22 
23**NEVER use a single KSampler with only one model for WAN 2.2 I2V.**
24 
25Two native approaches are available:
261. Native Dual Hi-Lo (Default): `WanFirstLastFrameToVideo` + dual `KSamplerAdvanced` two-pass
272. WanVideoWrapper: `WanVideoVACEStartToEndFrame` + `WanVideoVACEEncode` + `WanVideoSampler` (VACE, caching, context windows)
28 
29## Models
30 
31### UNET Pairs (Always load BOTH Hi and Lo)
32 
33Remix NSFW (Recommended, built-in lightning, fp16):
34| Model | Loader | Notes |
35|-------|--------|-------|
36| `Wan2.2_Remix_NSFW_i2v_14b_high_lighting_fp16_v2.1.safetensors` | `UNETLoader` | HighNoise, built-in lightning acceleration |
37| `Wan2.2_Remix_NSFW_i2v_14b_low_lighting_fp16_v2.1.safetensors` | `UNETLoader` | LowNoise, built-in lightning acceleration |
38 
39GGUF Q8 (Alternative, needs external lightning LoRAs):
40| Model | Loader | Notes |
41|-------|--------|-------|
42| `Wan2.2-I2V-A14B-HighNoise-Q8_0.gguf` | `UnetLoaderGGUF` | HighNoise, quantized |
43| `Wan2.2-I2V-A14B-LowNoise-Q8_0.gguf` | `UnetLoaderGGUF` | LowNoise, quantized |
44 
45Official fp8:
46| Model | Loader | Notes |
47|-------|--------|-------|
48| `wan2.2_i2v_high_noise_14B_fp8_scaled.safetensors` | `UNETLoader` | HighNoise, needs lightning LoRA |
49| `wan2.2_i2v_low_noise_14B_fp8_scaled.safetensors` | `UNETLoader` | LowNoise, needs lightning LoRA |
50 
51### Text Encoder
52 
53| Model | Node | Notes |
54|-------|------|-------|
55| `nsfw_wan_umt5-xxl_bf16_fixed.safetensors` | `CLIPLoaderGGUF` (type=`wan`) | NSFW-tuned, pair with Remix models |
56| `umt5_xxl_fp8_e4m3fn_scaled.safetensors` | `CLIPLoader` (type=`wan`) | Standard UMT5-XXL fp8 |
57 
58### CLIP Vision + VAE
59 
60| Component | Node | Model |
61|-----------|------|-------|
62| **CLIP Vision** | `CLIPVisionLoader` | `clip_vision_h.safetensors` |
63| **VAE** | `VAELoader` | `wan_2.1_vae.safetensors` |
64 
65## ModelSamplingSD3 (REQUIRED)
66 
67WAN 2.2 uses flow matching and requires `ModelSamplingSD3` applied to each UNET:
68 
69```json
70{"class_type": "ModelSamplingSD3", "inputs": {"model": ["<unet>", 0], "shift": 5}}
71```
72 
73shift=5 for lightning/Remix models. shift=8 for standard (non-lightning) models.
74 
75## Lightning LoRAs
76 
77Remix NSFW models have lightning baked in. No external LoRA needed.
78 
79For GGUF/fp8 models, use paired hi/lo lightning LoRAs:
80- `wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors` → HighNoise UNET
81- `wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors` → LowNoise UNET
82 
83## LoRA Stacks (rgthree)
84 
85Each model path has two stacked loaders (Common + Specific), each supporting 4 LoRA slots:
86 
87```
88Hi path: UNETLoader(HN) → ModelSamplingSD3(shift=5) → Hi Common Stack → Hi Lora Stack → MODEL_HI
89Lo path: UNETLoader(LN) → ModelSamplingSD3(shift=5) → Lo Common Stack → Lo Lora Stack → MODEL_LO
90```
91 
92Common stacks hold shared LoRAs (quality/style). Specific stacks hold model-variant LoRAs. Set slots to `"None"` when unused. Even with no LoRAs, include the stacks. They pass CLIP through for text encoding.
93 
94## Image Resizing (ImageResizeKJv2)
95 
96Input frames MUST be resized to the target video resolution before FLF and CLIPVisionEncode. The end frame inherits width/height from the start frame's resize so the dimensions match.
97 
98```json
99{"class_type": "ImageResizeKJv2", "inputs": {
100 "image": ["<load_image>", 0], "width": 480, "height": 720,
101 "upscale_method": "nearest-exact", "keep_proportion": "crop",
102 "pad_color": "0, 0, 0", "crop_position": "center", "divisible_by": 2
103}}
104```
105 
106## KSamplerAdvanced Two-Pass Settings
107 
108| Parameter | Pass 1 (Hi) | Pass 2 (Lo) |
109|-----------|-------------|-------------|
110| model | Hi LoRA stack output | Lo LoRA stack output |
111| add_noise | **enable** | **disable** |
112| steps | 4 | 4 |
113| cfg | 1 | 1 |
114| sampler_name | **uni_pc** | **uni_pc** |
115| scheduler | **beta** | **beta** |
116| start_at_step | 0 | 2 |
117| end_at_step | 2 | 4 |
118| return_with_leftover_noise | **enable** | **disable** |
119| latent_image | WanFLF output[2] | **Pass 1 output[0]** |
120 
121Both passes share the same positive/negative conditioning from `WanFirstLastFrameToVideo` outputs [0] and [1].
122 
123For standard (non-lightning) models: steps=20, split at step 10, cfg=4, sampler=euler, scheduler=simple, shift=8.
124 
125## Negative Prompt (REQUIRED)
126 
127Always include a quality negative prompt:
128 
129```
130The tones are vibrant, overexposed, static, details are unclear, subtitles, style, work, painting, image, still, overall grayish, worst quality, low quality, JPEG compression artifacts, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, distorted limbs, merged fingers, motionless image, cluttered background, three legs, many people in the background, walking backwards
131```
132 
133## Node: WanFirstLastFrameToVideo
134 
135```
136Required Inputs:
137 - positive: CONDITIONING (from CLIPTextEncode)
138 - negative: CONDITIONING (from CLIPTextEncode with negative prompt)
139 - vae: VAE
140 - width: INT (from ImageResizeKJv2 end frame output[1])
141 - height: INT (from ImageResizeKJv2 end frame output[2])
142 - length: INT (default 81, step 4) — number of frames
143 - batch_size: INT (default 1)
144 
145Optional Inputs:
146 - clip_vision_start_image: CLIP_VISION_OUTPUT (from CLIPVisionEncode)
147 - clip_vision_end_image: CLIP_VISION_OUTPUT (from CLIPVisionEncode)
148 - start_image: IMAGE (resized start frame)
149 - end_image: IMAGE (resized end frame)
150 
151Outputs:
152 - [0] positive: CONDITIONING → feed to BOTH Hi and Lo KSamplerAdvanced
153 - [1] negative: CONDITIONING → feed to BOTH Hi and Lo KSamplerAdvanced
154 - [2] latent: LATENT → feed to Hi Pass only (Lo Pass gets Hi Pass output)
155```
156 
157## Pipeline Flow
158 
159```
160UNETLoader (HighNoise) → ModelSamplingSD3 (shift=5) → Hi Common Stack → Hi Lora Stack → MODEL_HI
161UNETLoader (LowNoise) → ModelSamplingSD3 (shift=5) → Lo Common Stack → Lo Lora Stack → MODEL_LO
162CLIPLoaderGGUF (wan) → CLIP
163 ├─ CLIPTextEncode (positive) → CONDITIONING
164 └─ CLIPTextEncode (negative) → CONDITIONING
165CLIPVisionLoader → CLIPVisionEncode (start) + CLIPVisionEncode (end)
166VAELoader → VAE
167LoadImage (start) → ImageResizeKJv2 (480x720) → resized start
168LoadImage (end) → ImageResizeKJv2 (match dims) → resized end
169 
170WanFirstLastFrameToVideo (positive, negative, vae, clip_vision_start, clip_vision_end,
171 start_image, end_image, width/height from resize)
172 → modified positive [0], modified negative [1], latent [2]
173 
174KSamplerAdvanced (Hi: MODEL_HI, steps 0→2, add_noise=enable, return_leftover=enable)
175 → noisy LATENT
176KSamplerAdvanced (Lo: MODEL_LO, steps 2→4, add_noise=disable, return_leftover=disable)
177 → final LATENT
178 
179VAEDecode → IMAGE → VHS_VideoCombine (raw output)
180 → VRAM_Debug → SeedVR2VideoUpscaler (1080p) → VHS_VideoCombine (upscaled)
181```
182 
183## Complete workflow (API JSON)
184 
185The full Native FLF (Remix NSFW + Lightning) graph is in [`references/workflows.md`](references/workflows.md).
186 
187## Optional: Video Upscaling with SeedVR2
188 
189Add after `VAEDecode` for AI-powered video upscaling to 1080p. Use `VRAM_Debug` to free VRAM between generation and upscaling:
190 
191```json
192{
193 "25": { "class_type": "VRAM_Debug", "inputs": {
194 "image_pass": ["23", 0], "empty_cache": true, "gc_collect": true, "unload_all_models": true
195 }},
196 "26": { "class_type": "SeedVR2LoadDiTModel", "inputs": {
197 "model": "seedvr2_ema_3b_fp8_e4m3fn.safetensors", "device": "cuda:0",
198 "blocks_to_swap": 0, "swap_io_components": false, "cache_model": false, "attention_mode": "sdpa"
199 }},
200 "27": { "class_type": "SeedVR2LoadVAEModel", "inputs": {
201 "model": "ema_vae_fp16.safetensors", "device": "cuda:0",
202 "encode_tiled": false, "decode_tiled": false, "cache_model": false
203 }},
204 "28": { "class_type": "SeedVR2VideoUpscaler", "inputs": {
205 "image": ["25", 1], "dit": ["26", 0], "vae": ["27", 0],
206 "seed": 0, "resolution": 1080, "max_resolution": 0,
207 "batch_size": 5, "uniform_batch_size": false, "color_correction": "lab"
208 }},
209 "29": { "class_type": "VHS_VideoCombine", "inputs": {
210 "images": ["28", 0], "frame_rate": 16, "loop_count": 0,
211 "filename_prefix": "wan_flf_upscaled", "format": "video/h264-mp4",
212 "pingpong": false, "save_output": true,
213 "pix_fmt": "yuv420p", "crf": 19, "save_metadata": true, "trim_to_audio": false
214 }}
215}
216```
217 
218## Alternative: GGUF Models with Lightning LoRAs
219 
220When using GGUF Q8 models instead of Remix, add paired lightning LoRAs:
221 
222```
223Hi path: UnetLoaderGGUF(HN Q8) → ModelSamplingSD3(shift=5) → LoraLoaderModelOnly(hi_noise_lightning) → Hi Common Stack → Hi Lora Stack
224Lo path: UnetLoaderGGUF(LN Q8) → ModelSamplingSD3(shift=5) → LoraLoaderModelOnly(lo_noise_lightning) → Lo Common Stack → Lo Lora Stack
225```
226 
227LoRA files:
228- `Unknown\no tags\wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors`
229- `Unknown\no tags\wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors`
230 
231## Approach 2: WanVideoWrapper (Advanced Control)
232 
233Uses the WanVideoWrapper custom node pack for more control over conditioning, caching, context windows, and advanced features.
234 
235### Key Differences from Native
236 
237- Uses `WANVIDEOMODEL` type instead of generic `MODEL`
238- Uses `WANVIDIMAGE_EMBEDS` for conditioning instead of `CONDITIONING`
239- Has own sampler (`WanVideoSampler`) with shift parameter and scheduler options
240- Supports TeaCache, MagCache, EasyCache for speed optimization
241- Supports context windows for longer videos
242- VACE module provides more flexible frame conditioning
243 
244### VACE-Based FLF Pipeline
245 
246```
247WanVideoModelLoader → WANVIDEOMODEL
248WanVideoVAELoader → WANVAE
249WanVideoTextEncode → WANVIDEOTEXTEMBEDS
250WanVideoClipVisionEncode (start + end images) → WANVIDIMAGE_CLIPEMBEDS
251 
252WanVideoVACEStartToEndFrame (start_image, end_image, num_frames=81)
253 → images batch, masks
254 
255WanVideoVACEEncode (vae, input_frames, input_masks, width, height, num_frames)
256 → WANVIDIMAGE_EMBEDS (vace_embeds)
257 
258WanVideoSampler (model, image_embeds, text_embeds, steps, cfg, shift, scheduler)
259 → LATENT
260 
261WanVideoDecode (vae, samples) → IMAGE → VHS_VideoCombine → MP4
262```
263 
264### WanVideoSampler Settings
265 
266| Parameter | Standard | Lightning | Notes |
267|-----------|----------|-----------|-------|
268| steps | 30 | 4 | |
269| cfg | 6.0 | 1.0 | |
270| shift | 5.0 | 5.0 | Flow matching shift |
271| scheduler | unipc | euler | WanVideoWrapper has own schedulers |
272| force_offload | true | true | Move model to CPU after sampling |
273 
274### When to Use WanVideoWrapper vs Native
275 
276| Feature | Native | WanVideoWrapper |
277|---------|--------|-----------------|
278| Simplicity | Simpler | More complex |
279| Dual Hi-Lo | Manual two-pass | May handle internally |
280| LoRA loading | Lora Loader Stack (rgthree) | WanVideoLoraSelect → WanVideoModelLoader `lora` (see merge_loras caveat) |
281| Caching (TeaCache) | Not available | Built-in |
282| Context windows | Not available | WanVideoContextOptions |
283| Block swap (VRAM) | Not available | WanVideoBlockSwap |
284| VACE conditioning | Not available | Full VACE support |
285| Long video (>81 frames) | Limited | InfiniteTalk / context windows |
286 
287Recommendation: use Native dual hi-lo for standard FLF transitions. Use WanVideoWrapper when you need caching, context windows, VRAM management, or advanced conditioning.
288 
289### ⚠️ CRITICAL: `merge_loras=false` with fp8-scaled models
290 
291When loading a LoRA through `WanVideoLoraSelect``WanVideoModelLoader`'s `lora`
292input on an fp8-quantized model (`quantization=fp8_e4m3fn_scaled`, e.g. the
293official `wan2.2_i2v_high/low_noise_14B_fp8_scaled` weights), you **MUST set the
294`WanVideoLoraSelect` widget `merge_loras=false`.**
295 
296- `merge_loras=true` (the node default) tries to bake the LoRA deltas into the
297 already-quantized fp8 weights. That merge path hard-crashes ComfyUI during
298 LoRA loading. The process dies with no Python traceback (so
299 `panel_get_errors` / the frontend show nothing; only a process restart/OOM-style
300 symptom). This is the #1 cause of a "crashed on lora loading" report with the
301 wrapper.
302- `merge_loras=false` applies the LoRA as a runtime patch during the forward
303 pass instead of merging. It is fp8-safe with negligible speed cost. This is the
304 correct setting for the `lightx2v` 4-step lightning LoRAs (hi + lo) on the fp8
305 hi/lo I2V models.
306- It also pairs cleanly with block swap: `WanVideoBlockSwap` (e.g. 20 to 30 of 40
307 blocks → RAM) + `merge_loras=false` is the verified combo for fp8 14B I2V at
308 720p/81f on a 24GB card. (If you instead use a non-quantized bf16/fp16 model,
309 `merge_loras=true` is fine.)
310 
311Separately, at 720p/81f enable `enable_vae_tiling=true` on `WanVideoDecode`.
312The full-frame decode is the other common uncaught-OOM crash point.
313 
314## Resolution & Frame Count
315 
316### Standard Resolutions
317 
318| Aspect | Resolution | Megapixels |
319|--------|-----------|------------|
320| Portrait 2:3 | 480x720 | 0.35MP (recommended default) |
321| Landscape 16:9 | 832x480 | 0.4MP |
322| Portrait 9:16 | 480x832 | 0.4MP |
323| Square | 640x640 | 0.4MP |
324 
325Width and height must be divisible by 16. Use `ImageResizeKJv2` with `divisible_by: 2` and `keep_proportion: crop`.
326 
327### Frame Count
328 
329- 81 frames at 16fps = ~5 seconds (default, recommended)
330- 49 frames at 16fps = ~3 seconds (faster, less motion)
331- 121 frames at 16fps = ~7.5 seconds (longer, more VRAM)
332- Frame count should be `4n + 1` (1, 5, 9, ..., 49, 81, 121)
333 
334### Frame Rate
335 
336Standard: 16 fps for WAN 2.2 output.
337 
338## Video Output
339 
340### VHS_VideoCombine
341 
342```json
343{
344 "class_type": "VHS_VideoCombine",
345 "inputs": {
346 "images": ["<vae_decode>", 0],
347 "frame_rate": 16,
348 "loop_count": 0,
349 "filename_prefix": "wan_flf",
350 "format": "video/h264-mp4",
351 "pingpong": false,
352 "save_output": true,
353 "pix_fmt": "yuv420p",
354 "crf": 19,
355 "save_metadata": true,
356 "trim_to_audio": false
357 }
358}
359```
360 
361## VRAM Considerations
362 
363### Dual Hi-Lo with Remix fp16
364 
365- Two UNETs loaded sequentially (ComfyUI offloads between passes): ~14GB each
366- NSFW UMT5-XXL bf16: ~8GB (offloaded after text encoding)
367- CLIP Vision H: ~1.5GB (offloaded after encoding)
368- VAE: ~200MB
369- Latent (81 frames at 480x720): ~1-2GB
370 
371ComfyUI manages VRAM by offloading models between passes. The Hi UNET is offloaded before the Lo UNET loads.
372 
373### Tips
374 
3751. Always `clear_vram` before switching to WAN from another model family
3762. Use `VRAM_Debug` node between generation and SeedVR2 upscaling to free all VRAM
3773. For 24GB GPUs, 81 frames at 480x720 is the practical maximum
3784. Remix NSFW models have lightning baked in. No separate LoRA needed, 4 steps total
379 
380## Morph LoRAs (Smooth Metamorphosis)
381 
382By default, FLF produces a transition/dissolve between frames. For true morphing (one shape continuously reshaping into another), use a morph LoRA on both Hi and Lo paths.
383 
384### Magical Morph (Recommended)
385 
386| Variant | File | Strength | Notes |
387|---------|------|----------|-------|
388| HighNoise | `wan2.2_i2v_magical_morph_highnoise.safetensors` | 0.7-1.0 | Apply to Hi Common stack |
389| LowNoise | `wan2.2_i2v_magical_morph_lownoise.safetensors` | 0.7-1.0 | Apply to Lo Common stack |
390 
391- Source: [NikolaSigmoid/wan2.2-i2v-loras-magical-morph](https://huggingface.co/NikolaSigmoid/wan2.2-i2v-loras-magical-morph)
392- No trigger word needed. The LoRA modifies the denoising behavior
393- Strength 1.0 can add visual sparkle/particle effects. Reduce to 0.7-0.8 for cleaner morphs
394- Works with Remix NSFW models (no conflict with built-in lightning)
395 
396### SkinMorph Redmond (Alternative — Face/Body Focus)
397 
398For person-to-person morphs (identity, gender transforms):
399- Trigger word: `Skin morph`
400- Strength: 0.8-1.0
401- Source: [CivitAI](https://civitai.com/models/2210162/wan22-skinmorph-redmond-i2v-14b)
402 
403## Prompt Tips
404 
405Describe the transition motion in addition to the start/end states:
406 
407```
408Good: "A small cat sitting on the ground smoothly transforms and grows into a woman standing tall, seamless transformation, cinematic"
409Bad: "A cat and a girl"
410```
411 
412IMPORTANT: prompt language affects visuals.
413- AVOID words like "magical", "enchanted", "mystical". They cause literal sparkle/particle effects
414- USE clean motion language: "smoothly transforms", "gradually reshapes", "seamlessly morphs", "transitions into"
415- The morph LoRA handles the morphing effect. The prompt should describe motion and form change, not style
416- Include scale/position cues when subjects differ in size: "grows into", "expands upward", "shrinks down"
417 
418## Settings Quick Reference
419 
420| Config | Lightning (Remix) | Standard |
421|--------|------------------|----------|
422| Models | Remix NSFW Hi+Lo fp16 | Official Hi+Lo fp8 |
423| CLIP | nsfw_wan_umt5-xxl_bf16_fixed | umt5_xxl_fp8_e4m3fn_scaled |
424| ModelSamplingSD3 shift | 5 | 8 |
425| Total steps | 4 | 20 |
426| Hi pass end_at_step | 2 | 10 |
427| CFG | 1 | 4 |
428| Sampler | uni_pc | euler |
429| Scheduler | beta | simple |
430| External LoRA needed | No (built-in) | Yes (paired hi/lo) |
431 
432## Multi-Step Pipeline Pattern
433 
434### Anchor Frame Strategy (Proportions)
435 
436When the start and end frames have different subject sizes (e.g., small cat → tall person), generate the "anchor" frame first (the one with the most complex composition), then use Qwen Edit to create the other frame from it. This gives you:
437- Consistent background/scene between frames
438- Correct relative proportions (the edit inherits the scene scale)
439- Better FLF results since both frames share the same visual context
440 
441Example, cat-to-girl morph:
4421. Generate girl standing in front of barn with Z-Image (she fills the frame)
4432. Qwen Edit: "Replace the woman with a small cat sitting at the bottom of the image"
4443. FLF: cat (start) → girl (end). Proportions are correct because the barn establishes scale
445 
446Anti-pattern: generating cat and girl independently produces mismatched scale.
447 
448### Full Pipeline
449 
4501. Generate anchor frame with Z-Image/SDXL/Flux (portrait orientation for standing subjects)
4512. Qwen Edit to create second frame. The edit preserves scene context
4523. Clear VRAM between model families
4534. **Stage both frames as inputs.** When the frames are ComfyUI OUTPUTS from a prior stage (the generated/edited frames above), use `upload_image (action:"stage")` with each output's `{ filename, subfolder?, type? }` and feed the returned input filename into each `LoadImage`. (For a frame already on local disk, use `upload_image (action:"image")`.) NEVER copy the output file into, or guess, a filesystem `input/` path. ComfyUI's input/output dirs may be CUSTOM (`--input-directory` / `--output-directory`), so a guessed path makes `LoadImage` reject the file (`Invalid image file`) and wastes the render. `upload_image (action:"stage")` routes through the server API (`/view``/upload/image`), which resolves the real dirs correctly.
4545. Run dual hi-lo FLF with morph LoRA if morphing is desired
4556. Optionally upscale with SeedVR2 to 1080p
456 
457Proven timing on RTX 4090: Z-Image (35s) → Qwen Edit (78s) → WAN FLF 81 frames (139s) = ~4 minutes total.
458 
459## Working with Saved Workflows
460 
461Use `get_workflow (action:"analyze")` to understand any saved WAN FLF workflow before modifying or executing it. It returns a structured summary with sections, node IDs, key settings, and virtual wire connections. No raw JSON needed.
462 
463```
464get_workflow(action="analyze", filename="Wan FirstLastFrame Advanced.json") # summary view (default)
465get_workflow(action="analyze", filename="Wan FirstLastFrame Advanced.json", view="flat") # mermaid diagram
466```
467 
468Only use `get_workflow` when you need the raw JSON for `enqueue_workflow` or `create_workflow (action:"modify")`.
469 
470## Sources
471 
472- **Official:** none found.
473- **Empirical:** sampler values, wiring, and prompt notes from working graphs in `packs/` and observed renders; not a vendor prompting guide.
474 

Discussion

Alternatives

Also in Video production