SCAIL-2 (Wan 2.1 14B): the character or characters in a reference image replace the people in a driving clip, or perform its motion on a new background. SAM 3.1 tracks every person in both, and each identity is painted one colour in both masks, so several characters bind to several performers in left-to-right order. One segment of the ComfyUI SCAIL-2 character-replacement template (Base subgraph) on its non-turbo schedule, with the DPO and relight LoRAs as toggles.
Tags: motionscail-2wan2.1character-replacementperformance-transfermulti-characterrunpod-serverlessvolume-backed
Inputs (20)#
The typed parameter surface callers bind when they request this workflow. Enum options and numeric bounds are the values the workflow document declares.
reference_imageimagerequireddriving_videovideorequiredpromptstringrequireddefault The character from the reference image dances in the scene of the driving video, natural lighting, cinematic.negative_promptstringdefault modeenumdefault replacementreplacementanimationdriving_subjectstringdefault humanreference_subjectstringdefault humancharacter_indicesstringdefault identity_orderenumdefault left_to_rightnoneleft_to_rightareamax_charactersintegerdefault 4min 1max 64dpo_lorabooleandefault truerelight_lorabooleandefault falseresolutionenumdefault 896x512896x512512x896832x480480x832lengthintegerdefault 33min 5max 81stepsintegerdefault 40min 1max 40cfgfloatdefault 5.0min 1.0max 20.0pose_strengthfloatdefault 1.0min 0.0max 10.0pose_startfloatdefault 0.0min 0.0max 1.0pose_endfloatdefault 1.0min 0.0max 1.0seedintegerdefault 0min 0ComfyUI node graph (29)#
The executable ComfyUI prompt graph: 29 nodes across 24 distinct node classes, wired by 43 data dependencies. Nodes tinted green come from a custom node pack this workflow declares; the rest are ComfyUI core / baked-community classes.
Nodes (29)#
1UNETLoadercoreunet_name = wan2.1_14B_SCAIL_2_fp16.safetensorsweight_dtype = defaultMODEL2LoraLoaderModelOnlycoremodel = ◂ node 1 · out[0]lora_name = wan2.1_SCAIL_2_DPO_lora_bf16.safetensorsstrength_model = 1.0MODEL3LoraLoaderModelOnlycoremodel = ◂ node 2 · out[0]lora_name = wan2.1_SCAIL_2_relight_lora_bf16.safetensorsstrength_model = 1.0MODEL4ModelSamplingSD3coremodel = ◂ node 3 · out[0]shift = 5MODEL5CLIPLoadercoreclip_name = umt5_xxl_fp16.safetensorstype = wandevice = defaultCLIP6CLIPTextEncodecoreclip = ◂ node 5 · out[0]text = {{prompt}} tmplCONDITIONING7CLIPTextEncodecoreclip = ◂ node 5 · out[0]text = {{negative_prompt}} tmplCONDITIONING8VAELoadercorevae_name = wan_2.1_vae.safetensorsVAE9CLIPVisionLoadercoreclip_name = clip_vision_h.safetensorsCLIP_VISION10LoadImagecoreimage = {{reference_image}} tmplIMAGEMASK11CLIPVisionEncodecoreclip_vision = ◂ node 9 · out[0]image = ◂ node 10 · out[0]crop = noneCLIP_VISION_OUTPUT12LoadVideocorefile = {{driving_video}} tmplVIDEO13GetVideoComponentscorevideo = ◂ node 12 · out[0]IMAGEAUDIOFLOATCOMBOCOMBO14ImageFromBatchcoreimage = ◂ node 13 · out[0]batch_index = 0length = {{length}} tmplIMAGE15ResizeImageMaskNodecoreinput = ◂ node 14 · out[0]resize_type = scale dimensionsresize_type.width = {{resolution_map[resolution].width}} tmplresize_type.height = {{resolution_map[resolution].height}} tmplresize_type.crop = centerscale_method = areaIMAGE16GetImageSizecoreimage = ◂ node 15 · out[0]INTINTINT17CheckpointLoaderSimplecoreckpt_name = sam3.1_multiplex_fp16.safetensorsMODELCLIPVAE18CLIPTextEncodecoreclip = ◂ node 17 · out[1]text = {{driving_subject}} tmplCONDITIONING19SAM3_VideoTrackcoreimages = ◂ node 15 · out[0]model = ◂ node 17 · out[0]conditioning = ◂ node 18 · out[0]detection_threshold = 0.5max_objects = {{max_characters}} tmpldetect_interval = 1SAM3_TRACK_DATA20CLIPTextEncodecoreclip = ◂ node 17 · out[1]text = {{reference_subject}} tmplCONDITIONING21SAM3_VideoTrackcoreimages = ◂ node 10 · out[0]model = ◂ node 17 · out[0]conditioning = ◂ node 20 · out[0]detection_threshold = 0.5max_objects = {{max_characters}} tmpldetect_interval = 1SAM3_TRACK_DATA22SCAIL2ColoredMaskcoredriving_track_data = ◂ node 19 · out[0]ref_track_data = ◂ node 21 · out[0]object_indices = {{character_indices}} tmplsort_by = {{identity_order}} tmplreplacement_mode = {{mode == 'replacement'}} tmplIMAGEIMAGE23WanSCAILToVideocorepositive = ◂ node 6 · out[0]negative = ◂ node 7 · out[0]vae = ◂ node 8 · out[0]pose_video = ◂ node 15 · out[0]pose_video_mask = ◂ node 22 · out[0]reference_image = ◂ node 10 · out[0]reference_image_mask = ◂ node 22 · out[1]clip_vision_output = ◂ node 11 · out[0]width = {{resolution_map[resolution].width}} tmplheight = {{resolution_map[resolution].height}} tmpllength = ◂ node 16 · out[2]batch_size = 1pose_strength = {{pose_strength}} tmplpose_start = {{pose_start}} tmplpose_end = {{pose_end}} tmplvideo_frame_offset = 0previous_frame_count = 5replacement_mode = {{mode == 'replacement'}} tmplCONDITIONINGCONDITIONINGLATENTINT24KSamplerSelectcoresampler_name = eulerSAMPLER25BasicSchedulercoremodel = ◂ node 3 · out[0]scheduler = simplesteps = {{steps}} tmpldenoise = 1.0SIGMAS26SamplerCustomcoremodel = ◂ node 4 · out[0]add_noise = truenoise_seed = {{seed}} tmplcfg = {{cfg}} tmplpositive = ◂ node 23 · out[0]negative = ◂ node 23 · out[1]sampler = ◂ node 24 · out[0]sigmas = ◂ node 25 · out[0]latent_image = ◂ node 23 · out[2]LATENTLATENT27VAEDecodecoresamples = ◂ node 26 · out[1]vae = ◂ node 8 · out[0]IMAGE28CreateVideocoreimages = ◂ node 27 · out[0]audio = ◂ node 13 · out[1]fps = ◂ node 13 · out[2]VIDEO29SaveVideocorevideo = ◂ node 28 · out[0]filename_prefix = scail2-animateformat = mp4Parameter banks (2)#
The prompt / configuration lookup tables this workflow keys into from its inputs — the vocabulary that turns a style / palette / preset selection into graph parameters.
resolution_map (4)#
896x512{"width": 896, "height": 512}512x896{"width": 512, "height": 896}832x480{"width": 832, "height": 480}480x832{"width": 480, "height": 832}requires_families (1)#
scail2Models & dependencies#
Models required (7)#
wan2.1_14B_SCAIL_2_fp16.safetensorswan2.1_SCAIL_2_DPO_lora_bf16.safetensorswan2.1_SCAIL_2_relight_lora_bf16.safetensorsumt5_xxl_fp16.safetensorswan_2.1_vae.safetensorsclip_vision_h.safetensorssam3.1_multiplex_fp16.safetensorsOutput contract#
What a successful run of this workflow returns.
primary{"type": "video", "format": "mp4", "codec": "h264", "fps_source": "source", "audio": true, "alpha": false, "description": "The reference characters in the driving performance, at the driving clip's frame rate with its audio track when it has one."}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.
assetFamilyanim-character-turnaround-packoutputPackageProfilevideo-master-profilecontrolModalitiesmodel-lockprompt-template-locksampler-scheduler-lockseed-lockidentity-lockpose-constraintcontrolnet-segmentationtemporal-lockreference-ensembleconsistencyDimensionsidentitymotionlightingwardrobenotesSCAIL-2 (A.02.06). controlnet-segmentation is literal: SAM 3.1 tracks every person in the driving clip and the reference, and SCAIL2ColoredMask paints each identity one colour in both, which binds reference characters to driving performers (reference-ensemble when there are several). lighting is a real dimension only with the relight LoRA on.