Generated reference · ComfyUI workflow · motion

Wan 2.2 Image-to-Video

Wan2.2 I2V A14B: animate a supplied still. Same two-expert schedule as the T2V graph, with one structural difference taken from ComfyUI 0.34.0's own video_wan2_2_14B_i2v template — WanImageToVideo produces the positive, negative AND latent …

motion17nodesGPU H100out video~120sv1.0.0

On this page

Wan2.2 I2V A14B: animate a supplied still. Same two-expert schedule as the T2V graph, with one structural difference taken from ComfyUI 0.34.0's own video_wan2_2_14B_i2v template — WanImageToVideo produces the positive, negative AND latent that both samplers consume, so the start image conditions the clip rather than merely seeding it. That template leaves clip_vision_output UNLINKED, so no CLIP-vision tower is loaded here. Defaults are the template's: euler/simple, shift 5.0, 20 steps split at 10, CFG 3.5, 81 frames at 16 fps.

17Graph nodes
13Node classes
18Inputs
22Models

Tags: motionwan2.2image-to-videorunpod-serverlessvolume-backed

Inputs (18)#

The typed parameter surface callers bind when they request this workflow. Enum options and numeric bounds are the values the workflow document declares.

start_imageimagerequired
The still to animate. Its aspect should match the chosen resolution; Wan does not letterbox, it stretches.
end_imageimage
Optional final frame. Supplying one switches the graph to WanFirstLastFrameToVideo, which interpolates between the two stills instead of animating forward from one. EXPERIMENTAL: proved offline against ComfyUI's node signature, never rendered on a GPU.
promptstringrequireddefault the paper boat rocks and drifts forward, water rippling around it
What should HAPPEN in the clip. For image-to-video, describe the motion rather than the scene — the scene is already in the image.
negative_promptstringdefault 色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走
Wan's own published default negative prompt (Chinese, as shipped). Replacing it with an English translation measurably weakens it — the model was trained with this text.
seedintegerdefault -1
Random seed (-1 = random). Both experts share it.
resolutionenumdefault 480p_landscape_832x480
Frame size. 720p costs roughly 2.4x a 480p clip of the same length. The two match_image_aspect_* values derive width and height from the supplied start image instead, scaling its SHORT side to 480 or 720 and snapping both to a multiple of 16 — Wan does not letterbox, it stretches, so a mismatched canvas distorts the still.
options: 480p_landscape_832x480480p_portrait_480x832720p_landscape_1280x720720p_portrait_720x1280square_624x624match_image_aspect_480pmatch_image_aspect_720p
lengthintegerdefault 81min 5max 121
Frames, and it must be 4n+1 — Wan's temporal compression plus the first frame. At 16 fps the default 81 is about 5 seconds. The executor refuses anything else before billing (motion-caps.ts).
fpsintegerdefault 16min 8max 30
Frame rate written into the container. Wan 2.2 was trained at 16 fps; a higher number here plays the same frames faster, it does not generate more.
stepsintegerdefault 20min 4max 40
Total sampling steps across BOTH experts. Overridden by speed_mode=lightx2v_4step, which forces 4.
boundary_ratiofloatdefault 0.5min 0.1max 0.9
Where the high-noise expert hands over to the low-noise one, as a fraction of steps. The template splits 20 at 10 and 4 at 2 — both 0.5.
cfgfloatdefault 3.5min 1.0max 10.0
Classifier-free guidance, applied to both experts. Overridden by speed_mode=lightx2v_4step, which forces 1.0.
shiftfloatdefault 5.0min 1.0max 12.0
ModelSamplingSD3 flow shift on both experts. 5.0 is the template value.
speed_modeenumdefault quality
lightx2v_4step splices the I2V 4-step distilled LoRA onto BOTH experts and forces the template's lightning schedule (4 steps, split at 2, CFG 1.0), overriding steps/cfg/boundary_ratio. Note the I2V LoRAs are v1 files, not the v1.1 the T2V graph uses — that is what Comfy-Org publishes.
options: qualitylightx2v_4step
samplerenumdefault euler
Sampler for both experts
options: euleruni_pcdpmpp_2m
schedulerenumdefault simple
Sigma schedule for both experts
options: simplebeta
motion_presetenumdefault none
A documented phrase appended to the prompt (motion_map); `none` appends nothing at all. This is prompt guidance and nothing more — there is no camera control in this graph, and the model may ignore it.
options: nonestatic cameraslow push inorbit lefthandhelddolly out
loraenumdefault none
Optional Wan 2.2 LoRA pair (A.03.03/A.03.04). Wan 2.2 A14B is two experts, so every entry is two Civitai files: its high-noise file loads on the high-noise expert and its low-noise file on the low-noise expert, both at lora_strength, and an entry missing either file is refused at render rather than loaded by halves. Only pairs whose Civitai versions name Wan Video 2.2 I2V-A14B as their base are offered here. camera-tiltdown-undershot-v2 = the camera descends while tilting up to a low angle; camera-tiltup-overhead-v1.1 = the camera travels forward and rises to an overhead view; hip-sway-type1 = hip sway; hip-bump-dance = hip bump dance. Trigger phrases are NOT appended: each entry's phrases, as its Civitai versions list them in trainedWords, are in option_details (optionDetails in the catalog listing), and the prompt should use the one that fits the subject. Every pair rendered one live clip on 2026-09-14 (A.05.02; see proof_note). none adds no loader.
options: nonecamera-tiltdown-undershot-v2camera-tiltup-overhead-v1.1hip-sway-type1hip-bump-dancensfw-posing-nude-v2bouncing-boobs-wan22twerking-i2vslow-twerk
lora_strengthfloatdefault 1min -2max 2
LoRA strength on BOTH experts (LoraLoaderModelOnly.strength_model on the high-noise and the low-noise half alike). A slider LoRA is meant to be driven negative as well as positive; the motion LoRAs sit at 1.0.

ComfyUI node graph (17)#

The executable ComfyUI prompt graph: 17 nodes across 13 distinct node classes, wired by 22 data dependencies. Nodes tinted green come from a custom node pack this workflow declares; the rest are ComfyUI core / baked-community classes.

flowchart TD n0["1: UNETLoader"] n1["2: UNETLoader"] n2["3: CLIPLoader"] n3["4: VAELoader"] n4["5: ModelSamplingSD3"] n5["6: ModelSamplingSD3"] n6["7: CLIPTextEncode"] n7["8: CLIPTextEncode"] n8["9: LoadImage"] n9["10: KSamplerAdvanced"] n10["11: KSamplerAdvanced"] n11["12: VAEDecode"] n12["13: CreateVideo"] n13["14: SaveVideo"] n14["15: ImageFromBatch"] n15["16: SaveImage"] n16["17: WanImageToVideo"] n0 -->|model| n4 n1 -->|model| n5 n2 -->|clip| n6 n2 -->|clip| n7 n4 -->|model| n9 n16 -->|positive| n9 n16 -->|negative| n9 n16 -->|latent_image| n9 n5 -->|model| n10 n16 -->|positive| n10 n16 -->|negative| n10 n9 -->|latent_image| n10 n10 -->|samples| n11 n3 -->|vae| n11 n11 -->|images| n12 n12 -->|video| n13 n11 -->|image| n14 n14 -->|images| n15 n6 -->|positive| n16 n7 -->|negative| n16 n3 -->|vae| n16 n8 -->|start_image| n16
Data-flow DAG — scroll to zoom, drag to pan.

Nodes (17)#

1UNETLoadercore
unet_name = wan2.2_i2v_high_noise_14B_fp16.safetensorsweight_dtype = default
outputs: MODEL
2UNETLoadercore
unet_name = wan2.2_i2v_low_noise_14B_fp16.safetensorsweight_dtype = default
outputs: MODEL
3CLIPLoadercore
clip_name = umt5_xxl_fp16.safetensorstype = wandevice = default
outputs: CLIP
4VAELoadercore
vae_name = wan_2.1_vae.safetensors
outputs: VAE
5ModelSamplingSD3core
model = ◂ node 1 · out[0]shift = {{shift}} tmpl
outputs: MODEL
6ModelSamplingSD3core
model = ◂ node 2 · out[0]shift = {{shift}} tmpl
outputs: MODEL
7CLIPTextEncodecore
text = {{constructed_prompt}} tmplclip = ◂ node 3 · out[0]
outputs: CONDITIONING
8CLIPTextEncodecore
text = {{negative_prompt}} tmplclip = ◂ node 3 · out[0]
outputs: CONDITIONING
9LoadImagecore
image = {{start_image}} tmpl
outputs: IMAGEMASK
10KSamplerAdvancedcore
model = ◂ node 5 · out[0]positive = ◂ node 17 · out[0]negative = ◂ node 17 · out[1]latent_image = ◂ node 17 · out[2]add_noise = enablenoise_seed = {{seed}} tmplsteps = {{steps}} tmplcfg = {{cfg}} tmplsampler_name = {{sampler}} tmplscheduler = {{scheduler}} tmplstart_at_step = 0end_at_step = {{int(round(steps * boundary_ratio))}} tmplreturn_with_leftover_noise = enable
outputs: LATENT
11KSamplerAdvancedcore
model = ◂ node 6 · out[0]positive = ◂ node 17 · out[0]negative = ◂ node 17 · out[1]latent_image = ◂ node 10 · out[0]add_noise = disablenoise_seed = {{seed}} tmplsteps = {{steps}} tmplcfg = {{cfg}} tmplsampler_name = {{sampler}} tmplscheduler = {{scheduler}} tmplstart_at_step = {{int(round(steps * boundary_ratio))}} tmplend_at_step = {{steps}} tmplreturn_with_leftover_noise = disable
outputs: LATENT
12VAEDecodecore
samples = ◂ node 11 · out[0]vae = ◂ node 4 · out[0]
outputs: IMAGE
13CreateVideocore
images = ◂ node 12 · out[0]fps = {{fps}} tmpl
outputs: VIDEO
14SaveVideocore
video = ◂ node 13 · out[0]filename_prefix = wan22-i2vformat = mp4codec = h264
15ImageFromBatchcore
image = ◂ node 12 · out[0]batch_index = {{length - 1}} tmpllength = 1
outputs: IMAGE
16SaveImagecore
images = ◂ node 15 · out[0]filename_prefix = wan22-i2v-lastframe
17WanImageToVideocore
positive = ◂ node 7 · out[0]negative = ◂ node 8 · out[0]vae = ◂ node 4 · out[0]start_image = ◂ node 9 · out[0]width = {{resolution_map[resolution].width}} tmplheight = {{resolution_map[resolution].height}} tmpllength = {{length}} tmplbatch_size = 1
outputs: CONDITIONINGCONDITIONINGLATENT

Prompt construction#

template
{base_prompt}{motion}

Variables (2)#

base_prompt
{{prompt}} tmpl
motion
{{motion_map[motion_preset]}} tmpl

Parameter banks (7)#

The prompt / configuration lookup tables this workflow keys into from its inputs — the vocabulary that turns a style / palette / preset selection into graph parameters.

option_policy (1)#

lora
{"camera-tiltdown-undershot-v2": {"distribution": "service", "content": "neutral"}, "camera-tiltup-overhead-v1.1": {"distribution": "service", "content": "neutral"}, "hip-sway-type1": {"distribution": "service", "content": "racy"}, "hip-bump-dance": {"distribution": "service", "content": "racy"}, "nsfw-posing-nude-v2": {"distribution": "internal_only", "content": "explicit"}, "bouncing-boobs-wan22": {"distribution": "internal_only", "content": "explicit"}, "twerking-i2v": {"distribution": "internal_only", "content": "explicit"}, "slow-twerk": {"distribution": "internal_only", "content": "explicit"}}

resolution_map (7)#

480p_landscape_832x480
{"width": 832, "height": 480}
480p_portrait_480x832
{"width": 480, "height": 832}
720p_landscape_1280x720
{"width": 1280, "height": 720}
720p_portrait_720x1280
{"width": 720, "height": 1280}
square_624x624
{"width": 624, "height": 624}
match_image_aspect_480p
{"width": 832, "height": 480}
match_image_aspect_720p
{"width": 1280, "height": 720}

requires_families (2)#

wan22-i2vwan-shared

motion_map (6)#

none
static camera
, static camera
slow push in
, slow push in
orbit left
, camera orbits left
handheld
, handheld camera
dolly out
, camera dollies out

lora_pair_map (8)#

camera-tiltdown-undershot-v2
{"high": "wan22-camera-tiltdown-undershot-v2-high.safetensors", "low": "wan22-camera-tiltdown-undershot-v2-low.safetensors"}
camera-tiltup-overhead-v1.1
{"high": "wan22-camera-tiltup-overhead-v1.1-high.safetensors", "low": "wan22-camera-tiltup-overhead-v1.1-low.safetensors"}
hip-sway-type1
{"high": "wan22-hip-sway-type1-high.safetensors", "low": "wan22-hip-sway-type1-low.safetensors"}
hip-bump-dance
{"high": "wan22-hip-bump-dance-high.safetensors", "low": "wan22-hip-bump-dance-low.safetensors"}
nsfw-posing-nude-v2
{"high": "wan22-nsfw-posing-nude-v2-high.safetensors", "low": "wan22-nsfw-posing-nude-v2-low.safetensors"}
bouncing-boobs-wan22
{"high": "wan22-bouncing-boobs-wan22-high.safetensors", "low": "wan22-bouncing-boobs-wan22-low.safetensors"}
twerking-i2v
{"high": "wan22-twerking-i2v-high.safetensors", "low": "wan22-twerking-i2v-low.safetensors"}
slow-twerk
{"high": "wan22-slow-twerk-high.safetensors", "low": "wan22-slow-twerk-low.safetensors"}

post_render (3)#

wan_lora_pair
{"input": "lora", "strength_input": "lora_strength", "pair_map": "lora_pair_map", "none_value": "none"}
wan_speed_mode
{"input": "speed_mode", "fast_value": "lightx2v_4step", "lora_high": "wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors", "lora_low": "wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors", "steps": 4, "split": 2, "cfg": 1.0, "strength": 1.0}
wan_first_last_frame
{"input": "end_image", "node_class": "WanImageToVideo", "swap_to": "WanFirstLastFrameToVideo"}

submission (1)#

fit_to_image
{"input": "resolution", "image_input": "start_image", "match_values": {"match_image_aspect_480p": 480, "match_image_aspect_720p": 720}, "node_classes": ["WanImageToVideo", "WanFirstLastFrameToVideo"], "multiple_of": 16, "_comment": "The resolution_map entries for these two values are the tier's landscape default and are only what the template renders before this transform overwrites them; the real numbers come from the image."}

Models & dependencies#

Models required (22)#

wan2.2_i2v_high_noise_14B_fp16.safetensors
wan2.2_i2v_low_noise_14B_fp16.safetensors
umt5_xxl_fp16.safetensors
wan_2.1_vae.safetensors
wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors
wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors
wan22-camera-tiltdown-undershot-v2-high.safetensors
wan22-camera-tiltdown-undershot-v2-low.safetensors
wan22-camera-tiltup-overhead-v1.1-high.safetensors
wan22-camera-tiltup-overhead-v1.1-low.safetensors
wan22-hip-sway-type1-high.safetensors
wan22-hip-sway-type1-low.safetensors
wan22-hip-bump-dance-high.safetensors
wan22-hip-bump-dance-low.safetensors
wan22-nsfw-posing-nude-v2-high.safetensors
wan22-nsfw-posing-nude-v2-low.safetensors
wan22-bouncing-boobs-wan22-high.safetensors
wan22-bouncing-boobs-wan22-low.safetensors
wan22-twerking-i2v-high.safetensors
wan22-twerking-i2v-low.safetensors
wan22-slow-twerk-high.safetensors
wan22-slow-twerk-low.safetensors

Output contract#

What a successful run of this workflow returns.

type
video
format
mp4
codec
h264
fps_source
fixed
audio
false
alpha
false
expected_dimensions
{"width": "{{resolution_map[resolution].width}}", "height": "{{resolution_map[resolution].height}}", "frames": "{{length}}"}

Taxonomy & routing#

How the control plane classifies this workflow — from the committed workflow-taxonomy-registry.json. It drives the consistency / control surface the agentic director can exercise over the workflow.

assetFamily
keyframe-anchored-motion
outputPackageProfile
video-master-profile
controlModalities
model-locksampler-scheduler-lockseed-lockprompt-template-lockkeyframe-anchor-lockmotion-vector-locktemporal-lock
consistencyDimensions
motionidentitylightingenvironment
notes
Wan2.2 I2V A14B. keyframe-anchor-lock is real here and not in the T2V graph: the start image is carried through WanImageToVideo into both experts' conditioning, so it anchors the clip rather than only seeding it.