From dcae850b96a34fa0cf6490e607c7a0bf7afe2b79 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Wed, 24 Dec 2025 17:07:59 +0200 Subject: [PATCH 01/22] Allow higher lora scale --- nodes_model_loading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes_model_loading.py b/nodes_model_loading.py index e7c95e6..b8aa419 100644 --- a/nodes_model_loading.py +++ b/nodes_model_loading.py @@ -364,7 +364,7 @@ class WanVideoLoraSelect: "required": { "lora": (folder_paths.get_filename_list("loras"), {"tooltip": "LORA models are expected to be in ComfyUI/models/loras with .safetensors extension"}), - "strength": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.0001, "tooltip": "LORA strength, set to 0.0 to unmerge the LORA"}), + "strength": ("FLOAT", {"default": 1.0, "min": -1000.0, "max": 1000.0, "step": 0.0001, "tooltip": "LORA strength, set to 0.0 to unmerge the LORA"}), }, "optional": { "prev_lora":("WANVIDLORA", {"default": None, "tooltip": "For loading multiple LoRAs"}), From c42bf94b07f67bb67eea724638ea9c3c7956c207 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Wed, 24 Dec 2025 17:58:30 +0200 Subject: [PATCH 02/22] Automatically adjust LoRA alpha for Peft rs_lora weights At least the original StoryMem -LoRAs need this --- nodes_model_loading.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/nodes_model_loading.py b/nodes_model_loading.py index b8aa419..f669f99 100644 --- a/nodes_model_loading.py +++ b/nodes_model_loading.py @@ -178,7 +178,7 @@ def standardize_lora_key_format(lora_sd): new_key += f".{component}" - # Handle weight type - this is the critical fix + # Handle weight type if weight_type: if weight_type == 'alpha': new_key += '.alpha' @@ -209,12 +209,12 @@ def standardize_lora_key_format(lora_sd): new_key = new_key.replace('time_embedding', 'time.embedding') new_key = new_key.replace('time_projection', 'time.projection') - # Replace remaining underscores with dots, carefully + # Replace remaining underscores with dots parts = new_key.split('.') final_parts = [] for part in parts: if part in ['img_emb', 'self_attn', 'cross_attn']: - final_parts.append(part) # Keep these intact + final_parts.append(part) else: final_parts.append(part.replace('_', '.')) new_key = '.'.join(final_parts) @@ -274,6 +274,20 @@ def standardize_lora_key_format(lora_sd): new_sd[k] = v return new_sd +def compensate_rs_lora_format(lora_sd): + rank = lora_sd["base_model.model.blocks.0.cross_attn.k.lora_A.weight"].shape[0] + alpha = torch.tensor(2 * 128 * rank ** 0.5) + log.info(f"Detected rank stabilized peft lora format with rank {rank}, setting alpha to {alpha} to compensate.") + new_sd = {} + for k, v in lora_sd.items(): + if k.endswith(".lora_A.weight"): + new_sd[k] = v + new_k = k.replace(".lora_A.weight", ".alpha") + new_sd[new_k] = alpha + else: + new_sd[k] = v + return new_sd + class WanVideoBlockSwap: @classmethod def INPUT_TYPES(s): @@ -756,6 +770,8 @@ class WanVideoSetLoRAs: lora_sd = load_torch_file(lora_path, safe_load=True) if "dwpose_embedding.0.weight" in lora_sd: #unianimate raise NotImplementedError("Unianimate LoRA patching is not implemented in this node.") + if "base_model.model.blocks.0.cross_attn.k.lora_A.weight" in lora_sd: # assume rs_lora + lora_sd = compensate_rs_lora_format(lora_sd) lora_sd = standardize_lora_key_format(lora_sd) if l["blocks"]: @@ -967,7 +983,8 @@ def add_lora_weights(patcher, lora, base_dtype, merge_loras=False): from .unianimate.nodes import update_transformer log.info("Unianimate LoRA detected, patching model...") patcher.model.diffusion_model, unianimate_sd = update_transformer(patcher.model.diffusion_model, lora_sd) - + if "base_model.model.blocks.0.cross_attn.k.lora_A.weight" in lora_sd: # assume rs_lora + lora_sd = compensate_rs_lora_format(lora_sd) lora_sd = standardize_lora_key_format(lora_sd) if l["blocks"]: From 95255c7ffa29d90af6b0597b10d59a7946618b61 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Wed, 24 Dec 2025 18:44:05 +0200 Subject: [PATCH 03/22] Add node to add story memory latents --- nodes.py | 23 +++++++++++++++++++++++ nodes_sampler.py | 18 ++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/nodes.py b/nodes.py index 0c78f44..8ca9031 100644 --- a/nodes.py +++ b/nodes.py @@ -888,6 +888,27 @@ class WanVideoAddMTVMotion: updated["mtv_crafter_motion"] = new_entry return (updated,) +class WanVideoAddStoryMemLatents: + @classmethod + def INPUT_TYPES(s): + return {"required": { + "embeds": ("WANVIDIMAGE_EMBEDS",), + "memory_latents": ("LATENT",), + } + } + + RETURN_TYPES = ("WANVIDIMAGE_EMBEDS",) + RETURN_NAMES = ("image_embeds",) + FUNCTION = "add" + CATEGORY = "WanVideoWrapper" + + def add(self, embeds, memory_latents): + updated = dict(embeds) + samples = memory_latents["samples"][0] + updated["story_mem_latents"] = samples + + return (updated,) + #region I2V encode class WanVideoImageToVideoEncode: @classmethod @@ -2255,6 +2276,7 @@ NODE_CLASS_MAPPINGS = { "TextImageEncodeQwenVL": TextImageEncodeQwenVL, "WanVideoUniLumosEmbeds": WanVideoUniLumosEmbeds, "WanVideoAddTTMLatents": WanVideoAddTTMLatents, + "WanVideoAddStoryMemLatents": WanVideoAddStoryMemLatents, } NODE_DISPLAY_NAME_MAPPINGS = { @@ -2296,4 +2318,5 @@ NODE_DISPLAY_NAME_MAPPINGS = { "WanVideoAddBindweaveEmbeds": "WanVideo Add Bindweave Embeds", "WanVideoUniLumosEmbeds": "WanVideo UniLumos Embeds", "WanVideoAddTTMLatents": "WanVideo Add TTMLatents", + "WanVideoAddStoryMemLatents": "WanVideo Add StoryMem Latents", } diff --git a/nodes_sampler.py b/nodes_sampler.py index a1ec60f..40c16a8 100644 --- a/nodes_sampler.py +++ b/nodes_sampler.py @@ -301,14 +301,20 @@ class WanVideoSampler: has_ref = image_embeds.get("has_ref", False) #I2V + story_mem_latents = image_embeds.get("story_mem_latents", None) image_cond = image_embeds.get("image_embeds", None) if image_cond is not None: if transformer.in_dim == 16: raise ValueError("T2V (text to video) model detected, encoded images only work with I2V (Image to video) models") elif transformer.in_dim not in [48, 32]: # fun 2.1 models don't use the mask image_cond_mask = image_embeds.get("mask", None) - if image_cond_mask is not None: - image_cond = torch.cat([image_cond_mask, image_cond]) + # StoryMem + if story_mem_latents is not None: + image_cond = torch.cat([story_mem_latents.to(image_cond), image_cond], dim=1) + image_cond_mask = torch.cat([torch.ones_like(story_mem_latents)[:4], image_cond_mask], dim=1) if image_cond_mask is not None else None + + if image_cond_mask is not None: + image_cond = torch.cat([image_cond_mask, image_cond]) else: image_cond[:, 1:] = 0 @@ -336,10 +342,12 @@ class WanVideoSampler: end_image = image_embeds.get("end_image", None) fun_or_fl2v_model = image_embeds.get("fun_or_fl2v_model", False) - + latent_frames = (image_embeds["num_frames"] - 1) // 4 + latent_frames = latent_frames + (2 if end_image is not None and not fun_or_fl2v_model else 1) + latent_frames = latent_frames + story_mem_latents.shape[1] if story_mem_latents is not None else latent_frames noise = torch.randn( #C, T, H, W 48 if is_5b else 16, - (image_embeds["num_frames"] - 1) // 4 + (2 if end_image is not None and not fun_or_fl2v_model else 1), + latent_frames, image_embeds["lat_h"], image_embeds["lat_w"], dtype=torch.float32, @@ -3248,6 +3256,8 @@ class WanVideoSampler: latent = latent[:,:-humo_reference_count] if longcat_ref_latent is not None: latent = latent[:, longcat_ref_latent.shape[1]:] + if story_mem_latents is not None: + latent = latent[:, story_mem_latents.shape[1]:] cache_states = None if cache_args is not None: From f988d19fdbc1582678255cce3ebb5bd40aa8014b Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Thu, 25 Dec 2025 20:44:37 +0200 Subject: [PATCH 04/22] StoryMem latents are supposed to be encoded one by one --- nodes.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nodes.py b/nodes.py index 8ca9031..d754566 100644 --- a/nodes.py +++ b/nodes.py @@ -892,8 +892,9 @@ class WanVideoAddStoryMemLatents: @classmethod def INPUT_TYPES(s): return {"required": { + "vae": ("WANVAE",), "embeds": ("WANVIDIMAGE_EMBEDS",), - "memory_latents": ("LATENT",), + "memory_images": ("IMAGE",), } } @@ -902,11 +903,10 @@ class WanVideoAddStoryMemLatents: FUNCTION = "add" CATEGORY = "WanVideoWrapper" - def add(self, embeds, memory_latents): + def add(self, vae, embeds, memory_images): updated = dict(embeds) - samples = memory_latents["samples"][0] - updated["story_mem_latents"] = samples - + story_mem_latents, = WanVideoEncodeLatentBatch().encode(vae, memory_images) + updated["story_mem_latents"] = story_mem_latents["samples"].squeeze(2).permute(1, 0, 2, 3) # [C, T, H, W] return (updated,) #region I2V encode @@ -2143,7 +2143,7 @@ class WanVideoEncodeLatentBatch: CATEGORY = "WanVideoWrapper" DESCRIPTION = "Encodes a batch of images individually to create a latent video batch where each video is a single frame, useful for I2V init purposes, for example as multiple context window inits" - def encode(self, vae, images, enable_vae_tiling, tile_x, tile_y, tile_stride_x, tile_stride_y, latent_strength=1.0): + def encode(self, vae, images, enable_vae_tiling=False, tile_x=272, tile_y=272, tile_stride_x=144, tile_stride_y=128, latent_strength=1.0): vae.to(device) images = images.clone() From 264212dddbc0c2d3b28474d15035e0182f6524e4 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:27:48 +0200 Subject: [PATCH 05/22] Fix uncond variable name when using zero star or fresca --- nodes_sampler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nodes_sampler.py b/nodes_sampler.py index 40c16a8..1adcc22 100644 --- a/nodes_sampler.py +++ b/nodes_sampler.py @@ -1742,7 +1742,7 @@ class WanVideoSampler: base_params['y'] = [image_cond_input] * 2 if image_cond_input is not None else None base_params['clip_fea'] = torch.cat([clip_fea, clip_fea], dim=0) cache_state_uncond = None - [noise_pred_cond, noise_pred_uncond], _, cache_state_cond = transformer( + [noise_pred_cond, noise_pred_uncond_text], _, cache_state_cond = transformer( context=positive_embeds + negative_embeds, is_uncond=False, pred_id=cache_state[0] if cache_state else None, **base_params @@ -1759,7 +1759,7 @@ class WanVideoSampler: if use_cfg_zero_star: alpha = optimized_scale( noise_pred_cond.view(batch_size, -1), - noise_pred_uncond.view(batch_size, -1) + noise_pred_uncond_text.view(batch_size, -1) ).view(batch_size, 1, 1, 1) noise_pred_uncond_text = noise_pred_uncond_text * alpha @@ -1774,7 +1774,7 @@ class WanVideoSampler: #https://github.com/WikiChao/FreSca if use_fresca: - filtered_cond = fourier_filter(noise_pred_cond - noise_pred_uncond, fresca_scale_low, fresca_scale_high, fresca_freq_cutoff) + filtered_cond = fourier_filter(noise_pred_cond - noise_pred_uncond_text, fresca_scale_low, fresca_scale_high, fresca_freq_cutoff) noise_pred = noise_pred_uncond_text + cfg_scale * filtered_cond * alpha else: noise_pred = noise_pred_uncond_text + cfg_scale * (noise_pred_cond - noise_pred_uncond_text) From 74f337e06cebb1c5ed8acbccac4e871cdf30d19e Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:41:32 +0200 Subject: [PATCH 06/22] Adjust StoryMem lora scaling This was probably too high afterall --- nodes_model_loading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes_model_loading.py b/nodes_model_loading.py index f669f99..1f9a1d8 100644 --- a/nodes_model_loading.py +++ b/nodes_model_loading.py @@ -276,7 +276,7 @@ def standardize_lora_key_format(lora_sd): def compensate_rs_lora_format(lora_sd): rank = lora_sd["base_model.model.blocks.0.cross_attn.k.lora_A.weight"].shape[0] - alpha = torch.tensor(2 * 128 * rank ** 0.5) + alpha = torch.tensor(rank * rank // rank ** 0.5) log.info(f"Detected rank stabilized peft lora format with rank {rank}, setting alpha to {alpha} to compensate.") new_sd = {} for k, v in lora_sd.items(): From 20942b8fd9bfb9eba5b6b454d72275300cd25f97 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 12:51:22 +0200 Subject: [PATCH 07/22] Cleanup: Remove flowedit code, restructure some other code Due to lack of use and code maintainability --- multitalk/multitalk_loop.py | 483 +++++++++++++++++ nodes.py | 28 - nodes_sampler.py | 891 ++++---------------------------- utils.py | 88 +++- wanvideo/schedulers/__init__.py | 2 +- 5 files changed, 673 insertions(+), 819 deletions(-) create mode 100644 multitalk/multitalk_loop.py diff --git a/multitalk/multitalk_loop.py b/multitalk/multitalk_loop.py new file mode 100644 index 0000000..ed8b0af --- /dev/null +++ b/multitalk/multitalk_loop.py @@ -0,0 +1,483 @@ +import torch +import os +import gc +from PIL import Image +import numpy as np +from ..latent_preview import prepare_callback +from ..wanvideo.schedulers import get_scheduler +from .multitalk import timestep_transform, add_noise +from ..utils import log, print_memory, temporal_score_rescaling, offload_transformer, init_blockswap +from comfy.utils import load_torch_file +from ..nodes_model_loading import load_weights +from ..HuMo.nodes import get_audio_emb_window +import comfy.model_management as mm +from tqdm import tqdm +import copy + +VAE_STRIDE = (4, 8, 8) +PATCH_SIZE = (1, 2, 2) +vae_upscale_factor = 16 +script_directory = os.path.dirname(os.path.abspath(__file__)) + +device = mm.get_torch_device() +offload_device = mm.unet_offload_device() + +def multitalk_loop(self, **kwargs): + # Unpack kwargs into local variables + (latent, total_steps, steps, start_step, end_step, shift, cfg, denoise_strength, + sigmas, weight_dtype, transformer, patcher, block_swap_args, model, vae, dtype, + scheduler, scheduler_step_args, text_embeds, image_embeds, multitalk_embeds, + multitalk_audio_embeds, unianim_data, dwpose_data, unianimate_poses, uni3c_embeds, + humo_image_cond, humo_image_cond_neg, humo_audio, humo_reference_count, + add_noise_to_samples, audio_stride, use_tsr, tsr_k, tsr_sigma, fantasy_portrait_input, + noise, timesteps, force_offload, add_cond, control_latents, audio_proj, + control_camera_latents, samples, masks, seed_g, gguf_reader, predict_func + ) = (kwargs.get(k) for k in ( + 'latent', 'total_steps', 'steps', 'start_step', 'end_step', 'shift', 'cfg', + 'denoise_strength', 'sigmas', 'weight_dtype', 'transformer', 'patcher', + 'block_swap_args', 'model', 'vae', 'dtype', 'scheduler', 'scheduler_step_args', + 'text_embeds', 'image_embeds', 'multitalk_embeds', 'multitalk_audio_embeds', + 'unianim_data', 'dwpose_data', 'unianimate_poses', 'uni3c_embeds', + 'humo_image_cond', 'humo_image_cond_neg', 'humo_audio', 'humo_reference_count', + 'add_noise_to_samples', 'audio_stride', 'use_tsr', 'tsr_k', 'tsr_sigma', + 'fantasy_portrait_input', 'noise', 'timesteps', 'force_offload', 'add_cond', + 'control_latents', 'audio_proj', 'control_camera_latents', 'samples', 'masks', + 'seed_g', 'gguf_reader', 'predict_with_cfg' + )) + + mode = image_embeds.get("multitalk_mode", "multitalk") + if mode == "auto": + mode = transformer.multitalk_model_type.lower() + log.info(f"Multitalk mode: {mode}") + cond_frame = None + offload = image_embeds.get("force_offload", False) + offloaded = False + tiled_vae = image_embeds.get("tiled_vae", False) + frame_num = clip_length = image_embeds.get("frame_window_size", 81) + + clip_embeds = image_embeds.get("clip_context", None) + if clip_embeds is not None: + clip_embeds = clip_embeds.to(dtype) + colormatch = image_embeds.get("colormatch", "disabled") + motion_frame = image_embeds.get("motion_frame", 25) + target_w = image_embeds.get("target_w", None) + target_h = image_embeds.get("target_h", None) + original_images = cond_image = image_embeds.get("multitalk_start_image", None) + if original_images is None: + original_images = torch.zeros([noise.shape[0], 1, target_h, target_w], device=device) + + output_path = image_embeds.get("output_path", "") + img_counter = 0 + + if len(multitalk_embeds['audio_features'])==2 and (multitalk_embeds['ref_target_masks'] is None): + face_scale = 0.1 + x_min, x_max = int(target_h * face_scale), int(target_h * (1 - face_scale)) + lefty_min, lefty_max = int((target_w//2) * face_scale), int((target_w//2) * (1 - face_scale)) + righty_min, righty_max = int((target_w//2) * face_scale + (target_w//2)), int((target_w//2) * (1 - face_scale) + (target_w//2)) + human_mask1, human_mask2 = (torch.zeros([target_h, target_w]) for _ in range(2)) + human_mask1[x_min:x_max, lefty_min:lefty_max] = 1 + human_mask2[x_min:x_max, righty_min:righty_max] = 1 + background_mask = torch.where((human_mask1 + human_mask2) > 0, torch.tensor(0), torch.tensor(1)) + human_masks = [human_mask1, human_mask2, background_mask] + ref_target_masks = torch.stack(human_masks, dim=0) + multitalk_embeds['ref_target_masks'] = ref_target_masks + + gen_video_list = [] + is_first_clip = True + arrive_last_frame = False + cur_motion_frames_num = 1 + audio_start_idx = iteration_count = step_iteration_count = 0 + audio_end_idx = (audio_start_idx + clip_length) * audio_stride + indices = (torch.arange(4 + 1) - 2) * 1 + current_condframe_index = 0 + + audio_embedding = multitalk_audio_embeds + human_num = len(audio_embedding) + audio_embs = None + cond_frame = None + + uni3c_data = None + if uni3c_embeds is not None: + transformer.controlnet = uni3c_embeds["controlnet"] + uni3c_data = uni3c_embeds.copy() + + encoded_silence = None + + try: + silence_path = os.path.join(script_directory, "encoded_silence.safetensors") + encoded_silence = load_torch_file(silence_path)["audio_emb"].to(dtype) + except: + log.warning("No encoded silence file found, padding with end of audio embedding instead.") + + total_frames = len(audio_embedding[0]) + estimated_iterations = total_frames // (frame_num - motion_frame) + 1 + callback = prepare_callback(patcher, estimated_iterations) + + if frame_num >= total_frames: + arrive_last_frame = True + estimated_iterations = 1 + + log.info(f"Sampling {total_frames} frames in {estimated_iterations} windows, at {latent.shape[3]*vae_upscale_factor}x{latent.shape[2]*vae_upscale_factor} with {steps} steps") + + while True: # start video generation iteratively + self.cache_state = [None, None] + + cur_motion_frames_latent_num = int(1 + (cur_motion_frames_num-1) // 4) + if mode == "infinitetalk": + cond_image = original_images[:, :, current_condframe_index:current_condframe_index+1] if cond_image is not None else None + if multitalk_embeds is not None: + audio_embs = [] + # split audio with window size + for human_idx in range(human_num): + center_indices = torch.arange(audio_start_idx, audio_end_idx, audio_stride).unsqueeze(1) + indices.unsqueeze(0) + center_indices = torch.clamp(center_indices, min=0, max=audio_embedding[human_idx].shape[0]-1) + audio_emb = audio_embedding[human_idx][center_indices].unsqueeze(0).to(device) + audio_embs.append(audio_emb) + audio_embs = torch.concat(audio_embs, dim=0).to(dtype) + + h, w = (cond_image.shape[-2], cond_image.shape[-1]) if cond_image is not None else (target_h, target_w) + lat_h, lat_w = h // VAE_STRIDE[1], w // VAE_STRIDE[2] + latent_frame_num = (frame_num - 1) // 4 + 1 + + noise = torch.randn( + 16, latent_frame_num, + lat_h, lat_w, dtype=torch.float32, device=torch.device("cpu"), generator=seed_g).to(device) + + # Calculate the correct latent slice based on current iteration + if is_first_clip: + latent_start_idx = 0 + latent_end_idx = noise.shape[1] + else: + new_frames_per_iteration = frame_num - motion_frame + new_latent_frames_per_iteration = ((new_frames_per_iteration - 1) // 4 + 1) + latent_start_idx = iteration_count * new_latent_frames_per_iteration + latent_end_idx = latent_start_idx + noise.shape[1] + + if samples is not None: + noise_mask = samples.get("noise_mask", None) + input_samples = samples["samples"] + if input_samples is not None: + input_samples = input_samples.squeeze(0).to(noise) + # Check if we have enough frames in input_samples + if latent_end_idx > input_samples.shape[1]: + # We need more frames than available - pad the input_samples at the end + pad_length = latent_end_idx - input_samples.shape[1] + last_frame = input_samples[:, -1:].repeat(1, pad_length, 1, 1) + input_samples = torch.cat([input_samples, last_frame], dim=1) + input_samples = input_samples[:, latent_start_idx:latent_end_idx] + if noise_mask is not None: + original_image = input_samples.to(device) + + assert input_samples.shape[1] == noise.shape[1], f"Slice mismatch: {input_samples.shape[1]} vs {noise.shape[1]}" + + if add_noise_to_samples: + latent_timestep = timesteps[0] + noise = noise * latent_timestep / 1000 + (1 - latent_timestep / 1000) * input_samples + else: + noise = input_samples + + # diff diff prep + if noise_mask is not None: + if len(noise_mask.shape) == 4: + noise_mask = noise_mask.squeeze(1) + if audio_end_idx > noise_mask.shape[0]: + noise_mask = noise_mask.repeat(audio_end_idx // noise_mask.shape[0], 1, 1) + noise_mask = noise_mask[audio_start_idx:audio_end_idx] + noise_mask = torch.nn.functional.interpolate( + noise_mask.unsqueeze(0).unsqueeze(0), # Add batch and channel dims [1,1,T,H,W] + size=(noise.shape[1], noise.shape[2], noise.shape[3]), + mode='trilinear', + align_corners=False + ).repeat(1, noise.shape[0], 1, 1, 1) + + thresholds = torch.arange(len(timesteps), dtype=original_image.dtype) / len(timesteps) + thresholds = thresholds.reshape(-1, 1, 1, 1, 1).to(device) + masks = (1-noise_mask.repeat(len(timesteps), 1, 1, 1, 1).to(device)) > thresholds + + # zero padding and vae encode for img cond + if cond_image is not None or cond_frame is not None: + cond_ = cond_image if (is_first_clip or humo_image_cond is None) else cond_frame + cond_frame_num = cond_.shape[2] + video_frames = torch.zeros(1, 3, frame_num-cond_frame_num, target_h, target_w, device=device, dtype=vae.dtype) + padding_frames_pixels_values = torch.concat([cond_.to(device, vae.dtype), video_frames], dim=2) + + # encode + vae.to(device) + y = vae.encode(padding_frames_pixels_values, device=device, tiled=tiled_vae, pbar=False).to(dtype)[0] + + if mode == "multitalk": + latent_motion_frames = y[:, :cur_motion_frames_latent_num] # C T H W + else: + cond_ = cond_image if is_first_clip else cond_frame + latent_motion_frames = vae.encode(cond_.to(device, vae.dtype), device=device, tiled=tiled_vae, pbar=False).to(dtype)[0] + + vae.to(offload_device) + + #motion_frame_index = cur_motion_frames_latent_num if mode == "infinitetalk" else 1 + msk = torch.zeros(4, latent_frame_num, lat_h, lat_w, device=device, dtype=dtype) + msk[:, :1] = 1 + y = torch.cat([msk, y]) # 4+C T H W + mm.soft_empty_cache() + else: + y = None + latent_motion_frames = noise[:, :1] + + partial_humo_cond_input = partial_humo_cond_neg_input = partial_humo_audio = partial_humo_audio_neg = None + if humo_image_cond is not None: + partial_humo_cond_input = humo_image_cond[:, :latent_frame_num] + partial_humo_cond_neg_input = humo_image_cond_neg[:, :latent_frame_num] + if y is not None: + partial_humo_cond_input[:, :1] = y[:, :1] + if humo_reference_count > 0: + partial_humo_cond_input[:, -humo_reference_count:] = humo_image_cond[:, -humo_reference_count:] + partial_humo_cond_neg_input[:, -humo_reference_count:] = humo_image_cond_neg[:, -humo_reference_count:] + + if humo_audio is not None: + if is_first_clip: + audio_embs = None + + partial_humo_audio, _ = get_audio_emb_window(humo_audio, frame_num, frame0_idx=audio_start_idx) + #zero_audio_pad = torch.zeros(humo_reference_count, *partial_humo_audio.shape[1:], device=partial_humo_audio.device, dtype=partial_humo_audio.dtype) + partial_humo_audio[-humo_reference_count:] = 0 + partial_humo_audio_neg = torch.zeros_like(partial_humo_audio, device=partial_humo_audio.device, dtype=partial_humo_audio.dtype) + + if scheduler == "multitalk": + timesteps = list(np.linspace(1000, 1, steps, dtype=np.float32)) + timesteps.append(0.) + timesteps = [torch.tensor([t], device=device) for t in timesteps] + timesteps = [timestep_transform(t, shift=shift, num_timesteps=1000) for t in timesteps] + else: + if isinstance(scheduler, dict): + sample_scheduler = copy.deepcopy(scheduler["sample_scheduler"]) + timesteps = scheduler["timesteps"] + else: + sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, total_steps, start_step, end_step, shift, device, transformer.dim, denoise_strength, sigmas=sigmas) + timesteps = [torch.tensor([float(t)], device=device) for t in timesteps] + [torch.tensor([0.], device=device)] + + # sample videos + latent = noise + + # injecting motion frames + if not is_first_clip and mode == "multitalk": + latent_motion_frames = latent_motion_frames.to(latent.dtype).to(device) + motion_add_noise = torch.randn(latent_motion_frames.shape, device=torch.device("cpu"), generator=seed_g).to(device).contiguous() + add_latent = add_noise(latent_motion_frames, motion_add_noise, timesteps[0]) + latent[:, :add_latent.shape[1]] = add_latent + + if offloaded: + # Load weights + if transformer.patched_linear and gguf_reader is None: + load_weights(patcher.model.diffusion_model, patcher.model["sd"], weight_dtype, base_dtype=dtype, transformer_load_device=device, block_swap_args=block_swap_args) + elif gguf_reader is not None: #handle GGUF + load_weights(transformer, patcher.model["sd"], base_dtype=dtype, transformer_load_device=device, patcher=patcher, gguf=True, reader=gguf_reader, block_swap_args=block_swap_args) + #blockswap init + init_blockswap(transformer, block_swap_args, model) + + # Use the appropriate prompt for this section + if len(text_embeds["prompt_embeds"]) > 1: + prompt_index = min(iteration_count, len(text_embeds["prompt_embeds"]) - 1) + positive = [text_embeds["prompt_embeds"][prompt_index]] + log.info(f"Using prompt index: {prompt_index}") + else: + positive = text_embeds["prompt_embeds"] + + # uni3c slices + if uni3c_embeds is not None: + vae.to(device) + # Pad original_images if needed + num_frames = original_images.shape[2] + if audio_end_idx > num_frames: + pad_len = audio_end_idx - num_frames + last_frame = original_images[:, :, -1:].repeat(1, 1, pad_len, 1, 1) + padded_images = torch.cat([original_images, last_frame], dim=2) + else: + padded_images = original_images + render_latent = vae.encode( + padded_images[:, :, audio_start_idx:audio_end_idx].to(device, vae.dtype), + device=device, tiled=tiled_vae + ).to(dtype) + + vae.to(offload_device) + uni3c_data['render_latent'] = render_latent + + # unianimate slices + partial_unianim_data = None + if unianim_data is not None: + partial_dwpose = dwpose_data[:, :, latent_start_idx:latent_end_idx] + partial_unianim_data = { + "dwpose": partial_dwpose, + "random_ref": unianim_data["random_ref"], + "strength": unianimate_poses["strength"], + "start_percent": unianimate_poses["start_percent"], + "end_percent": unianimate_poses["end_percent"] + } + + # fantasy portrait slices + partial_fantasy_portrait_input = None + if fantasy_portrait_input is not None: + adapter_proj = fantasy_portrait_input["adapter_proj"] + if latent_end_idx > adapter_proj.shape[1]: + pad_len = latent_end_idx - adapter_proj.shape[1] + last_frame = adapter_proj[:, -1:, :, :].repeat(1, pad_len, 1, 1) + padded_proj = torch.cat([adapter_proj, last_frame], dim=1) + else: + padded_proj = adapter_proj + partial_fantasy_portrait_input = fantasy_portrait_input.copy() + partial_fantasy_portrait_input["adapter_proj"] = padded_proj[:, latent_start_idx:latent_end_idx] + + mm.soft_empty_cache() + gc.collect() + # sampling loop + sampling_pbar = tqdm(total=len(timesteps)-1, desc=f"Sampling audio indices {audio_start_idx}-{audio_end_idx}", position=0, leave=True) + for i in range(len(timesteps)-1): + timestep = timesteps[i] + latent_model_input = latent.to(device) + if mode == "infinitetalk": + if humo_image_cond is None or not is_first_clip: + latent_model_input[:, :cur_motion_frames_latent_num] = latent_motion_frames + + noise_pred, _, self.cache_state = predict_func( + latent_model_input, cfg[min(i, len(timesteps)-1)], positive, text_embeds["negative_prompt_embeds"], + timestep, i, y, clip_embeds, control_latents, None, partial_unianim_data, audio_proj, control_camera_latents, add_cond, + cache_state=self.cache_state, multitalk_audio_embeds=audio_embs, fantasy_portrait_input=partial_fantasy_portrait_input, + humo_image_cond=partial_humo_cond_input, humo_image_cond_neg=partial_humo_cond_neg_input, humo_audio=partial_humo_audio, humo_audio_neg=partial_humo_audio_neg, + uni3c_data = uni3c_data) + + if callback is not None: + callback_latent = (latent_model_input.to(device) - noise_pred.to(device) * timestep.to(device) / 1000).detach().permute(1,0,2,3) + callback(step_iteration_count, callback_latent, None, estimated_iterations*(len(timesteps)-1)) + del callback_latent + + sampling_pbar.update(1) + step_iteration_count += 1 + + # update latent + if use_tsr: + noise_pred = temporal_score_rescaling(noise_pred, latent, timestep, tsr_k, tsr_sigma) + if scheduler == "multitalk": + noise_pred = -noise_pred + dt = (timesteps[i] - timesteps[i + 1]) / 1000 + latent = latent + noise_pred * dt[:, None, None, None] + else: + latent = sample_scheduler.step(noise_pred.unsqueeze(0), timestep, latent.unsqueeze(0).to(noise_pred.device), **scheduler_step_args)[0].squeeze(0) + del noise_pred, latent_model_input, timestep + + # differential diffusion inpaint + if masks is not None: + if i < len(timesteps) - 1: + image_latent = add_noise(original_image.to(device), noise.to(device), timesteps[i+1]) + mask = masks[i].to(latent) + latent = image_latent * mask + latent * (1-mask) + + # injecting motion frames + if not is_first_clip and mode == "multitalk": + latent_motion_frames = latent_motion_frames.to(latent.dtype).to(device) + motion_add_noise = torch.randn(latent_motion_frames.shape, device=torch.device("cpu"), generator=seed_g).to(device).contiguous() + add_latent = add_noise(latent_motion_frames, motion_add_noise, timesteps[i+1]) + latent[:, :add_latent.shape[1]] = add_latent + else: + if humo_image_cond is None or not is_first_clip: + latent[:, :cur_motion_frames_latent_num] = latent_motion_frames + + del noise, latent_motion_frames + if offload: + offload_transformer(transformer, remove_lora=False) + offloaded = True + if humo_image_cond is not None and humo_reference_count > 0: + latent = latent[:,:-humo_reference_count] + vae.to(device) + videos = vae.decode(latent.unsqueeze(0).to(device, vae.dtype), device=device, tiled=tiled_vae, pbar=False)[0].cpu() + + vae.to(offload_device) + + sampling_pbar.close() + + # optional color correction (less relevant for InfiniteTalk) + if colormatch != "disabled": + videos = videos.permute(1, 2, 3, 0).float().numpy() + from color_matcher import ColorMatcher + cm = ColorMatcher() + cm_result_list = [] + for img in videos: + if mode == "multitalk": + cm_result = cm.transfer(src=img, ref=original_images[0].permute(1, 2, 3, 0).squeeze(0).cpu().float().numpy(), method=colormatch) + else: + cm_result = cm.transfer(src=img, ref=cond_image[0].permute(1, 2, 3, 0).squeeze(0).cpu().float().numpy(), method=colormatch) + cm_result_list.append(torch.from_numpy(cm_result).to(vae.dtype)) + + videos = torch.stack(cm_result_list, dim=0).permute(3, 0, 1, 2) + + # optionally save generated samples to disk + if output_path: + video_np = videos.clamp(-1.0, 1.0).add(1.0).div(2.0).mul(255).cpu().float().numpy().transpose(1, 2, 3, 0).astype('uint8') + num_frames_to_save = video_np.shape[0] if is_first_clip else video_np.shape[0] - cur_motion_frames_num + log.info(f"Saving {num_frames_to_save} generated frames to {output_path}") + start_idx = 0 if is_first_clip else cur_motion_frames_num + for i in range(start_idx, video_np.shape[0]): + im = Image.fromarray(video_np[i]) + im.save(os.path.join(output_path, f"frame_{img_counter:05d}.png")) + img_counter += 1 + else: + gen_video_list.append(videos if is_first_clip else videos[:, cur_motion_frames_num:]) + + current_condframe_index += 1 + iteration_count += 1 + + # decide whether is done + if arrive_last_frame: + break + + # update next condition frames + is_first_clip = False + cur_motion_frames_num = motion_frame + + cond_ = videos[:, -cur_motion_frames_num:].unsqueeze(0) + if mode == "infinitetalk": + cond_frame = cond_ + else: + cond_image = cond_ + + del videos, latent + + # Repeat audio emb + if multitalk_embeds is not None: + audio_start_idx += (frame_num - cur_motion_frames_num - humo_reference_count) + audio_end_idx = audio_start_idx + clip_length + if audio_end_idx >= len(audio_embedding[0]): + arrive_last_frame = True + miss_lengths = [] + source_frames = [] + for human_inx in range(human_num): + source_frame = len(audio_embedding[human_inx]) + source_frames.append(source_frame) + if audio_end_idx >= len(audio_embedding[human_inx]): + log.warning(f"Audio embedding for subject {human_inx} not long enough: {len(audio_embedding[human_inx])}, need {audio_end_idx}, padding...") + miss_length = audio_end_idx - len(audio_embedding[human_inx]) + 3 + log.warning(f"Padding length: {miss_length}") + if encoded_silence is not None: + add_audio_emb = encoded_silence[-1*miss_length:] + else: + add_audio_emb = torch.flip(audio_embedding[human_inx][-1*miss_length:], dims=[0]) + audio_embedding[human_inx] = torch.cat([audio_embedding[human_inx], add_audio_emb.to(device, dtype)], dim=0) + miss_lengths.append(miss_length) + else: + miss_lengths.append(0) + if mode == "infinitetalk" and current_condframe_index >= original_images.shape[2]: + last_frame = original_images[:, :, -1:, :, :] + miss_length = 1 + original_images = torch.cat([original_images, last_frame.repeat(1, 1, miss_length, 1, 1)], dim=2) + + if not output_path: + gen_video_samples = torch.cat(gen_video_list, dim=1) + else: + gen_video_samples = torch.zeros(3, 1, 64, 64) # dummy output + + if force_offload: + if not model["auto_cpu_offload"]: + offload_transformer(transformer) + try: + print_memory(device) + torch.cuda.reset_peak_memory_stats(device) + except: + pass + return {"video": gen_video_samples.permute(1, 2, 3, 0), "output_path": output_path}, diff --git a/nodes.py b/nodes.py index d754566..67f5142 100644 --- a/nodes.py +++ b/nodes.py @@ -1847,33 +1847,7 @@ class WanVideoContextOptions: } return (context_options,) - - -class WanVideoFlowEdit: - @classmethod - def INPUT_TYPES(s): - return {"required": { - "source_embeds": ("WANVIDEOTEXTEMBEDS", ), - "skip_steps": ("INT", {"default": 4, "min": 0}), - "drift_steps": ("INT", {"default": 0, "min": 0}), - "drift_flow_shift": ("FLOAT", {"default": 3.0, "min": 1.0, "max": 30.0, "step": 0.01}), - "source_cfg": ("FLOAT", {"default": 6.0, "min": 0.0, "max": 30.0, "step": 0.01}), - "drift_cfg": ("FLOAT", {"default": 6.0, "min": 0.0, "max": 30.0, "step": 0.01}), - }, - "optional": { - "source_image_embeds": ("WANVIDIMAGE_EMBEDS", ), - } - } - RETURN_TYPES = ("FLOWEDITARGS", ) - RETURN_NAMES = ("flowedit_args",) - FUNCTION = "process" - CATEGORY = "WanVideoWrapper" - DESCRIPTION = "Flowedit options for WanVideo" - - def process(self, **kwargs): - return (kwargs,) - class WanVideoLoopArgs: @classmethod def INPUT_TYPES(s): @@ -2249,7 +2223,6 @@ NODE_CLASS_MAPPINGS = { "WanVideoEnhanceAVideo": WanVideoEnhanceAVideo, "WanVideoContextOptions": WanVideoContextOptions, "WanVideoTextEmbedBridge": WanVideoTextEmbedBridge, - "WanVideoFlowEdit": WanVideoFlowEdit, "WanVideoControlEmbeds": WanVideoControlEmbeds, "WanVideoSLG": WanVideoSLG, "WanVideoLoopArgs": WanVideoLoopArgs, @@ -2292,7 +2265,6 @@ NODE_DISPLAY_NAME_MAPPINGS = { "WanVideoEnhanceAVideo": "WanVideo Enhance-A-Video", "WanVideoContextOptions": "WanVideo Context Options", "WanVideoTextEmbedBridge": "WanVideo TextEmbed Bridge", - "WanVideoFlowEdit": "WanVideo FlowEdit", "WanVideoControlEmbeds": "WanVideo Control Embeds", "WanVideoSLG": "WanVideo SLG", "WanVideoLoopArgs": "WanVideo Loop Args", diff --git a/nodes_sampler.py b/nodes_sampler.py index 1adcc22..e1216a9 100644 --- a/nodes_sampler.py +++ b/nodes_sampler.py @@ -3,16 +3,14 @@ import torch import numpy as np from tqdm import tqdm import inspect -from PIL import Image -from diffusers.schedulers import FlowMatchEulerDiscreteScheduler -from .wanvideo.schedulers.fm_solvers import get_sampling_sigmas, retrieve_timesteps from .wanvideo.modules.model import rope_params from .custom_linear import remove_lora_from_module, set_lora_params, _replace_linear from .wanvideo.schedulers import get_scheduler, scheduler_list from .gguf.gguf import set_lora_params_gguf -from .multitalk.multitalk import timestep_transform, add_noise +from .multitalk.multitalk import add_noise from .utils import(log, print_memory, apply_lora, fourier_filter, optimized_scale, setup_radial_attention, - compile_model, dict_to_device, tangential_projection, get_raag_guidance, temporal_score_rescaling) + compile_model, dict_to_device, tangential_projection, get_raag_guidance, temporal_score_rescaling, offload_transformer, init_blockswap) +from .multitalk.multitalk_loop import multitalk_loop from .cache_methods.cache_methods import cache_report from .nodes_model_loading import load_weights from .enhance_a_video.globals import set_enhance_weight, set_num_frames @@ -20,7 +18,7 @@ from .WanMove.trajectory import replace_feature from contextlib import nullcontext from comfy import model_management as mm -from comfy.utils import ProgressBar, load_torch_file +from comfy.utils import ProgressBar from comfy.cli_args import args, LatentPreviewMethod script_directory = os.path.dirname(os.path.abspath(__file__)) @@ -33,82 +31,6 @@ rope_functions = ["default", "comfy", "comfy_chunked"] VAE_STRIDE = (4, 8, 8) PATCH_SIZE = (1, 2, 2) -try: - from .gguf.gguf import GGUFParameter -except: - pass - -class MetaParameter(torch.nn.Parameter): - def __new__(cls, dtype, quant_type=None): - data = torch.empty(0, dtype=dtype) - self = torch.nn.Parameter(data, requires_grad=False) - self.quant_type = quant_type - return self - -def offload_transformer(transformer, remove_lora=True): - transformer.teacache_state.clear_all() - transformer.magcache_state.clear_all() - transformer.easycache_state.clear_all() - - if transformer.patched_linear: - for name, param in transformer.named_parameters(): - if "loras" in name or "controlnet" in name: - continue - module = transformer - subnames = name.split('.') - for subname in subnames[:-1]: - module = getattr(module, subname) - attr_name = subnames[-1] - if param.data.is_floating_point(): - meta_param = torch.nn.Parameter(torch.empty_like(param.data, device='meta'), requires_grad=False) - setattr(module, attr_name, meta_param) - elif isinstance(param.data, GGUFParameter): - quant_type = getattr(param, 'quant_type', None) - setattr(module, attr_name, MetaParameter(param.data.dtype, quant_type)) - else: - pass - if remove_lora: - remove_lora_from_module(transformer) - else: - transformer.to(offload_device) - - for block in transformer.blocks: - block.kv_cache = None - if transformer.audio_model is not None and hasattr(block, 'audio_block'): - block.audio_block = None - - mm.soft_empty_cache() - gc.collect() - - -def init_blockswap(transformer, block_swap_args, model): - if not transformer.patched_linear: - if block_swap_args is not None: - for name, param in transformer.named_parameters(): - if "block" not in name or "control_adapter" in name or "face" in name: - param.data = param.data.to(device) - elif block_swap_args["offload_txt_emb"] and "txt_emb" in name: - param.data = param.data.to(offload_device) - elif block_swap_args["offload_img_emb"] and "img_emb" in name: - param.data = param.data.to(offload_device) - - transformer.block_swap( - block_swap_args["blocks_to_swap"] - 1 , - block_swap_args["offload_txt_emb"], - block_swap_args["offload_img_emb"], - vace_blocks_to_swap = block_swap_args.get("vace_blocks_to_swap", None), - ) - elif model["auto_cpu_offload"]: - for module in transformer.modules(): - if hasattr(module, "offload"): - module.offload() - if hasattr(module, "onload"): - module.onload() - for block in transformer.blocks: - block.modulation = torch.nn.Parameter(block.modulation.to(device)) - transformer.head.modulation = torch.nn.Parameter(transformer.head.modulation.to(device)) - else: - transformer.to(device) class WanVideoSampler: @classmethod @@ -132,7 +54,7 @@ class WanVideoSampler: "feta_args": ("FETAARGS", ), "context_options": ("WANVIDCONTEXT", ), "cache_args": ("CACHEARGS", ), - "flowedit_args": ("FLOWEDITARGS", ), + "flowedit_args": ("FLOWEDITARGS", {"tooltip": "FlowEdit support has been deprecated"}), "batched_cfg": ("BOOLEAN", {"default": False, "tooltip": "Batch cond and uncond for faster sampling, possibly faster on some hardware, uses more memory"}), "slg_args": ("SLGARGS", ), "rope_function": (rope_functions, {"default": "comfy", "tooltip": "Comfy's RoPE implementation doesn't use complex numbers and can thus be compiled, that should be a lot faster when using torch.compile. Chunked version has reduced peak VRAM usage when not using torch.compile"}), @@ -159,7 +81,8 @@ class WanVideoSampler: force_offload=True, samples=None, feta_args=None, denoise_strength=1.0, context_options=None, cache_args=None, teacache_args=None, flowedit_args=None, batched_cfg=False, slg_args=None, rope_function="default", loop_args=None, experimental_args=None, sigmas=None, unianimate_poses=None, fantasytalking_embeds=None, uni3c_embeds=None, multitalk_embeds=None, freeinit_args=None, start_step=0, end_step=-1, add_noise_to_samples=False): - + if flowedit_args is not None: + raise Exception("FlowEdit support has been deprecated and removed due to lack of use and code maintainability") patcher = model model = model.model transformer = model.diffusion_model @@ -253,7 +176,7 @@ class WanVideoSampler: timesteps = scheduler["timesteps"] start_step = scheduler.get("start_step", start_step) elif scheduler != "multitalk": - sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, steps, start_step, end_step, shift, device, transformer.dim, flowedit_args, denoise_strength, sigmas=sigmas, log_timesteps=True) + sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, steps, start_step, end_step, shift, device, transformer.dim, denoise_strength, sigmas=sigmas, log_timesteps=True) log.info(f"sigmas: {sample_scheduler.sigmas}") else: timesteps = torch.tensor([1000, 750, 500, 250], device=device) @@ -994,43 +917,6 @@ class WanVideoSampler: if transformer.attention_mode == "radial_sage_attention": setup_radial_attention(transformer, transformer_options, latent, seq_len, latent_video_length, context_options=context_options) - # FlowEdit setup - if flowedit_args is not None: - source_embeds = flowedit_args["source_embeds"] - source_embeds = dict_to_device(source_embeds, device) - source_image_embeds = flowedit_args.get("source_image_embeds", image_embeds) - source_image_cond = source_image_embeds.get("image_embeds", None) - source_clip_fea = source_image_embeds.get("clip_fea", clip_fea) - if source_image_cond is not None: - source_image_cond = source_image_cond.to(dtype) - skip_steps = flowedit_args["skip_steps"] - drift_steps = flowedit_args["drift_steps"] - source_cfg = flowedit_args["source_cfg"] - if not isinstance(source_cfg, list): - source_cfg = [source_cfg] * (steps +1) - drift_cfg = flowedit_args["drift_cfg"] - if not isinstance(drift_cfg, list): - drift_cfg = [drift_cfg] * (steps +1) - - x_init = samples["samples"].clone().squeeze(0).to(device) - x_tgt = samples["samples"].squeeze(0).to(device) - - sample_scheduler = FlowMatchEulerDiscreteScheduler( - num_train_timesteps=1000, - shift=flowedit_args["drift_flow_shift"], - use_dynamic_shifting=False) - - sampling_sigmas = get_sampling_sigmas(steps, flowedit_args["drift_flow_shift"]) - - drift_timesteps, _ = retrieve_timesteps( - sample_scheduler, - device=device, - sigmas=sampling_sigmas) - - if drift_steps > 0: - drift_timesteps = torch.cat([drift_timesteps, torch.tensor([0]).to(drift_timesteps.device)]).to(drift_timesteps.device) - timesteps[-drift_steps:] = drift_timesteps[-drift_steps:] - # Experimental args use_cfg_zero_star = use_tangential = use_fresca = bidirectional_sampling = use_tsr = False raag_alpha = 0.0 @@ -1834,7 +1720,7 @@ class WanVideoSampler: # FreeInit noise reinitialization (after first iteration) if freeinit_args is not None and iter_idx > 0: # restart scheduler for each iteration - sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, steps, start_step, end_step, shift, device, transformer.dim, flowedit_args, denoise_strength, sigmas=sigmas) + sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, steps, start_step, end_step, shift, device, transformer.dim, denoise_strength, sigmas=sigmas) # Re-apply start_step and end_step logic to timesteps and sigmas if end_step != -1: @@ -1884,9 +1770,6 @@ class WanVideoSampler: pbar = ProgressBar(len(timesteps) - ttm_start_step) #region main loop start for idx, t in enumerate(tqdm(timesteps[ttm_start_step:], disable=multitalk_sampling or wananimate_loop)): - if flowedit_args is not None: - if idx < skip_steps: - continue if bidirectional_sampling: latent_flipped = torch.flip(latent, dims=[1]) @@ -1941,129 +1824,6 @@ class WanVideoSampler: enhance_enabled = False if feta_args is not None and feta_start_percent <= current_step_percentage <= feta_end_percent: enhance_enabled = True - - #flow-edit - if flowedit_args is not None: - sigma = t / 1000.0 - sigma_prev = (timesteps[idx + 1] if idx < len(timesteps) - 1 else timesteps[-1]) / 1000.0 - noise = torch.randn(x_init.shape, generator=seed_g, device=torch.device("cpu")) - if idx < len(timesteps) - drift_steps: - cfg = drift_cfg - - zt_src = (1-sigma) * x_init + sigma * noise.to(t) - zt_tgt = x_tgt + zt_src - x_init - - #source - if idx < len(timesteps) - drift_steps: - if context_options is not None: - counter = torch.zeros_like(zt_src, device=intermediate_device) - vt_src = torch.zeros_like(zt_src, device=intermediate_device) - context_queue = list(context(idx, steps, latent_video_length, context_frames, context_stride, context_overlap)) - for c in context_queue: - window_id = self.window_tracker.get_window_id(c) - - if cache_args is not None: - current_teacache = self.window_tracker.get_teacache(window_id, self.cache_state) - else: - current_teacache = None - - prompt_index = min(int(max(c) / section_size), num_prompts - 1) - if context_options["verbose"]: - log.info(f"Prompt index: {prompt_index}") - - if len(source_embeds["prompt_embeds"]) > 1: - positive = source_embeds["prompt_embeds"][prompt_index] - else: - positive = source_embeds["prompt_embeds"] - - partial_img_emb = None - if source_image_cond is not None: - partial_img_emb = source_image_cond[:, c, :, :] - partial_img_emb[:, 0, :, :] = source_image_cond[:, 0, :, :].to(intermediate_device) - - partial_zt_src = zt_src[:, c, :, :] - vt_src_context, _, new_teacache = predict_with_cfg( - partial_zt_src, cfg[idx], - positive, source_embeds["negative_prompt_embeds"], - timestep, idx, partial_img_emb, control_latents, - source_clip_fea, current_teacache) - - if cache_args is not None: - self.window_tracker.cache_states[window_id] = new_teacache - - window_mask = create_window_mask(vt_src_context, c, latent_video_length, context_overlap) - vt_src[:, c, :, :] += vt_src_context * window_mask - counter[:, c, :, :] += window_mask - vt_src /= counter - else: - vt_src, _, self.cache_state_source = predict_with_cfg( - zt_src, cfg[idx], - source_embeds["prompt_embeds"], - source_embeds["negative_prompt_embeds"], - timestep, idx, source_image_cond, - source_clip_fea, control_latents, - cache_state=self.cache_state_source) - else: - if idx == len(timesteps) - drift_steps: - x_tgt = zt_tgt - zt_tgt = x_tgt - vt_src = 0 - #target - if context_options is not None: - counter = torch.zeros_like(zt_tgt, device=intermediate_device) - vt_tgt = torch.zeros_like(zt_tgt, device=intermediate_device) - context_queue = list(context(idx, steps, latent_video_length, context_frames, context_stride, context_overlap)) - for c in context_queue: - window_id = self.window_tracker.get_window_id(c) - - if cache_args is not None: - current_teacache = self.window_tracker.get_teacache(window_id, self.cache_state) - else: - current_teacache = None - - prompt_index = min(int(max(c) / section_size), num_prompts - 1) - if context_options["verbose"]: - log.info(f"Prompt index: {prompt_index}") - - if len(text_embeds["prompt_embeds"]) > 1: - positive = text_embeds["prompt_embeds"][prompt_index] - else: - positive = text_embeds["prompt_embeds"] - - partial_img_emb = None - partial_control_latents = None - if image_cond is not None: - partial_img_emb = image_cond[:, c, :, :] - partial_img_emb[:, 0, :, :] = image_cond[:, 0, :, :].to(intermediate_device) - if control_latents is not None: - partial_control_latents = control_latents[:, c, :, :] - - partial_zt_tgt = zt_tgt[:, c, :, :] - vt_tgt_context, _, new_teacache = predict_with_cfg( - partial_zt_tgt, cfg[idx], - positive, text_embeds["negative_prompt_embeds"], - timestep, idx, partial_img_emb, partial_control_latents, - clip_fea, current_teacache) - - if cache_args is not None: - self.window_tracker.cache_states[window_id] = new_teacache - - window_mask = create_window_mask(vt_tgt_context, c, latent_video_length, context_overlap) - vt_tgt[:, c, :, :] += vt_tgt_context * window_mask - counter[:, c, :, :] += window_mask - vt_tgt /= counter - else: - vt_tgt, _,self.cache_state = predict_with_cfg( - zt_tgt, cfg[idx], - text_embeds["prompt_embeds"], - text_embeds["negative_prompt_embeds"], - timestep, idx, image_cond, clip_fea, control_latents, - cache_state=self.cache_state) - v_delta = vt_tgt - vt_src - x_tgt = x_tgt.to(torch.float32) - v_delta = v_delta.to(torch.float32) - x_tgt = x_tgt + (sigma_prev - sigma) * v_delta - x0 = x_tgt #region context windowing elif context_options is not None: counter = torch.zeros_like(latent_model_input, device=intermediate_device) @@ -2258,443 +2018,7 @@ class WanVideoSampler: noise_pred /= counter #region multitalk elif multitalk_sampling: - mode = image_embeds.get("multitalk_mode", "multitalk") - if mode == "auto": - mode = transformer.multitalk_model_type.lower() - log.info(f"Multitalk mode: {mode}") - cond_frame = None - offload = image_embeds.get("force_offload", False) - offloaded = False - tiled_vae = image_embeds.get("tiled_vae", False) - frame_num = clip_length = image_embeds.get("frame_window_size", 81) - - clip_embeds = image_embeds.get("clip_context", None) - if clip_embeds is not None: - clip_embeds = clip_embeds.to(dtype) - colormatch = image_embeds.get("colormatch", "disabled") - motion_frame = image_embeds.get("motion_frame", 25) - target_w = image_embeds.get("target_w", None) - target_h = image_embeds.get("target_h", None) - original_images = cond_image = image_embeds.get("multitalk_start_image", None) - if original_images is None: - original_images = torch.zeros([noise.shape[0], 1, target_h, target_w], device=device) - - output_path = image_embeds.get("output_path", "") - img_counter = 0 - - if len(multitalk_embeds['audio_features'])==2 and (multitalk_embeds['ref_target_masks'] is None): - face_scale = 0.1 - x_min, x_max = int(target_h * face_scale), int(target_h * (1 - face_scale)) - lefty_min, lefty_max = int((target_w//2) * face_scale), int((target_w//2) * (1 - face_scale)) - righty_min, righty_max = int((target_w//2) * face_scale + (target_w//2)), int((target_w//2) * (1 - face_scale) + (target_w//2)) - human_mask1, human_mask2 = (torch.zeros([target_h, target_w]) for _ in range(2)) - human_mask1[x_min:x_max, lefty_min:lefty_max] = 1 - human_mask2[x_min:x_max, righty_min:righty_max] = 1 - background_mask = torch.where((human_mask1 + human_mask2) > 0, torch.tensor(0), torch.tensor(1)) - human_masks = [human_mask1, human_mask2, background_mask] - ref_target_masks = torch.stack(human_masks, dim=0) - multitalk_embeds['ref_target_masks'] = ref_target_masks - - gen_video_list = [] - is_first_clip = True - arrive_last_frame = False - cur_motion_frames_num = 1 - audio_start_idx = iteration_count = step_iteration_count = 0 - audio_end_idx = (audio_start_idx + clip_length) * audio_stride - indices = (torch.arange(4 + 1) - 2) * 1 - current_condframe_index = 0 - - audio_embedding = multitalk_audio_embeds - human_num = len(audio_embedding) - audio_embs = None - cond_frame = None - - uni3c_data = uni3c_data_input = None - if uni3c_embeds is not None: - transformer.controlnet = uni3c_embeds["controlnet"] - uni3c_data = uni3c_embeds.copy() - - encoded_silence = None - - try: - silence_path = os.path.join(script_directory, "multitalk", "encoded_silence.safetensors") - encoded_silence = load_torch_file(silence_path)["audio_emb"].to(dtype) - except: - log.warning("No encoded silence file found, padding with end of audio embedding instead.") - - total_frames = len(audio_embedding[0]) - estimated_iterations = total_frames // (frame_num - motion_frame) + 1 - callback = prepare_callback(patcher, estimated_iterations) - - if frame_num >= total_frames: - arrive_last_frame = True - estimated_iterations = 1 - - log.info(f"Sampling {total_frames} frames in {estimated_iterations} windows, at {latent.shape[3]*vae_upscale_factor}x{latent.shape[2]*vae_upscale_factor} with {steps} steps") - - while True: # start video generation iteratively - self.cache_state = [None, None] - - cur_motion_frames_latent_num = int(1 + (cur_motion_frames_num-1) // 4) - if mode == "infinitetalk": - cond_image = original_images[:, :, current_condframe_index:current_condframe_index+1] if cond_image is not None else None - if multitalk_embeds is not None: - audio_embs = [] - # split audio with window size - for human_idx in range(human_num): - center_indices = torch.arange(audio_start_idx, audio_end_idx, audio_stride).unsqueeze(1) + indices.unsqueeze(0) - center_indices = torch.clamp(center_indices, min=0, max=audio_embedding[human_idx].shape[0]-1) - audio_emb = audio_embedding[human_idx][center_indices].unsqueeze(0).to(device) - audio_embs.append(audio_emb) - audio_embs = torch.concat(audio_embs, dim=0).to(dtype) - - h, w = (cond_image.shape[-2], cond_image.shape[-1]) if cond_image is not None else (target_h, target_w) - lat_h, lat_w = h // VAE_STRIDE[1], w // VAE_STRIDE[2] - seq_len = ((frame_num - 1) // VAE_STRIDE[0] + 1) * lat_h * lat_w // (PATCH_SIZE[1] * PATCH_SIZE[2]) - latent_frame_num = (frame_num - 1) // 4 + 1 - - noise = torch.randn( - 16, latent_frame_num, - lat_h, lat_w, dtype=torch.float32, device=torch.device("cpu"), generator=seed_g).to(device) - - # Calculate the correct latent slice based on current iteration - if is_first_clip: - latent_start_idx = 0 - latent_end_idx = noise.shape[1] - else: - new_frames_per_iteration = frame_num - motion_frame - new_latent_frames_per_iteration = ((new_frames_per_iteration - 1) // 4 + 1) - latent_start_idx = iteration_count * new_latent_frames_per_iteration - latent_end_idx = latent_start_idx + noise.shape[1] - - if samples is not None: - noise_mask = samples.get("noise_mask", None) - input_samples = samples["samples"] - if input_samples is not None: - input_samples = input_samples.squeeze(0).to(noise) - # Check if we have enough frames in input_samples - if latent_end_idx > input_samples.shape[1]: - # We need more frames than available - pad the input_samples at the end - pad_length = latent_end_idx - input_samples.shape[1] - last_frame = input_samples[:, -1:].repeat(1, pad_length, 1, 1) - input_samples = torch.cat([input_samples, last_frame], dim=1) - input_samples = input_samples[:, latent_start_idx:latent_end_idx] - if noise_mask is not None: - original_image = input_samples.to(device) - - assert input_samples.shape[1] == noise.shape[1], f"Slice mismatch: {input_samples.shape[1]} vs {noise.shape[1]}" - - if add_noise_to_samples: - latent_timestep = timesteps[0] - noise = noise * latent_timestep / 1000 + (1 - latent_timestep / 1000) * input_samples - else: - noise = input_samples - - # diff diff prep - if noise_mask is not None: - if len(noise_mask.shape) == 4: - noise_mask = noise_mask.squeeze(1) - if audio_end_idx > noise_mask.shape[0]: - noise_mask = noise_mask.repeat(audio_end_idx // noise_mask.shape[0], 1, 1) - noise_mask = noise_mask[audio_start_idx:audio_end_idx] - noise_mask = torch.nn.functional.interpolate( - noise_mask.unsqueeze(0).unsqueeze(0), # Add batch and channel dims [1,1,T,H,W] - size=(noise.shape[1], noise.shape[2], noise.shape[3]), - mode='trilinear', - align_corners=False - ).repeat(1, noise.shape[0], 1, 1, 1) - - thresholds = torch.arange(len(timesteps), dtype=original_image.dtype) / len(timesteps) - thresholds = thresholds.reshape(-1, 1, 1, 1, 1).to(device) - masks = (1-noise_mask.repeat(len(timesteps), 1, 1, 1, 1).to(device)) > thresholds - - # zero padding and vae encode for img cond - if cond_image is not None or cond_frame is not None: - cond_ = cond_image if (is_first_clip or humo_image_cond is None) else cond_frame - cond_frame_num = cond_.shape[2] - video_frames = torch.zeros(1, 3, frame_num-cond_frame_num, target_h, target_w, device=device, dtype=vae.dtype) - padding_frames_pixels_values = torch.concat([cond_.to(device, vae.dtype), video_frames], dim=2) - - # encode - vae.to(device) - y = vae.encode(padding_frames_pixels_values, device=device, tiled=tiled_vae, pbar=False).to(dtype)[0] - - if mode == "multitalk": - latent_motion_frames = y[:, :cur_motion_frames_latent_num] # C T H W - else: - cond_ = cond_image if is_first_clip else cond_frame - latent_motion_frames = vae.encode(cond_.to(device, vae.dtype), device=device, tiled=tiled_vae, pbar=False).to(dtype)[0] - - vae.to(offload_device) - - #motion_frame_index = cur_motion_frames_latent_num if mode == "infinitetalk" else 1 - msk = torch.zeros(4, latent_frame_num, lat_h, lat_w, device=device, dtype=dtype) - msk[:, :1] = 1 - y = torch.cat([msk, y]) # 4+C T H W - mm.soft_empty_cache() - else: - y = None - latent_motion_frames = noise[:, :1] - - partial_humo_cond_input = partial_humo_cond_neg_input = partial_humo_audio = partial_humo_audio_neg = None - if humo_image_cond is not None: - partial_humo_cond_input = humo_image_cond[:, :latent_frame_num] - partial_humo_cond_neg_input = humo_image_cond_neg[:, :latent_frame_num] - if y is not None: - partial_humo_cond_input[:, :1] = y[:, :1] - if humo_reference_count > 0: - partial_humo_cond_input[:, -humo_reference_count:] = humo_image_cond[:, -humo_reference_count:] - partial_humo_cond_neg_input[:, -humo_reference_count:] = humo_image_cond_neg[:, -humo_reference_count:] - - if humo_audio is not None: - if is_first_clip: - audio_embs = None - - partial_humo_audio, _ = get_audio_emb_window(humo_audio, frame_num, frame0_idx=audio_start_idx) - #zero_audio_pad = torch.zeros(humo_reference_count, *partial_humo_audio.shape[1:], device=partial_humo_audio.device, dtype=partial_humo_audio.dtype) - partial_humo_audio[-humo_reference_count:] = 0 - partial_humo_audio_neg = torch.zeros_like(partial_humo_audio, device=partial_humo_audio.device, dtype=partial_humo_audio.dtype) - - if scheduler == "multitalk": - timesteps = list(np.linspace(1000, 1, steps, dtype=np.float32)) - timesteps.append(0.) - timesteps = [torch.tensor([t], device=device) for t in timesteps] - timesteps = [timestep_transform(t, shift=shift, num_timesteps=1000) for t in timesteps] - else: - if isinstance(scheduler, dict): - sample_scheduler = copy.deepcopy(scheduler["sample_scheduler"]) - timesteps = scheduler["timesteps"] - else: - sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, total_steps, start_step, end_step, shift, device, transformer.dim, flowedit_args, denoise_strength, sigmas=sigmas) - timesteps = [torch.tensor([float(t)], device=device) for t in timesteps] + [torch.tensor([0.], device=device)] - - # sample videos - latent = noise - - # injecting motion frames - if not is_first_clip and mode == "multitalk": - latent_motion_frames = latent_motion_frames.to(latent.dtype).to(device) - motion_add_noise = torch.randn(latent_motion_frames.shape, device=torch.device("cpu"), generator=seed_g).to(device).contiguous() - add_latent = add_noise(latent_motion_frames, motion_add_noise, timesteps[0]) - latent[:, :add_latent.shape[1]] = add_latent - - if offloaded: - # Load weights - if transformer.patched_linear and gguf_reader is None: - load_weights(patcher.model.diffusion_model, patcher.model["sd"], weight_dtype, base_dtype=dtype, transformer_load_device=device, block_swap_args=block_swap_args) - elif gguf_reader is not None: #handle GGUF - load_weights(transformer, patcher.model["sd"], base_dtype=dtype, transformer_load_device=device, patcher=patcher, gguf=True, reader=gguf_reader, block_swap_args=block_swap_args) - #blockswap init - init_blockswap(transformer, block_swap_args, model) - - # Use the appropriate prompt for this section - if len(text_embeds["prompt_embeds"]) > 1: - prompt_index = min(iteration_count, len(text_embeds["prompt_embeds"]) - 1) - positive = [text_embeds["prompt_embeds"][prompt_index]] - log.info(f"Using prompt index: {prompt_index}") - else: - positive = text_embeds["prompt_embeds"] - - # uni3c slices - if uni3c_embeds is not None: - vae.to(device) - # Pad original_images if needed - num_frames = original_images.shape[2] - if audio_end_idx > num_frames: - pad_len = audio_end_idx - num_frames - last_frame = original_images[:, :, -1:].repeat(1, 1, pad_len, 1, 1) - padded_images = torch.cat([original_images, last_frame], dim=2) - else: - padded_images = original_images - render_latent = vae.encode( - padded_images[:, :, audio_start_idx:audio_end_idx].to(device, vae.dtype), - device=device, tiled=tiled_vae - ).to(dtype) - - vae.to(offload_device) - uni3c_data['render_latent'] = render_latent - - # unianimate slices - partial_unianim_data = None - if unianim_data is not None: - partial_dwpose = dwpose_data[:, :, latent_start_idx:latent_end_idx] - partial_unianim_data = { - "dwpose": partial_dwpose, - "random_ref": unianim_data["random_ref"], - "strength": unianimate_poses["strength"], - "start_percent": unianimate_poses["start_percent"], - "end_percent": unianimate_poses["end_percent"] - } - - # fantasy portrait slices - partial_fantasy_portrait_input = None - if fantasy_portrait_input is not None: - adapter_proj = fantasy_portrait_input["adapter_proj"] - if latent_end_idx > adapter_proj.shape[1]: - pad_len = latent_end_idx - adapter_proj.shape[1] - last_frame = adapter_proj[:, -1:, :, :].repeat(1, pad_len, 1, 1) - padded_proj = torch.cat([adapter_proj, last_frame], dim=1) - else: - padded_proj = adapter_proj - partial_fantasy_portrait_input = fantasy_portrait_input.copy() - partial_fantasy_portrait_input["adapter_proj"] = padded_proj[:, latent_start_idx:latent_end_idx] - - mm.soft_empty_cache() - gc.collect() - # sampling loop - sampling_pbar = tqdm(total=len(timesteps)-1, desc=f"Sampling audio indices {audio_start_idx}-{audio_end_idx}", position=0, leave=True) - for i in range(len(timesteps)-1): - timestep = timesteps[i] - latent_model_input = latent.to(device) - if mode == "infinitetalk": - if humo_image_cond is None or not is_first_clip: - latent_model_input[:, :cur_motion_frames_latent_num] = latent_motion_frames - - noise_pred, _, self.cache_state = predict_with_cfg( - latent_model_input, cfg[min(i, len(timesteps)-1)], positive, text_embeds["negative_prompt_embeds"], - timestep, i, y, clip_embeds, control_latents, None, partial_unianim_data, audio_proj, control_camera_latents, add_cond, - cache_state=self.cache_state, multitalk_audio_embeds=audio_embs, fantasy_portrait_input=partial_fantasy_portrait_input, - humo_image_cond=partial_humo_cond_input, humo_image_cond_neg=partial_humo_cond_neg_input, humo_audio=partial_humo_audio, humo_audio_neg=partial_humo_audio_neg, - uni3c_data = uni3c_data) - - if callback is not None: - callback_latent = (latent_model_input.to(device) - noise_pred.to(device) * t.to(device) / 1000).detach().permute(1,0,2,3) - callback(step_iteration_count, callback_latent, None, estimated_iterations*(len(timesteps)-1)) - del callback_latent - - sampling_pbar.update(1) - step_iteration_count += 1 - - # update latent - if use_tsr: - noise_pred = temporal_score_rescaling(noise_pred, latent, timestep, tsr_k, tsr_sigma) - if scheduler == "multitalk": - noise_pred = -noise_pred - dt = (timesteps[i] - timesteps[i + 1]) / 1000 - latent = latent + noise_pred * dt[:, None, None, None] - else: - latent = sample_scheduler.step(noise_pred.unsqueeze(0), timestep, latent.unsqueeze(0).to(noise_pred.device), **scheduler_step_args)[0].squeeze(0) - del noise_pred, latent_model_input, timestep - - # differential diffusion inpaint - if masks is not None: - if i < len(timesteps) - 1: - image_latent = add_noise(original_image.to(device), noise.to(device), timesteps[i+1]) - mask = masks[i].to(latent) - latent = image_latent * mask + latent * (1-mask) - - # injecting motion frames - if not is_first_clip and mode == "multitalk": - latent_motion_frames = latent_motion_frames.to(latent.dtype).to(device) - motion_add_noise = torch.randn(latent_motion_frames.shape, device=torch.device("cpu"), generator=seed_g).to(device).contiguous() - add_latent = add_noise(latent_motion_frames, motion_add_noise, timesteps[i+1]) - latent[:, :add_latent.shape[1]] = add_latent - else: - if humo_image_cond is None or not is_first_clip: - latent[:, :cur_motion_frames_latent_num] = latent_motion_frames - - del noise, latent_motion_frames - if offload: - offload_transformer(transformer, remove_lora=False) - offloaded = True - if humo_image_cond is not None and humo_reference_count > 0: - latent = latent[:,:-humo_reference_count] - vae.to(device) - videos = vae.decode(latent.unsqueeze(0).to(device, vae.dtype), device=device, tiled=tiled_vae, pbar=False)[0].cpu() - - vae.to(offload_device) - - sampling_pbar.close() - - # optional color correction (less relevant for InfiniteTalk) - if colormatch != "disabled": - videos = videos.permute(1, 2, 3, 0).float().numpy() - from color_matcher import ColorMatcher - cm = ColorMatcher() - cm_result_list = [] - for img in videos: - if mode == "multitalk": - cm_result = cm.transfer(src=img, ref=original_images[0].permute(1, 2, 3, 0).squeeze(0).cpu().float().numpy(), method=colormatch) - else: - cm_result = cm.transfer(src=img, ref=cond_image[0].permute(1, 2, 3, 0).squeeze(0).cpu().float().numpy(), method=colormatch) - cm_result_list.append(torch.from_numpy(cm_result).to(vae.dtype)) - - videos = torch.stack(cm_result_list, dim=0).permute(3, 0, 1, 2) - - # optionally save generated samples to disk - if output_path: - video_np = videos.clamp(-1.0, 1.0).add(1.0).div(2.0).mul(255).cpu().float().numpy().transpose(1, 2, 3, 0).astype('uint8') - num_frames_to_save = video_np.shape[0] if is_first_clip else video_np.shape[0] - cur_motion_frames_num - log.info(f"Saving {num_frames_to_save} generated frames to {output_path}") - start_idx = 0 if is_first_clip else cur_motion_frames_num - for i in range(start_idx, video_np.shape[0]): - im = Image.fromarray(video_np[i]) - im.save(os.path.join(output_path, f"frame_{img_counter:05d}.png")) - img_counter += 1 - else: - gen_video_list.append(videos if is_first_clip else videos[:, cur_motion_frames_num:]) - - current_condframe_index += 1 - iteration_count += 1 - - # decide whether is done - if arrive_last_frame: - break - - # update next condition frames - is_first_clip = False - cur_motion_frames_num = motion_frame - - cond_ = videos[:, -cur_motion_frames_num:].unsqueeze(0) - if mode == "infinitetalk": - cond_frame = cond_ - else: - cond_image = cond_ - - del videos, latent - - # Repeat audio emb - if multitalk_embeds is not None: - audio_start_idx += (frame_num - cur_motion_frames_num - humo_reference_count) - audio_end_idx = audio_start_idx + clip_length - if audio_end_idx >= len(audio_embedding[0]): - arrive_last_frame = True - miss_lengths = [] - source_frames = [] - for human_inx in range(human_num): - source_frame = len(audio_embedding[human_inx]) - source_frames.append(source_frame) - if audio_end_idx >= len(audio_embedding[human_inx]): - log.warning(f"Audio embedding for subject {human_inx} not long enough: {len(audio_embedding[human_inx])}, need {audio_end_idx}, padding...") - miss_length = audio_end_idx - len(audio_embedding[human_inx]) + 3 - log.warning(f"Padding length: {miss_length}") - if encoded_silence is not None: - add_audio_emb = encoded_silence[-1*miss_length:] - else: - add_audio_emb = torch.flip(audio_embedding[human_inx][-1*miss_length:], dims=[0]) - audio_embedding[human_inx] = torch.cat([audio_embedding[human_inx], add_audio_emb.to(device, dtype)], dim=0) - miss_lengths.append(miss_length) - else: - miss_lengths.append(0) - if mode == "infinitetalk" and current_condframe_index >= original_images.shape[2]: - last_frame = original_images[:, :, -1:, :, :] - miss_length = 1 - original_images = torch.cat([original_images, last_frame.repeat(1, 1, miss_length, 1, 1)], dim=2) - - if not output_path: - gen_video_samples = torch.cat(gen_video_list, dim=1) - else: - gen_video_samples = torch.zeros(3, 1, 64, 64) # dummy output - - if force_offload: - if not model["auto_cpu_offload"]: - offload_transformer(transformer) - try: - print_memory(device) - torch.cuda.reset_peak_memory_stats(device) - except: - pass - return {"video": gen_video_samples.permute(1, 2, 3, 0), "output_path": output_path}, + return multitalk_loop(**locals()) # region framepack loop elif framepack: framepack_out = [] @@ -2779,7 +2103,7 @@ class WanVideoSampler: sample_scheduler = copy.deepcopy(scheduler["sample_scheduler"]) timesteps = scheduler["timesteps"] else: - sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, total_steps, start_step, end_step, shift, device, transformer.dim, flowedit_args, denoise_strength, sigmas=sigmas) + sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, total_steps, start_step, end_step, shift, device, transformer.dim, denoise_strength, sigmas=sigmas) latent = noise.to(device) for i, t in enumerate(tqdm(timesteps, desc=f"Sampling audio indices {left_idx}-{right_idx}", position=0)): @@ -2959,12 +2283,12 @@ class WanVideoSampler: if input_samples is not None: input_samples = input_samples.squeeze(0).to(noise) # Check if we have enough frames in input_samples - if latent_end_idx > input_samples.shape[1]: - # We need more frames than available - pad the input_samples at the end - pad_length = latent_end_idx - input_samples.shape[1] - last_frame = input_samples[:, -1:].repeat(1, pad_length, 1, 1) - input_samples = torch.cat([input_samples, last_frame], dim=1) - input_samples = input_samples[:, latent_start_idx:latent_end_idx] + # if latent_end_idx > input_samples.shape[1]: + # # We need more frames than available - pad the input_samples at the end + # pad_length = latent_end_idx - input_samples.shape[1] + # last_frame = input_samples[:, -1:].repeat(1, pad_length, 1, 1) + # input_samples = torch.cat([input_samples, last_frame], dim=1) + # input_samples = input_samples[:, latent_start_idx:latent_end_idx] if noise_mask is not None: original_image = input_samples.to(device) @@ -3000,7 +2324,7 @@ class WanVideoSampler: sample_scheduler = copy.deepcopy(scheduler["sample_scheduler"]) timesteps = scheduler["timesteps"] else: - sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, total_steps, start_step, end_step, shift, device, transformer.dim, flowedit_args, denoise_strength, sigmas=sigmas) + sample_scheduler, timesteps,_,_ = get_scheduler(scheduler, total_steps, start_step, end_step, shift, device, transformer.dim, denoise_strength, sigmas=sigmas) # sample videos latent = noise @@ -3096,17 +2420,17 @@ class WanVideoSampler: current_ref_images = videos[:, -refert_num:].clone().detach() # optionally save generated samples to disk - if output_path: - video_np = videos.clamp(-1.0, 1.0).add(1.0).div(2.0).mul(255).cpu().float().numpy().transpose(1, 2, 3, 0).astype('uint8') - num_frames_to_save = video_np.shape[0] if is_first_clip else video_np.shape[0] - cur_motion_frames_num - log.info(f"Saving {num_frames_to_save} generated frames to {output_path}") - start_idx = 0 if is_first_clip else cur_motion_frames_num - for i in range(start_idx, video_np.shape[0]): - im = Image.fromarray(video_np[i]) - im.save(os.path.join(output_path, f"frame_{img_counter:05d}.png")) - img_counter += 1 - else: - gen_video_list.append(videos) + # if output_path: + # video_np = videos.clamp(-1.0, 1.0).add(1.0).div(2.0).mul(255).cpu().float().numpy().transpose(1, 2, 3, 0).astype('uint8') + # num_frames_to_save = video_np.shape[0] if is_first_clip else video_np.shape[0] - cur_motion_frames_num + # log.info(f"Saving {num_frames_to_save} generated frames to {output_path}") + # start_idx = 0 if is_first_clip else cur_motion_frames_num + # for i in range(start_idx, video_np.shape[0]): + # im = Image.fromarray(video_np[i]) + # im.save(os.path.join(output_path, f"frame_{img_counter:05d}.png")) + # img_counter += 1 + # else: + gen_video_list.append(videos) del videos @@ -3155,94 +2479,87 @@ class WanVideoSampler: noise_pred = torch.cat([noise_pred[:, latent_video_length - shift_idx:]] + [noise_pred[:, :latent_video_length - shift_idx]], dim=1) shift_idx = (shift_idx + latent_skip) % latent_video_length + latent = latent.to(intermediate_device) - if flowedit_args is None: - latent = latent.to(intermediate_device) + if self.noise_front_pad_num > 0: + noise_pred = noise_pred[:, self.noise_front_pad_num:] - if self.noise_front_pad_num > 0: - noise_pred = noise_pred[:, self.noise_front_pad_num:] + if use_tsr: + noise_pred = temporal_score_rescaling(noise_pred, latent, timestep, tsr_k, tsr_sigma) - if use_tsr: - noise_pred = temporal_score_rescaling(noise_pred, latent, timestep, tsr_k, tsr_sigma) + if transformer.is_longcat: + noise_pred = -noise_pred - if transformer.is_longcat: - noise_pred = -noise_pred - - if len(timestep.shape) != 1 and clean_latent_indices and not is_pusa: #5b and longcat, skip clean latents for scheduler step - step_process_indices = [i for i in range(latent.shape[1]) if i not in clean_latent_indices] - latent[:, step_process_indices] = sample_scheduler.step(noise_pred[:, step_process_indices].unsqueeze(0), orig_timestep, - latent[:, step_process_indices].unsqueeze(0), **scheduler_step_args)[0].squeeze(0) - else: - if latents_to_not_step > 0: - raw_latent = latent[:, :latents_to_not_step] - noise_pred_in = noise_pred[:, latents_to_not_step:] - latent = latent[:, latents_to_not_step:] - elif recammaster is not None or mocha_embeds is not None: - noise_pred_in = noise_pred[:, :orig_noise_len] - latent = latent[:, :orig_noise_len] - else: - noise_pred_in = noise_pred - latent = sample_scheduler.step(noise_pred_in.unsqueeze(0), timestep, latent.unsqueeze(0), **scheduler_step_args)[0].squeeze(0) - if noise_pred_flipped is not None: - latent_backwards = sample_scheduler_flipped.step(noise_pred_flipped.unsqueeze(0), timestep, latent_flipped.unsqueeze(0), **scheduler_step_args)[0].squeeze(0) - latent_backwards = torch.flip(latent_backwards, dims=[1]) - latent = latent * 0.5 + latent_backwards * 0.5 - if latents_to_not_step > 0: - latent = torch.cat([raw_latent, latent], dim=1) - - if latent_ovi is not None: - latent_ovi = sample_scheduler_ovi.step(noise_pred_ovi.unsqueeze(0), t, latent_ovi.to(device).unsqueeze(0), **scheduler_step_args)[0].squeeze(0) - - #InfiniteTalk first frame handling - if (extra_latents is not None - and not multitalk_sampling - and transformer.multitalk_model_type=="InfiniteTalk"): - for entry in extra_latents: - add_index = entry["index"] - num_extra_frames = entry["samples"].shape[2] - latent[:, add_index:add_index+num_extra_frames] = entry["samples"].to(latent) - - # differential diffusion inpaint - if masks is not None: - if idx < len(timesteps) - 1: - noise_timestep = timesteps[idx+1] - image_latent = sample_scheduler.scale_noise( - original_image.to(device), torch.tensor([noise_timestep]), noise.to(device) - ) - mask = masks[idx].to(latent) - latent = image_latent * mask + latent * (1-mask) - - # TTM - if ttm_reference_latents is not None and (idx + ttm_start_step) < ttm_end_step: - if idx + ttm_start_step + 1 < len(sample_scheduler.all_timesteps): - noisy_latents = add_noise(ttm_reference_latents, noise, sample_scheduler.all_timesteps[idx + ttm_start_step + 1].to(noise.device)).to(latent) - latent = latent * (1 - motion_mask) + noisy_latents * motion_mask - else: - latent = latent * (1 - motion_mask) + ttm_reference_latents.to(latent) * motion_mask - - if freeinit_args is not None: - current_latent = latent.clone() - - if callback is not None: - if recammaster is not None or mocha_embeds is not None: - callback_latent = (latent_model_input[:, :orig_noise_len].to(device) - noise_pred[:, :orig_noise_len].to(device) * t.to(device) / 1000).detach() - #elif phantom_latents is not None: - # callback_latent = (latent_model_input[:,:-phantom_latents.shape[1]].to(device) - noise_pred[:,:-phantom_latents.shape[1]].to(device) * t.to(device) / 1000).detach() - elif humo_reference_count > 0: - callback_latent = (latent_model_input[:,:-humo_reference_count].to(device) - noise_pred[:,:-humo_reference_count].to(device) * t.to(device) / 1000).detach() - elif "rcm" in sample_scheduler.__class__.__name__.lower(): - callback_latent = (latent_model_input.to(device) - noise_pred.to(device) * t.to(device)).detach() - else: - callback_latent = (latent_model_input.to(device) - noise_pred.to(device) * t.to(device) / 1000).detach() - callback(idx, callback_latent.permute(1,0,2,3), None, len(timesteps)) - else: - pbar.update(1) + if len(timestep.shape) != 1 and clean_latent_indices and not is_pusa: #5b and longcat, skip clean latents for scheduler step + step_process_indices = [i for i in range(latent.shape[1]) if i not in clean_latent_indices] + latent[:, step_process_indices] = sample_scheduler.step(noise_pred[:, step_process_indices].unsqueeze(0), orig_timestep, + latent[:, step_process_indices].unsqueeze(0), **scheduler_step_args)[0].squeeze(0) else: - if callback is not None: - callback_latent = (zt_tgt.to(device) - vt_tgt.to(device) * t.to(device) / 1000).detach() - callback(idx, callback_latent.permute(1,0,2,3), None, len(timesteps)) + if latents_to_not_step > 0: + raw_latent = latent[:, :latents_to_not_step] + noise_pred_in = noise_pred[:, latents_to_not_step:] + latent = latent[:, latents_to_not_step:] + elif recammaster is not None or mocha_embeds is not None: + noise_pred_in = noise_pred[:, :orig_noise_len] + latent = latent[:, :orig_noise_len] else: - pbar.update(1) + noise_pred_in = noise_pred + latent = sample_scheduler.step(noise_pred_in.unsqueeze(0), timestep, latent.unsqueeze(0), **scheduler_step_args)[0].squeeze(0) + if noise_pred_flipped is not None: + latent_backwards = sample_scheduler_flipped.step(noise_pred_flipped.unsqueeze(0), timestep, latent_flipped.unsqueeze(0), **scheduler_step_args)[0].squeeze(0) + latent_backwards = torch.flip(latent_backwards, dims=[1]) + latent = latent * 0.5 + latent_backwards * 0.5 + if latents_to_not_step > 0: + latent = torch.cat([raw_latent, latent], dim=1) + + if latent_ovi is not None: + latent_ovi = sample_scheduler_ovi.step(noise_pred_ovi.unsqueeze(0), t, latent_ovi.to(device).unsqueeze(0), **scheduler_step_args)[0].squeeze(0) + + #InfiniteTalk first frame handling + if (extra_latents is not None + and not multitalk_sampling + and transformer.multitalk_model_type=="InfiniteTalk"): + for entry in extra_latents: + add_index = entry["index"] + num_extra_frames = entry["samples"].shape[2] + latent[:, add_index:add_index+num_extra_frames] = entry["samples"].to(latent) + + # differential diffusion inpaint + if masks is not None: + if idx < len(timesteps) - 1: + noise_timestep = timesteps[idx+1] + image_latent = sample_scheduler.scale_noise( + original_image.to(device), torch.tensor([noise_timestep]), noise.to(device) + ) + mask = masks[idx].to(latent) + latent = image_latent * mask + latent * (1-mask) + + # TTM + if ttm_reference_latents is not None and (idx + ttm_start_step) < ttm_end_step: + if idx + ttm_start_step + 1 < len(sample_scheduler.all_timesteps): + noisy_latents = add_noise(ttm_reference_latents, noise, sample_scheduler.all_timesteps[idx + ttm_start_step + 1].to(noise.device)).to(latent) + latent = latent * (1 - motion_mask) + noisy_latents * motion_mask + else: + latent = latent * (1 - motion_mask) + ttm_reference_latents.to(latent) * motion_mask + + if freeinit_args is not None: + current_latent = latent.clone() + + if callback is not None: + if recammaster is not None or mocha_embeds is not None: + callback_latent = (latent_model_input[:, :orig_noise_len].to(device) - noise_pred[:, :orig_noise_len].to(device) * t.to(device) / 1000).detach() + #elif phantom_latents is not None: + # callback_latent = (latent_model_input[:,:-phantom_latents.shape[1]].to(device) - noise_pred[:,:-phantom_latents.shape[1]].to(device) * t.to(device) / 1000).detach() + elif humo_reference_count > 0: + callback_latent = (latent_model_input[:,:-humo_reference_count].to(device) - noise_pred[:,:-humo_reference_count].to(device) * t.to(device) / 1000).detach() + elif "rcm" in sample_scheduler.__class__.__name__.lower(): + callback_latent = (latent_model_input.to(device) - noise_pred.to(device) * t.to(device)).detach() + else: + callback_latent = (latent_model_input.to(device) - noise_pred.to(device) * t.to(device) / 1000).detach() + callback(idx, callback_latent.permute(1,0,2,3), None, len(timesteps)) + else: + pbar.update(1) + except Exception as e: log.error(f"Error during sampling: {e}") if force_offload: diff --git a/utils.py b/utils.py index ddfb1c1..243e5a6 100644 --- a/utils.py +++ b/utils.py @@ -4,17 +4,99 @@ import logging import math from tqdm import tqdm from pathlib import Path -import os +import gc import types, collections from comfy.utils import ProgressBar, copy_to_param, set_attr_param from comfy.model_patcher import get_key_weight, string_to_seed from comfy.lora import calculate_weight -from comfy.model_management import cast_to_device + from comfy.float import stochastic_rounding +from .custom_linear import remove_lora_from_module import folder_paths logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') log = logging.getLogger(__name__) +import comfy.model_management as mm +device = mm.get_torch_device() +offload_device = mm.unet_offload_device() + +try: + from .gguf.gguf import GGUFParameter +except: + pass + +class MetaParameter(torch.nn.Parameter): + def __new__(cls, dtype, quant_type=None): + data = torch.empty(0, dtype=dtype) + self = torch.nn.Parameter(data, requires_grad=False) + self.quant_type = quant_type + return self + +def offload_transformer(transformer, remove_lora=True): + transformer.teacache_state.clear_all() + transformer.magcache_state.clear_all() + transformer.easycache_state.clear_all() + + if transformer.patched_linear: + for name, param in transformer.named_parameters(): + if "loras" in name or "controlnet" in name: + continue + module = transformer + subnames = name.split('.') + for subname in subnames[:-1]: + module = getattr(module, subname) + attr_name = subnames[-1] + if param.data.is_floating_point(): + meta_param = torch.nn.Parameter(torch.empty_like(param.data, device='meta'), requires_grad=False) + setattr(module, attr_name, meta_param) + elif isinstance(param.data, GGUFParameter): + quant_type = getattr(param, 'quant_type', None) + setattr(module, attr_name, MetaParameter(param.data.dtype, quant_type)) + else: + pass + if remove_lora: + remove_lora_from_module(transformer) + else: + transformer.to(offload_device) + + for block in transformer.blocks: + block.kv_cache = None + if transformer.audio_model is not None and hasattr(block, 'audio_block'): + block.audio_block = None + + mm.soft_empty_cache() + gc.collect() + + +def init_blockswap(transformer, block_swap_args, model): + if not transformer.patched_linear: + if block_swap_args is not None: + for name, param in transformer.named_parameters(): + if "block" not in name or "control_adapter" in name or "face" in name: + param.data = param.data.to(device) + elif block_swap_args["offload_txt_emb"] and "txt_emb" in name: + param.data = param.data.to(offload_device) + elif block_swap_args["offload_img_emb"] and "img_emb" in name: + param.data = param.data.to(offload_device) + + transformer.block_swap( + block_swap_args["blocks_to_swap"] - 1 , + block_swap_args["offload_txt_emb"], + block_swap_args["offload_img_emb"], + vace_blocks_to_swap = block_swap_args.get("vace_blocks_to_swap", None), + ) + elif model["auto_cpu_offload"]: + for module in transformer.modules(): + if hasattr(module, "offload"): + module.offload() + if hasattr(module, "onload"): + module.onload() + for block in transformer.blocks: + block.modulation = torch.nn.Parameter(block.modulation.to(device)) + transformer.head.modulation = torch.nn.Parameter(transformer.head.modulation.to(device)) + else: + transformer.to(device) + def check_device_same(first_device, second_device): if first_device.type != second_device.type: return False @@ -140,7 +222,7 @@ def patch_weight_to_device(self, key, device_to=None, inplace_update=False, back self.backup[key] = collections.namedtuple('Dimension', ['weight', 'inplace_update'])(weight.to(device=self.offload_device, copy=inplace_update), inplace_update) if device_to is not None: - temp_weight = cast_to_device(weight, device_to, torch.float32, copy=True) + temp_weight = mm.cast_to_device(weight, device_to, torch.float32, copy=True) else: temp_weight = weight.to(torch.float32, copy=True) if convert_func is not None: diff --git a/wanvideo/schedulers/__init__.py b/wanvideo/schedulers/__init__.py index abb450f..b5d6c62 100644 --- a/wanvideo/schedulers/__init__.py +++ b/wanvideo/schedulers/__init__.py @@ -42,7 +42,7 @@ def _apply_custom_sigmas(sample_scheduler, sigmas, device): sample_scheduler.timesteps = (sample_scheduler.sigmas[:-1] * 1000).to(torch.int64).to(device) sample_scheduler.num_inference_steps = len(sample_scheduler.timesteps) -def get_scheduler(scheduler, steps, start_step, end_step, shift, device, transformer_dim=5120, flowedit_args=None, denoise_strength=1.0, sigmas=None, log_timesteps=False, enhance_hf=False, **kwargs): +def get_scheduler(scheduler, steps, start_step, end_step, shift, device, transformer_dim=5120, denoise_strength=1.0, sigmas=None, log_timesteps=False, enhance_hf=False, **kwargs): timesteps = None if sigmas is not None: steps = len(sigmas) - 1 From b2c520ca448606180d0c802829b7d60aa0b2b802 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 12:55:13 +0200 Subject: [PATCH 08/22] Fix s2v --- wanvideo/modules/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wanvideo/modules/model.py b/wanvideo/modules/model.py index 89f180f..2a0b794 100644 --- a/wanvideo/modules/model.py +++ b/wanvideo/modules/model.py @@ -2187,7 +2187,7 @@ class WanModel(torch.nn.Module): def rope_encode_comfy(self, t, h, w, freq_offset=0, t_start=0, ref_frame_shape=None, pose_frame_shape=None, steps_t=None, steps_h=None, steps_w=None, ntk_alphas=[1,1,1], device=None, dtype=None, - ref_frame_index=10, longcat_num_ref_latents=None): + ref_frame_index=10, longcat_num_ref_latents=0): patch_size = self.patch_size t_len = ((t + (patch_size[0] // 2)) // patch_size[0]) From 027bed8c3d91b7b97f5b5ee069ce233fab9154e7 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 13:51:05 +0200 Subject: [PATCH 09/22] Cleanup --- nodes_sampler.py | 28 ++++++++++++---------------- wanvideo/modules/model.py | 2 +- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/nodes_sampler.py b/nodes_sampler.py index e1216a9..42fd8cf 100644 --- a/nodes_sampler.py +++ b/nodes_sampler.py @@ -599,12 +599,10 @@ class WanVideoSampler: portrait_cfg = [portrait_cfg] * (steps + 1) # MiniMax Remover - minimax_latents = minimax_mask_latents = None minimax_latents = image_embeds.get("minimax_latents", None) minimax_mask_latents = image_embeds.get("minimax_mask_latents", None) if minimax_latents is not None: - log.info(f"minimax_latents: {minimax_latents.shape}") - log.info(f"minimax_mask_latents: {minimax_mask_latents.shape}") + log.info(f"minimax_latents: {minimax_latents.shape}, minimax_mask_latents: {minimax_mask_latents.shape}") minimax_latents = minimax_latents.to(device, dtype) minimax_mask_latents = minimax_mask_latents.to(device, dtype) @@ -691,7 +689,7 @@ class WanVideoSampler: framepack = False s2v_audio_embeds = image_embeds.get("audio_embeds", None) if s2v_audio_embeds is not None: - log.info(f"Using S2V audio embeddings") + log.info("Using S2V audio embeddings") framepack = s2v_audio_embeds.get("enable_framepack", False) if framepack and context_options is not None: raise ValueError("S2V framepack and context windows cannot be used at the same time") @@ -1685,7 +1683,6 @@ class WanVideoSampler: log.info(f"Input sequence length: {seq_len}") log.info(f"Sampling {(latent_video_length-1) * 4 + 1} frames at {latent.shape[3]*vae_upscale_factor}x{latent.shape[2]*vae_upscale_factor} with {steps-ttm_start_step} steps") - intermediate_device = device # Differential diffusion prep masks = None @@ -1826,8 +1823,8 @@ class WanVideoSampler: enhance_enabled = True #region context windowing elif context_options is not None: - counter = torch.zeros_like(latent_model_input, device=intermediate_device) - noise_pred = torch.zeros_like(latent_model_input, device=intermediate_device) + counter = torch.zeros_like(latent_model_input, device=device) + noise_pred = torch.zeros_like(latent_model_input, device=device) context_queue = list(context(idx, steps, latent_video_length, context_frames, context_stride, context_overlap)) fraction_per_context = 1.0 / len(context_queue) context_pbar = ProgressBar(steps) @@ -1857,13 +1854,12 @@ class WanVideoSampler: else: positive = text_embeds["prompt_embeds"] - partial_img_emb = None - partial_control_latents = None + partial_img_emb = partial_control_latents = None if image_cond is not None: - partial_img_emb = image_cond[:, c] + partial_img_emb = image_cond[:, c].to(device) if c[0] != 0 and context_reference_latent is not None: if context_reference_latent.shape[0] == 1: #only single extra init latent - new_init_image = context_reference_latent[0, :, 0].to(intermediate_device) + new_init_image = context_reference_latent[0, :, 0].to(device) # Concatenate the first 4 channels of partial_img_emb with new_init_image to match the required shape partial_img_emb[:, 0] = torch.cat([image_cond[:4, 0], new_init_image], dim=0) elif context_reference_latent.shape[0] > 1: @@ -1872,10 +1868,10 @@ class WanVideoSampler: extra_init_index = min(int(max(c) / section_size), num_extra_inits - 1) if context_options["verbose"]: log.info(f"extra init image index: {extra_init_index}") - new_init_image = context_reference_latent[extra_init_index, :, 0].to(intermediate_device) + new_init_image = context_reference_latent[extra_init_index, :, 0].to(device) partial_img_emb[:, 0] = torch.cat([image_cond[:4, 0], new_init_image], dim=0) else: - new_init_image = image_cond[:, 0].to(intermediate_device) + new_init_image = image_cond[:, 0].to(device) partial_img_emb[:, 0] = new_init_image if control_latents is not None: @@ -1893,14 +1889,14 @@ class WanVideoSampler: if has_ref: if c[0] != 0 and context_reference_latent is not None: if context_reference_latent.shape[0] == 1: #only single extra init latent - partial_context[16:32, :1] = context_reference_latent[0, :, :1].to(intermediate_device) + partial_context[16:32, :1] = context_reference_latent[0, :, :1].to(device) elif context_reference_latent.shape[0] > 1: num_extra_inits = context_reference_latent.shape[0] section_size = (latent_video_length / num_extra_inits) extra_init_index = min(int(max(c) / section_size), num_extra_inits - 1) if context_options["verbose"]: log.info(f"extra init image index: {extra_init_index}") - partial_context[16:32, :1] = context_reference_latent[extra_init_index, :, :1].to(intermediate_device) + partial_context[16:32, :1] = context_reference_latent[extra_init_index, :, :1].to(device) else: partial_context[:, 0] = vace_entry["context"][0][:, 0] @@ -2479,7 +2475,7 @@ class WanVideoSampler: noise_pred = torch.cat([noise_pred[:, latent_video_length - shift_idx:]] + [noise_pred[:, :latent_video_length - shift_idx]], dim=1) shift_idx = (shift_idx + latent_skip) % latent_video_length - latent = latent.to(intermediate_device) + latent = latent.to(device) if self.noise_front_pad_num > 0: noise_pred = noise_pred[:, self.noise_front_pad_num:] diff --git a/wanvideo/modules/model.py b/wanvideo/modules/model.py index 2a0b794..96df41c 100644 --- a/wanvideo/modules/model.py +++ b/wanvideo/modules/model.py @@ -2648,7 +2648,7 @@ class WanModel(torch.nn.Module): device=x.device, dtype=x.dtype ) - log.info("Generated new RoPE frequencies") + tqdm.write("Generated new RoPE frequencies") if s2v_ref_latent is not None: freqs_ref = self.rope_encode_comfy( From 220aac277155d286092ec79f5cf426b9fa4e7f29 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 13:52:27 +0200 Subject: [PATCH 10/22] Update LongCatAvatar_audio_image_to_video_example_01.json --- ...vatar_audio_image_to_video_example_01.json | 1209 ++++++++--------- 1 file changed, 554 insertions(+), 655 deletions(-) diff --git a/example_workflows/LongCatAvatar_audio_image_to_video_example_01.json b/example_workflows/LongCatAvatar_audio_image_to_video_example_01.json index cfd6784..f982637 100644 --- a/example_workflows/LongCatAvatar_audio_image_to_video_example_01.json +++ b/example_workflows/LongCatAvatar_audio_image_to_video_example_01.json @@ -18,7 +18,7 @@ "flags": { "collapsed": true }, - "order": 69, + "order": 66, "mode": 0, "inputs": [ { @@ -42,44 +42,6 @@ "wanmodel" ] }, - { - "id": 264, - "type": "SetNode", - "pos": [ - 1774.0058566239184, - -2289.9456989986097 - ], - "size": [ - 210, - 60 - ], - "flags": { - "collapsed": true - }, - "order": 63, - "mode": 0, - "inputs": [ - { - "name": "CLIP_VISION", - "type": "CLIP_VISION", - "link": 466 - } - ], - "outputs": [ - { - "name": "*", - "type": "*", - "links": null - } - ], - "title": "Set_clip_vision_model", - "properties": { - "previousName": "clip_vision_model" - }, - "widgets_values": [ - "clip_vision_model" - ] - }, { "id": 247, "type": "SetNode", @@ -94,7 +56,7 @@ "flags": { "collapsed": true }, - "order": 55, + "order": 53, "mode": 0, "inputs": [ { @@ -134,7 +96,7 @@ "flags": { "collapsed": true }, - "order": 56, + "order": 54, "mode": 0, "inputs": [ { @@ -206,7 +168,7 @@ 112 ], "flags": {}, - "order": 76, + "order": 73, "mode": 0, "inputs": [ { @@ -217,9 +179,9 @@ ], "outputs": [], "properties": { - "Node name for S&R": "PreviewAny", "cnr_id": "comfy-core", - "ver": "0.3.50" + "ver": "0.3.50", + "Node name for S&R": "PreviewAny" }, "widgets_values": [ null, @@ -261,29 +223,6 @@ "color": "#1b4669", "bgcolor": "#29699c" }, - { - "id": 299, - "type": "Note", - "pos": [ - 1486.8775607254809, - -2203.5067341548597 - ], - "size": [ - 290.9361267089844, - 88 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "Clip vision is not strictly necessary\n\nAny I2V model should work, MAGREF can be interesting to play with as well." - ], - "color": "#432", - "bgcolor": "#653" - }, { "id": 240, "type": "SetNode", @@ -298,7 +237,7 @@ "flags": { "collapsed": true }, - "order": 58, + "order": 56, "mode": 0, "inputs": [ { @@ -336,7 +275,7 @@ 314 ], "flags": {}, - "order": 3, + "order": 2, "mode": 0, "inputs": [], "outputs": [ @@ -354,9 +293,9 @@ } ], "properties": { - "Node name for S&R": "LoadImage", "cnr_id": "comfy-core", - "ver": "0.3.50" + "ver": "0.3.50", + "Node name for S&R": "LoadImage" }, "widgets_values": [ "man.png", @@ -375,7 +314,7 @@ 58 ], "flags": {}, - "order": 4, + "order": 3, "mode": 0, "inputs": [], "outputs": [ @@ -389,9 +328,9 @@ ], "title": "Width", "properties": { - "Node name for S&R": "INTConstant", "cnr_id": "comfyui-kjnodes", - "ver": "e435e999e4b1a828a6b5f6d8f037e66f4a798324" + "ver": "e435e999e4b1a828a6b5f6d8f037e66f4a798324", + "Node name for S&R": "INTConstant" }, "widgets_values": [ 832 @@ -411,7 +350,7 @@ 58 ], "flags": {}, - "order": 5, + "order": 4, "mode": 0, "inputs": [], "outputs": [ @@ -425,9 +364,9 @@ ], "title": "Height", "properties": { - "Node name for S&R": "INTConstant", "cnr_id": "comfyui-kjnodes", - "ver": "e435e999e4b1a828a6b5f6d8f037e66f4a798324" + "ver": "e435e999e4b1a828a6b5f6d8f037e66f4a798324", + "Node name for S&R": "INTConstant" }, "widgets_values": [ 480 @@ -447,7 +386,7 @@ 46 ], "flags": {}, - "order": 67, + "order": 64, "mode": 0, "inputs": [ { @@ -476,9 +415,9 @@ } ], "properties": { - "Node name for S&R": "MelBandRoFormerSampler", "cnr_id": "ComfyUI-MelBandRoFormer", - "ver": "b68d9077815387b64d596f8c39607052b95b6eba" + "ver": "b68d9077815387b64d596f8c39607052b95b6eba", + "Node name for S&R": "MelBandRoFormerSampler" }, "widgets_values": [] }, @@ -494,7 +433,7 @@ 336 ], "flags": {}, - "order": 54, + "order": 52, "mode": 0, "inputs": [ { @@ -550,9 +489,9 @@ } ], "properties": { - "Node name for S&R": "ImageResizeKJv2", "cnr_id": "comfyui-kjnodes", - "ver": "f7eb33abc80a2aded1b46dff0dd14d07856a7d50" + "ver": "f7eb33abc80a2aded1b46dff0dd14d07856a7d50", + "Node name for S&R": "ImageResizeKJv2" }, "widgets_values": [ 832, @@ -562,8 +501,7 @@ "0, 0, 0", "center", 16, - "cpu", - "Output: 1 x 832 x 480 | 4.57MB" + "cpu" ] }, { @@ -580,7 +518,7 @@ "flags": { "collapsed": true }, - "order": 65, + "order": 61, "mode": 0, "inputs": [ { @@ -616,7 +554,7 @@ 136 ], "flags": {}, - "order": 6, + "order": 5, "mode": 0, "inputs": [], "outputs": [ @@ -629,9 +567,9 @@ } ], "properties": { - "Node name for S&R": "LoadAudio", "cnr_id": "comfy-core", - "ver": "0.3.41" + "ver": "0.3.41", + "Node name for S&R": "LoadAudio" }, "widgets_values": [ "man.mp3", @@ -651,7 +589,7 @@ 106 ], "flags": {}, - "order": 7, + "order": 6, "mode": 0, "inputs": [ { @@ -672,9 +610,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoVAELoader", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "c3ee35f3ece76e38099dc516182d69b406e16772" + "ver": "c3ee35f3ece76e38099dc516182d69b406e16772", + "Node name for S&R": "WanVideoVAELoader" }, "widgets_values": [ "Wan2_1_VAE_bf16.safetensors", @@ -696,7 +634,7 @@ 82 ], "flags": {}, - "order": 57, + "order": 55, "mode": 0, "inputs": [ { @@ -716,9 +654,9 @@ } ], "properties": { - "Node name for S&R": "TrimAudioDuration", "cnr_id": "comfy-core", - "ver": "0.5.0" + "ver": "0.5.0", + "Node name for S&R": "TrimAudioDuration" }, "widgets_values": [ 0, @@ -737,7 +675,7 @@ 386.354248046875 ], "flags": {}, - "order": 8, + "order": 7, "mode": 0, "inputs": [ { @@ -768,9 +706,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoTextEncodeCached", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "ff779c91714d8ee3484cd4119b082c72a1734b72" + "ver": "ff779c91714d8ee3484cd4119b082c72a1734b72", + "Node name for S&R": "WanVideoTextEncodeCached" }, "widgets_values": [ "umt5-xxl-enc-bf16.safetensors", @@ -798,7 +736,7 @@ "flags": { "collapsed": true }, - "order": 59, + "order": 57, "mode": 0, "inputs": [ { @@ -834,7 +772,7 @@ 58 ], "flags": {}, - "order": 9, + "order": 8, "mode": 0, "inputs": [], "outputs": [ @@ -848,6 +786,8 @@ ], "title": "cfg", "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "79f529a84a8c20fe5dcdfa984c6be7a94102c014", "Node name for S&R": "FloatConstant" }, "widgets_values": [ @@ -870,7 +810,7 @@ "flags": { "collapsed": true }, - "order": 10, + "order": 9, "mode": 0, "inputs": [], "outputs": [ @@ -904,7 +844,7 @@ "flags": { "collapsed": true }, - "order": 11, + "order": 10, "mode": 0, "inputs": [], "outputs": [ @@ -938,7 +878,7 @@ "flags": { "collapsed": true }, - "order": 85, + "order": 82, "mode": 0, "inputs": [ { @@ -968,9 +908,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoEncode", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490" + "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490", + "Node name for S&R": "WanVideoEncode" }, "widgets_values": [ false, @@ -998,7 +938,7 @@ "flags": { "collapsed": true }, - "order": 12, + "order": 11, "mode": 0, "inputs": [], "outputs": [ @@ -1033,7 +973,7 @@ "flags": { "collapsed": true }, - "order": 87, + "order": 84, "mode": 0, "inputs": [ { @@ -1058,9 +998,9 @@ } ], "properties": { - "Node name for S&R": "ReplaceVideoLatentFrames", "cnr_id": "comfy-core", - "ver": "0.5.0" + "ver": "0.5.0", + "Node name for S&R": "ReplaceVideoLatentFrames" }, "widgets_values": [ 0 @@ -1080,7 +1020,7 @@ "flags": { "collapsed": true }, - "order": 13, + "order": 12, "mode": 0, "inputs": [], "outputs": [ @@ -1114,7 +1054,7 @@ "flags": { "collapsed": true }, - "order": 14, + "order": 13, "mode": 0, "inputs": [], "outputs": [ @@ -1146,7 +1086,7 @@ "flags": { "collapsed": true }, - "order": 15, + "order": 14, "mode": 0, "inputs": [], "outputs": [ @@ -1180,7 +1120,7 @@ "flags": { "collapsed": true }, - "order": 16, + "order": 15, "mode": 0, "inputs": [], "outputs": [ @@ -1210,7 +1150,7 @@ 426.8679387019231 ], "flags": {}, - "order": 75, + "order": 72, "mode": 0, "inputs": [ { @@ -1270,9 +1210,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoSamplerv2", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd" + "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd", + "Node name for S&R": "WanVideoSamplerv2" }, "widgets_values": [ 1, @@ -1294,7 +1234,7 @@ 26 ], "flags": {}, - "order": 77, + "order": 74, "mode": 0, "inputs": [ { @@ -1332,7 +1272,7 @@ "flags": { "collapsed": true }, - "order": 17, + "order": 16, "mode": 0, "inputs": [], "outputs": [ @@ -1365,7 +1305,7 @@ 26 ], "flags": {}, - "order": 81, + "order": 78, "mode": 0, "inputs": [ { @@ -1403,7 +1343,7 @@ "flags": { "collapsed": true }, - "order": 18, + "order": 17, "mode": 0, "inputs": [], "outputs": [ @@ -1437,7 +1377,7 @@ "flags": { "collapsed": true }, - "order": 19, + "order": 18, "mode": 0, "inputs": [], "outputs": [ @@ -1469,7 +1409,7 @@ 58 ], "flags": {}, - "order": 20, + "order": 19, "mode": 0, "inputs": [], "outputs": [ @@ -1483,6 +1423,8 @@ ], "title": "frames_per_window", "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "79f529a84a8c20fe5dcdfa984c6be7a94102c014", "Node name for S&R": "INTConstant" }, "widgets_values": [ @@ -1505,7 +1447,7 @@ "flags": { "collapsed": true }, - "order": 61, + "order": 59, "mode": 0, "inputs": [ { @@ -1545,7 +1487,7 @@ "flags": { "collapsed": true }, - "order": 62, + "order": 60, "mode": 0, "inputs": [ { @@ -1585,7 +1527,7 @@ "flags": { "collapsed": true }, - "order": 60, + "order": 58, "mode": 0, "inputs": [ { @@ -1625,7 +1567,7 @@ "flags": { "collapsed": true }, - "order": 21, + "order": 20, "mode": 0, "inputs": [], "outputs": [ @@ -1645,40 +1587,6 @@ "color": "#1b4669", "bgcolor": "#29699c" }, - { - "id": 413, - "type": "GetNode", - "pos": [ - 5071.410986510317, - -1685.578721396226 - ], - "size": [ - 210, - 60 - ], - "flags": { - "collapsed": true - }, - "order": 22, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "LATENT", - "type": "LATENT", - "links": [ - 775 - ] - } - ], - "title": "Get_ref_latent", - "properties": {}, - "widgets_values": [ - "ref_latent" - ], - "color": "#323", - "bgcolor": "#535" - }, { "id": 443, "type": "GetNode", @@ -1693,7 +1601,7 @@ "flags": { "collapsed": true }, - "order": 23, + "order": 21, "mode": 0, "inputs": [], "outputs": [ @@ -1727,7 +1635,7 @@ "flags": { "collapsed": true }, - "order": 70, + "order": 67, "mode": 0, "inputs": [ { @@ -1767,7 +1675,7 @@ "flags": { "collapsed": true }, - "order": 24, + "order": 22, "mode": 0, "inputs": [], "outputs": [ @@ -1801,7 +1709,7 @@ "flags": { "collapsed": true }, - "order": 25, + "order": 23, "mode": 0, "inputs": [], "outputs": [ @@ -1833,7 +1741,7 @@ 242 ], "flags": {}, - "order": 66, + "order": 63, "mode": 0, "inputs": [ { @@ -1863,9 +1771,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoEncode", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490" + "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490", + "Node name for S&R": "WanVideoEncode" }, "widgets_values": [ false, @@ -1891,7 +1799,7 @@ 198 ], "flags": {}, - "order": 78, + "order": 75, "mode": 0, "inputs": [ { @@ -1916,9 +1824,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoDecode", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490" + "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490", + "Node name for S&R": "WanVideoDecode" }, "widgets_values": [ false, @@ -1943,7 +1851,7 @@ 238 ], "flags": {}, - "order": 72, + "order": 69, "mode": 0, "inputs": [ { @@ -1992,9 +1900,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoLongCatAvatarExtendEmbeds", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd" + "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd", + "Node name for S&R": "WanVideoLongCatAvatarExtendEmbeds" }, "widgets_values": [ 93, @@ -2019,7 +1927,7 @@ 146 ], "flags": {}, - "order": 89, + "order": 86, "mode": 0, "inputs": [ { @@ -2063,9 +1971,9 @@ } ], "properties": { - "Node name for S&R": "ImageBatchExtendWithOverlap", "cnr_id": "comfyui-kjnodes", - "ver": "16cbf238a74cac17082d6888bc8934899c850645" + "ver": "16cbf238a74cac17082d6888bc8934899c850645", + "Node name for S&R": "ImageBatchExtendWithOverlap" }, "widgets_values": [ 13, @@ -2075,40 +1983,6 @@ "color": "#2a363b", "bgcolor": "#3f5159" }, - { - "id": 418, - "type": "GetNode", - "pos": [ - 5063.620609727339, - -1950.8726913782168 - ], - "size": [ - 210, - 60 - ], - "flags": { - "collapsed": true - }, - "order": 26, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "MULTITALK_EMBEDS", - "type": "MULTITALK_EMBEDS", - "links": [ - 783 - ] - } - ], - "title": "Get_audio_embeds", - "properties": {}, - "widgets_values": [ - "audio_embeds" - ], - "color": "#323", - "bgcolor": "#535" - }, { "id": 344, "type": "GetImageSizeAndCount", @@ -2121,7 +1995,7 @@ 86 ], "flags": {}, - "order": 80, + "order": 77, "mode": 0, "inputs": [ { @@ -2160,9 +2034,9 @@ } ], "properties": { - "Node name for S&R": "GetImageSizeAndCount", "cnr_id": "comfyui-kjnodes", - "ver": "16cbf238a74cac17082d6888bc8934899c850645" + "ver": "16cbf238a74cac17082d6888bc8934899c850645", + "Node name for S&R": "GetImageSizeAndCount" }, "widgets_values": [], "color": "#2a363b", @@ -2182,7 +2056,7 @@ "flags": { "collapsed": true }, - "order": 83, + "order": 80, "mode": 0, "inputs": [ { @@ -2221,9 +2095,9 @@ } ], "properties": { - "Node name for S&R": "GetImageRangeFromBatch", "cnr_id": "comfyui-kjnodes", - "ver": "16cbf238a74cac17082d6888bc8934899c850645" + "ver": "16cbf238a74cac17082d6888bc8934899c850645", + "Node name for S&R": "GetImageRangeFromBatch" }, "widgets_values": [ -1, @@ -2246,7 +2120,7 @@ "flags": { "collapsed": true }, - "order": 88, + "order": 85, "mode": 0, "inputs": [ { @@ -2270,9 +2144,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoDecode", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490" + "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490", + "Node name for S&R": "WanVideoDecode" }, "widgets_values": [ false, @@ -2299,7 +2173,7 @@ "flags": { "collapsed": true }, - "order": 27, + "order": 24, "mode": 0, "inputs": [], "outputs": [ @@ -2333,7 +2207,7 @@ "flags": { "collapsed": true }, - "order": 28, + "order": 25, "mode": 0, "inputs": [], "outputs": [ @@ -2367,7 +2241,7 @@ "flags": { "collapsed": true }, - "order": 97, + "order": 94, "mode": 0, "inputs": [ { @@ -2397,9 +2271,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoEncode", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490" + "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490", + "Node name for S&R": "WanVideoEncode" }, "widgets_values": [ false, @@ -2427,7 +2301,7 @@ "flags": { "collapsed": true }, - "order": 29, + "order": 26, "mode": 0, "inputs": [], "outputs": [ @@ -2462,7 +2336,7 @@ "flags": { "collapsed": true }, - "order": 98, + "order": 95, "mode": 0, "inputs": [ { @@ -2487,9 +2361,9 @@ } ], "properties": { - "Node name for S&R": "ReplaceVideoLatentFrames", "cnr_id": "comfy-core", - "ver": "0.5.0" + "ver": "0.5.0", + "Node name for S&R": "ReplaceVideoLatentFrames" }, "widgets_values": [ 0 @@ -2509,7 +2383,7 @@ "flags": { "collapsed": true }, - "order": 30, + "order": 27, "mode": 0, "inputs": [], "outputs": [ @@ -2543,7 +2417,7 @@ "flags": { "collapsed": true }, - "order": 31, + "order": 28, "mode": 0, "inputs": [], "outputs": [ @@ -2575,7 +2449,7 @@ "flags": { "collapsed": true }, - "order": 32, + "order": 29, "mode": 0, "inputs": [], "outputs": [ @@ -2609,7 +2483,7 @@ "flags": { "collapsed": true }, - "order": 33, + "order": 30, "mode": 0, "inputs": [], "outputs": [ @@ -2642,7 +2516,7 @@ 26 ], "flags": {}, - "order": 93, + "order": 90, "mode": 0, "inputs": [ { @@ -2680,7 +2554,7 @@ "flags": { "collapsed": true }, - "order": 34, + "order": 31, "mode": 0, "inputs": [], "outputs": [ @@ -2712,7 +2586,7 @@ 26 ], "flags": {}, - "order": 102, + "order": 99, "mode": 0, "inputs": [ { @@ -2733,40 +2607,6 @@ "horizontal": false } }, - { - "id": 459, - "type": "GetNode", - "pos": [ - 7859.880789998097, - -1675.4559507379802 - ], - "size": [ - 210, - 34 - ], - "flags": { - "collapsed": true - }, - "order": 35, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "LATENT", - "type": "LATENT", - "links": [ - 835 - ] - } - ], - "title": "Get_ref_latent", - "properties": {}, - "widgets_values": [ - "ref_latent" - ], - "color": "#323", - "bgcolor": "#535" - }, { "id": 460, "type": "ImageBatchExtendWithOverlap", @@ -2779,7 +2619,7 @@ 146 ], "flags": {}, - "order": 100, + "order": 97, "mode": 0, "inputs": [ { @@ -2823,9 +2663,9 @@ } ], "properties": { - "Node name for S&R": "ImageBatchExtendWithOverlap", "cnr_id": "comfyui-kjnodes", - "ver": "16cbf238a74cac17082d6888bc8934899c850645" + "ver": "16cbf238a74cac17082d6888bc8934899c850645", + "Node name for S&R": "ImageBatchExtendWithOverlap" }, "widgets_values": [ 13, @@ -2835,132 +2675,6 @@ "color": "#2a363b", "bgcolor": "#3f5159" }, - { - "id": 461, - "type": "WanVideoLongCatAvatarExtendEmbeds", - "pos": [ - 7854.07317149529, - -1892.6690512715838 - ], - "size": [ - 379.476171875, - 238 - ], - "flags": {}, - "order": 94, - "mode": 0, - "inputs": [ - { - "name": "prev_latents", - "type": "LATENT", - "link": 845 - }, - { - "name": "audio_embeds", - "type": "MULTITALK_EMBEDS", - "link": 834 - }, - { - "name": "ref_latent", - "shape": 7, - "type": "LATENT", - "link": 835 - }, - { - "name": "samples", - "shape": 7, - "type": "LATENT", - "link": null - }, - { - "name": "num_frames", - "type": "INT", - "widget": { - "name": "num_frames" - }, - "link": 836 - }, - { - "name": "overlap", - "type": "INT", - "widget": { - "name": "overlap" - }, - "link": 837 - }, - { - "name": "frames_processed", - "type": "INT", - "widget": { - "name": "frames_processed" - }, - "link": 838 - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "links": [ - 826 - ] - }, - { - "name": "samples_slice", - "type": "LATENT", - "links": null - } - ], - "properties": { - "Node name for S&R": "WanVideoLongCatAvatarExtendEmbeds", - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd" - }, - "widgets_values": [ - 93, - 13, - 93, - "pad_with_start", - 10, - 3 - ], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 462, - "type": "GetNode", - "pos": [ - 7852.090413215118, - -1940.749920719971 - ], - "size": [ - 210, - 34 - ], - "flags": { - "collapsed": true - }, - "order": 36, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "MULTITALK_EMBEDS", - "type": "MULTITALK_EMBEDS", - "links": [ - 834 - ] - } - ], - "title": "Get_audio_embeds", - "properties": {}, - "widgets_values": [ - "audio_embeds" - ], - "color": "#323", - "bgcolor": "#535" - }, { "id": 463, "type": "GetImageSizeAndCount", @@ -2973,7 +2687,7 @@ 86 ], "flags": {}, - "order": 92, + "order": 89, "mode": 0, "inputs": [ { @@ -3012,9 +2726,9 @@ } ], "properties": { - "Node name for S&R": "GetImageSizeAndCount", "cnr_id": "comfyui-kjnodes", - "ver": "16cbf238a74cac17082d6888bc8934899c850645" + "ver": "16cbf238a74cac17082d6888bc8934899c850645", + "Node name for S&R": "GetImageSizeAndCount" }, "widgets_values": [], "color": "#2a363b", @@ -3034,7 +2748,7 @@ "flags": { "collapsed": true }, - "order": 95, + "order": 92, "mode": 0, "inputs": [ { @@ -3073,9 +2787,9 @@ } ], "properties": { - "Node name for S&R": "GetImageRangeFromBatch", "cnr_id": "comfyui-kjnodes", - "ver": "16cbf238a74cac17082d6888bc8934899c850645" + "ver": "16cbf238a74cac17082d6888bc8934899c850645", + "Node name for S&R": "GetImageRangeFromBatch" }, "widgets_values": [ -1, @@ -3098,7 +2812,7 @@ "flags": { "collapsed": true }, - "order": 99, + "order": 96, "mode": 0, "inputs": [ { @@ -3122,9 +2836,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoDecode", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490" + "ver": "ae6fe0853e2d1ba0f1f47e086befdb089dc07490", + "Node name for S&R": "WanVideoDecode" }, "widgets_values": [ false, @@ -3151,7 +2865,7 @@ "flags": { "collapsed": true }, - "order": 37, + "order": 32, "mode": 0, "inputs": [], "outputs": [ @@ -3183,7 +2897,7 @@ 26 ], "flags": {}, - "order": 91, + "order": 88, "mode": 0, "inputs": [ { @@ -3218,7 +2932,7 @@ 26 ], "flags": {}, - "order": 86, + "order": 83, "mode": 0, "inputs": [ { @@ -3253,7 +2967,7 @@ 106 ], "flags": {}, - "order": 38, + "order": 33, "mode": 0, "inputs": [], "outputs": [ @@ -3264,9 +2978,9 @@ } ], "properties": { - "Node name for S&R": "Wav2VecModelLoader", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "6fce0e2d3bb976b0006bc6d8e37e1f23460938ee" + "ver": "6fce0e2d3bb976b0006bc6d8e37e1f23460938ee", + "Node name for S&R": "Wav2VecModelLoader" }, "widgets_values": [ "wav2vec2-chinese-base_fp16.safetensors", @@ -3286,7 +3000,7 @@ 106 ], "flags": {}, - "order": 39, + "order": 34, "mode": 0, "inputs": [], "outputs": [ @@ -3299,9 +3013,9 @@ } ], "properties": { - "Node name for S&R": "DownloadAndLoadWav2VecModel", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0" + "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", + "Node name for S&R": "DownloadAndLoadWav2VecModel" }, "widgets_values": [ "TencentGameMate/chinese-wav2vec2-base", @@ -3321,7 +3035,7 @@ 125.51774597167969 ], "flags": {}, - "order": 40, + "order": 35, "mode": 0, "inputs": [], "outputs": [], @@ -3345,7 +3059,7 @@ 58 ], "flags": {}, - "order": 41, + "order": 36, "mode": 0, "inputs": [], "outputs": [ @@ -3358,9 +3072,9 @@ } ], "properties": { - "Node name for S&R": "MelBandRoFormerModelLoader", "cnr_id": "ComfyUI-MelBandRoFormer", - "ver": "b68d9077815387b64d596f8c39607052b95b6eba" + "ver": "b68d9077815387b64d596f8c39607052b95b6eba", + "Node name for S&R": "MelBandRoFormerModelLoader" }, "widgets_values": [ "MelBandRoformer_fp32.safetensors" @@ -3378,7 +3092,7 @@ 91.6759033203125 ], "flags": {}, - "order": 42, + "order": 37, "mode": 0, "inputs": [], "outputs": [], @@ -3404,7 +3118,7 @@ "flags": { "collapsed": true }, - "order": 68, + "order": 65, "mode": 0, "inputs": [ { @@ -3440,7 +3154,7 @@ 212.22914465030635 ], "flags": {}, - "order": 43, + "order": 38, "mode": 0, "inputs": [], "outputs": [], @@ -3463,7 +3177,7 @@ 58 ], "flags": {}, - "order": 44, + "order": 39, "mode": 0, "inputs": [], "outputs": [ @@ -3477,6 +3191,8 @@ ], "title": "Overlap", "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "79f529a84a8c20fe5dcdfa984c6be7a94102c014", "Node name for S&R": "INTConstant" }, "widgets_values": [ @@ -3499,7 +3215,7 @@ "flags": { "collapsed": true }, - "order": 74, + "order": 71, "mode": 0, "inputs": [ { @@ -3541,7 +3257,7 @@ "flags": { "collapsed": true }, - "order": 73, + "order": 70, "mode": 0, "inputs": [ { @@ -3577,7 +3293,7 @@ 560.3785864245906 ], "flags": {}, - "order": 84, + "order": 81, "mode": 0, "inputs": [ { @@ -3638,9 +3354,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoSamplerv2", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd" + "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd", + "Node name for S&R": "WanVideoSamplerv2" }, "widgets_values": [ 1, @@ -3650,98 +3366,6 @@ false ] }, - { - "id": 346, - "type": "WanVideoLongCatAvatarExtendEmbeds", - "pos": [ - 5065.603368007511, - -1902.7918219298297 - ], - "size": [ - 379.476171875, - 238 - ], - "flags": {}, - "order": 82, - "mode": 0, - "inputs": [ - { - "name": "prev_latents", - "type": "LATENT", - "link": 806 - }, - { - "name": "audio_embeds", - "type": "MULTITALK_EMBEDS", - "link": 783 - }, - { - "name": "ref_latent", - "shape": 7, - "type": "LATENT", - "link": 775 - }, - { - "name": "samples", - "shape": 7, - "type": "LATENT", - "link": null - }, - { - "name": "num_frames", - "type": "INT", - "widget": { - "name": "num_frames" - }, - "link": 814 - }, - { - "name": "overlap", - "type": "INT", - "widget": { - "name": "overlap" - }, - "link": 799 - }, - { - "name": "frames_processed", - "type": "INT", - "widget": { - "name": "frames_processed" - }, - "link": 727 - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "links": [ - 635 - ] - }, - { - "name": "samples_slice", - "type": "LATENT", - "links": null - } - ], - "properties": { - "Node name for S&R": "WanVideoLongCatAvatarExtendEmbeds", - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd" - }, - "widgets_values": [ - 93, - 13, - 93, - "pad_with_start", - 10, - 3 - ], - "color": "#323", - "bgcolor": "#535" - }, { "id": 468, "type": "GetNode", @@ -3756,7 +3380,7 @@ "flags": { "collapsed": true }, - "order": 45, + "order": 40, "mode": 0, "inputs": [], "outputs": [ @@ -3788,7 +3412,7 @@ "flags": { "collapsed": true }, - "order": 46, + "order": 41, "mode": 0, "inputs": [], "outputs": [ @@ -3818,7 +3442,7 @@ 560.3785864245906 ], "flags": {}, - "order": 96, + "order": 93, "mode": 0, "inputs": [ { @@ -3878,9 +3502,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoSamplerv2", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd" + "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd", + "Node name for S&R": "WanVideoSamplerv2" }, "widgets_values": [ 1, @@ -3890,58 +3514,6 @@ false ] }, - { - "id": 138, - "type": "WanVideoLoraSelect", - "pos": [ - 564.2077204363451, - -2675.4893783617654 - ], - "size": [ - 503.4073486328125, - 200 - ], - "flags": {}, - "order": 47, - "mode": 0, - "inputs": [ - { - "name": "prev_lora", - "shape": 7, - "type": "WANVIDLORA", - "link": null - }, - { - "name": "blocks", - "shape": 7, - "type": "SELECTEDBLOCKS", - "link": null - } - ], - "outputs": [ - { - "name": "lora", - "type": "WANVIDLORA", - "links": [ - 848 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoLoraSelect", - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0" - }, - "widgets_values": [ - "LongCat_distill_lora_rank128_bf16.safetensors", - 1, - false, - false, - "
Metadata
Metadata
formatpt
model_typeLongCat_distill_lora
" - ], - "color": "#223", - "bgcolor": "#335" - }, { "id": 453, "type": "VHS_VideoCombine", @@ -3954,7 +3526,7 @@ 334 ], "flags": {}, - "order": 101, + "order": 98, "mode": 0, "inputs": [ { @@ -3989,9 +3561,9 @@ } ], "properties": { - "Node name for S&R": "VHS_VideoCombine", "cnr_id": "comfyui-videohelpersuite", - "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8" + "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8", + "Node name for S&R": "VHS_VideoCombine" }, "widgets_values": { "frame_rate": 16, @@ -4028,10 +3600,10 @@ ], "size": [ 991.5499877929688, - 908.5096083420973 + 334 ], "flags": {}, - "order": 90, + "order": 87, "mode": 0, "inputs": [ { @@ -4066,9 +3638,9 @@ } ], "properties": { - "Node name for S&R": "VHS_VideoCombine", "cnr_id": "comfyui-videohelpersuite", - "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8" + "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8", + "Node name for S&R": "VHS_VideoCombine" }, "widgets_values": { "frame_rate": 16, @@ -4108,7 +3680,7 @@ 326 ], "flags": {}, - "order": 71, + "order": 68, "mode": 0, "inputs": [ { @@ -4169,9 +3741,9 @@ } ], "properties": { - "Node name for S&R": "MultiTalkWav2VecEmbeds", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "3d7801cee4c8e3106078dd9b9f146caee95069ba" + "ver": "3d7801cee4c8e3106078dd9b9f146caee95069ba", + "Node name for S&R": "MultiTalkWav2VecEmbeds" }, "widgets_values": [ true, @@ -4198,7 +3770,7 @@ 142.90990081361315 ], "flags": {}, - "order": 48, + "order": 42, "mode": 0, "inputs": [], "outputs": [], @@ -4222,7 +3794,7 @@ 250 ], "flags": {}, - "order": 49, + "order": 43, "mode": 0, "inputs": [], "outputs": [ @@ -4233,9 +3805,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoTorchCompileSettings", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "f3614e6720744247f3211d60f7b9333f43572384" + "ver": "f3614e6720744247f3211d60f7b9333f43572384", + "Node name for S&R": "WanVideoTorchCompileSettings" }, "widgets_values": [ "inductor", @@ -4251,41 +3823,6 @@ "color": "#223", "bgcolor": "#335" }, - { - "id": 238, - "type": "CLIPVisionLoader", - "pos": [ - 1468.7586642411059, - -2311.9486286861097 - ], - "size": [ - 270, - 58 - ], - "flags": {}, - "order": 50, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "CLIP_VISION", - "type": "CLIP_VISION", - "links": [ - 466 - ] - } - ], - "properties": { - "Node name for S&R": "CLIPVisionLoader", - "cnr_id": "comfy-core", - "ver": "0.3.50" - }, - "widgets_values": [ - "clip_vision_h.safetensors" - ], - "color": "#233", - "bgcolor": "#355" - }, { "id": 134, "type": "WanVideoBlockSwap", @@ -4298,7 +3835,7 @@ 202 ], "flags": {}, - "order": 51, + "order": 44, "mode": 0, "inputs": [], "outputs": [ @@ -4311,9 +3848,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoBlockSwap", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0" + "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", + "Node name for S&R": "WanVideoBlockSwap" }, "widgets_values": [ 25, @@ -4339,7 +3876,7 @@ 178.89092796458362 ], "flags": {}, - "order": 52, + "order": 45, "mode": 0, "inputs": [], "outputs": [], @@ -4363,7 +3900,7 @@ 338 ], "flags": {}, - "order": 64, + "order": 62, "mode": 0, "inputs": [ { @@ -4431,9 +3968,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoModelLoader", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0" + "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", + "Node name for S&R": "WanVideoModelLoader" }, "widgets_values": [ "LongCat/LongCat-Avatar_bf16.safetensors", @@ -4458,7 +3995,7 @@ 353.33726502245645 ], "flags": {}, - "order": 53, + "order": 46, "mode": 0, "inputs": [ { @@ -4479,9 +4016,9 @@ } ], "properties": { - "Node name for S&R": "WanVideoSchedulerv2", "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd" + "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd", + "Node name for S&R": "WanVideoSchedulerv2" }, "widgets_values": [ "longcat_distill_euler", @@ -4489,8 +4026,7 @@ 12, 0, -1, - false, - "Sigmas Plot" + false ] }, { @@ -4502,10 +4038,10 @@ ], "size": [ 991.5499877929688, - 908.5096083420973 + 334 ], "flags": {}, - "order": 79, + "order": 76, "mode": 0, "inputs": [ { @@ -4540,9 +4076,9 @@ } ], "properties": { - "Node name for S&R": "VHS_VideoCombine", "cnr_id": "comfyui-videohelpersuite", - "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8" + "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8", + "Node name for S&R": "VHS_VideoCombine" }, "widgets_values": { "frame_rate": 16, @@ -4569,6 +4105,377 @@ } } } + }, + { + "id": 346, + "type": "WanVideoLongCatAvatarExtendEmbeds", + "pos": [ + 5071.598514635023, + -1893.1993348384901 + ], + "size": [ + 379.476171875, + 238 + ], + "flags": {}, + "order": 79, + "mode": 0, + "inputs": [ + { + "name": "prev_latents", + "type": "LATENT", + "link": 806 + }, + { + "name": "audio_embeds", + "type": "MULTITALK_EMBEDS", + "link": 783 + }, + { + "name": "ref_latent", + "shape": 7, + "type": "LATENT", + "link": 775 + }, + { + "name": "samples", + "shape": 7, + "type": "LATENT", + "link": null + }, + { + "name": "num_frames", + "type": "INT", + "widget": { + "name": "num_frames" + }, + "link": 814 + }, + { + "name": "overlap", + "type": "INT", + "widget": { + "name": "overlap" + }, + "link": 799 + }, + { + "name": "frames_processed", + "type": "INT", + "widget": { + "name": "frames_processed" + }, + "link": 727 + } + ], + "outputs": [ + { + "name": "image_embeds", + "type": "WANVIDIMAGE_EMBEDS", + "links": [ + 635 + ] + }, + { + "name": "samples_slice", + "type": "LATENT", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-WanVideoWrapper", + "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd", + "Node name for S&R": "WanVideoLongCatAvatarExtendEmbeds" + }, + "widgets_values": [ + 93, + 13, + 93, + "pad_with_start", + 10, + 3 + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 461, + "type": "WanVideoLongCatAvatarExtendEmbeds", + "pos": [ + 7854.073171495291, + -1890.2709706651597 + ], + "size": [ + 379.476171875, + 238 + ], + "flags": {}, + "order": 91, + "mode": 0, + "inputs": [ + { + "name": "prev_latents", + "type": "LATENT", + "link": 845 + }, + { + "name": "audio_embeds", + "type": "MULTITALK_EMBEDS", + "link": 834 + }, + { + "name": "ref_latent", + "shape": 7, + "type": "LATENT", + "link": 835 + }, + { + "name": "samples", + "shape": 7, + "type": "LATENT", + "link": null + }, + { + "name": "num_frames", + "type": "INT", + "widget": { + "name": "num_frames" + }, + "link": 836 + }, + { + "name": "overlap", + "type": "INT", + "widget": { + "name": "overlap" + }, + "link": 837 + }, + { + "name": "frames_processed", + "type": "INT", + "widget": { + "name": "frames_processed" + }, + "link": 838 + } + ], + "outputs": [ + { + "name": "image_embeds", + "type": "WANVIDIMAGE_EMBEDS", + "links": [ + 826 + ] + }, + { + "name": "samples_slice", + "type": "LATENT", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-WanVideoWrapper", + "ver": "93f7af6dc8559e2f6815caa67fd0982e4d8940dd", + "Node name for S&R": "WanVideoLongCatAvatarExtendEmbeds" + }, + "widgets_values": [ + 93, + 13, + 93, + "pad_with_start", + 10, + 3 + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 462, + "type": "GetNode", + "pos": [ + 7854.4886035986365, + -1994.7075576927305 + ], + "size": [ + 210, + 34 + ], + "flags": { + "collapsed": true + }, + "order": 47, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MULTITALK_EMBEDS", + "type": "MULTITALK_EMBEDS", + "links": [ + 834 + ] + } + ], + "title": "Get_audio_embeds", + "properties": {}, + "widgets_values": [ + "audio_embeds" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 459, + "type": "GetNode", + "pos": [ + 7856.283614199908, + -1940.447919500377 + ], + "size": [ + 210, + 34 + ], + "flags": { + "collapsed": true + }, + "order": 48, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 835 + ] + } + ], + "title": "Get_ref_latent", + "properties": {}, + "widgets_values": [ + "ref_latent" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 418, + "type": "GetNode", + "pos": [ + 5071.548239647001, + -1978.6194414594738 + ], + "size": [ + 210, + 60 + ], + "flags": { + "collapsed": true + }, + "order": 49, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MULTITALK_EMBEDS", + "type": "MULTITALK_EMBEDS", + "links": [ + 783 + ] + } + ], + "title": "Get_audio_embeds", + "properties": {}, + "widgets_values": [ + "audio_embeds" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 413, + "type": "GetNode", + "pos": [ + 5072.818279856921, + -1936.9548335806312 + ], + "size": [ + 210, + 60 + ], + "flags": { + "collapsed": true + }, + "order": 50, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 775 + ] + } + ], + "title": "Get_ref_latent", + "properties": {}, + "widgets_values": [ + "ref_latent" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 138, + "type": "WanVideoLoraSelect", + "pos": [ + 564.2077204363451, + -2675.4893783617654 + ], + "size": [ + 503.4073486328125, + 200 + ], + "flags": {}, + "order": 51, + "mode": 0, + "inputs": [ + { + "name": "prev_lora", + "shape": 7, + "type": "WANVIDLORA", + "link": null + }, + { + "name": "blocks", + "shape": 7, + "type": "SELECTEDBLOCKS", + "link": null + } + ], + "outputs": [ + { + "name": "lora", + "type": "WANVIDLORA", + "links": [ + 848 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-WanVideoWrapper", + "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", + "Node name for S&R": "WanVideoLoraSelect" + }, + "widgets_values": [ + "LongCat_distill_lora_rank128_bf16.safetensors", + 0.9, + false, + false + ], + "color": "#223", + "bgcolor": "#335" } ], "links": [ @@ -4620,14 +4527,6 @@ 0, "*" ], - [ - 466, - 238, - 0, - 264, - 0, - "*" - ], [ 494, 283, @@ -5403,13 +5302,13 @@ "config": {}, "extra": { "ds": { - "scale": 0.3138428376721308, + "scale": 0.5054470284993439, "offset": [ - -367.5989031130344, - 3444.003601779404 + -329.7995482986256, + 2961.065863628347 ] }, - "frontendVersion": "1.36.2", + "frontendVersion": "1.36.7", "workflowRendererVersion": "LG", "node_versions": { "comfy-core": "0.5.1", From 4b709a7a04e67b2332dad017b5eee18514c68182 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 15:44:08 +0200 Subject: [PATCH 11/22] Cleanup example_workflows folder some --- ...nvideo_2_1_14B_FLF2V_720P_example_02.json} | 0 ..._1_14B_Fun_control_camera_example_01.json} | 0 ...video_2_1_14B_Fun_control_example_01.json} | 0 ... => wanvideo_2_1_14B_HuMo_example_01.json} | 0 ...deo_2_1_14B_I2V_ATI_track_testing_01.json} | 0 ...1_14B_I2V_FantasyPortrait_example_01.json} | 0 ..._1_14B_I2V_FantasyTalking_example_01.json} | 0 ..._2_1_14B_I2V_InfiniteTalk_example_03.json} | 0 ...n => wanvideo_2_1_14B_I2V_example_03.json} | 0 ...ideo_2_1_14B_MTV_Crafter_example_WIP.json} | 0 ..._2_1_14B_MoCha_replace_subject_KJ_02.json} | 0 ...AllAnimation_pose_control_example_01.json} | 0 ..._1_14B_SCAIL_pose_control_example_01.json} | 0 ..._1_14B_Stand-In_reference_example_01.json} | 0 ...SteadyDancer_pose_control_example_01.json} | 0 ...ideo_2_1_14B_T2V_14B_lynx_example_01.json} | 0 ...n => wanvideo_2_1_14B_T2V_example_03.json} | 0 ..._2_1_14B_V2V_InfiniteTalk_example_02.json} | 0 ...video_2_1_14B_WanMove_I2V_example_01.json} | 0 ...1_14B_phantom_subject2vid_example_02.json} | 0 ...wanvideo_2_1_14B_pusa_I2V_example_01.json} | 0 ...video_2_1_14B_skyreels_a2_example_01.json} | 0 ...ffusion_forcing_extension_example_01.json} | 0 ...eo_2_2_Fun_control_camera_example_01.json} | 0 ... wanvideo_2_2_Fun_control_example_03.json} | 0 ...ideo_2_2_I2V_A14B_TimeToMove_example.json} | 0 ...=> wanvideo_2_2_I2V_A14B_example_WIP.json} | 0 .../wanvideo_flowedit_I2V_example_01.json | 1965 --------------- .../wanvideo_long_T2V_example_01.json | 780 ------ ...anvideo_mocha_replacement_original_01.json | 2138 ----------------- .../wanvideo_multitalk_test_02.json | 1389 ----------- ...deo_multitalk_test_context_windows_01.json | 1891 --------------- .../wanvideo_vid2vid_example_01.json | 1044 -------- 33 files changed, 9207 deletions(-) rename example_workflows/{wanvideo_FLF2V_720P_example_02.json => wanvideo_2_1_14B_FLF2V_720P_example_02.json} (100%) rename example_workflows/{wanvideo_Fun_control_camera_example_01.json => wanvideo_2_1_14B_Fun_control_camera_example_01.json} (100%) rename example_workflows/{wanvideo_Fun_control_example_01.json => wanvideo_2_1_14B_Fun_control_example_01.json} (100%) rename example_workflows/{wanvideo_HuMo_example_01.json => wanvideo_2_1_14B_HuMo_example_01.json} (100%) rename example_workflows/{wanvideo_ATI_testing_01.json => wanvideo_2_1_14B_I2V_ATI_track_testing_01.json} (100%) rename example_workflows/{wanvideo_2_1_I2V_FantasyPortrait_example_01.json => wanvideo_2_1_14B_I2V_FantasyPortrait_example_01.json} (100%) rename example_workflows/{wanvideo_I2V_FantasyTalking_example_01.json => wanvideo_2_1_14B_I2V_FantasyTalking_example_01.json} (100%) rename example_workflows/{wanvideo_I2V_InfiniteTalk_example_03.json => wanvideo_2_1_14B_I2V_InfiniteTalk_example_03.json} (100%) rename example_workflows/{wanvideo_480p_I2V_example_03.json => wanvideo_2_1_14B_I2V_example_03.json} (100%) rename example_workflows/{wanvideo_MTV_Crafter_example_WIP.json => wanvideo_2_1_14B_MTV_Crafter_example_WIP.json} (100%) rename example_workflows/{wanvideo_MoCha_replace_subject_KJ_02.json => wanvideo_2_1_14B_MoCha_replace_subject_KJ_02.json} (100%) rename example_workflows/{Wan21_OneToAllAnimation_example_01.json => wanvideo_2_1_14B_OneToAllAnimation_pose_control_example_01.json} (100%) rename example_workflows/{wanvideo_SCAIL_pose_control_example_01.json => wanvideo_2_1_14B_SCAIL_pose_control_example_01.json} (100%) rename example_workflows/{wanvideo_Stand-In_reference_example_01.json => wanvideo_2_1_14B_Stand-In_reference_example_01.json} (100%) rename example_workflows/{wanvideo_SteadyDancer_example_01.json => wanvideo_2_1_14B_SteadyDancer_pose_control_example_01.json} (100%) rename example_workflows/{wanvideo_T2V_14B_lynx_example_01.json => wanvideo_2_1_14B_T2V_14B_lynx_example_01.json} (100%) rename example_workflows/{wanvideo_T2V_example_03.json => wanvideo_2_1_14B_T2V_example_03.json} (100%) rename example_workflows/{wanvideo_InfiniteTalk_V2V_example_02.json => wanvideo_2_1_14B_V2V_InfiniteTalk_example_02.json} (100%) rename example_workflows/{wanvideo_WanMove_I2V_example_01.json => wanvideo_2_1_14B_WanMove_I2V_example_01.json} (100%) rename example_workflows/{wanvideo_phantom_subject2vid_example_02.json => wanvideo_2_1_14B_phantom_subject2vid_example_02.json} (100%) rename example_workflows/{wanvideo_14B_pusa_I2V_example_01.json => wanvideo_2_1_14B_pusa_I2V_example_01.json} (100%) rename example_workflows/{wanvideo_skyreels_a2_example_01.json => wanvideo_2_1_14B_skyreels_a2_example_01.json} (100%) rename example_workflows/{wanvideo_skyreels_diffusion_forcing_extension_example_01.json => wanvideo_2_1_14B_skyreels_diffusion_forcing_extension_example_01.json} (100%) rename example_workflows/{wanvideo_Fun2_2_control_camera_example_01.json => wanvideo_2_2_Fun_control_camera_example_01.json} (100%) rename example_workflows/{wanvideo_Fun_2_2_control_example_03.json => wanvideo_2_2_Fun_control_example_03.json} (100%) rename example_workflows/{wanvideo2_2_I2V_A14B_TimeToMove_example.json => wanvideo_2_2_I2V_A14B_TimeToMove_example.json} (100%) rename example_workflows/{wanvideo2_2_I2V_A14B_example_WIP.json => wanvideo_2_2_I2V_A14B_example_WIP.json} (100%) delete mode 100644 example_workflows/wanvideo_flowedit_I2V_example_01.json delete mode 100644 example_workflows/wanvideo_long_T2V_example_01.json delete mode 100644 example_workflows/wanvideo_mocha_replacement_original_01.json delete mode 100644 example_workflows/wanvideo_multitalk_test_02.json delete mode 100644 example_workflows/wanvideo_multitalk_test_context_windows_01.json delete mode 100644 example_workflows/wanvideo_vid2vid_example_01.json diff --git a/example_workflows/wanvideo_FLF2V_720P_example_02.json b/example_workflows/wanvideo_2_1_14B_FLF2V_720P_example_02.json similarity index 100% rename from example_workflows/wanvideo_FLF2V_720P_example_02.json rename to example_workflows/wanvideo_2_1_14B_FLF2V_720P_example_02.json diff --git a/example_workflows/wanvideo_Fun_control_camera_example_01.json b/example_workflows/wanvideo_2_1_14B_Fun_control_camera_example_01.json similarity index 100% rename from example_workflows/wanvideo_Fun_control_camera_example_01.json rename to example_workflows/wanvideo_2_1_14B_Fun_control_camera_example_01.json diff --git a/example_workflows/wanvideo_Fun_control_example_01.json b/example_workflows/wanvideo_2_1_14B_Fun_control_example_01.json similarity index 100% rename from example_workflows/wanvideo_Fun_control_example_01.json rename to example_workflows/wanvideo_2_1_14B_Fun_control_example_01.json diff --git a/example_workflows/wanvideo_HuMo_example_01.json b/example_workflows/wanvideo_2_1_14B_HuMo_example_01.json similarity index 100% rename from example_workflows/wanvideo_HuMo_example_01.json rename to example_workflows/wanvideo_2_1_14B_HuMo_example_01.json diff --git a/example_workflows/wanvideo_ATI_testing_01.json b/example_workflows/wanvideo_2_1_14B_I2V_ATI_track_testing_01.json similarity index 100% rename from example_workflows/wanvideo_ATI_testing_01.json rename to example_workflows/wanvideo_2_1_14B_I2V_ATI_track_testing_01.json diff --git a/example_workflows/wanvideo_2_1_I2V_FantasyPortrait_example_01.json b/example_workflows/wanvideo_2_1_14B_I2V_FantasyPortrait_example_01.json similarity index 100% rename from example_workflows/wanvideo_2_1_I2V_FantasyPortrait_example_01.json rename to example_workflows/wanvideo_2_1_14B_I2V_FantasyPortrait_example_01.json diff --git a/example_workflows/wanvideo_I2V_FantasyTalking_example_01.json b/example_workflows/wanvideo_2_1_14B_I2V_FantasyTalking_example_01.json similarity index 100% rename from example_workflows/wanvideo_I2V_FantasyTalking_example_01.json rename to example_workflows/wanvideo_2_1_14B_I2V_FantasyTalking_example_01.json diff --git a/example_workflows/wanvideo_I2V_InfiniteTalk_example_03.json b/example_workflows/wanvideo_2_1_14B_I2V_InfiniteTalk_example_03.json similarity index 100% rename from example_workflows/wanvideo_I2V_InfiniteTalk_example_03.json rename to example_workflows/wanvideo_2_1_14B_I2V_InfiniteTalk_example_03.json diff --git a/example_workflows/wanvideo_480p_I2V_example_03.json b/example_workflows/wanvideo_2_1_14B_I2V_example_03.json similarity index 100% rename from example_workflows/wanvideo_480p_I2V_example_03.json rename to example_workflows/wanvideo_2_1_14B_I2V_example_03.json diff --git a/example_workflows/wanvideo_MTV_Crafter_example_WIP.json b/example_workflows/wanvideo_2_1_14B_MTV_Crafter_example_WIP.json similarity index 100% rename from example_workflows/wanvideo_MTV_Crafter_example_WIP.json rename to example_workflows/wanvideo_2_1_14B_MTV_Crafter_example_WIP.json diff --git a/example_workflows/wanvideo_MoCha_replace_subject_KJ_02.json b/example_workflows/wanvideo_2_1_14B_MoCha_replace_subject_KJ_02.json similarity index 100% rename from example_workflows/wanvideo_MoCha_replace_subject_KJ_02.json rename to example_workflows/wanvideo_2_1_14B_MoCha_replace_subject_KJ_02.json diff --git a/example_workflows/Wan21_OneToAllAnimation_example_01.json b/example_workflows/wanvideo_2_1_14B_OneToAllAnimation_pose_control_example_01.json similarity index 100% rename from example_workflows/Wan21_OneToAllAnimation_example_01.json rename to example_workflows/wanvideo_2_1_14B_OneToAllAnimation_pose_control_example_01.json diff --git a/example_workflows/wanvideo_SCAIL_pose_control_example_01.json b/example_workflows/wanvideo_2_1_14B_SCAIL_pose_control_example_01.json similarity index 100% rename from example_workflows/wanvideo_SCAIL_pose_control_example_01.json rename to example_workflows/wanvideo_2_1_14B_SCAIL_pose_control_example_01.json diff --git a/example_workflows/wanvideo_Stand-In_reference_example_01.json b/example_workflows/wanvideo_2_1_14B_Stand-In_reference_example_01.json similarity index 100% rename from example_workflows/wanvideo_Stand-In_reference_example_01.json rename to example_workflows/wanvideo_2_1_14B_Stand-In_reference_example_01.json diff --git a/example_workflows/wanvideo_SteadyDancer_example_01.json b/example_workflows/wanvideo_2_1_14B_SteadyDancer_pose_control_example_01.json similarity index 100% rename from example_workflows/wanvideo_SteadyDancer_example_01.json rename to example_workflows/wanvideo_2_1_14B_SteadyDancer_pose_control_example_01.json diff --git a/example_workflows/wanvideo_T2V_14B_lynx_example_01.json b/example_workflows/wanvideo_2_1_14B_T2V_14B_lynx_example_01.json similarity index 100% rename from example_workflows/wanvideo_T2V_14B_lynx_example_01.json rename to example_workflows/wanvideo_2_1_14B_T2V_14B_lynx_example_01.json diff --git a/example_workflows/wanvideo_T2V_example_03.json b/example_workflows/wanvideo_2_1_14B_T2V_example_03.json similarity index 100% rename from example_workflows/wanvideo_T2V_example_03.json rename to example_workflows/wanvideo_2_1_14B_T2V_example_03.json diff --git a/example_workflows/wanvideo_InfiniteTalk_V2V_example_02.json b/example_workflows/wanvideo_2_1_14B_V2V_InfiniteTalk_example_02.json similarity index 100% rename from example_workflows/wanvideo_InfiniteTalk_V2V_example_02.json rename to example_workflows/wanvideo_2_1_14B_V2V_InfiniteTalk_example_02.json diff --git a/example_workflows/wanvideo_WanMove_I2V_example_01.json b/example_workflows/wanvideo_2_1_14B_WanMove_I2V_example_01.json similarity index 100% rename from example_workflows/wanvideo_WanMove_I2V_example_01.json rename to example_workflows/wanvideo_2_1_14B_WanMove_I2V_example_01.json diff --git a/example_workflows/wanvideo_phantom_subject2vid_example_02.json b/example_workflows/wanvideo_2_1_14B_phantom_subject2vid_example_02.json similarity index 100% rename from example_workflows/wanvideo_phantom_subject2vid_example_02.json rename to example_workflows/wanvideo_2_1_14B_phantom_subject2vid_example_02.json diff --git a/example_workflows/wanvideo_14B_pusa_I2V_example_01.json b/example_workflows/wanvideo_2_1_14B_pusa_I2V_example_01.json similarity index 100% rename from example_workflows/wanvideo_14B_pusa_I2V_example_01.json rename to example_workflows/wanvideo_2_1_14B_pusa_I2V_example_01.json diff --git a/example_workflows/wanvideo_skyreels_a2_example_01.json b/example_workflows/wanvideo_2_1_14B_skyreels_a2_example_01.json similarity index 100% rename from example_workflows/wanvideo_skyreels_a2_example_01.json rename to example_workflows/wanvideo_2_1_14B_skyreels_a2_example_01.json diff --git a/example_workflows/wanvideo_skyreels_diffusion_forcing_extension_example_01.json b/example_workflows/wanvideo_2_1_14B_skyreels_diffusion_forcing_extension_example_01.json similarity index 100% rename from example_workflows/wanvideo_skyreels_diffusion_forcing_extension_example_01.json rename to example_workflows/wanvideo_2_1_14B_skyreels_diffusion_forcing_extension_example_01.json diff --git a/example_workflows/wanvideo_Fun2_2_control_camera_example_01.json b/example_workflows/wanvideo_2_2_Fun_control_camera_example_01.json similarity index 100% rename from example_workflows/wanvideo_Fun2_2_control_camera_example_01.json rename to example_workflows/wanvideo_2_2_Fun_control_camera_example_01.json diff --git a/example_workflows/wanvideo_Fun_2_2_control_example_03.json b/example_workflows/wanvideo_2_2_Fun_control_example_03.json similarity index 100% rename from example_workflows/wanvideo_Fun_2_2_control_example_03.json rename to example_workflows/wanvideo_2_2_Fun_control_example_03.json diff --git a/example_workflows/wanvideo2_2_I2V_A14B_TimeToMove_example.json b/example_workflows/wanvideo_2_2_I2V_A14B_TimeToMove_example.json similarity index 100% rename from example_workflows/wanvideo2_2_I2V_A14B_TimeToMove_example.json rename to example_workflows/wanvideo_2_2_I2V_A14B_TimeToMove_example.json diff --git a/example_workflows/wanvideo2_2_I2V_A14B_example_WIP.json b/example_workflows/wanvideo_2_2_I2V_A14B_example_WIP.json similarity index 100% rename from example_workflows/wanvideo2_2_I2V_A14B_example_WIP.json rename to example_workflows/wanvideo_2_2_I2V_A14B_example_WIP.json diff --git a/example_workflows/wanvideo_flowedit_I2V_example_01.json b/example_workflows/wanvideo_flowedit_I2V_example_01.json deleted file mode 100644 index 18f16af..0000000 --- a/example_workflows/wanvideo_flowedit_I2V_example_01.json +++ /dev/null @@ -1,1965 +0,0 @@ -{ - "last_node_id": 73, - "last_link_id": 92, - "nodes": [ - { - "id": 46, - "type": "WanVideoTextEmbedBridge", - "pos": [ - -947.5358276367188, - -63.66567611694336 - ], - "size": [ - 315, - 46 - ], - "flags": {}, - "order": 25, - "mode": 2, - "inputs": [ - { - "name": "positive", - "type": "CONDITIONING", - "link": 54 - }, - { - "name": "negative", - "type": "CONDITIONING", - "link": 55 - } - ], - "outputs": [ - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "links": null - } - ], - "properties": { - "Node name for S&R": "WanVideoTextEmbedBridge" - }, - "widgets_values": [] - }, - { - "id": 50, - "type": "CLIPTextEncode", - "pos": [ - -1397.5355224609375, - 196.33407592773438 - ], - "size": [ - 400, - 200 - ], - "flags": {}, - "order": 19, - "mode": 2, - "inputs": [ - { - "name": "clip", - "type": "CLIP", - "link": 53 - } - ], - "outputs": [ - { - "name": "CONDITIONING", - "type": "CONDITIONING", - "slot_index": 0, - "links": [ - 55 - ] - } - ], - "properties": { - "Node name for S&R": "CLIPTextEncode" - }, - "widgets_values": [ - "色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走" - ] - }, - { - "id": 48, - "type": "CLIPLoader", - "pos": [ - -1757.53515625, - -53.66567611694336 - ], - "size": [ - 315, - 98.00003051757812 - ], - "flags": {}, - "order": 0, - "mode": 2, - "inputs": [], - "outputs": [ - { - "name": "CLIP", - "type": "CLIP", - "slot_index": 0, - "links": [ - 52, - 53 - ] - } - ], - "properties": { - "Node name for S&R": "CLIPLoader" - }, - "widgets_values": [ - "umt5_xxl_fp16.safetensors", - "wan", - "default" - ] - }, - { - "id": 49, - "type": "CLIPTextEncode", - "pos": [ - -1397.5355224609375, - -53.66567611694336 - ], - "size": [ - 400, - 200 - ], - "flags": {}, - "order": 18, - "mode": 2, - "inputs": [ - { - "name": "clip", - "type": "CLIP", - "link": 52 - } - ], - "outputs": [ - { - "name": "CONDITIONING", - "type": "CONDITIONING", - "slot_index": 0, - "links": [ - 54 - ] - } - ], - "properties": { - "Node name for S&R": "CLIPTextEncode" - }, - "widgets_values": [ - "high quality nature video featuring a red panda balancing on a bamboo stem while a bird lands on it's head, on the background there is a waterfall" - ] - }, - { - "id": 42, - "type": "Note", - "pos": [ - -580, - -760 - ], - "size": [ - 314.96246337890625, - 152.77333068847656 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "Adjust the blocks to swap based on your VRAM, this is a tradeoff between speed and memory usage.\n\nAlternatively there's option to use VRAM management introduced in DiffSynt-Studios. This is usually slower, but saves even more VRAM compared to BlockSwap" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 45, - "type": "WanVideoVRAMManagement", - "pos": [ - -210, - -580 - ], - "size": [ - 315, - 58 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "vram_management_args", - "type": "VRAM_MANAGEMENTARGS", - "links": [] - } - ], - "properties": { - "Node name for S&R": "WanVideoVRAMManagement" - }, - "widgets_values": [ - 1 - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 36, - "type": "Note", - "pos": [ - 160, - -1010 - ], - "size": [ - 374.3061828613281, - 171.9547576904297 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "fp8_fast seems to cause huge quality degradation\n\nfp_16_fast enables \"Full FP16 Accmumulation in FP16 GEMMs\" feature available in the very latest pytorch nightly, this is around 20% speed boost. \n\nSageattn if you have it installed can be used for almost double inference speed" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 33, - "type": "Note", - "pos": [ - 170, - -1150 - ], - "size": [ - 359.0753479003906, - 88 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "Models:\nhttps://huggingface.co/Kijai/WanVideo_comfy/tree/main" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 51, - "type": "Note", - "pos": [ - -1727.53515625, - -223.66603088378906 - ], - "size": [ - 253.16725158691406, - 88 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "You can also use native ComfyUI text encoding with these nodes instead of the original, the models are node specific and can't otherwise be mixed." - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 60, - "type": "Note", - "pos": [ - -432.5627136230469, - -224.5513458251953 - ], - "size": [ - 253.16725158691406, - 88 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "You can use either the original clip vision or the normal comfyui clip vision loader, they are the same model in the end." - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 59, - "type": "CLIPVisionLoader", - "pos": [ - -158.17127990722656, - -210.2847442626953 - ], - "size": [ - 315, - 58 - ], - "flags": {}, - "order": 7, - "mode": 2, - "inputs": [], - "outputs": [ - { - "name": "CLIP_VISION", - "type": "CLIP_VISION", - "links": null - } - ], - "properties": { - "Node name for S&R": "CLIPVisionLoader" - }, - "widgets_values": [ - "clip_vision_h.safetensors" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 11, - "type": "LoadWanVideoT5TextEncoder", - "pos": [ - 161.7229461669922, - -501.2225036621094 - ], - "size": [ - 377.1661376953125, - 130 - ], - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "wan_t5_model", - "type": "WANTEXTENCODER", - "slot_index": 0, - "links": [ - 15, - 69 - ] - } - ], - "properties": { - "Node name for S&R": "LoadWanVideoT5TextEncoder" - }, - "widgets_values": [ - "umt5-xxl-enc-bf16.safetensors", - "bf16", - "offload_device", - "disabled" - ], - "color": "#332922", - "bgcolor": "#593930" - }, - { - "id": 44, - "type": "Note", - "pos": [ - -620.9041137695312, - -1049.732421875 - ], - "size": [ - 303.0501403808594, - 88 - ], - "flags": {}, - "order": 9, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "If you have Triton installed, connect this for ~30% speed increase" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 39, - "type": "WanVideoBlockSwap", - "pos": [ - -210, - -760 - ], - "size": [ - 315, - 130 - ], - "flags": {}, - "order": 10, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "block_swap_args", - "type": "BLOCKSWAPARGS", - "slot_index": 0, - "links": [] - } - ], - "properties": { - "Node name for S&R": "WanVideoBlockSwap" - }, - "widgets_values": [ - 20, - false, - false, - true - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 56, - "type": "LoadWanVideoClipTextEncoder", - "pos": [ - -357.8293762207031, - -83.7756118774414 - ], - "size": [ - 510.6601257324219, - 106 - ], - "flags": {}, - "order": 11, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "wan_clip_vision", - "type": "CLIP_VISION", - "slot_index": 0, - "links": [ - 58, - 82 - ] - } - ], - "properties": { - "Node name for S&R": "LoadWanVideoClipTextEncoder" - }, - "widgets_values": [ - "open-clip-xlm-roberta-large-vit-huge-14_visual_fp32.safetensors", - "fp16", - "offload_device" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 35, - "type": "WanVideoTorchCompileSettings", - "pos": [ - -276.8500671386719, - -1050.6326904296875 - ], - "size": [ - 390.5999755859375, - 178 - ], - "flags": {}, - "order": 12, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "torch_compile_args", - "type": "WANCOMPILEARGS", - "slot_index": 0, - "links": [ - 75 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoTorchCompileSettings" - }, - "widgets_values": [ - "inductor", - false, - "default", - false, - 64, - true - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 66, - "type": "WanVideoTextEncode", - "pos": [ - 153.09332275390625, - 872.6924438476562 - ], - "size": [ - 420.30511474609375, - 261.5306701660156 - ], - "flags": {}, - "order": 21, - "mode": 0, - "inputs": [ - { - "name": "t5", - "type": "WANTEXTENCODER", - "link": 69 - }, - { - "name": "model_to_offload", - "shape": 7, - "type": "WANVIDEOMODEL", - "link": null - } - ], - "outputs": [ - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "slot_index": 0, - "links": [ - 70 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoTextEncode" - }, - "widgets_values": [ - "video of a wolf", - "bad quality, cartoon, painting", - true - ], - "color": "#332922", - "bgcolor": "#593930" - }, - { - "id": 16, - "type": "WanVideoTextEncode", - "pos": [ - 157.61514282226562, - 245.40008544921875 - ], - "size": [ - 420.30511474609375, - 261.5306701660156 - ], - "flags": {}, - "order": 20, - "mode": 0, - "inputs": [ - { - "name": "t5", - "type": "WANTEXTENCODER", - "link": 15 - }, - { - "name": "model_to_offload", - "shape": 7, - "type": "WANVIDEOMODEL", - "link": null - } - ], - "outputs": [ - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "slot_index": 0, - "links": [ - 30 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoTextEncode" - }, - "widgets_values": [ - "cybernetic wolf is turning it's head", - "色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走", - true - ], - "color": "#332922", - "bgcolor": "#593930" - }, - { - "id": 65, - "type": "VHS_LoadVideo", - "pos": [ - -336.5810241699219, - 681.5027465820312 - ], - "size": [ - 392.0638732910156, - 696.0638427734375 - ], - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [ - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 66, - 71 - ] - }, - { - "name": "frame_count", - "type": "INT", - "links": null - }, - { - "name": "audio", - "type": "AUDIO", - "links": null - }, - { - "name": "video_info", - "type": "VHS_VIDEOINFO", - "links": null - } - ], - "properties": { - "Node name for S&R": "VHS_LoadVideo" - }, - "widgets_values": { - "video": "wolf_interpolated.mp4", - "force_rate": 0, - "custom_width": 0, - "custom_height": 0, - "frame_load_cap": 0, - "skip_first_frames": 0, - "select_every_nth": 1, - "format": "AnimateDiff", - "choose video to upload": "image", - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "wolf_interpolated.mp4", - "type": "input", - "format": "video/mp4", - "force_rate": 0, - "custom_width": 0, - "custom_height": 0, - "frame_load_cap": 0, - "skip_first_frames": 0, - "select_every_nth": 1 - } - } - } - }, - { - "id": 58, - "type": "LoadImage", - "pos": [ - -347.4864501953125, - 119.20101928710938 - ], - "size": [ - 413.10479736328125, - 498.3180847167969 - ], - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 59, - 77 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "hunhyuanwolf.png", - "image", - "" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 30, - "type": "VHS_VideoCombine", - "pos": [ - 1684.1597900390625, - -394.2595520019531 - ], - "size": [ - 904.313232421875, - 1232.313232421875 - ], - "flags": {}, - "order": 32, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 36 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "properties": { - "Node name for S&R": "VHS_VideoCombine" - }, - "widgets_values": { - "frame_rate": 16, - "loop_count": 0, - "filename_prefix": "WanVideoWrapper_I2V", - "format": "video/h264-mp4", - "pix_fmt": "yuv420p", - "crf": 19, - "save_metadata": true, - "trim_to_audio": false, - "pingpong": false, - "save_output": true, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "WanVideoWrapper_I2V_00432.mp4", - "subfolder": "", - "type": "output", - "format": "video/h264-mp4", - "frame_rate": 16, - "workflow": "WanVideoWrapper_I2V_00432.png", - "fullpath": "N:\\AI\\ComfyUI\\output\\WanVideoWrapper_I2V_00432.mp4" - } - } - } - }, - { - "id": 68, - "type": "ImageConcatMulti", - "pos": [ - 2073.08251953125, - -643.741455078125 - ], - "size": [ - 315, - 170 - ], - "flags": {}, - "order": 33, - "mode": 0, - "inputs": [ - { - "name": "image_1", - "type": "IMAGE", - "link": 78 - }, - { - "name": "image_2", - "type": "IMAGE", - "link": 77 - }, - { - "name": "image_3", - "type": "IMAGE", - "link": 79 - } - ], - "outputs": [ - { - "name": "images", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 80 - ] - } - ], - "properties": {}, - "widgets_values": [ - 3, - "right", - true, - null - ] - }, - { - "id": 67, - "type": "GetImageSizeAndCount", - "pos": [ - 136.5249786376953, - 714.924072265625 - ], - "size": [ - 277.20001220703125, - 86 - ], - "flags": {}, - "order": 23, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 71 - } - ], - "outputs": [ - { - "name": "image", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 78, - 81 - ] - }, - { - "label": "512 width", - "name": "width", - "type": "INT", - "slot_index": 1, - "links": [ - 72, - 85 - ] - }, - { - "label": "512 height", - "name": "height", - "type": "INT", - "slot_index": 2, - "links": [ - 73, - 86 - ] - }, - { - "label": "53 count", - "name": "count", - "type": "INT", - "slot_index": 3, - "links": [ - 74, - 87 - ] - } - ], - "properties": { - "Node name for S&R": "GetImageSizeAndCount" - }, - "widgets_values": [] - }, - { - "id": 57, - "type": "WanVideoImageClipEncode", - "pos": [ - 287.3013000488281, - -147.04237365722656 - ], - "size": [ - 310.4956359863281, - 326 - ], - "flags": {}, - "order": 28, - "mode": 0, - "inputs": [ - { - "name": "clip_vision", - "type": "CLIP_VISION", - "link": 58 - }, - { - "name": "image", - "type": "IMAGE", - "link": 59 - }, - { - "name": "vae", - "type": "WANVAE", - "link": 63 - }, - { - "name": "generation_width", - "type": "INT", - "widget": { - "name": "generation_width" - }, - "link": 72 - }, - { - "name": "generation_height", - "type": "INT", - "widget": { - "name": "generation_height" - }, - "link": 73 - }, - { - "name": "num_frames", - "type": "INT", - "widget": { - "name": "num_frames" - }, - "link": 74 - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "slot_index": 0, - "links": [ - 64 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoImageClipEncode" - }, - "widgets_values": [ - 832, - 480, - 81, - true, - 0.030000000000000006, - 1, - 1, - false - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 70, - "type": "GetImageRangeFromBatch", - "pos": [ - 546.9578247070312, - 766.3284912109375 - ], - "size": [ - 428.4000244140625, - 102 - ], - "flags": { - "collapsed": true - }, - "order": 27, - "mode": 0, - "inputs": [ - { - "name": "images", - "shape": 7, - "type": "IMAGE", - "link": 81 - }, - { - "name": "masks", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 88 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "Node name for S&R": "GetImageRangeFromBatch" - }, - "widgets_values": [ - 0, - 1 - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 71, - "type": "WanVideoImageClipEncode", - "pos": [ - 855.04638671875, - 844.81201171875 - ], - "size": [ - 310.4956359863281, - 326 - ], - "flags": {}, - "order": 29, - "mode": 0, - "inputs": [ - { - "name": "clip_vision", - "type": "CLIP_VISION", - "link": 82 - }, - { - "name": "image", - "type": "IMAGE", - "link": 88 - }, - { - "name": "vae", - "type": "WANVAE", - "link": 84 - }, - { - "name": "generation_width", - "type": "INT", - "widget": { - "name": "generation_width" - }, - "link": 85 - }, - { - "name": "generation_height", - "type": "INT", - "widget": { - "name": "generation_height" - }, - "link": 86 - }, - { - "name": "num_frames", - "type": "INT", - "widget": { - "name": "num_frames" - }, - "link": 87 - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "slot_index": 0, - "links": [] - } - ], - "properties": { - "Node name for S&R": "WanVideoImageClipEncode" - }, - "widgets_values": [ - 832, - 480, - 81, - true, - 0.030000000000000006, - 1, - 1, - false - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 38, - "type": "WanVideoVAELoader", - "pos": [ - 169.25408935546875, - -322.9471740722656 - ], - "size": [ - 372.7727966308594, - 82 - ], - "flags": {}, - "order": 15, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "vae", - "type": "WANVAE", - "slot_index": 0, - "links": [ - 43, - 63, - 67, - 84 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoVAELoader" - }, - "widgets_values": [ - "wanvideo\\Wan2_1_VAE_bf16.safetensors", - "bf16" - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 22, - "type": "WanVideoModelLoader", - "pos": [ - 150, - -780 - ], - "size": [ - 477.4410095214844, - 226.43276977539062 - ], - "flags": {}, - "order": 22, - "mode": 0, - "inputs": [ - { - "name": "compile_args", - "shape": 7, - "type": "WANCOMPILEARGS", - "link": 75 - }, - { - "name": "block_swap_args", - "shape": 7, - "type": "BLOCKSWAPARGS", - "link": null - }, - { - "name": "lora", - "shape": 7, - "type": "WANVIDLORA", - "link": null - }, - { - "name": "vram_management_args", - "shape": 7, - "type": "VRAM_MANAGEMENTARGS", - "link": null - } - ], - "outputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "slot_index": 0, - "links": [ - 29 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoModelLoader" - }, - "widgets_values": [ - "WanVideo\\Wan2_1-I2V-14B-480P_fp8_e4m3fn.safetensors", - "fp16_fast", - "fp8_e4m3fn", - "offload_device", - "sageattn" - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 52, - "type": "WanVideoTeaCache", - "pos": [ - 1323.885986328125, - -630.6788940429688 - ], - "size": [ - 315, - 154 - ], - "flags": {}, - "order": 16, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "cache_args", - "type": "CACHEARGS", - "links": [ - 91 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoTeaCache" - }, - "widgets_values": [ - 0.20000000000000004, - 2, - -1, - "offload_device", - true - ] - }, - { - "id": 27, - "type": "WanVideoSampler", - "pos": [ - 1315.2401123046875, - -401.48028564453125 - ], - "size": [ - 315, - 767 - ], - "flags": {}, - "order": 30, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "link": 29 - }, - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "link": 30 - }, - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "link": 64 - }, - { - "name": "samples", - "shape": 7, - "type": "LATENT", - "link": 68 - }, - { - "name": "feta_args", - "shape": 7, - "type": "FETAARGS", - "link": null - }, - { - "name": "context_options", - "shape": 7, - "type": "WANVIDCONTEXT", - "link": null - }, - { - "name": "cache_args", - "shape": 7, - "type": "CACHEARGS", - "link": 91 - }, - { - "name": "flowedit_args", - "shape": 7, - "type": "FLOWEDITARGS", - "link": 65 - }, - { - "name": "slg_args", - "shape": 7, - "type": "SLGARGS", - "link": 92 - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "slot_index": 0, - "links": [ - 33 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoSampler" - }, - "widgets_values": [ - 25, - 4.000000000000001, - 5.000000000000001, - 123, - "fixed", - true, - "euler", - 0, - 0.9500000000000002, - false, - "comfy", - "" - ] - }, - { - "id": 73, - "type": "WanVideoSLG", - "pos": [ - 927.0363159179688, - -366.92950439453125 - ], - "size": [ - 315, - 106 - ], - "flags": {}, - "order": 17, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "slg_args", - "type": "SLGARGS", - "links": [ - 92 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoSLG" - }, - "widgets_values": [ - "9", - 0.20000000000000004, - 0.9000000000000001 - ] - }, - { - "id": 63, - "type": "WanVideoFlowEdit", - "pos": [ - 879.3870849609375, - 407.6827697753906 - ], - "size": [ - 310.8893737792969, - 174 - ], - "flags": {}, - "order": 26, - "mode": 0, - "inputs": [ - { - "name": "source_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "link": 70 - }, - { - "name": "source_image_embeds", - "shape": 7, - "type": "WANVIDIMAGE_EMBEDS", - "link": null - } - ], - "outputs": [ - { - "name": "flowedit_args", - "type": "FLOWEDITARGS", - "links": [ - 65 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoFlowEdit" - }, - "widgets_values": [ - 2, - 8, - 7.000000000000002, - 6, - 6 - ] - }, - { - "id": 64, - "type": "WanVideoEncode", - "pos": [ - 874.3060302734375, - 117.539794921875 - ], - "size": [ - 315, - 242 - ], - "flags": {}, - "order": 24, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 67 - }, - { - "name": "image", - "type": "IMAGE", - "link": 66 - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "slot_index": 0, - "links": [ - 68 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoEncode" - }, - "widgets_values": [ - false, - 272, - 272, - 144, - 128, - 0, - 1 - ] - }, - { - "id": 28, - "type": "WanVideoDecode", - "pos": [ - 1688.0194091796875, - -647.6461791992188 - ], - "size": [ - 315, - 174 - ], - "flags": {}, - "order": 31, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 43 - }, - { - "name": "samples", - "type": "LATENT", - "link": 33 - } - ], - "outputs": [ - { - "name": "images", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 36, - 79 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoDecode" - }, - "widgets_values": [ - false, - 272, - 272, - 144, - 128 - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 69, - "type": "VHS_VideoCombine", - "pos": [ - 2655.1708984375, - -395.2093811035156 - ], - "size": [ - 1507.1126708984375, - 844.3505249023438 - ], - "flags": {}, - "order": 34, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 80 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "properties": { - "Node name for S&R": "VHS_VideoCombine" - }, - "widgets_values": { - "frame_rate": 16, - "loop_count": 0, - "filename_prefix": "WanVideoWrapper_I2V", - "format": "video/h264-mp4", - "pix_fmt": "yuv420p", - "crf": 19, - "save_metadata": true, - "trim_to_audio": false, - "pingpong": false, - "save_output": true, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "WanVideoWrapper_I2V_00433.mp4", - "subfolder": "", - "type": "output", - "format": "video/h264-mp4", - "frame_rate": 16, - "workflow": "WanVideoWrapper_I2V_00433.png", - "fullpath": "N:\\AI\\ComfyUI\\output\\WanVideoWrapper_I2V_00433.mp4" - } - } - } - } - ], - "links": [ - [ - 15, - 11, - 0, - 16, - 0, - "WANTEXTENCODER" - ], - [ - 29, - 22, - 0, - 27, - 0, - "WANVIDEOMODEL" - ], - [ - 30, - 16, - 0, - 27, - 1, - "WANVIDEOTEXTEMBEDS" - ], - [ - 33, - 27, - 0, - 28, - 1, - "LATENT" - ], - [ - 36, - 28, - 0, - 30, - 0, - "IMAGE" - ], - [ - 43, - 38, - 0, - 28, - 0, - "VAE" - ], - [ - 52, - 48, - 0, - 49, - 0, - "CLIP" - ], - [ - 53, - 48, - 0, - 50, - 0, - "CLIP" - ], - [ - 54, - 49, - 0, - 46, - 0, - "CONDITIONING" - ], - [ - 55, - 50, - 0, - 46, - 1, - "CONDITIONING" - ], - [ - 58, - 56, - 0, - 57, - 0, - "CLIP_VISION" - ], - [ - 59, - 58, - 0, - 57, - 1, - "IMAGE" - ], - [ - 63, - 38, - 0, - 57, - 2, - "WANVAE" - ], - [ - 64, - 57, - 0, - 27, - 2, - "WANVIDIMAGE_EMBEDS" - ], - [ - 65, - 63, - 0, - 27, - 7, - "FLOWEDITARGS" - ], - [ - 66, - 65, - 0, - 64, - 1, - "IMAGE" - ], - [ - 67, - 38, - 0, - 64, - 0, - "WANVAE" - ], - [ - 68, - 64, - 0, - 27, - 3, - "LATENT" - ], - [ - 69, - 11, - 0, - 66, - 0, - "WANTEXTENCODER" - ], - [ - 70, - 66, - 0, - 63, - 0, - "WANVIDEOTEXTEMBEDS" - ], - [ - 71, - 65, - 0, - 67, - 0, - "IMAGE" - ], - [ - 72, - 67, - 1, - 57, - 3, - "INT" - ], - [ - 73, - 67, - 2, - 57, - 4, - "INT" - ], - [ - 74, - 67, - 3, - 57, - 5, - "INT" - ], - [ - 75, - 35, - 0, - 22, - 0, - "WANCOMPILEARGS" - ], - [ - 77, - 58, - 0, - 68, - 1, - "IMAGE" - ], - [ - 78, - 67, - 0, - 68, - 0, - "IMAGE" - ], - [ - 79, - 28, - 0, - 68, - 2, - "IMAGE" - ], - [ - 80, - 68, - 0, - 69, - 0, - "IMAGE" - ], - [ - 81, - 67, - 0, - 70, - 0, - "IMAGE" - ], - [ - 82, - 56, - 0, - 71, - 0, - "CLIP_VISION" - ], - [ - 84, - 38, - 0, - 71, - 2, - "WANVAE" - ], - [ - 85, - 67, - 1, - 71, - 3, - "INT" - ], - [ - 86, - 67, - 2, - 71, - 4, - "INT" - ], - [ - 87, - 67, - 3, - 71, - 5, - "INT" - ], - [ - 88, - 70, - 0, - 71, - 1, - "IMAGE" - ], - [ - 91, - 52, - 0, - 27, - 6, - "TEACACHEARGS" - ], - [ - 92, - 73, - 0, - 27, - 8, - "SLGARGS" - ] - ], - "groups": [ - { - "id": 1, - "title": "ComfyUI text encoding alternative", - "bounding": [ - -1820.35107421875, - -367.5990905761719, - 1210.621337890625, - 805.9080810546875 - ], - "color": "#3f789e", - "font_size": 24, - "flags": {} - } - ], - "config": {}, - "extra": { - "ds": { - "scale": 0.6115909044841833, - "offset": [ - 973.5038468672901, - 1390.6616196111634 - ] - }, - "node_versions": { - "ComfyUI-WanVideoWrapper": "173aff236710272df37b3165c79297cd9b924e5a", - "comfy-core": "0.3.26", - "ComfyUI-VideoHelperSuite": "0a75c7958fe320efcb052f1d9f8451fd20c730a8", - "ComfyUI-KJNodes": "7c488a16ef420acf0276a4f8e31fc024a969d24b" - }, - "VHS_latentpreview": true, - "VHS_latentpreviewrate": 0, - "VHS_MetadataImage": true, - "VHS_KeepIntermediate": true - }, - "version": 0.4 -} \ No newline at end of file diff --git a/example_workflows/wanvideo_long_T2V_example_01.json b/example_workflows/wanvideo_long_T2V_example_01.json deleted file mode 100644 index 6f07fa6..0000000 --- a/example_workflows/wanvideo_long_T2V_example_01.json +++ /dev/null @@ -1,780 +0,0 @@ -{ - "id": "8b7a9a57-2303-4ef5-9fc2-bf41713bd1fc", - "revision": 0, - "last_node_id": 46, - "last_link_id": 58, - "nodes": [ - { - "id": 33, - "type": "Note", - "pos": [ - 227.3764190673828, - -205.28524780273438 - ], - "size": [ - 351.70458984375, - 88 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "Models:\nhttps://huggingface.co/Kijai/WanVideo_comfy/tree/main" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 11, - "type": "LoadWanVideoT5TextEncoder", - "pos": [ - 224.15325927734375, - -34.481563568115234 - ], - "size": [ - 377.1661376953125, - 130 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "wan_t5_model", - "type": "WANTEXTENCODER", - "slot_index": 0, - "links": [ - 15 - ] - } - ], - "properties": { - "Node name for S&R": "LoadWanVideoT5TextEncoder" - }, - "widgets_values": [ - "umt5-xxl-enc-bf16.safetensors", - "bf16", - "offload_device", - "disabled" - ] - }, - { - "id": 28, - "type": "WanVideoDecode", - "pos": [ - 1692.973876953125, - -404.8614501953125 - ], - "size": [ - 315, - 174 - ], - "flags": {}, - "order": 12, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 43 - }, - { - "name": "samples", - "type": "LATENT", - "link": 33 - } - ], - "outputs": [ - { - "name": "images", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 48 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoDecode" - }, - "widgets_values": [ - true, - 272, - 272, - 144, - 128 - ] - }, - { - "id": 38, - "type": "WanVideoVAELoader", - "pos": [ - 1687.4093017578125, - -582.2750854492188 - ], - "size": [ - 416.25482177734375, - 82 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "vae", - "type": "WANVAE", - "slot_index": 0, - "links": [ - 43 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoVAELoader" - }, - "widgets_values": [ - "wanvideo\\Wan2_1_VAE_bf16.safetensors", - "bf16" - ] - }, - { - "id": 42, - "type": "GetImageSizeAndCount", - "pos": [ - 1708.7301025390625, - -140.99705505371094 - ], - "size": [ - 277.20001220703125, - 86 - ], - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 48 - } - ], - "outputs": [ - { - "name": "image", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 56 - ] - }, - { - "label": "832 width", - "name": "width", - "type": "INT", - "links": null - }, - { - "label": "480 height", - "name": "height", - "type": "INT", - "links": null - }, - { - "label": "257 count", - "name": "count", - "type": "INT", - "links": null - } - ], - "properties": { - "Node name for S&R": "GetImageSizeAndCount" - }, - "widgets_values": [] - }, - { - "id": 16, - "type": "WanVideoTextEncode", - "pos": [ - 675.8850708007812, - -36.032100677490234 - ], - "size": [ - 420.30511474609375, - 261.5306701660156 - ], - "flags": {}, - "order": 10, - "mode": 0, - "inputs": [ - { - "name": "t5", - "type": "WANTEXTENCODER", - "link": 15 - }, - { - "name": "model_to_offload", - "shape": 7, - "type": "WANVIDEOMODEL", - "link": null - } - ], - "outputs": [ - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "slot_index": 0, - "links": [ - 30 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoTextEncode" - }, - "widgets_values": [ - "high quality nature video featuring a red panda balancing on a bamboo stem while a bird lands on it's head, on the background there is a waterfall", - "色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走", - true - ] - }, - { - "id": 30, - "type": "VHS_VideoCombine", - "pos": [ - 2127.120849609375, - -511.9014587402344 - ], - "size": [ - 873.2135620117188, - 840.2385864257812 - ], - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 56 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "properties": { - "Node name for S&R": "VHS_VideoCombine" - }, - "widgets_values": { - "frame_rate": 16, - "loop_count": 0, - "filename_prefix": "WanVideo2_1_T2V", - "format": "video/h264-mp4", - "pix_fmt": "yuv420p", - "crf": 19, - "save_metadata": true, - "trim_to_audio": false, - "pingpong": false, - "save_output": true, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "WanVideo2_1_T2V_00412.mp4", - "subfolder": "", - "type": "output", - "format": "video/h264-mp4", - "frame_rate": 16, - "workflow": "WanVideo2_1_T2V_00412.png", - "fullpath": "N:\\AI\\ComfyUI\\output\\WanVideo2_1_T2V_00412.mp4" - } - } - } - }, - { - "id": 37, - "type": "WanVideoEmptyEmbeds", - "pos": [ - 1305.26708984375, - -571.7843627929688 - ], - "size": [ - 315, - 106 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "links": [ - 42 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoEmptyEmbeds" - }, - "widgets_values": [ - 832, - 480, - 257 - ] - }, - { - "id": 35, - "type": "WanVideoTorchCompileSettings", - "pos": [ - 193.47103881835938, - -614.6900024414062 - ], - "size": [ - 390.5999755859375, - 178 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "torch_compile_args", - "type": "WANCOMPILEARGS", - "slot_index": 0, - "links": [] - } - ], - "properties": { - "Node name for S&R": "WanVideoTorchCompileSettings" - }, - "widgets_values": [ - "inductor", - false, - "default", - false, - 64, - true - ] - }, - { - "id": 45, - "type": "WanVideoTeaCache", - "pos": [ - 931.4036865234375, - -792.5159912109375 - ], - "size": [ - 315, - 154 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "cache_args", - "type": "CACHEARGS", - "links": [ - 58 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoTeaCache" - }, - "widgets_values": [ - 0.10000000000000002, - 1, - -1, - "offload_device", - true - ] - }, - { - "id": 36, - "type": "Note", - "pos": [ - 796.0189208984375, - -521.5020751953125 - ], - "size": [ - 298.2554016113281, - 108.62744140625 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "sdpa should work too, haven't tested flaash\n\nfp8_fast seems to cause huge quality degradation" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 46, - "type": "Note", - "pos": [ - 937.9556274414062, - -940.750244140625 - ], - "size": [ - 297.4364013671875, - 88 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "TeaCache with context windows is VERY experimental and lower values than normal should be used." - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 27, - "type": "WanVideoSampler", - "pos": [ - 1315.2401123046875, - -401.48028564453125 - ], - "size": [ - 315, - 574.1923217773438 - ], - "flags": {}, - "order": 11, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "link": 29 - }, - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "link": 30 - }, - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "link": 42 - }, - { - "name": "samples", - "shape": 7, - "type": "LATENT", - "link": null - }, - { - "name": "feta_args", - "shape": 7, - "type": "FETAARGS", - "link": null - }, - { - "name": "context_options", - "shape": 7, - "type": "WANVIDCONTEXT", - "link": 57 - }, - { - "name": "cache_args", - "shape": 7, - "type": "CACHEARGS", - "link": 58 - }, - { - "name": "flowedit_args", - "shape": 7, - "type": "FLOWEDITARGS", - "link": null - }, - { - "name": "slg_args", - "shape": 7, - "type": "SLGARGS", - "link": null - }, - { - "name": "loop_args", - "shape": 7, - "type": "LOOPARGS", - "link": null - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "slot_index": 0, - "links": [ - 33 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoSampler" - }, - "widgets_values": [ - 30, - 6, - 5, - 1057359483639288, - "fixed", - true, - "unipc", - 0, - 1, - "", - "comfy" - ] - }, - { - "id": 43, - "type": "WanVideoContextOptions", - "pos": [ - 1307.9542236328125, - -855.8865356445312 - ], - "size": [ - 315, - 226 - ], - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [ - { - "name": "vae", - "shape": 7, - "type": "WANVAE", - "link": null - } - ], - "outputs": [ - { - "name": "context_options", - "type": "WANVIDCONTEXT", - "slot_index": 0, - "links": [ - 57 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoContextOptions" - }, - "widgets_values": [ - "uniform_standard", - 81, - 4, - 16, - true, - false, - 6, - 2 - ] - }, - { - "id": 22, - "type": "WanVideoModelLoader", - "pos": [ - 620.3950805664062, - -357.8426818847656 - ], - "size": [ - 477.4410095214844, - 226.43276977539062 - ], - "flags": {}, - "order": 9, - "mode": 0, - "inputs": [ - { - "name": "compile_args", - "shape": 7, - "type": "WANCOMPILEARGS", - "link": null - }, - { - "name": "block_swap_args", - "shape": 7, - "type": "BLOCKSWAPARGS", - "link": null - }, - { - "name": "lora", - "shape": 7, - "type": "WANVIDLORA", - "link": null - }, - { - "name": "vram_management_args", - "shape": 7, - "type": "VRAM_MANAGEMENTARGS", - "link": null - } - ], - "outputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "slot_index": 0, - "links": [ - 29 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoModelLoader" - }, - "widgets_values": [ - "WanVideo\\wan2.1_t2v_1.3B_fp16.safetensors", - "fp16", - "disabled", - "offload_device", - "sdpa" - ] - } - ], - "links": [ - [ - 15, - 11, - 0, - 16, - 0, - "WANTEXTENCODER" - ], - [ - 29, - 22, - 0, - 27, - 0, - "WANVIDEOMODEL" - ], - [ - 30, - 16, - 0, - 27, - 1, - "WANVIDEOTEXTEMBEDS" - ], - [ - 33, - 27, - 0, - 28, - 1, - "LATENT" - ], - [ - 42, - 37, - 0, - 27, - 2, - "WANVIDIMAGE_EMBEDS" - ], - [ - 43, - 38, - 0, - 28, - 0, - "VAE" - ], - [ - 48, - 28, - 0, - 42, - 0, - "IMAGE" - ], - [ - 56, - 42, - 0, - 30, - 0, - "IMAGE" - ], - [ - 57, - 43, - 0, - 27, - 5, - "WANVIDCONTEXT" - ], - [ - 58, - 45, - 0, - 27, - 6, - "TEACACHEARGS" - ] - ], - "groups": [], - "config": {}, - "extra": { - "ds": { - "scale": 0.8140274938684471, - "offset": [ - -122.25834160503663, - 993.5739491626379 - ] - }, - "node_versions": { - "ComfyUI-WanVideoWrapper": "5a2383621a05825d0d0437781afcb8552d9590fd", - "ComfyUI-KJNodes": "a5bd3c86c8ed6b83c55c2d0e7a59515b15a0137f", - "ComfyUI-VideoHelperSuite": "0a75c7958fe320efcb052f1d9f8451fd20c730a8" - }, - "VHS_latentpreview": true, - "VHS_latentpreviewrate": 0, - "VHS_MetadataImage": true, - "VHS_KeepIntermediate": true - }, - "version": 0.4 -} \ No newline at end of file diff --git a/example_workflows/wanvideo_mocha_replacement_original_01.json b/example_workflows/wanvideo_mocha_replacement_original_01.json deleted file mode 100644 index 13c181a..0000000 --- a/example_workflows/wanvideo_mocha_replacement_original_01.json +++ /dev/null @@ -1,2138 +0,0 @@ -{ - "id": "c6e410bc-5e2c-460b-ae81-c91b6094fbb1", - "revision": 0, - "last_node_id": 342, - "last_link_id": 616, - "nodes": [ - { - "id": 243, - "type": "SetNode", - "pos": [ - -4658.337890625, - 111.99787139892578 - ], - "size": [ - 210, - 60 - ], - "flags": {}, - "order": 17, - "mode": 0, - "inputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "link": 391 - } - ], - "outputs": [ - { - "name": "*", - "type": "*", - "links": null - } - ], - "title": "Set_input_video", - "properties": { - "previousName": "input_video" - }, - "widgets_values": [ - "input_video" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 249, - "type": "PreviewImage", - "pos": [ - -4242.11767578125, - 42.481197357177734 - ], - "size": [ - 261.0582580566406, - 258 - ], - "flags": {}, - "order": 21, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 398 - } - ], - "outputs": [], - "properties": { - "Node name for S&R": "PreviewImage" - }, - "widgets_values": [] - }, - { - "id": 300, - "type": "LoadImage", - "pos": [ - -4988.6552734375, - 1341.486328125 - ], - "size": [ - 274.080078125, - 314.000244140625 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 494 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "title": "Load Reference Image", - "properties": { - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "character-3-2 (1).png", - "image" - ] - }, - { - "id": 246, - "type": "ImageResizeKJv2", - "pos": [ - -4653.63427734375, - 500.123291015625 - ], - "size": [ - 270, - 336.0001220703125 - ], - "flags": {}, - "order": 19, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 395 - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - }, - { - "name": "width", - "type": "INT", - "widget": { - "name": "width" - }, - "link": 595 - }, - { - "name": "height", - "type": "INT", - "widget": { - "name": "height" - }, - "link": 598 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 396, - 600 - ] - }, - { - "name": "width", - "type": "INT", - "links": [ - 501 - ] - }, - { - "name": "height", - "type": "INT", - "links": [ - 502 - ] - }, - { - "name": "mask", - "type": "MASK", - "links": null - } - ], - "properties": { - "Node name for S&R": "ImageResizeKJv2" - }, - "widgets_values": [ - 832, - 480, - "lanczos", - "pad", - "127,127,127", - "center", - 16, - "cpu" - ] - }, - { - "id": 298, - "type": "PreviewImage", - "pos": [ - -4980.3505859375, - 1790.142578125 - ], - "size": [ - 452.59210205078125, - 258 - ], - "flags": {}, - "order": 28, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 495 - } - ], - "outputs": [], - "properties": { - "Node name for S&R": "PreviewImage" - }, - "widgets_values": [] - }, - { - "id": 296, - "type": "ImageResizeKJv2", - "pos": [ - -4652.1630859375, - 1343.4151611328125 - ], - "size": [ - 270, - 336.0001220703125 - ], - "flags": {}, - "order": 25, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 494 - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - }, - { - "name": "width", - "type": "INT", - "widget": { - "name": "width" - }, - "link": 501 - }, - { - "name": "height", - "type": "INT", - "widget": { - "name": "height" - }, - "link": 502 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 495, - 601 - ] - }, - { - "name": "width", - "type": "INT", - "links": [] - }, - { - "name": "height", - "type": "INT", - "links": [] - }, - { - "name": "mask", - "type": "MASK", - "links": null - } - ], - "properties": { - "Node name for S&R": "ImageResizeKJv2" - }, - "widgets_values": [ - 983, - 480, - "lanczos", - "pad", - "127,127,127", - "center", - 16, - "cpu" - ] - }, - { - "id": 332, - "type": "SetNode", - "pos": [ - -4295.95556640625, - 1368.134033203125 - ], - "size": [ - 210, - 60 - ], - "flags": {}, - "order": 29, - "mode": 0, - "inputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "link": 601 - } - ], - "outputs": [ - { - "name": "*", - "type": "*", - "links": null - } - ], - "title": "Set_ref2", - "properties": { - "previousName": "ref2" - }, - "widgets_values": [ - "ref2" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 331, - "type": "SetNode", - "pos": [ - -4293.26025390625, - 497.8930358886719 - ], - "size": [ - 210, - 60 - ], - "flags": {}, - "order": 24, - "mode": 0, - "inputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "link": 600 - } - ], - "outputs": [ - { - "name": "*", - "type": "*", - "links": null - } - ], - "title": "Set_ref1", - "properties": { - "previousName": "ref1" - }, - "widgets_values": [ - "ref1" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 336, - "type": "GetNode", - "pos": [ - -2132.648681640625, - 1672.94140625 - ], - "size": [ - 210, - 58 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 606 - ] - } - ], - "title": "Get_ref1", - "properties": {}, - "widgets_values": [ - "ref1" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 308, - "type": "WanVideoVAELoader", - "pos": [ - -2121.183349609375, - 732.5975341796875 - ], - "size": [ - 397.5917663574219, - 92.40150451660156 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "name": "compile_args", - "shape": 7, - "type": "WANCOMPILEARGS", - "link": null - } - ], - "outputs": [ - { - "name": "vae", - "type": "WANVAE", - "links": [ - 602, - 603 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoVAELoader" - }, - "widgets_values": [ - "Wan2_1_VAE_bf16.safetensors", - "bf16" - ] - }, - { - "id": 312, - "type": "WanVideoLoraSelectMulti", - "pos": [ - -3116.08837890625, - 837.6162109375 - ], - "size": [ - 715.7383422851562, - 365.4935302734375 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [ - { - "name": "prev_lora", - "shape": 7, - "type": "WANVIDLORA", - "link": null - }, - { - "name": "blocks", - "shape": 7, - "type": "SELECTEDBLOCKS", - "link": null - } - ], - "outputs": [ - { - "name": "lora", - "type": "WANVIDLORA", - "links": [ - 558 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoLoraSelectMulti" - }, - "widgets_values": [ - "lightx2v/lightx2v_T2V_14B_cfg_step_distill_v2_lora_rank64_bf16.safetensors", - 1, - "none", - 1, - "none", - 1, - "none", - 1, - "none", - 1, - false, - true - ] - }, - { - "id": 335, - "type": "GetNode", - "pos": [ - -2138.790771484375, - 1564.837890625 - ], - "size": [ - 210, - 58 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "MASK", - "type": "MASK", - "links": [ - 605 - ] - } - ], - "title": "Get_mask", - "properties": {}, - "widgets_values": [ - "mask" - ], - "color": "#1c5715", - "bgcolor": "#1f401b" - }, - { - "id": 304, - "type": "WanVideoDecode", - "pos": [ - -806.5786743164062, - 779.7594604492188 - ], - "size": [ - 270, - 198 - ], - "flags": {}, - "order": 26, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 602 - }, - { - "name": "samples", - "type": "LATENT", - "link": 563 - } - ], - "outputs": [ - { - "name": "images", - "type": "IMAGE", - "links": [ - 611 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoDecode" - }, - "widgets_values": [ - false, - 272, - 272, - 144, - 128, - "default" - ] - }, - { - "id": 339, - "type": "GetNode", - "pos": [ - -711.1921997070312, - 1158.8116455078125 - ], - "size": [ - 210, - 58 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 612 - ] - } - ], - "title": "Get_input_video", - "properties": {}, - "widgets_values": [ - "input_video" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 338, - "type": "ImageConcanate", - "pos": [ - -400.39190673828125, - 1184.6094970703125 - ], - "size": [ - 270, - 102 - ], - "flags": {}, - "order": 30, - "mode": 0, - "inputs": [ - { - "name": "image1", - "type": "IMAGE", - "link": 612 - }, - { - "name": "image2", - "type": "IMAGE", - "link": 611 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 613 - ] - } - ], - "properties": { - "Node name for S&R": "ImageConcanate" - }, - "widgets_values": [ - "right", - true - ] - }, - { - "id": 318, - "type": "VHS_VideoCombine", - "pos": [ - -57.351234436035156, - 1083.17822265625 - ], - "size": [ - 523.336669921875, - 334 - ], - "flags": {}, - "order": 32, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 613 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "properties": { - "Node name for S&R": "VHS_VideoCombine" - }, - "widgets_values": { - "frame_rate": 24, - "loop_count": 0, - "filename_prefix": "AnimateDiff", - "format": "video/h264-mp4", - "pix_fmt": "yuv420p", - "crf": 19, - "save_metadata": true, - "trim_to_audio": false, - "pingpong": false, - "save_output": true, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "AnimateDiff_00981.mp4", - "subfolder": "", - "type": "output", - "format": "video/h264-mp4", - "frame_rate": 24, - "workflow": "AnimateDiff_00981.png", - "fullpath": "/home/deepspeed/workdir/ComfyUI/output/AnimateDiff_00981.mp4" - } - } - } - }, - { - "id": 245, - "type": "ImageResizeKJv2", - "pos": [ - -4685.974609375, - -395.6787109375 - ], - "size": [ - 270, - 336.0001220703125 - ], - "flags": {}, - "order": 15, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 390 - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 391, - 397 - ] - }, - { - "name": "width", - "type": "INT", - "links": [ - 595 - ] - }, - { - "name": "height", - "type": "INT", - "links": [ - 598 - ] - }, - { - "name": "mask", - "type": "MASK", - "links": null - } - ], - "properties": { - "Node name for S&R": "ImageResizeKJv2" - }, - "widgets_values": [ - 832, - 480, - "lanczos", - "resize", - "0, 0, 0", - "center", - 16, - "cpu" - ] - }, - { - "id": 248, - "type": "GetImageRangeFromBatch", - "pos": [ - -4244.3369140625, - -117.3695297241211 - ], - "size": [ - 340.3267517089844, - 102 - ], - "flags": {}, - "order": 18, - "mode": 0, - "inputs": [ - { - "name": "images", - "shape": 7, - "type": "IMAGE", - "link": 397 - }, - { - "name": "masks", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 398, - 597, - 614 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "Node name for S&R": "GetImageRangeFromBatch" - }, - "widgets_values": [ - 0, - 1 - ] - }, - { - "id": 328, - "type": "MaskPreview", - "pos": [ - -2074.385498046875, - -147.24452209472656 - ], - "size": [ - 354.98046875, - 276.60577392578125 - ], - "flags": {}, - "order": 33, - "mode": 0, - "inputs": [ - { - "name": "mask", - "type": "MASK", - "link": 592 - } - ], - "outputs": [], - "properties": { - "Node name for S&R": "MaskPreview" - }, - "widgets_values": [] - }, - { - "id": 325, - "type": "DownloadAndLoadSAM2Model", - "pos": [ - -2080.1123046875, - -334.4346008300781 - ], - "size": [ - 270, - 130 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "sam2_model", - "type": "SAM2MODEL", - "links": [ - 587 - ] - } - ], - "properties": { - "Node name for S&R": "DownloadAndLoadSAM2Model", - "cnr_id": "ComfyUI-segment-anything-2", - "ver": "c59676b008a76237002926f684d0ca3a9b29ac54" - }, - "widgets_values": [ - "sam2_hiera_base_plus.safetensors", - "video", - "cuda", - "fp16" - ] - }, - { - "id": 326, - "type": "Sam2Segmentation", - "pos": [ - -1742.36962890625, - -537.3062133789062 - ], - "size": [ - 272.087890625, - 182 - ], - "flags": {}, - "order": 27, - "mode": 0, - "inputs": [ - { - "name": "sam2_model", - "type": "SAM2MODEL", - "link": 587 - }, - { - "name": "image", - "type": "IMAGE", - "link": 614 - }, - { - "name": "coordinates_positive", - "shape": 7, - "type": "STRING", - "link": 588 - }, - { - "name": "coordinates_negative", - "shape": 7, - "type": "STRING", - "link": 589 - }, - { - "name": "bboxes", - "shape": 7, - "type": "BBOX", - "link": null - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "mask", - "type": "MASK", - "links": [ - 590 - ] - } - ], - "properties": { - "Node name for S&R": "Sam2Segmentation", - "cnr_id": "ComfyUI-segment-anything-2", - "ver": "c59676b008a76237002926f684d0ca3a9b29ac54" - }, - "widgets_values": [ - false, - false - ] - }, - { - "id": 330, - "type": "SetNode", - "pos": [ - -1393.6978759765625, - -505.46051025390625 - ], - "size": [ - 210, - 60 - ], - "flags": {}, - "order": 34, - "mode": 0, - "inputs": [ - { - "name": "MASK", - "type": "MASK", - "link": 599 - } - ], - "outputs": [ - { - "name": "*", - "type": "*", - "links": null - } - ], - "title": "Set_mask", - "properties": { - "previousName": "mask" - }, - "widgets_values": [ - "mask" - ], - "color": "#1c5715", - "bgcolor": "#1f401b" - }, - { - "id": 327, - "type": "GrowMask", - "pos": [ - -1743.5830078125, - -304.02972412109375 - ], - "size": [ - 270, - 82 - ], - "flags": { - "collapsed": false - }, - "order": 31, - "mode": 0, - "inputs": [ - { - "name": "mask", - "type": "MASK", - "link": 590 - } - ], - "outputs": [ - { - "name": "MASK", - "type": "MASK", - "links": [ - 592, - 599 - ] - } - ], - "properties": { - "Node name for S&R": "GrowMask", - "cnr_id": "comfy-core", - "ver": "0.3.59" - }, - "widgets_values": [ - 5, - true - ] - }, - { - "id": 333, - "type": "GetNode", - "pos": [ - -2141.247802734375, - 1465.3330078125 - ], - "size": [ - 210, - 60 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 604 - ] - } - ], - "title": "Get_input_video", - "properties": {}, - "widgets_values": [ - "input_video" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 311, - "type": "WanVideoModelLoader", - "pos": [ - -3117.3388671875, - 1273.5108642578125 - ], - "size": [ - 608.3448486328125, - 329.97747802734375 - ], - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [ - { - "name": "compile_args", - "shape": 7, - "type": "WANCOMPILEARGS", - "link": null - }, - { - "name": "block_swap_args", - "shape": 7, - "type": "BLOCKSWAPARGS", - "link": null - }, - { - "name": "lora", - "shape": 7, - "type": "WANVIDLORA", - "link": 558 - }, - { - "name": "vram_management_args", - "shape": 7, - "type": "VRAM_MANAGEMENTARGS", - "link": null - }, - { - "name": "extra_model", - "shape": 7, - "type": "VACEPATH", - "link": null - }, - { - "name": "fantasytalking_model", - "shape": 7, - "type": "FANTASYTALKINGMODEL", - "link": null - }, - { - "name": "multitalk_model", - "shape": 7, - "type": "MULTITALKMODEL", - "link": null - }, - { - "name": "fantasyportrait_model", - "shape": 7, - "type": "FANTASYPORTRAITMODEL", - "link": null - } - ], - "outputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "links": [ - 615 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoModelLoader" - }, - "widgets_values": [ - "character_render/v14-long-step15000.ckpt", - "bf16", - "disabled", - "offload_device", - "sdpa", - "default" - ] - }, - { - "id": 313, - "type": "WanVideoTextEncodeCached", - "pos": [ - -2113.37060546875, - 943.2658081054688 - ], - "size": [ - 400, - 302 - ], - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [ - { - "name": "extender_args", - "shape": 7, - "type": "WANVIDEOPROMPTEXTENDER_ARGS", - "link": null - } - ], - "outputs": [ - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "links": [ - 559 - ] - }, - { - "name": "negative_text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "links": null - }, - { - "name": "positive_prompt", - "type": "STRING", - "links": null - } - ], - "properties": { - "Node name for S&R": "WanVideoTextEncodeCached" - }, - "widgets_values": [ - "umt5-xxl-enc-fp8_e4m3fn.safetensors", - "bf16", - "", - "", - "disabled", - true, - "gpu" - ] - }, - { - "id": 247, - "type": "PreviewImage", - "pos": [ - -4993.5771484375, - 894.2095947265625 - ], - "size": [ - 385.585205078125, - 258 - ], - "flags": {}, - "order": 23, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 396 - } - ], - "outputs": [], - "properties": { - "Node name for S&R": "PreviewImage" - }, - "widgets_values": [] - }, - { - "id": 314, - "type": "WanVideoSampler", - "pos": [ - -1281.765380859375, - 1061.5728759765625 - ], - "size": [ - 327.80859375, - 734 - ], - "flags": {}, - "order": 20, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "link": 615 - }, - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "link": 581 - }, - { - "name": "text_embeds", - "shape": 7, - "type": "WANVIDEOTEXTEMBEDS", - "link": 559 - }, - { - "name": "samples", - "shape": 7, - "type": "LATENT", - "link": null - }, - { - "name": "feta_args", - "shape": 7, - "type": "FETAARGS", - "link": null - }, - { - "name": "context_options", - "shape": 7, - "type": "WANVIDCONTEXT", - "link": null - }, - { - "name": "cache_args", - "shape": 7, - "type": "CACHEARGS", - "link": null - }, - { - "name": "flowedit_args", - "shape": 7, - "type": "FLOWEDITARGS", - "link": null - }, - { - "name": "slg_args", - "shape": 7, - "type": "SLGARGS", - "link": null - }, - { - "name": "loop_args", - "shape": 7, - "type": "LOOPARGS", - "link": null - }, - { - "name": "experimental_args", - "shape": 7, - "type": "EXPERIMENTALARGS", - "link": null - }, - { - "name": "sigmas", - "shape": 7, - "type": "SIGMAS", - "link": null - }, - { - "name": "unianimate_poses", - "shape": 7, - "type": "UNIANIMATE_POSE", - "link": null - }, - { - "name": "fantasytalking_embeds", - "shape": 7, - "type": "FANTASYTALKING_EMBEDS", - "link": null - }, - { - "name": "uni3c_embeds", - "shape": 7, - "type": "UNI3C_EMBEDS", - "link": null - }, - { - "name": "multitalk_embeds", - "shape": 7, - "type": "MULTITALK_EMBEDS", - "link": null - }, - { - "name": "freeinit_args", - "shape": 7, - "type": "FREEINITARGS", - "link": null - }, - { - "name": "character_render_latent", - "shape": 7, - "type": "LATENT", - "link": null - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "links": [ - 563 - ] - }, - { - "name": "denoised_samples", - "type": "LATENT", - "links": null - } - ], - "properties": { - "Node name for S&R": "WanVideoSampler" - }, - "widgets_values": [ - 6, - 1.0000000000000002, - 5, - 42, - "fixed", - true, - "dpm++_sde", - 0, - 1, - false, - "comfy", - 0, - -1, - false - ] - }, - { - "id": 128, - "type": "VHS_LoadVideo", - "pos": [ - -4986.1728515625, - -396.7111511230469 - ], - "size": [ - 247.455078125, - 310 - ], - "flags": {}, - "order": 9, - "mode": 0, - "inputs": [ - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 390 - ] - }, - { - "name": "frame_count", - "type": "INT", - "links": [] - }, - { - "name": "audio", - "type": "AUDIO", - "links": null - }, - { - "name": "video_info", - "type": "VHS_VIDEOINFO", - "links": null - } - ], - "title": "Load Reference Video", - "properties": { - "Node name for S&R": "VHS_LoadVideo", - "cnr_id": "comfyui-videohelpersuite", - "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8" - }, - "widgets_values": { - "video": "10月15日 (5)(1).mp4", - "force_rate": 0, - "custom_width": 0, - "custom_height": 0, - "frame_load_cap": 81, - "skip_first_frames": 0, - "select_every_nth": 1, - "format": "AnimateDiff", - "choose video to upload": "image", - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "10月15日 (5)(1).mp4", - "type": "input", - "format": "video/mp4", - "force_rate": 0, - "custom_width": 0, - "custom_height": 0, - "frame_load_cap": 81, - "skip_first_frames": 0, - "select_every_nth": 1 - } - } - } - }, - { - "id": 212, - "type": "LoadImage", - "pos": [ - -4993.25927734375, - 483.2601013183594 - ], - "size": [ - 274.080078125, - 314.0001220703125 - ], - "flags": {}, - "order": 10, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 395 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "title": "Load Reference Image", - "properties": { - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "character-3.png", - "image" - ] - }, - { - "id": 323, - "type": "PointsEditor", - "pos": [ - -2991.7236328125, - -528.9296875 - ], - "size": [ - 877, - 748 - ], - "flags": {}, - "order": 22, - "mode": 0, - "inputs": [ - { - "name": "bg_image", - "shape": 7, - "type": "IMAGE", - "link": 597 - } - ], - "outputs": [ - { - "name": "positive_coords", - "type": "STRING", - "links": [ - 588 - ] - }, - { - "name": "negative_coords", - "type": "STRING", - "links": [ - 589 - ] - }, - { - "name": "bbox", - "type": "BBOX", - "links": null - }, - { - "name": "bbox_mask", - "type": "MASK", - "links": null - }, - { - "name": "cropped_image", - "type": "IMAGE", - "links": null - } - ], - "properties": { - "Node name for S&R": "PointsEditor", - "imgData": { - "name": "bg_image", - "base64": [ - "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KKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACgUUUAFFFFABRRRQAoqRTUVSKaaAkpp6UuaQ9KoQwikp9JikMVetWENV161MppiLA5pHj3CmqalU0AZ8ke2oqvzrwaokYNJoY6P71Xo1BAqghwauwyDApoTJHWoWGDVgkEVE4ptDTGZpaZUi1DVjVahtpMc1Ljim45pDsCipFWhB7VKFzQAiDmrCLmmItTqKQDlHNTKeKjzijdgUATbqp3V0I1ODzTbm6EaHnmsSaZpGyTRYTdiSa4aRqWFjmqoqaLNAlK5sQScCrTyBYiazoCaLy42xlR1pWLZn3cnmTE1XpScmkqjF7hRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACnrTKeDTQD80hpM0ZqrgLRjNJmlBGetAhQKkHSmAj1FLuHqKAJVapFaqwYeoqRXX+8PzoAll+YVRcYNXDIhH3h+dVZcZ4I/OhgiKpY2xUVKDSTGXlfIpxqpG+O9WFkXuw/OquIRxilSgshH3l/OkV1B+8PzqWXFlgDikxzSLJHj76/nT98f8Az0X86g1uhyipRUYkiH/LRPzp3nRf89E/OgNCdAKlFVVuIv8Anqn/AH1Thcxf89U/76FAronY8VXmn2KaGuIz0kT/AL6FVLlkdDiRPzoQm0U55jIx54qClPWkFMzbuOUZNWoozUMeBjJq7E0Y6uo/Gg0ikSj5EzWfcS+Y9WbqdQmFYH6Gs80IJvsJRRRQZBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH//2Q==" - ] - } - }, - "widgets_values": [ - "{\"positive\":[{\"x\":362.3956220422853,\"y\":221.12275243258088},{\"x\":429.96090750779615,\"y\":319.3995312915057}],\"negative\":[{\"x\":72.97050830275268,\"y\":59.45745120965033}]}", - "[{\"x\":362.3956220422853,\"y\":221.12275243258088},{\"x\":429.96090750779615,\"y\":319.3995312915057}]", - "[{\"x\":72.97050830275268,\"y\":59.45745120965033}]", - "[{}]", - "[{}]", - "xyxy", - 832, - 448, - false, - "", - null - ] - }, - { - "id": 302, - "type": "MochaEmbeds", - "pos": [ - -1842.8629150390625, - 1508.8265380859375 - ], - "size": [ - 270, - 234 - ], - "flags": {}, - "order": 16, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 603 - }, - { - "name": "input_video", - "type": "IMAGE", - "link": 604 - }, - { - "name": "mask", - "type": "MASK", - "link": 605 - }, - { - "name": "ref1", - "type": "IMAGE", - "link": 606 - }, - { - "name": "ref2", - "shape": 7, - "type": "IMAGE", - "link": 616 - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "links": [ - 581 - ] - } - ], - "properties": { - "Node name for S&R": "MochaEmbeds" - }, - "widgets_values": [ - 832, - false - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 337, - "type": "GetNode", - "pos": [ - -2132.64892578125, - 1783.503173828125 - ], - "size": [ - 210, - 58 - ], - "flags": {}, - "order": 11, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 616 - ] - } - ], - "title": "Get_ref2", - "properties": {}, - "widgets_values": [ - "ref2" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 341, - "type": "MarkdownNote", - "pos": [ - -5599.3466796875, - -465.1884765625 - ], - "size": [ - 537.5685424804688, - 332.75048828125 - ], - "flags": { - "collapsed": false - }, - "order": 12, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "# Github\nhttps://github.com/Orange-3DV-Team/MoCha\n\n# Project Page\nhttps://orange-3dv-team.github.io/MoCha/\n\n# Huggingface Checkpoint\n\nhttps://huggingface.co/Orange-3DV-Team/MoCha\n\nhttps://huggingface.co/Kijai/WanVideo_comfy" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 342, - "type": "MarkdownNote", - "pos": [ - -5621.03955078125, - 471.94781494140625 - ], - "size": [ - 517.5745239257812, - 247.94821166992188 - ], - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "1. We recommend using a reference image with a clean background.\n2. Ref2 is optional. You can use a face image as ref2 to enhance face fiedlity.\n3. The model will achieve the best results when the pose of the character in the reference image is close to the pose of the character in the first frame of the video." - ], - "color": "#432", - "bgcolor": "#653" - } - ], - "links": [ - [ - 390, - 128, - 0, - 245, - 0, - "IMAGE" - ], - [ - 391, - 245, - 0, - 243, - 0, - "IMAGE" - ], - [ - 395, - 212, - 0, - 246, - 0, - "IMAGE" - ], - [ - 396, - 246, - 0, - 247, - 0, - "IMAGE" - ], - [ - 397, - 245, - 0, - 248, - 0, - "IMAGE" - ], - [ - 398, - 248, - 0, - 249, - 0, - "IMAGE" - ], - [ - 494, - 300, - 0, - 296, - 0, - "IMAGE" - ], - [ - 495, - 296, - 0, - 298, - 0, - "IMAGE" - ], - [ - 501, - 246, - 1, - 296, - 2, - "INT" - ], - [ - 502, - 246, - 2, - 296, - 3, - "INT" - ], - [ - 558, - 312, - 0, - 311, - 2, - "WANVIDLORA" - ], - [ - 559, - 313, - 0, - 314, - 2, - "WANVIDEOTEXTEMBEDS" - ], - [ - 563, - 314, - 0, - 304, - 1, - "LATENT" - ], - [ - 581, - 302, - 0, - 314, - 1, - "WANVIDIMAGE_EMBEDS" - ], - [ - 587, - 325, - 0, - 326, - 0, - "SAM2MODEL" - ], - [ - 588, - 323, - 0, - 326, - 2, - "STRING" - ], - [ - 589, - 323, - 1, - 326, - 3, - "STRING" - ], - [ - 590, - 326, - 0, - 327, - 0, - "MASK" - ], - [ - 592, - 327, - 0, - 328, - 0, - "MASK" - ], - [ - 595, - 245, - 1, - 246, - 2, - "INT" - ], - [ - 597, - 248, - 0, - 323, - 0, - "IMAGE" - ], - [ - 598, - 245, - 2, - 246, - 3, - "INT" - ], - [ - 599, - 327, - 0, - 330, - 0, - "*" - ], - [ - 600, - 246, - 0, - 331, - 0, - "*" - ], - [ - 601, - 296, - 0, - 332, - 0, - "*" - ], - [ - 602, - 308, - 0, - 304, - 0, - "WANVAE" - ], - [ - 603, - 308, - 0, - 302, - 0, - "WANVAE" - ], - [ - 604, - 333, - 0, - 302, - 1, - "IMAGE" - ], - [ - 605, - 335, - 0, - 302, - 2, - "MASK" - ], - [ - 606, - 336, - 0, - 302, - 3, - "IMAGE" - ], - [ - 611, - 304, - 0, - 338, - 1, - "IMAGE" - ], - [ - 612, - 339, - 0, - 338, - 0, - "IMAGE" - ], - [ - 613, - 338, - 0, - 318, - 0, - "IMAGE" - ], - [ - 614, - 248, - 0, - 326, - 1, - "IMAGE" - ], - [ - 615, - 311, - 0, - 314, - 0, - "WANVIDEOMODEL" - ], - [ - 616, - 337, - 0, - 302, - 4, - "IMAGE" - ] - ], - "groups": [ - { - "id": 7, - "title": "Input Video", - "bounding": [ - -5017.30029296875, - -499.0201110839844, - 1719.6763916015625, - 869.1625366210938 - ], - "color": "#3f789e", - "font_size": 24, - "flags": { - "pinned": true - } - }, - { - "id": 9, - "title": "ref1", - "bounding": [ - -5009.6689453125, - 406.9666442871094, - 965.9547729492188, - 822.7760009765625 - ], - "color": "#3f789e", - "font_size": 24, - "flags": { - "pinned": true - } - }, - { - "id": 10, - "title": "ref2 (Optional)", - "bounding": [ - -5006.66064453125, - 1265.4342041015625, - 971.7285766601562, - 796.7326049804688 - ], - "color": "#3f789e", - "font_size": 24, - "flags": { - "pinned": true - } - }, - { - "id": 11, - "title": "First Frame Mask", - "bounding": [ - -3017.013916015625, - -623.8658447265625, - 1884.53564453125, - 1125.91064453125 - ], - "color": "#3f789e", - "font_size": 24, - "flags": {} - } - ], - "config": {}, - "extra": { - "ds": { - "scale": 0.895430243255371, - "offset": [ - 3416.8035155009957, - -580.9858195581344 - ] - }, - "frontendVersion": "1.27.10", - "node_versions": { - "ComfyUI-WanVideoWrapper": "5a2383621a05825d0d0437781afcb8552d9590fd", - "comfy-core": "0.3.26", - "ComfyUI-VideoHelperSuite": "0a75c7958fe320efcb052f1d9f8451fd20c730a8" - }, - "VHS_latentpreview": false, - "VHS_latentpreviewrate": 0, - "VHS_MetadataImage": true, - "VHS_KeepIntermediate": true - }, - "version": 0.4 -} \ No newline at end of file diff --git a/example_workflows/wanvideo_multitalk_test_02.json b/example_workflows/wanvideo_multitalk_test_02.json deleted file mode 100644 index a3113c3..0000000 --- a/example_workflows/wanvideo_multitalk_test_02.json +++ /dev/null @@ -1,1389 +0,0 @@ -{ - "id": "8b7a9a57-2303-4ef5-9fc2-bf41713bd1fc", - "revision": 0, - "last_node_id": 194, - "last_link_id": 336, - "nodes": [ - { - "id": 130, - "type": "WanVideoDecode", - "pos": [ - 3391.91015625, - -2268.65966796875 - ], - "size": [ - 315, - 198 - ], - "flags": {}, - "order": 19, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 193 - }, - { - "name": "samples", - "type": "LATENT", - "link": 194 - } - ], - "outputs": [ - { - "name": "images", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 196 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "c3ee35f3ece76e38099dc516182d69b406e16772", - "Node name for S&R": "WanVideoDecode" - }, - "widgets_values": [ - false, - 272, - 272, - 144, - 128, - "default" - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 192, - "type": "WanVideoImageToVideoMultiTalk", - "pos": [ - 3007.274169921875, - -1897.335693359375 - ], - "size": [ - 315.2046813964844, - 242 - ], - "flags": {}, - "order": 16, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 325 - }, - { - "name": "start_image", - "shape": 7, - "type": "IMAGE", - "link": 326 - }, - { - "name": "clip_embeds", - "shape": 7, - "type": "WANVIDIMAGE_CLIPEMBEDS", - "link": 329 - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "links": [ - 328 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "49430f900bf812a1e281560bafafd04c43dfdf13", - "Node name for S&R": "WanVideoImageToVideoMultiTalk" - }, - "widgets_values": [ - 832, - 480, - 81, - 25, - false, - "mkl", - false - ] - }, - { - "id": 133, - "type": "LoadImage", - "pos": [ - 1011.3872680664062, - -1517.9957275390625 - ], - "size": [ - 341.23583984375, - 424.5613708496094 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 283 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.41", - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "Mona-Lisa-oil-wood-panel-Leonardo-da.webp", - "image" - ] - }, - { - "id": 173, - "type": "CLIPVisionLoader", - "pos": [ - 1659.6119384765625, - -1829.4974365234375 - ], - "size": [ - 270, - 58 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "CLIP_VISION", - "type": "CLIP_VISION", - "links": [ - 330 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.41", - "Node name for S&R": "CLIPVisionLoader" - }, - "widgets_values": [ - "clip_vision_h.safetensors" - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 159, - "type": "AudioCrop", - "pos": [ - 1936.6385498046875, - -1060.82666015625 - ], - "size": [ - 270, - 82 - ], - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [ - { - "name": "audio", - "type": "AUDIO", - "link": 257 - } - ], - "outputs": [ - { - "name": "AUDIO", - "type": "AUDIO", - "links": [ - 296, - 301 - ] - } - ], - "properties": { - "cnr_id": "audio-separation-nodes-comfyui", - "ver": "31a4567726e035097cc2d1f767767908a6fda2ea", - "Node name for S&R": "AudioCrop" - }, - "widgets_values": [ - "0:00", - "2:00" - ] - }, - { - "id": 171, - "type": "ImageResizeKJv2", - "pos": [ - 1434.24169921875, - -1517.93603515625 - ], - "size": [ - 270, - 286 - ], - "flags": {}, - "order": 10, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 283 - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 326, - 331 - ] - }, - { - "name": "width", - "type": "INT", - "links": [] - }, - { - "name": "height", - "type": "INT", - "links": [] - }, - { - "name": "mask", - "type": "MASK", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "f7eb33abc80a2aded1b46dff0dd14d07856a7d50", - "Node name for S&R": "ImageResizeKJv2" - }, - "widgets_values": [ - 832, - 480, - "lanczos", - "crop", - "0, 0, 0", - "center", - 2, - "cpu" - ] - }, - { - "id": 193, - "type": "WanVideoClipVisionEncode", - "pos": [ - 2196.71337890625, - -1549.066162109375 - ], - "size": [ - 280.9771423339844, - 262 - ], - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [ - { - "name": "clip_vision", - "type": "CLIP_VISION", - "link": 330 - }, - { - "name": "image_1", - "type": "IMAGE", - "link": 331 - }, - { - "name": "image_2", - "shape": 7, - "type": "IMAGE", - "link": null - }, - { - "name": "negative_image", - "shape": 7, - "type": "IMAGE", - "link": null - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_CLIPEMBEDS", - "links": [ - 329 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "49430f900bf812a1e281560bafafd04c43dfdf13", - "Node name for S&R": "WanVideoClipVisionEncode" - }, - "widgets_values": [ - 1, - 1, - "center", - "average", - true, - 0, - 0.5000000000000001 - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 177, - "type": "WanVideoTorchCompileSettings", - "pos": [ - 1641.0926513671875, - -2447.249267578125 - ], - "size": [ - 342.74609375, - 202 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "torch_compile_args", - "type": "WANCOMPILEARGS", - "links": [ - 299 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "f3614e6720744247f3211d60f7b9333f43572384", - "Node name for S&R": "WanVideoTorchCompileSettings" - }, - "widgets_values": [ - "inductor", - false, - "default", - false, - 64, - true, - 128 - ] - }, - { - "id": 134, - "type": "WanVideoBlockSwap", - "pos": [ - 1209.63037109375, - -2396.775146484375 - ], - "size": [ - 281.404296875, - 154 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "block_swap_args", - "type": "BLOCKSWAPARGS", - "links": [ - 332 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "WanVideoBlockSwap" - }, - "widgets_values": [ - 15, - false, - false, - true, - 0 - ] - }, - { - "id": 135, - "type": "WanVideoTextEncode", - "pos": [ - 2834.335693359375, - -2292.33642578125 - ], - "size": [ - 469.3669128417969, - 323.4193115234375 - ], - "flags": {}, - "order": 11, - "mode": 0, - "inputs": [ - { - "name": "t5", - "shape": 7, - "type": "WANTEXTENCODER", - "link": 202 - }, - { - "name": "model_to_offload", - "shape": 7, - "type": "WANVIDEOMODEL", - "link": null - } - ], - "outputs": [ - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "links": [ - 306 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "WanVideoTextEncode" - }, - "widgets_values": [ - "A woman passionately singing. A close-up shot captures her expressive performance.", - "bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, images, static, overall gray, worst quality, low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, misshapen limbs, fused fingers, still picture, messy background, three legs, many people in the background, walking backwards", - true, - false, - "gpu" - ] - }, - { - "id": 136, - "type": "LoadWanVideoT5TextEncoder", - "pos": [ - 2236.692626953125, - -2039.4443359375 - ], - "size": [ - 370.9598693847656, - 130 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "wan_t5_model", - "type": "WANTEXTENCODER", - "links": [ - 202 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "LoadWanVideoT5TextEncoder" - }, - "widgets_values": [ - "umt5-xxl-enc-bf16.safetensors", - "bf16", - "offload_device", - "disabled" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 137, - "type": "DownloadAndLoadWav2VecModel", - "pos": [ - 2229.880859375, - -1822.4462890625 - ], - "size": [ - 330.96728515625, - 106 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "wav2vec_model", - "type": "WAV2VECMODEL", - "links": [ - 334 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "DownloadAndLoadWav2VecModel" - }, - "widgets_values": [ - "TencentGameMate/chinese-wav2vec2-base", - "fp16", - "main_device" - ] - }, - { - "id": 131, - "type": "VHS_VideoCombine", - "pos": [ - 3906.588134765625, - -2240.1123046875 - ], - "size": [ - 1386.326416015625, - 334 - ], - "flags": {}, - "order": 20, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 196 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": 296 - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-videohelpersuite", - "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8", - "Node name for S&R": "VHS_VideoCombine" - }, - "widgets_values": { - "frame_rate": 25, - "loop_count": 0, - "filename_prefix": "WanVideo2_1_multitalk", - "format": "video/h264-mp4", - "pix_fmt": "yuv420p", - "crf": 19, - "save_metadata": true, - "trim_to_audio": false, - "pingpong": false, - "save_output": false, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "WanVideo2_1_multitalk_00002-audio.mp4", - "subfolder": "", - "type": "temp", - "format": "video/h264-mp4", - "frame_rate": 25, - "workflow": "WanVideo2_1_multitalk_00002.png", - "fullpath": "N:\\AI\\ComfyUI\\temp\\WanVideo2_1_multitalk_00002-audio.mp4" - } - } - } - }, - { - "id": 170, - "type": "AudioSeparation", - "pos": [ - 2274.1318359375, - -988.1599731445312 - ], - "size": [ - 270, - 166 - ], - "flags": {}, - "order": 15, - "mode": 0, - "inputs": [ - { - "name": "audio", - "type": "AUDIO", - "link": 301 - } - ], - "outputs": [ - { - "name": "Bass", - "type": "AUDIO", - "links": null - }, - { - "name": "Drums", - "type": "AUDIO", - "links": null - }, - { - "name": "Other", - "type": "AUDIO", - "links": null - }, - { - "name": "Vocals", - "type": "AUDIO", - "links": [ - 335 - ] - } - ], - "properties": { - "cnr_id": "audio-separation-nodes-comfyui", - "ver": "31a4567726e035097cc2d1f767767908a6fda2ea", - "Node name for S&R": "AudioSeparation" - }, - "widgets_values": [ - "linear", - 10, - 0.1 - ] - }, - { - "id": 194, - "type": "MultiTalkWav2VecEmbeds", - "pos": [ - 3032.306640625, - -1562.1412353515625 - ], - "size": [ - 291.08203125, - 278 - ], - "flags": {}, - "order": 17, - "mode": 0, - "inputs": [ - { - "name": "wav2vec_model", - "type": "WAV2VECMODEL", - "link": 334 - }, - { - "name": "audio_1", - "type": "AUDIO", - "link": 335 - }, - { - "name": "audio_2", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "audio_3", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "audio_4", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "ref_target_masks", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "multitalk_embeds", - "type": "MULTITALK_EMBEDS", - "links": [ - 336 - ] - }, - { - "name": "audio", - "type": "AUDIO", - "links": null - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "3d7801cee4c8e3106078dd9b9f146caee95069ba", - "Node name for S&R": "MultiTalkWav2VecEmbeds" - }, - "widgets_values": [ - true, - 250, - 25, - 1, - 1, - "para" - ] - }, - { - "id": 138, - "type": "WanVideoLoraSelect", - "pos": [ - 1009.5531005859375, - -2124.957763671875 - ], - "size": [ - 503.4073486328125, - 150 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [ - { - "name": "prev_lora", - "shape": 7, - "type": "WANVIDLORA", - "link": null - }, - { - "name": "blocks", - "shape": 7, - "type": "SELECTEDBLOCKS", - "link": null - } - ], - "outputs": [ - { - "name": "lora", - "type": "WANVIDLORA", - "links": [ - 256 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "WanVideoLoraSelect" - }, - "widgets_values": [ - "Wan21_T2V_14B_lightx2v_cfg_step_distill_lora_rank32.safetensors", - 0.8000000000000002, - false, - true - ] - }, - { - "id": 120, - "type": "MultiTalkModelLoader", - "pos": [ - 1067.93701171875, - -1936.950439453125 - ], - "size": [ - 447.0210266113281, - 82 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "model", - "type": "MULTITALKMODEL", - "links": [ - 270 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "MultiTalkModelLoader" - }, - "widgets_values": [ - "WanVideo\\WanVideo_2_1_Multitalk_14B_fp8_e4m3fn.safetensors", - "fp16" - ] - }, - { - "id": 122, - "type": "WanVideoModelLoader", - "pos": [ - 1610.768798828125, - -2170.692138671875 - ], - "size": [ - 595.2891235351562, - 274 - ], - "flags": {}, - "order": 12, - "mode": 0, - "inputs": [ - { - "name": "compile_args", - "shape": 7, - "type": "WANCOMPILEARGS", - "link": 299 - }, - { - "name": "block_swap_args", - "shape": 7, - "type": "BLOCKSWAPARGS", - "link": 332 - }, - { - "name": "lora", - "shape": 7, - "type": "WANVIDLORA", - "link": 256 - }, - { - "name": "vram_management_args", - "shape": 7, - "type": "VRAM_MANAGEMENTARGS", - "link": null - }, - { - "name": "vace_model", - "shape": 7, - "type": "VACEPATH", - "link": null - }, - { - "name": "fantasytalking_model", - "shape": 7, - "type": "FANTASYTALKINGMODEL", - "link": null - }, - { - "name": "multitalk_model", - "shape": 7, - "type": "MULTITALKMODEL", - "link": 270 - } - ], - "outputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "links": [ - 197 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "WanVideoModelLoader" - }, - "widgets_values": [ - "WanVideo\\Wan2_1-I2V-14B-480P_fp8_e4m3fn.safetensors", - "fp16_fast", - "fp8_e4m3fn", - "offload_device", - "sageattn" - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 129, - "type": "WanVideoVAELoader", - "pos": [ - 2043.939697265625, - -2401.840576171875 - ], - "size": [ - 315, - 82 - ], - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "vae", - "type": "WANVAE", - "slot_index": 0, - "links": [ - 193, - 325 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "c3ee35f3ece76e38099dc516182d69b406e16772", - "Node name for S&R": "WanVideoVAELoader" - }, - "widgets_values": [ - "wanvideo\\Wan2_1_VAE_bf16.safetensors", - "bf16" - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 125, - "type": "LoadAudio", - "pos": [ - 1451.6412353515625, - -1061.2105712890625 - ], - "size": [ - 357.32049560546875, - 136 - ], - "flags": {}, - "order": 9, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "AUDIO", - "type": "AUDIO", - "links": [ - 257 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.41", - "Node name for S&R": "LoadAudio" - }, - "widgets_values": [ - "test_song.mp3", - null, - null - ] - }, - { - "id": 128, - "type": "WanVideoSampler", - "pos": [ - 3461.539306640625, - -1928.31787109375 - ], - "size": [ - 315, - 781.39453125 - ], - "flags": {}, - "order": 18, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "link": 197 - }, - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "link": 328 - }, - { - "name": "text_embeds", - "shape": 7, - "type": "WANVIDEOTEXTEMBEDS", - "link": 306 - }, - { - "name": "samples", - "shape": 7, - "type": "LATENT", - "link": null - }, - { - "name": "feta_args", - "shape": 7, - "type": "FETAARGS", - "link": null - }, - { - "name": "context_options", - "shape": 7, - "type": "WANVIDCONTEXT", - "link": null - }, - { - "name": "cache_args", - "shape": 7, - "type": "CACHEARGS", - "link": null - }, - { - "name": "flowedit_args", - "shape": 7, - "type": "FLOWEDITARGS", - "link": null - }, - { - "name": "slg_args", - "shape": 7, - "type": "SLGARGS", - "link": null - }, - { - "name": "loop_args", - "shape": 7, - "type": "LOOPARGS", - "link": null - }, - { - "name": "experimental_args", - "shape": 7, - "type": "EXPERIMENTALARGS", - "link": null - }, - { - "name": "sigmas", - "shape": 7, - "type": "SIGMAS", - "link": null - }, - { - "name": "unianimate_poses", - "shape": 7, - "type": "UNIANIMATE_POSE", - "link": null - }, - { - "name": "fantasytalking_embeds", - "shape": 7, - "type": "FANTASYTALKING_EMBEDS", - "link": null - }, - { - "name": "uni3c_embeds", - "shape": 7, - "type": "UNI3C_EMBEDS", - "link": null - }, - { - "name": "multitalk_embeds", - "shape": 7, - "type": "MULTITALK_EMBEDS", - "link": 336 - }, - { - "name": "freeinit_args", - "shape": 7, - "type": "FREEINITARGS", - "link": null - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "slot_index": 0, - "links": [ - 194 - ] - }, - { - "name": "denoised_samples", - "type": "LATENT", - "links": null - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "c3ee35f3ece76e38099dc516182d69b406e16772", - "Node name for S&R": "WanVideoSampler" - }, - "widgets_values": [ - 4, - 1.0000000000000002, - 11.000000000000002, - 1, - "fixed", - true, - "flowmatch_distill", - 0, - 1, - false, - "comfy", - 0, - -1, - false - ] - } - ], - "links": [ - [ - 193, - 129, - 0, - 130, - 0, - "WANVAE" - ], - [ - 194, - 128, - 0, - 130, - 1, - "LATENT" - ], - [ - 196, - 130, - 0, - 131, - 0, - "IMAGE" - ], - [ - 197, - 122, - 0, - 128, - 0, - "WANVIDEOMODEL" - ], - [ - 202, - 136, - 0, - 135, - 0, - "WANTEXTENCODER" - ], - [ - 256, - 138, - 0, - 122, - 2, - "WANVIDLORA" - ], - [ - 257, - 125, - 0, - 159, - 0, - "AUDIO" - ], - [ - 270, - 120, - 0, - 122, - 6, - "MULTITALKMODEL" - ], - [ - 283, - 133, - 0, - 171, - 0, - "IMAGE" - ], - [ - 296, - 159, - 0, - 131, - 1, - "AUDIO" - ], - [ - 299, - 177, - 0, - 122, - 0, - "WANCOMPILEARGS" - ], - [ - 301, - 159, - 0, - 170, - 0, - "AUDIO" - ], - [ - 306, - 135, - 0, - 128, - 2, - "WANVIDEOTEXTEMBEDS" - ], - [ - 325, - 129, - 0, - 192, - 0, - "WANVAE" - ], - [ - 326, - 171, - 0, - 192, - 1, - "IMAGE" - ], - [ - 328, - 192, - 0, - 128, - 1, - "WANVIDIMAGE_EMBEDS" - ], - [ - 329, - 193, - 0, - 192, - 2, - "WANVIDIMAGE_CLIPEMBEDS" - ], - [ - 330, - 173, - 0, - 193, - 0, - "CLIP_VISION" - ], - [ - 331, - 171, - 0, - 193, - 1, - "IMAGE" - ], - [ - 332, - 134, - 0, - 122, - 1, - "BLOCKSWAPARGS" - ], - [ - 334, - 137, - 0, - 194, - 0, - "WAV2VECMODEL" - ], - [ - 335, - 170, - 3, - 194, - 1, - "AUDIO" - ], - [ - 336, - 194, - 0, - 128, - 15, - "MULTITALK_EMBEDS" - ] - ], - "groups": [ - { - "id": 1, - "title": "Models", - "bounding": [ - 969.4049072265625, - -2553.697509765625, - 1772.8997802734375, - 888.819580078125 - ], - "color": "#3f789e", - "font_size": 24, - "flags": {} - } - ], - "config": {}, - "extra": { - "ds": { - "scale": 0.6115909044841903, - "offset": [ - -732.1708708005202, - 2451.37832568256 - ] - }, - "frontendVersion": "1.25.1", - "node_versions": { - "ComfyUI-WanVideoWrapper": "0a11c67a0c0062b534178920a0d6dcaa75e7b5fe", - "comfy-core": "0.3.43", - "audio-separation-nodes-comfyui": "31a4567726e035097cc2d1f767767908a6fda2ea", - "ComfyUI-KJNodes": "f7eb33abc80a2aded1b46dff0dd14d07856a7d50", - "comfyui-videohelpersuite": "a7ce59e381934733bfae03b1be029756d6ce936d" - }, - "VHS_latentpreview": true, - "VHS_latentpreviewrate": 0, - "VHS_MetadataImage": true, - "VHS_KeepIntermediate": true - }, - "version": 0.4 -} \ No newline at end of file diff --git a/example_workflows/wanvideo_multitalk_test_context_windows_01.json b/example_workflows/wanvideo_multitalk_test_context_windows_01.json deleted file mode 100644 index 15a6ac4..0000000 --- a/example_workflows/wanvideo_multitalk_test_context_windows_01.json +++ /dev/null @@ -1,1891 +0,0 @@ -{ - "id": "8b7a9a57-2303-4ef5-9fc2-bf41713bd1fc", - "revision": 0, - "last_node_id": 190, - "last_link_id": 325, - "nodes": [ - { - "id": 133, - "type": "LoadImage", - "pos": [ - 1011.3872680664062, - -1517.9957275390625 - ], - "size": [ - 341.23583984375, - 424.5613708496094 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 283 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.41", - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "multitalk_single_example.png", - "image" - ] - }, - { - "id": 170, - "type": "AudioSeparation", - "pos": [ - 1926.405517578125, - -886.7852783203125 - ], - "size": [ - 270, - 166 - ], - "flags": {}, - "order": 19, - "mode": 0, - "inputs": [ - { - "name": "audio", - "type": "AUDIO", - "link": 301 - } - ], - "outputs": [ - { - "name": "Bass", - "type": "AUDIO", - "links": null - }, - { - "name": "Drums", - "type": "AUDIO", - "links": null - }, - { - "name": "Other", - "type": "AUDIO", - "links": null - }, - { - "name": "Vocals", - "type": "AUDIO", - "links": [ - 318 - ] - } - ], - "properties": { - "cnr_id": "audio-separation-nodes-comfyui", - "ver": "31a4567726e035097cc2d1f767767908a6fda2ea", - "Node name for S&R": "AudioSeparation" - }, - "widgets_values": [ - "linear", - 10, - 0.1 - ] - }, - { - "id": 137, - "type": "DownloadAndLoadWav2VecModel", - "pos": [ - 2955.85693359375, - -1515.0516357421875 - ], - "size": [ - 330.96728515625, - 106 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "wav2vec_model", - "type": "WAV2VECMODEL", - "links": [ - 317 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "DownloadAndLoadWav2VecModel" - }, - "widgets_values": [ - "TencentGameMate/chinese-wav2vec2-base", - "fp16", - "main_device" - ] - }, - { - "id": 135, - "type": "WanVideoTextEncode", - "pos": [ - 2871.396728515625, - -955.9310302734375 - ], - "size": [ - 469.3669128417969, - 323.4193115234375 - ], - "flags": {}, - "order": 17, - "mode": 0, - "inputs": [ - { - "name": "t5", - "type": "WANTEXTENCODER", - "link": 202 - }, - { - "name": "model_to_offload", - "shape": 7, - "type": "WANVIDEOMODEL", - "link": null - } - ], - "outputs": [ - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "links": [ - 306 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "WanVideoTextEncode" - }, - "widgets_values": [ - "Stationary camera view of A woman passionately singing into a professional microphone in a recording studio. She wears large black headphones and a dark cardigan over a gray top. Her long, wavy brown hair frames her face as she looks slightly upwards, her mouth open mid-song. The studio is equipped with various audio equipment, including a mixing console and a keyboard, with soundproofing panels on the walls. The lighting is warm and focused on her, creating a professional and intimate atmosphere. A close-up shot captures her expressive performance.", - "bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, images, static, overall gray, worst quality, low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, misshapen limbs, fused fingers, still picture, messy background, three legs, many people in the background, walking backwards", - true - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 128, - "type": "WanVideoSampler", - "pos": [ - 3461.539306640625, - -1928.31787109375 - ], - "size": [ - 315, - 781.39453125 - ], - "flags": {}, - "order": 26, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "link": 197 - }, - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "link": 198 - }, - { - "name": "text_embeds", - "shape": 7, - "type": "WANVIDEOTEXTEMBEDS", - "link": 306 - }, - { - "name": "samples", - "shape": 7, - "type": "LATENT", - "link": null - }, - { - "name": "feta_args", - "shape": 7, - "type": "FETAARGS", - "link": null - }, - { - "name": "context_options", - "shape": 7, - "type": "WANVIDCONTEXT", - "link": 321 - }, - { - "name": "cache_args", - "shape": 7, - "type": "CACHEARGS", - "link": null - }, - { - "name": "flowedit_args", - "shape": 7, - "type": "FLOWEDITARGS", - "link": null - }, - { - "name": "slg_args", - "shape": 7, - "type": "SLGARGS", - "link": null - }, - { - "name": "loop_args", - "shape": 7, - "type": "LOOPARGS", - "link": null - }, - { - "name": "experimental_args", - "shape": 7, - "type": "EXPERIMENTALARGS", - "link": null - }, - { - "name": "sigmas", - "shape": 7, - "type": "SIGMAS", - "link": null - }, - { - "name": "unianimate_poses", - "shape": 7, - "type": "UNIANIMATE_POSE", - "link": null - }, - { - "name": "fantasytalking_embeds", - "shape": 7, - "type": "FANTASYTALKING_EMBEDS", - "link": null - }, - { - "name": "uni3c_embeds", - "shape": 7, - "type": "UNI3C_EMBEDS", - "link": 308 - }, - { - "name": "multitalk_embeds", - "shape": 7, - "type": "MULTITALK_EMBEDS", - "link": 320 - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "slot_index": 0, - "links": [ - 194 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "c3ee35f3ece76e38099dc516182d69b406e16772", - "Node name for S&R": "WanVideoSampler" - }, - "widgets_values": [ - 5, - 1.0000000000000002, - 5.000000000000001, - 6, - "fixed", - true, - "dpm++_sde", - 0, - 1, - false, - "comfy", - "" - ] - }, - { - "id": 186, - "type": "VHS_DuplicateImages", - "pos": [ - 3737.267822265625, - -462.8251037597656 - ], - "size": [ - 214.232421875, - 78 - ], - "flags": {}, - "order": 21, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 325 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 314 - ] - }, - { - "name": "count", - "type": "INT", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-videohelpersuite", - "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8", - "Node name for S&R": "VHS_DuplicateImages" - }, - "widgets_values": { - "multiply_by": 81 - } - }, - { - "id": 131, - "type": "VHS_VideoCombine", - "pos": [ - 3944.93896484375, - -2433.943115234375 - ], - "size": [ - 1266.4205322265625, - 1067.0887451171875 - ], - "flags": {}, - "order": 28, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 196 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": 296 - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-videohelpersuite", - "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8", - "Node name for S&R": "VHS_VideoCombine" - }, - "widgets_values": { - "frame_rate": 25, - "loop_count": 0, - "filename_prefix": "WanVideo2_1_multitalk", - "format": "video/h264-mp4", - "pix_fmt": "yuv420p", - "crf": 19, - "save_metadata": true, - "trim_to_audio": false, - "pingpong": false, - "save_output": false, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "WanVideo2_1_multitalk_00001-audio.mp4", - "subfolder": "", - "type": "temp", - "format": "video/h264-mp4", - "frame_rate": 25, - "workflow": "WanVideo2_1_multitalk_00001.png", - "fullpath": "N:\\AI\\ComfyUI\\temp\\WanVideo2_1_multitalk_00001-audio.mp4" - } - } - } - }, - { - "id": 182, - "type": "WanVideoUni3C_embeds", - "pos": [ - 4198.1904296875, - -858.3336791992188 - ], - "size": [ - 270, - 146 - ], - "flags": {}, - "order": 25, - "mode": 0, - "inputs": [ - { - "name": "controlnet", - "type": "WANVIDEOCONTROLNET", - "link": 309 - }, - { - "name": "render_latent", - "type": "LATENT", - "link": 310 - }, - { - "name": "render_mask", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "uni3c_embeds", - "type": "UNI3C_EMBEDS", - "links": [ - 308 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "f3614e6720744247f3211d60f7b9333f43572384", - "Node name for S&R": "WanVideoUni3C_embeds" - }, - "widgets_values": [ - 1, - 0, - 0.10000000000000002 - ] - }, - { - "id": 125, - "type": "LoadAudio", - "pos": [ - 1451.6412353515625, - -1061.2105712890625 - ], - "size": [ - 357.32049560546875, - 136 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "AUDIO", - "type": "AUDIO", - "links": [ - 257 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.41", - "Node name for S&R": "LoadAudio" - }, - "widgets_values": [ - "Lumière · Lorien Testard · Alice Duport-Percier.mp3", - null, - null - ] - }, - { - "id": 177, - "type": "WanVideoTorchCompileSettings", - "pos": [ - 1076.12060546875, - -2674.260009765625 - ], - "size": [ - 342.74609375, - 202 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "torch_compile_args", - "type": "WANCOMPILEARGS", - "links": [ - 299 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "f3614e6720744247f3211d60f7b9333f43572384", - "Node name for S&R": "WanVideoTorchCompileSettings" - }, - "widgets_values": [ - "inductor", - false, - "default", - false, - 64, - true, - 128 - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 159, - "type": "AudioCrop", - "pos": [ - 1927.918212890625, - -1068.45703125 - ], - "size": [ - 270, - 82 - ], - "flags": {}, - "order": 15, - "mode": 4, - "inputs": [ - { - "name": "audio", - "type": "AUDIO", - "link": 257 - } - ], - "outputs": [ - { - "name": "AUDIO", - "type": "AUDIO", - "links": [ - 296, - 301 - ] - } - ], - "properties": { - "cnr_id": "audio-separation-nodes-comfyui", - "ver": "31a4567726e035097cc2d1f767767908a6fda2ea", - "Node name for S&R": "AudioCrop" - }, - "widgets_values": [ - "0:01", - "2:00" - ] - }, - { - "id": 187, - "type": "MultiTalkWav2VecEmbeds", - "pos": [ - 2956.00244140625, - -1333.2303466796875 - ], - "size": [ - 291.08203125, - 278 - ], - "flags": {}, - "order": 22, - "mode": 0, - "inputs": [ - { - "name": "wav2vec_model", - "type": "WAV2VECMODEL", - "link": 317 - }, - { - "name": "audio_1", - "type": "AUDIO", - "link": 318 - }, - { - "name": "audio_2", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "audio_3", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "audio_4", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "ref_target_masks", - "shape": 7, - "type": "MASK", - "link": null - }, - { - "name": "num_frames", - "type": "INT", - "widget": { - "name": "num_frames" - }, - "link": 319 - } - ], - "outputs": [ - { - "name": "multitalk_embeds", - "type": "MULTITALK_EMBEDS", - "links": [ - 320 - ] - }, - { - "name": "audio", - "type": "AUDIO", - "links": null - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "3d7801cee4c8e3106078dd9b9f146caee95069ba", - "Node name for S&R": "MultiTalkWav2VecEmbeds" - }, - "widgets_values": [ - true, - 81, - 25, - 1, - 1, - "para" - ] - }, - { - "id": 188, - "type": "Note", - "pos": [ - 3985.1123046875, - -638.2463989257812 - ], - "size": [ - 239.9966278076172, - 88 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "Uni3C control is used here only to lock the camera, which improves results when using context windows" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 134, - "type": "WanVideoBlockSwap", - "pos": [ - 1133.5965576171875, - -2395.964599609375 - ], - "size": [ - 281.404296875, - 154 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "block_swap_args", - "type": "BLOCKSWAPARGS", - "links": [ - 201 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "WanVideoBlockSwap" - }, - "widgets_values": [ - 10, - false, - false, - true, - 0 - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 138, - "type": "WanVideoLoraSelect", - "pos": [ - 945.2125854492188, - -2169.73095703125 - ], - "size": [ - 503.4073486328125, - 126 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [ - { - "name": "prev_lora", - "shape": 7, - "type": "WANVIDLORA", - "link": null - }, - { - "name": "blocks", - "shape": 7, - "type": "SELECTEDBLOCKS", - "link": null - } - ], - "outputs": [ - { - "name": "lora", - "type": "WANVIDLORA", - "links": [ - 256 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "WanVideoLoraSelect" - }, - "widgets_values": [ - "Wan21_T2V_14B_lightx2v_cfg_step_distill_lora_rank32.safetensors", - 1.2000000000000002, - false - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 120, - "type": "MultiTalkModelLoader", - "pos": [ - 1137.2589111328125, - -1927.4013671875 - ], - "size": [ - 314.59307861328125, - 83.98193359375 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "model", - "type": "MULTITALKMODEL", - "links": [ - 270 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "MultiTalkModelLoader" - }, - "widgets_values": [ - "WanVideo\\multitalk.safetensors", - "fp16" - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 122, - "type": "WanVideoModelLoader", - "pos": [ - 1529.2850341796875, - -2411.081298828125 - ], - "size": [ - 595.2891235351562, - 274 - ], - "flags": {}, - "order": 16, - "mode": 0, - "inputs": [ - { - "name": "compile_args", - "shape": 7, - "type": "WANCOMPILEARGS", - "link": 299 - }, - { - "name": "block_swap_args", - "shape": 7, - "type": "BLOCKSWAPARGS", - "link": 201 - }, - { - "name": "lora", - "shape": 7, - "type": "WANVIDLORA", - "link": 256 - }, - { - "name": "vram_management_args", - "shape": 7, - "type": "VRAM_MANAGEMENTARGS", - "link": null - }, - { - "name": "vace_model", - "shape": 7, - "type": "VACEPATH", - "link": null - }, - { - "name": "fantasytalking_model", - "shape": 7, - "type": "FANTASYTALKINGMODEL", - "link": null - }, - { - "name": "multitalk_model", - "shape": 7, - "type": "MULTITALKMODEL", - "link": 270 - } - ], - "outputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "links": [ - 197 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "WanVideoModelLoader" - }, - "widgets_values": [ - "WanVideo\\Wan2_1-I2V-14B-480P_fp8_e4m3fn.safetensors", - "fp16_fast", - "fp8_e4m3fn", - "offload_device", - "sageattn" - ], - "color": "#223", - "bgcolor": "#335" - }, - { - "id": 129, - "type": "WanVideoVAELoader", - "pos": [ - 1774.7691650390625, - -2647.38232421875 - ], - "size": [ - 315, - 82 - ], - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "vae", - "type": "WANVAE", - "slot_index": 0, - "links": [ - 193, - 199, - 311 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "c3ee35f3ece76e38099dc516182d69b406e16772", - "Node name for S&R": "WanVideoVAELoader" - }, - "widgets_values": [ - "wanvideo\\Wan2_1_VAE_bf16.safetensors", - "bf16" - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 172, - "type": "WanVideoClipVisionEncode", - "pos": [ - 2515.615234375, - -1964.957275390625 - ], - "size": [ - 280.9771423339844, - 262 - ], - "flags": {}, - "order": 20, - "mode": 0, - "inputs": [ - { - "name": "clip_vision", - "type": "CLIP_VISION", - "link": 288 - }, - { - "name": "image_1", - "type": "IMAGE", - "link": 323 - }, - { - "name": "image_2", - "shape": 7, - "type": "IMAGE", - "link": null - }, - { - "name": "negative_image", - "shape": 7, - "type": "IMAGE", - "link": null - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_CLIPEMBEDS", - "links": [ - 287 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "58104b620f6b52de2fc516ade9f31383b0e7eca9", - "Node name for S&R": "WanVideoClipVisionEncode" - }, - "widgets_values": [ - 1, - 1, - "center", - "average", - true, - 0, - 0.5 - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 183, - "type": "WanVideoUni3C_ControlnetLoader", - "pos": [ - 3802.052978515625, - -848.1785278320312 - ], - "size": [ - 322.4781188964844, - 154 - ], - "flags": {}, - "order": 9, - "mode": 0, - "inputs": [ - { - "name": "compile_args", - "shape": 7, - "type": "WANCOMPILEARGS", - "link": null - } - ], - "outputs": [ - { - "name": "controlnet", - "type": "WANVIDEOCONTROLNET", - "links": [ - 309 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "f3614e6720744247f3211d60f7b9333f43572384", - "Node name for S&R": "WanVideoUni3C_ControlnetLoader" - }, - "widgets_values": [ - "Wan21_Uni3C_controlnet_fp16.safetensors", - "fp16", - "fp8_e4m3fn", - "main_device", - "sageattn" - ] - }, - { - "id": 189, - "type": "WanVideoContextOptions", - "pos": [ - 2943.619873046875, - -2259.861572265625 - ], - "size": [ - 309.2419128417969, - 178 - ], - "flags": {}, - "order": 10, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "context_options", - "type": "WANVIDCONTEXT", - "links": [ - 321 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "3d7801cee4c8e3106078dd9b9f146caee95069ba", - "Node name for S&R": "WanVideoContextOptions" - }, - "widgets_values": [ - "static_standard", - 81, - 4, - 32, - true, - false - ] - }, - { - "id": 136, - "type": "LoadWanVideoT5TextEncoder", - "pos": [ - 2452.524658203125, - -945.0313720703125 - ], - "size": [ - 370.9598693847656, - 130 - ], - "flags": {}, - "order": 11, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "wan_t5_model", - "type": "WANTEXTENCODER", - "links": [ - 202 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "LoadWanVideoT5TextEncoder" - }, - "widgets_values": [ - "umt5-xxl-enc-fp8_e4m3fn.safetensors", - "bf16", - "offload_device", - "fp8_e4m3fn" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 173, - "type": "CLIPVisionLoader", - "pos": [ - 1834.0162353515625, - -2052.537109375 - ], - "size": [ - 270, - 58 - ], - "flags": {}, - "order": 12, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "CLIP_VISION", - "type": "CLIP_VISION", - "links": [ - 288 - ] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.41", - "Node name for S&R": "CLIPVisionLoader" - }, - "widgets_values": [ - "clip_vision_h.safetensors" - ], - "color": "#233", - "bgcolor": "#355" - }, - { - "id": 132, - "type": "WanVideoImageToVideoEncode", - "pos": [ - 2959.904052734375, - -1989.0770263671875 - ], - "size": [ - 308.2320251464844, - 390 - ], - "flags": {}, - "order": 23, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 199 - }, - { - "name": "clip_embeds", - "shape": 7, - "type": "WANVIDIMAGE_CLIPEMBEDS", - "link": 287 - }, - { - "name": "start_image", - "shape": 7, - "type": "IMAGE", - "link": 324 - }, - { - "name": "end_image", - "shape": 7, - "type": "IMAGE", - "link": null - }, - { - "name": "control_embeds", - "shape": 7, - "type": "WANVIDIMAGE_EMBEDS", - "link": null - }, - { - "name": "temporal_mask", - "shape": 7, - "type": "MASK", - "link": null - }, - { - "name": "extra_latents", - "shape": 7, - "type": "LATENT", - "link": null - }, - { - "name": "add_cond_latents", - "shape": 7, - "type": "ADD_COND_LATENTS", - "link": null - }, - { - "name": "width", - "type": "INT", - "widget": { - "name": "width" - }, - "link": 290 - }, - { - "name": "height", - "type": "INT", - "widget": { - "name": "height" - }, - "link": 291 - }, - { - "name": "num_frames", - "type": "INT", - "widget": { - "name": "num_frames" - }, - "link": 295 - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "links": [ - 198 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "WanVideoImageToVideoEncode" - }, - "widgets_values": [ - 512, - 720, - 81, - 0, - 1, - 1, - true, - false, - false - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 130, - "type": "WanVideoDecode", - "pos": [ - 3548.77880859375, - -2445.249755859375 - ], - "size": [ - 315, - 198 - ], - "flags": {}, - "order": 27, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 193 - }, - { - "name": "samples", - "type": "LATENT", - "link": 194 - } - ], - "outputs": [ - { - "name": "images", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 196 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "c3ee35f3ece76e38099dc516182d69b406e16772", - "Node name for S&R": "WanVideoDecode" - }, - "widgets_values": [ - false, - 272, - 272, - 144, - 128, - "default" - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 184, - "type": "WanVideoEncode", - "pos": [ - 4008.18798828125, - -454.33416748046875 - ], - "size": [ - 270, - 242 - ], - "flags": {}, - "order": 24, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 311 - }, - { - "name": "image", - "type": "IMAGE", - "link": 314 - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "links": [ - 310 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "f3614e6720744247f3211d60f7b9333f43572384", - "Node name for S&R": "WanVideoEncode" - }, - "widgets_values": [ - false, - 272, - 272, - 144, - 128, - 0, - 1 - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 171, - "type": "ImageResizeKJv2", - "pos": [ - 1434.2418212890625, - -1519.026123046875 - ], - "size": [ - 270, - 286 - ], - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 283 - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 322 - ] - }, - { - "name": "width", - "type": "INT", - "links": [ - 290 - ] - }, - { - "name": "height", - "type": "INT", - "links": [ - 291 - ] - }, - { - "name": "mask", - "type": "MASK", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "f7eb33abc80a2aded1b46dff0dd14d07856a7d50", - "Node name for S&R": "ImageResizeKJv2" - }, - "widgets_values": [ - 832, - 480, - "lanczos", - "crop", - "0, 0, 0", - "center", - 2, - "cpu" - ] - }, - { - "id": 175, - "type": "INTConstant", - "pos": [ - 2555.978759765625, - -1559.425537109375 - ], - "size": [ - 210, - 58 - ], - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "value", - "type": "INT", - "links": [ - 295, - 319 - ] - } - ], - "title": "Frames", - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "f7eb33abc80a2aded1b46dff0dd14d07856a7d50", - "Node name for S&R": "INTConstant" - }, - "widgets_values": [ - 257 - ], - "color": "#1b4669", - "bgcolor": "#29699c" - }, - { - "id": 190, - "type": "Reroute", - "pos": [ - 2263.9169921875, - -1514.1737060546875 - ], - "size": [ - 75, - 26 - ], - "flags": {}, - "order": 18, - "mode": 0, - "inputs": [ - { - "name": "", - "type": "*", - "link": 322 - } - ], - "outputs": [ - { - "name": "", - "type": "IMAGE", - "links": [ - 323, - 324, - 325 - ] - } - ], - "properties": { - "showOutputText": false, - "horizontal": false - } - } - ], - "links": [ - [ - 193, - 129, - 0, - 130, - 0, - "WANVAE" - ], - [ - 194, - 128, - 0, - 130, - 1, - "LATENT" - ], - [ - 196, - 130, - 0, - 131, - 0, - "IMAGE" - ], - [ - 197, - 122, - 0, - 128, - 0, - "WANVIDEOMODEL" - ], - [ - 198, - 132, - 0, - 128, - 1, - "WANVIDIMAGE_EMBEDS" - ], - [ - 199, - 129, - 0, - 132, - 0, - "WANVAE" - ], - [ - 201, - 134, - 0, - 122, - 1, - "BLOCKSWAPARGS" - ], - [ - 202, - 136, - 0, - 135, - 0, - "WANTEXTENCODER" - ], - [ - 256, - 138, - 0, - 122, - 2, - "WANVIDLORA" - ], - [ - 257, - 125, - 0, - 159, - 0, - "AUDIO" - ], - [ - 270, - 120, - 0, - 122, - 6, - "MULTITALKMODEL" - ], - [ - 283, - 133, - 0, - 171, - 0, - "IMAGE" - ], - [ - 287, - 172, - 0, - 132, - 1, - "WANVIDIMAGE_CLIPEMBEDS" - ], - [ - 288, - 173, - 0, - 172, - 0, - "CLIP_VISION" - ], - [ - 290, - 171, - 1, - 132, - 8, - "INT" - ], - [ - 291, - 171, - 2, - 132, - 9, - "INT" - ], - [ - 295, - 175, - 0, - 132, - 10, - "INT" - ], - [ - 296, - 159, - 0, - 131, - 1, - "AUDIO" - ], - [ - 299, - 177, - 0, - 122, - 0, - "WANCOMPILEARGS" - ], - [ - 301, - 159, - 0, - 170, - 0, - "AUDIO" - ], - [ - 306, - 135, - 0, - 128, - 2, - "WANVIDEOTEXTEMBEDS" - ], - [ - 308, - 182, - 0, - 128, - 14, - "UNI3C_EMBEDS" - ], - [ - 309, - 183, - 0, - 182, - 0, - "WANVIDEOCONTROLNET" - ], - [ - 310, - 184, - 0, - 182, - 1, - "LATENT" - ], - [ - 311, - 129, - 0, - 184, - 0, - "WANVAE" - ], - [ - 314, - 186, - 0, - 184, - 1, - "IMAGE" - ], - [ - 317, - 137, - 0, - 187, - 0, - "WAV2VECMODEL" - ], - [ - 318, - 170, - 3, - 187, - 1, - "AUDIO" - ], - [ - 319, - 175, - 0, - 187, - 6, - "INT" - ], - [ - 320, - 187, - 0, - 128, - 15, - "MULTITALK_EMBEDS" - ], - [ - 321, - 189, - 0, - 128, - 5, - "WANVIDCONTEXT" - ], - [ - 322, - 171, - 0, - 190, - 0, - "*" - ], - [ - 323, - 190, - 0, - 172, - 1, - "IMAGE" - ], - [ - 324, - 190, - 0, - 132, - 2, - "IMAGE" - ], - [ - 325, - 190, - 0, - 186, - 0, - "IMAGE" - ] - ], - "groups": [ - { - "id": 1, - "title": "Uni3C - camera lock", - "bounding": [ - 3490.82958984375, - -1000.6835327148438, - 1048.014404296875, - 834.3169555664062 - ], - "color": "#3f789e", - "font_size": 24, - "flags": {} - }, - { - "id": 2, - "title": "Models", - "bounding": [ - 897.584716796875, - -2795.149169921875, - 1293.1141357421875, - 1007.8966064453125 - ], - "color": "#88A", - "font_size": 24, - "flags": {} - } - ], - "config": {}, - "extra": { - "ds": { - "scale": 0.4177248169415945, - "offset": [ - -568.3731137113364, - 3021.0071032227147 - ] - }, - "frontendVersion": "1.23.4", - "node_versions": { - "ComfyUI-KJNodes": "f9118e0bbb39347ea7becb84ec03e397dfb4f644", - "comfyui-videohelpersuite": "a7ce59e381934733bfae03b1be029756d6ce936d" - }, - "VHS_latentpreview": true, - "VHS_latentpreviewrate": 0, - "VHS_MetadataImage": true, - "VHS_KeepIntermediate": true - }, - "version": 0.4 -} \ No newline at end of file diff --git a/example_workflows/wanvideo_vid2vid_example_01.json b/example_workflows/wanvideo_vid2vid_example_01.json deleted file mode 100644 index e9e5973..0000000 --- a/example_workflows/wanvideo_vid2vid_example_01.json +++ /dev/null @@ -1,1044 +0,0 @@ -{ - "id": "44436dc8-b9e0-461b-aea2-13203712292d", - "revision": 0, - "last_node_id": 49, - "last_link_id": 62, - "nodes": [ - { - "id": 36, - "type": "Note", - "pos": [ - 796.0189208984375, - -521.5020751953125 - ], - "size": [ - 298.2554016113281, - 108.62744140625 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "sdpa should work too, haven't tested flaash\n\nfp8_fast seems to cause huge quality degradation" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 35, - "type": "WanVideoTorchCompileSettings", - "pos": [ - 124.67726135253906, - -627.7935180664062 - ], - "size": [ - 390.5999755859375, - 178 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "torch_compile_args", - "type": "WANCOMPILEARGS", - "slot_index": 0, - "links": [] - } - ], - "properties": { - "Node name for S&R": "WanVideoTorchCompileSettings" - }, - "widgets_values": [ - "inductor", - false, - "default", - false, - 64, - true - ] - }, - { - "id": 11, - "type": "LoadWanVideoT5TextEncoder", - "pos": [ - 224.15325927734375, - -34.481563568115234 - ], - "size": [ - 377.1661376953125, - 130 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "wan_t5_model", - "type": "WANTEXTENCODER", - "slot_index": 0, - "links": [ - 15 - ] - } - ], - "properties": { - "Node name for S&R": "LoadWanVideoT5TextEncoder" - }, - "widgets_values": [ - "umt5-xxl-enc-bf16.safetensors", - "bf16", - "offload_device", - "disabled" - ] - }, - { - "id": 28, - "type": "WanVideoDecode", - "pos": [ - 1692.973876953125, - -404.8614501953125 - ], - "size": [ - 315, - 174 - ], - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 43 - }, - { - "name": "samples", - "type": "LATENT", - "link": 33 - } - ], - "outputs": [ - { - "name": "images", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 54 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoDecode" - }, - "widgets_values": [ - true, - 272, - 272, - 144, - 128 - ] - }, - { - "id": 45, - "type": "ImageConcatMulti", - "pos": [ - 1817.8916015625, - 102.76653289794922 - ], - "size": [ - 210, - 150 - ], - "flags": {}, - "order": 15, - "mode": 0, - "inputs": [ - { - "name": "image_1", - "type": "IMAGE", - "link": 53 - }, - { - "name": "image_2", - "type": "IMAGE", - "link": 54 - } - ], - "outputs": [ - { - "name": "images", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 55 - ] - } - ], - "properties": {}, - "widgets_values": [ - 2, - "right", - false, - "" - ] - }, - { - "id": 43, - "type": "VHS_LoadVideo", - "pos": [ - 304.38446044921875, - 285.45703125 - ], - "size": [ - 247.455078125, - 551.455078125 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [ - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 51 - ] - }, - { - "name": "frame_count", - "type": "INT", - "slot_index": 1, - "links": [ - 56 - ] - }, - { - "name": "audio", - "type": "AUDIO", - "links": null - }, - { - "name": "video_info", - "type": "VHS_VIDEOINFO", - "links": null - } - ], - "properties": { - "Node name for S&R": "VHS_LoadVideo" - }, - "widgets_values": { - "video": "wolf_interpolated.mp4", - "force_rate": 0, - "custom_width": 0, - "custom_height": 0, - "frame_load_cap": 0, - "skip_first_frames": 0, - "select_every_nth": 1, - "format": "AnimateDiff", - "choose video to upload": "image", - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "wolf_interpolated.mp4", - "type": "input", - "format": "video/mp4", - "force_rate": 0, - "custom_width": 0, - "custom_height": 0, - "frame_load_cap": 0, - "skip_first_frames": 0, - "select_every_nth": 1 - } - } - } - }, - { - "id": 37, - "type": "WanVideoEmptyEmbeds", - "pos": [ - 753.8429565429688, - 611.1437377929688 - ], - "size": [ - 315, - 146 - ], - "flags": {}, - "order": 12, - "mode": 0, - "inputs": [ - { - "name": "num_frames", - "type": "INT", - "widget": { - "name": "num_frames" - }, - "link": 56 - }, - { - "name": "width", - "type": "INT", - "widget": { - "name": "width" - }, - "link": 57 - }, - { - "name": "height", - "type": "INT", - "widget": { - "name": "height" - }, - "link": 58 - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "links": [ - 42 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoEmptyEmbeds" - }, - "widgets_values": [ - 512, - 512, - 53 - ] - }, - { - "id": 33, - "type": "Note", - "pos": [ - 197.6475830078125, - -179.16000366210938 - ], - "size": [ - 351.70458984375, - 88 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "Models:\nhttps://huggingface.co/Kijai/WanVideo_comfy/tree/main" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 38, - "type": "WanVideoVAELoader", - "pos": [ - 1687.4093017578125, - -582.2750854492188 - ], - "size": [ - 373.55645751953125, - 82 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "vae", - "type": "WANVAE", - "slot_index": 0, - "links": [ - 43, - 48 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoVAELoader" - }, - "widgets_values": [ - "wanvideo\\Wan2_1_VAE_bf16.safetensors", - "bf16" - ] - }, - { - "id": 30, - "type": "VHS_VideoCombine", - "pos": [ - 2117.870849609375, - -567.7182006835938 - ], - "size": [ - 942.6622314453125, - 809.3311157226562 - ], - "flags": {}, - "order": 16, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 55 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "properties": { - "Node name for S&R": "VHS_VideoCombine" - }, - "widgets_values": { - "frame_rate": 16, - "loop_count": 0, - "filename_prefix": "WanVideoWrapperV2V", - "format": "video/h264-mp4", - "pix_fmt": "yuv420p", - "crf": 19, - "save_metadata": true, - "trim_to_audio": false, - "pingpong": false, - "save_output": true, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "WanVideoWrapperV2V_00016.mp4", - "subfolder": "", - "type": "output", - "format": "video/h264-mp4", - "frame_rate": 16, - "workflow": "WanVideoWrapperV2V_00016.png", - "fullpath": "N:\\AI\\ComfyUI\\output\\WanVideoWrapperV2V_00016.mp4" - } - } - } - }, - { - "id": 42, - "type": "WanVideoEncode", - "pos": [ - 1298.557861328125, - 306.5940246582031 - ], - "size": [ - 315, - 242 - ], - "flags": {}, - "order": 11, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 48 - }, - { - "name": "image", - "type": "IMAGE", - "link": 52 - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "slot_index": 0, - "links": [ - 50 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoEncode" - }, - "widgets_values": [ - false, - 272, - 272, - 144, - 128, - 0, - 1 - ] - }, - { - "id": 44, - "type": "ImageResizeKJ", - "pos": [ - 744.0538940429688, - 288.3457336425781 - ], - "size": [ - 315, - 286 - ], - "flags": {}, - "order": 10, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 51 - }, - { - "name": "get_image_size", - "shape": 7, - "type": "IMAGE", - "link": null - }, - { - "name": "width_input", - "shape": 7, - "type": "INT", - "widget": { - "name": "width_input" - }, - "link": null - }, - { - "name": "height_input", - "shape": 7, - "type": "INT", - "widget": { - "name": "height_input" - }, - "link": null - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 52, - 53 - ] - }, - { - "name": "width", - "type": "INT", - "slot_index": 1, - "links": [ - 57 - ] - }, - { - "name": "height", - "type": "INT", - "slot_index": 2, - "links": [ - 58 - ] - } - ], - "properties": { - "Node name for S&R": "ImageResizeKJ" - }, - "widgets_values": [ - 512, - 512, - "lanczos", - false, - 16, - 0, - 0, - "disabled" - ] - }, - { - "id": 16, - "type": "WanVideoTextEncode", - "pos": [ - 675.8850708007812, - -36.032100677490234 - ], - "size": [ - 420.30511474609375, - 261.5306701660156 - ], - "flags": {}, - "order": 9, - "mode": 0, - "inputs": [ - { - "name": "t5", - "type": "WANTEXTENCODER", - "link": 15 - }, - { - "name": "model_to_offload", - "shape": 7, - "type": "WANVIDEOMODEL", - "link": null - } - ], - "outputs": [ - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "slot_index": 0, - "links": [ - 30 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoTextEncode" - }, - "widgets_values": [ - "high quality video featuring a red panda", - "色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走", - true - ] - }, - { - "id": 46, - "type": "WanVideoTeaCache", - "pos": [ - 1295.5970458984375, - -682.718017578125 - ], - "size": [ - 315, - 154 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "cache_args", - "type": "CACHEARGS", - "slot_index": 0, - "links": [ - 62 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoTeaCache" - }, - "widgets_values": [ - 0.25, - 1, - -1, - "offload_device", - "true" - ] - }, - { - "id": 27, - "type": "WanVideoSampler", - "pos": [ - 1310.73583984375, - -457.3343200683594 - ], - "size": [ - 315, - 699 - ], - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "link": 29 - }, - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "link": 30 - }, - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "link": 42 - }, - { - "name": "samples", - "shape": 7, - "type": "LATENT", - "link": 50 - }, - { - "name": "feta_args", - "shape": 7, - "type": "FETAARGS", - "link": null - }, - { - "name": "context_options", - "shape": 7, - "type": "WANVIDCONTEXT", - "link": null - }, - { - "name": "cache_args", - "shape": 7, - "type": "CACHEARGS", - "link": 62 - }, - { - "name": "flowedit_args", - "shape": 7, - "type": "FLOWEDITARGS", - "link": null - }, - { - "name": "slg_args", - "shape": 7, - "type": "SLGARGS", - "link": null - }, - { - "name": "loop_args", - "shape": 7, - "type": "LOOPARGS", - "link": null - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "slot_index": 0, - "links": [ - 33 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoSampler" - }, - "widgets_values": [ - 15, - 6.000000000000001, - 5.000000000000001, - 1057359483639288, - "fixed", - true, - "dpm++", - 0, - 0.5000000000000001, - "", - "comfy" - ] - }, - { - "id": 39, - "type": "WanVideoBlockSwap", - "pos": [ - 194.8857879638672, - -363.0874938964844 - ], - "size": [ - 315, - 130 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "block_swap_args", - "type": "BLOCKSWAPARGS", - "slot_index": 0, - "links": [] - } - ], - "properties": { - "Node name for S&R": "WanVideoBlockSwap" - }, - "widgets_values": [ - 20, - false, - false, - true - ] - }, - { - "id": 22, - "type": "WanVideoModelLoader", - "pos": [ - 620.3950805664062, - -357.8426818847656 - ], - "size": [ - 477.4410095214844, - 226.43276977539062 - ], - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [ - { - "name": "compile_args", - "shape": 7, - "type": "WANCOMPILEARGS", - "link": null - }, - { - "name": "block_swap_args", - "shape": 7, - "type": "BLOCKSWAPARGS", - "link": null - }, - { - "name": "lora", - "shape": 7, - "type": "WANVIDLORA", - "link": null - }, - { - "name": "vram_management_args", - "shape": 7, - "type": "VRAM_MANAGEMENTARGS", - "link": null - } - ], - "outputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "slot_index": 0, - "links": [ - 29 - ] - } - ], - "properties": { - "Node name for S&R": "WanVideoModelLoader" - }, - "widgets_values": [ - "WanVideo\\wan2.1_t2v_1.3B_fp16.safetensors", - "fp16", - "disabled", - "offload_device", - "sdpa" - ] - } - ], - "links": [ - [ - 15, - 11, - 0, - 16, - 0, - "WANTEXTENCODER" - ], - [ - 29, - 22, - 0, - 27, - 0, - "WANVIDEOMODEL" - ], - [ - 30, - 16, - 0, - 27, - 1, - "WANVIDEOTEXTEMBEDS" - ], - [ - 33, - 27, - 0, - 28, - 1, - "LATENT" - ], - [ - 42, - 37, - 0, - 27, - 2, - "WANVIDIMAGE_EMBEDS" - ], - [ - 43, - 38, - 0, - 28, - 0, - "VAE" - ], - [ - 48, - 38, - 0, - 42, - 0, - "WANVAE" - ], - [ - 50, - 42, - 0, - 27, - 3, - "LATENT" - ], - [ - 51, - 43, - 0, - 44, - 0, - "IMAGE" - ], - [ - 52, - 44, - 0, - 42, - 1, - "IMAGE" - ], - [ - 53, - 44, - 0, - 45, - 0, - "IMAGE" - ], - [ - 54, - 28, - 0, - 45, - 1, - "IMAGE" - ], - [ - 55, - 45, - 0, - 30, - 0, - "IMAGE" - ], - [ - 56, - 43, - 1, - 37, - 0, - "INT" - ], - [ - 57, - 44, - 1, - 37, - 1, - "INT" - ], - [ - 58, - 44, - 2, - 37, - 2, - "INT" - ], - [ - 62, - 46, - 0, - 27, - 6, - "TEACACHEARGS" - ] - ], - "groups": [], - "config": {}, - "extra": { - "ds": { - "scale": 0.6727499949326009, - "offset": [ - 391.99039310194877, - 810.1005303189878 - ] - }, - "node_versions": { - "ComfyUI-WanVideoWrapper": "5a2383621a05825d0d0437781afcb8552d9590fd", - "ComfyUI-KJNodes": "a5bd3c86c8ed6b83c55c2d0e7a59515b15a0137f", - "ComfyUI-VideoHelperSuite": "0a75c7958fe320efcb052f1d9f8451fd20c730a8" - }, - "VHS_latentpreview": true, - "VHS_latentpreviewrate": 0, - "VHS_MetadataImage": true, - "VHS_KeepIntermediate": true - }, - "version": 0.4 -} \ No newline at end of file From b132a82f7a4b86d4e72d15fe7daa952e1fc18c06 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 15:57:30 +0200 Subject: [PATCH 12/22] Fix LongCat-Avatar audio padding when not enough audio provided for given window --- LongCat/nodes.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/LongCat/nodes.py b/LongCat/nodes.py index 941a4fa..19c12e8 100644 --- a/LongCat/nodes.py +++ b/LongCat/nodes.py @@ -37,15 +37,16 @@ class WanVideoLongCatAvatarExtendEmbeds(io.ComfyNode): new_audio_embed = audio_embeds.copy() audio_features = torch.stack(new_audio_embed["audio_features"]) + num_audio_features = audio_features.shape[1] if audio_features.shape[1] < frames_processed + num_frames: deficit = frames_processed + num_frames - audio_features.shape[1] if if_not_enough_audio == "pad_with_start": - pad = audio_features[:, :1].repeat(1, deficit, 1, 1, 1) + pad = audio_features[:, :1].repeat(1, deficit, 1, 1) audio_features = torch.cat([audio_features, pad], dim=1) elif if_not_enough_audio == "mirror_from_end": to_add = audio_features[:, -deficit:, :].flip(dims=[1]) audio_features = torch.cat([audio_features, to_add], dim=1) - log.info(f"Not enough audio features, extended from {new_audio_embed['audio_features'].shape[1]} to {audio_features.shape[1]} frames.") + log.warning(f"Not enough audio features, padded with strategy '{if_not_enough_audio}' from {num_audio_features} to {audio_features.shape[1]} frames") ref_target_masks = new_audio_embed.get("ref_target_masks", None) if ref_target_masks is not None: From fd818faa08ce07e5530e71bd0ccc2985cac98105 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 16:09:01 +0200 Subject: [PATCH 13/22] Fix context window ref latent device --- nodes_sampler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodes_sampler.py b/nodes_sampler.py index 42fd8cf..2b60f43 100644 --- a/nodes_sampler.py +++ b/nodes_sampler.py @@ -1861,7 +1861,7 @@ class WanVideoSampler: if context_reference_latent.shape[0] == 1: #only single extra init latent new_init_image = context_reference_latent[0, :, 0].to(device) # Concatenate the first 4 channels of partial_img_emb with new_init_image to match the required shape - partial_img_emb[:, 0] = torch.cat([image_cond[:4, 0], new_init_image], dim=0) + partial_img_emb[:, 0] = torch.cat([image_cond[:4, 0].to(device), new_init_image], dim=0) elif context_reference_latent.shape[0] > 1: num_extra_inits = context_reference_latent.shape[0] section_size = (latent_video_length / num_extra_inits) @@ -1869,7 +1869,7 @@ class WanVideoSampler: if context_options["verbose"]: log.info(f"extra init image index: {extra_init_index}") new_init_image = context_reference_latent[extra_init_index, :, 0].to(device) - partial_img_emb[:, 0] = torch.cat([image_cond[:4, 0], new_init_image], dim=0) + partial_img_emb[:, 0] = torch.cat([image_cond[:4, 0].to(device), new_init_image], dim=0) else: new_init_image = image_cond[:, 0].to(device) partial_img_emb[:, 0] = new_init_image From a896101ec879e9b487e2b90dd9f15bca70726b0f Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 22:28:04 +0200 Subject: [PATCH 14/22] I don't know why this suddenly errors --- nodes_sampler.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nodes_sampler.py b/nodes_sampler.py index 2b60f43..5c47564 100644 --- a/nodes_sampler.py +++ b/nodes_sampler.py @@ -1379,15 +1379,14 @@ class WanVideoSampler: z = z * c_in timestep = c_noise + self.noise_front_pad_num = 0 if image_cond is not None: self.noise_front_pad_num = image_cond_input.shape[1] - z.shape[1] if self.noise_front_pad_num > 0: pad = torch.zeros((z.shape[0], self.noise_front_pad_num, z.shape[2], z.shape[3]), dtype=z.dtype, device=z.device) - z = torch.concat([pad, z], dim=1) + z = torch.cat([pad, z], dim=1) nonlocal seq_len seq_len = math.ceil((z.shape[2] * z.shape[3]) / 4 * z.shape[1]) - else: - self.noise_front_pad_num = 0 if background_latents is not None or foreground_latents is not None: z = torch.cat([z, foreground_latents.to(z), background_latents.to(z)], dim=0) From e855726f10163bcf1fa6e80e85b55ff67eb89d96 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 26 Dec 2025 23:12:18 +0200 Subject: [PATCH 15/22] Fix enhance-a-video --- nodes_sampler.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nodes_sampler.py b/nodes_sampler.py index 5c47564..57b73e8 100644 --- a/nodes_sampler.py +++ b/nodes_sampler.py @@ -1379,7 +1379,6 @@ class WanVideoSampler: z = z * c_in timestep = c_noise - self.noise_front_pad_num = 0 if image_cond is not None: self.noise_front_pad_num = image_cond_input.shape[1] - z.shape[1] if self.noise_front_pad_num > 0: @@ -1771,6 +1770,8 @@ class WanVideoSampler: latent_flipped = torch.flip(latent, dims=[1]) latent_model_input_flipped = latent_flipped.to(device) + self.noise_front_pad_num = 0 + #InfiniteTalk first frame handling if (extra_latents is not None and not multitalk_sampling @@ -1821,7 +1822,7 @@ class WanVideoSampler: if feta_args is not None and feta_start_percent <= current_step_percentage <= feta_end_percent: enhance_enabled = True #region context windowing - elif context_options is not None: + if context_options is not None: counter = torch.zeros_like(latent_model_input, device=device) noise_pred = torch.zeros_like(latent_model_input, device=device) context_queue = list(context(idx, steps, latent_video_length, context_frames, context_stride, context_overlap)) From 7a6efc145618be57d1a4a959205d5de8995427df Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Sun, 28 Dec 2025 00:35:14 +0200 Subject: [PATCH 16/22] Add node for SVI 2.0 Pro --- nodes.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/nodes.py b/nodes.py index 67f5142..f7ef927 100644 --- a/nodes.py +++ b/nodes.py @@ -909,6 +909,64 @@ class WanVideoAddStoryMemLatents: updated["story_mem_latents"] = story_mem_latents["samples"].squeeze(2).permute(1, 0, 2, 3) # [C, T, H, W] return (updated,) + +class WanVideoSVIProEmbeds: + @classmethod + def INPUT_TYPES(s): + return {"required": { + "anchor_samples": ("LATENT", {"tooltip": "Initial start image encoded"}), + "num_frames": ("INT", {"default": 81, "min": 1, "max": 10000, "step": 4, "tooltip": "Number of frames to encode"}), + }, + "optional": { + "prev_samples": ("LATENT", {"tooltip": "Last latent from previous generation"}), + "motion_latent_count": ("INT", {"default": 2, "min": 1, "max": 100, "step": 1, "tooltip": "Number of latents used to continue"}), + } + } + + RETURN_TYPES = ("WANVIDIMAGE_EMBEDS",) + RETURN_NAMES = ("image_embeds",) + FUNCTION = "add" + CATEGORY = "WanVideoWrapper" + + def add(self, anchor_samples, num_frames, prev_samples=None, motion_latent_count=1): + + anchor_latent = anchor_samples["samples"][0].clone() + + C, T, H, W = anchor_latent.shape + + total_latents = (num_frames - 1) // 4 + 1 + device = anchor_latent.device + dtype = anchor_latent.dtype + + if prev_samples is None or motion_latent_count == 0: + padding_size = total_latents - anchor_latent.shape[1] + padding = torch.zeros(C, padding_size, H, W, dtype=dtype, device=device) + y = torch.concat([anchor_latent, padding], dim=1) + else: + prev_latent = prev_samples["samples"][0].clone() + motion_latent = prev_latent[:, -motion_latent_count:] + padding_size = total_latents - anchor_latent.shape[1] - motion_latent.shape[1] + padding = torch.zeros(C, padding_size, H, W, dtype=dtype, device=device) + y = torch.concat([anchor_latent, motion_latent, padding], dim=1) + + msk = torch.ones(1, num_frames, H, W, device=device, dtype=dtype) + msk[:, 1:] = 0 + msk = torch.concat([torch.repeat_interleave(msk[:, 0:1], repeats=4, dim=1), msk[:, 1:]], dim=1) + msk = msk.view(1, msk.shape[1] // 4, 4, H, W) + msk = msk.transpose(1, 2)[0] + + image_embeds = { + "image_embeds": y, + + #"max_seq_len": max_seq_len, + "num_frames": num_frames, + "lat_h": H, + "lat_w": W, + "mask": msk + } + + return (image_embeds,) + #region I2V encode class WanVideoImageToVideoEncode: @classmethod @@ -2250,6 +2308,7 @@ NODE_CLASS_MAPPINGS = { "WanVideoUniLumosEmbeds": WanVideoUniLumosEmbeds, "WanVideoAddTTMLatents": WanVideoAddTTMLatents, "WanVideoAddStoryMemLatents": WanVideoAddStoryMemLatents, + "WanVideoSVIProEmbeds": WanVideoSVIProEmbeds, } NODE_DISPLAY_NAME_MAPPINGS = { @@ -2291,4 +2350,5 @@ NODE_DISPLAY_NAME_MAPPINGS = { "WanVideoUniLumosEmbeds": "WanVideo UniLumos Embeds", "WanVideoAddTTMLatents": "WanVideo Add TTMLatents", "WanVideoAddStoryMemLatents": "WanVideo Add StoryMem Latents", + "WanVideoSVIProEmbeds": "WanVideo SVIPro Embeds", } From 6fd4c6640c4dcdc963fffb53fbe74eafa0e64dcb Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Sun, 28 Dec 2025 01:27:18 +0200 Subject: [PATCH 17/22] Adjust scheduler graph drawing --- nodes_sampler.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/nodes_sampler.py b/nodes_sampler.py index 57b73e8..d054b90 100644 --- a/nodes_sampler.py +++ b/nodes_sampler.py @@ -2777,8 +2777,13 @@ class WanVideoScheduler: handles, labels = ax.get_legend_handles_labels() if labels: ax.legend() - if start_idx < end_idx and 0 <= start_idx < len(sigmas_np) and 0 < end_idx < len(sigmas_np): - ax.axvspan(start_idx, end_idx, color='lightblue', alpha=0.1, label='Sampled Range') + # Draw shaded range + range_start_idx = start_idx if start_idx > 0 else 0 + range_end_idx = end_idx if end_idx > 0 and end_idx < len(sigmas_np) else len(sigmas_np) - 1 + if range_start_idx < range_end_idx: + ax.axvspan(range_start_idx, range_end_idx, color='lightblue', alpha=0.1, label='Sampled Range') + + plt.tight_layout() plt.savefig(buf, format='png') plt.close(fig) From 1eab022bb0997934041c9b2112e0cb6d379101f4 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Sun, 28 Dec 2025 02:35:42 +0200 Subject: [PATCH 18/22] Update nodes.py --- nodes.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nodes.py b/nodes.py index f7ef927..23ff341 100644 --- a/nodes.py +++ b/nodes.py @@ -919,7 +919,7 @@ class WanVideoSVIProEmbeds: }, "optional": { "prev_samples": ("LATENT", {"tooltip": "Last latent from previous generation"}), - "motion_latent_count": ("INT", {"default": 2, "min": 1, "max": 100, "step": 1, "tooltip": "Number of latents used to continue"}), + "motion_latent_count": ("INT", {"default": 1, "min": 0, "max": 100, "step": 1, "tooltip": "Number of latents used to continue"}), } } @@ -957,8 +957,6 @@ class WanVideoSVIProEmbeds: image_embeds = { "image_embeds": y, - - #"max_seq_len": max_seq_len, "num_frames": num_frames, "lat_h": H, "lat_w": W, From 3730ccf603cadf090f4fc8af8ae657b6c2f93d80 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Sun, 28 Dec 2025 10:34:13 +0200 Subject: [PATCH 19/22] Fix s2v --- nodes_model_loading.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nodes_model_loading.py b/nodes_model_loading.py index 1f9a1d8..83abf6f 100644 --- a/nodes_model_loading.py +++ b/nodes_model_loading.py @@ -1235,9 +1235,7 @@ class WanVideoModelLoader: lynx_ip_layers = "lite" model_type = "t2v" - if "audio_injector.injector.0.k.weight" in sd: - model_type = "s2v" - elif not "text_embedding.0.weight" in sd: + if not "text_embedding.0.weight" in sd: model_type = "no_cross_attn" #minimaxremover elif "model_type.Wan2_1-FLF2V-14B-720P" in sd or "img_emb.emb_pos" in sd or "flf2v" in model.lower(): model_type = "fl2v" @@ -1247,6 +1245,8 @@ class WanVideoModelLoader: model_type = "t2v" elif "control_adapter.conv.weight" in sd: model_type = "t2v" + if "audio_injector.injector.0.k.weight" in sd: + model_type = "s2v" out_dim = 16 if dim == 5120: #14B From 486564060ff740754978fdbc43f4665bd4632266 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Mon, 29 Dec 2025 01:35:32 +0200 Subject: [PATCH 20/22] Add node to set attention mode per step and/or blocks --- nodes_model_loading.py | 54 +++++++++++++++++++++++++++++++-------- nodes_sampler.py | 1 + wanvideo/modules/model.py | 45 +++++++++++++++++++++----------- 3 files changed, 74 insertions(+), 26 deletions(-) diff --git a/nodes_model_loading.py b/nodes_model_loading.py index 83abf6f..01977f4 100644 --- a/nodes_model_loading.py +++ b/nodes_model_loading.py @@ -36,6 +36,9 @@ try: except: PromptServer = None +attention_modes = ["sdpa", "flash_attn_2", "flash_attn_3", "sageattn", "sageattn_3", "radial_sage_attention", "sageattn_compiled", + "sageattn_ultravico", "comfy"] + #from city96's gguf nodes def update_folder_names_and_paths(key, targets=[]): # check for existing key @@ -1006,6 +1009,43 @@ def add_lora_weights(patcher, lora, base_dtype, merge_loras=False): del lora_sd return patcher, control_lora, unianimate_sd +class WanVideoSetAttentionModeOverride: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("WANVIDEOMODEL", ), + "attention_mode": (attention_modes, {"default": "sdpa"}), + "start_step": ("INT", {"default": 1, "min": 1, "max": 10000, "step": 1, "tooltip": "Step to start applying the attention mode override"}), + "end_step": ("INT", {"default": 10000, "min": 1, "max": 10000, "step": 1, "tooltip": "Step to end applying the attention mode override"}), + "verbose": ("BOOLEAN", {"default": False, "tooltip": "Print verbose info about attention mode override during generation"}), + }, + "optional": { + "blocks":("INT", {"forceInput": True} ), + } + } + + RETURN_TYPES = ("WANVIDEOMODEL",) + RETURN_NAMES = ("model", ) + FUNCTION = "getmodelpath" + CATEGORY = "WanVideoWrapper" + DESCRIPTION = "Override the attention mode for the model for specific step and/or block range" + + def getmodelpath(self, model, attention_mode, start_step, end_step, verbose, blocks=None): + model_clone = model.clone() + attention_mode_override = { + "mode": attention_mode, + "start_step": start_step, + "end_step": end_step, + "verbose": verbose, + } + if blocks is not None: + attention_mode_override["blocks"] = blocks + model_clone.model_options['transformer_options']["attention_mode_override"] = attention_mode_override + + return (model_clone,) + + #region Model loading class WanVideoModelLoader: @classmethod @@ -1020,17 +1060,7 @@ class WanVideoModelLoader: "load_device": (["main_device", "offload_device"], {"default": "offload_device", "tooltip": "Initial device to load the model to, NOT recommended with the larger models unless you have 48GB+ VRAM"}), }, "optional": { - "attention_mode": ([ - "sdpa", - "flash_attn_2", - "flash_attn_3", - "sageattn", - "sageattn_3", - "radial_sage_attention", - "sageattn_compiled", - "sageattn_ultravico", - "comfy" - ], {"default": "sdpa"}), + "attention_mode": (attention_modes, {"default": "sdpa"}), "compile_args": ("WANCOMPILEARGS", ), "block_swap_args": ("BLOCKSWAPARGS", ), "lora": ("WANVIDLORA", {"default": None}), @@ -2043,6 +2073,7 @@ NODE_CLASS_MAPPINGS = { "WanVideoTorchCompileSettings": WanVideoTorchCompileSettings, "LoadWanVideoT5TextEncoder": LoadWanVideoT5TextEncoder, "LoadWanVideoClipTextEncoder": LoadWanVideoClipTextEncoder, + "WanVideoSetAttentionModeOverride": WanVideoSetAttentionModeOverride, } NODE_DISPLAY_NAME_MAPPINGS = { @@ -2061,4 +2092,5 @@ NODE_DISPLAY_NAME_MAPPINGS = { "WanVideoTorchCompileSettings": "WanVideo Torch Compile Settings", "LoadWanVideoT5TextEncoder": "WanVideo T5 Text Encoder Loader", "LoadWanVideoClipTextEncoder": "WanVideo CLIP Text Encoder Loader", + "WanVideoSetAttentionModeOverride": "WanVideo Set Attention Mode Override", } diff --git a/nodes_sampler.py b/nodes_sampler.py index d054b90..6072608 100644 --- a/nodes_sampler.py +++ b/nodes_sampler.py @@ -1414,6 +1414,7 @@ class WanVideoSampler: 'is_uncond': False, # is unconditional 'current_step': idx, # current step 'current_step_percentage': current_step_percentage, # current step percentage + 'attention_mode_override': transformer_options.get("attention_mode_override", None), 'last_step': len(timesteps) - 1 == idx, # is last step 'control_lora_enabled': control_lora_enabled, # control lora toggle for patch embed selection 'enhance_enabled': enhance_enabled, # enhance-a-video toggle diff --git a/wanvideo/modules/model.py b/wanvideo/modules/model.py index 96df41c..6a31cb9 100644 --- a/wanvideo/modules/model.py +++ b/wanvideo/modules/model.py @@ -497,7 +497,7 @@ class WanSelfAttention(nn.Module): attention_mode = self.attention_mode if attention_mode_override is not None: attention_mode = attention_mode_override - + # Concatenate main and IP keys/values for main attention full_k = torch.cat([k, k_ip], dim=1) full_v = torch.cat([v, v_ip], dim=1) @@ -1006,6 +1006,7 @@ class WanAttentionBlock(nn.Module): longcat_num_cond_latents=0, longcat_avatar_options=None, #longcat image cond amount x_onetoall_ref=None, onetoall_freqs=None, onetoall_ref=None, onetoall_ref_scale=1.0, #one-to-all e_tr=None, tr_num=0, tr_start=0, #token replacement + attention_mode_override=None, ): r""" Args: @@ -1150,6 +1151,10 @@ class WanAttentionBlock(nn.Module): if enhance_enabled: feta_scores = get_feta_scores(q, k) + if self.attention_mode == "sageattn_3" and attention_mode_override is None: + if current_step != 0 and not last_step: + attention_mode_override = "sageattn" + #self-attention split_attn = (context is not None and (context.shape[0] > 1 or (clip_embed is not None and clip_embed.shape[0] > 1)) @@ -1161,19 +1166,14 @@ class WanAttentionBlock(nn.Module): y = self.self_attn.forward_split(q, k, v, seq_lens, grid_sizes, seq_chunks) elif ref_target_masks is not None: #multi/infinite talk y, x_ref_attn_map = self.self_attn.forward_multitalk(q, k, v, seq_lens, grid_sizes, ref_target_masks) - elif self.attention_mode == "radial_sage_attention": + elif self.attention_mode == "radial_sage_attention" or attention_mode_override is not None and attention_mode_override == "radial_sage_attention": if self.dense_block or self.dense_timesteps is not None and current_step < self.dense_timesteps: if self.dense_attention_mode == "sparse_sage_attn": y = self.self_attn.forward_radial(q, k, v, dense_step=True) else: - y = self.self_attn.forward(q, k, v, seq_lens) + y = self.self_attn.forward(q, k, v, seq_lens, attention_mode_override=attention_mode_override) else: y = self.self_attn.forward_radial(q, k, v, dense_step=False) - elif self.attention_mode == "sageattn_3": - if current_step != 0 and not last_step: - y = self.self_attn.forward(q, k, v, seq_lens, attention_mode_override="sageattn_3") - else: - y = self.self_attn.forward(q, k, v, seq_lens, attention_mode_override="sageattn") elif x_ip is not None and self.kv_cache is None: #stand-in # First pass: cache IP keys/values and compute attention self.kv_cache = {"k_ip": k_ip.detach(), "v_ip": v_ip.detach()} @@ -1184,18 +1184,18 @@ class WanAttentionBlock(nn.Module): v_ip = self.kv_cache["v_ip"] full_k = torch.cat([k, k_ip], dim=1) full_v = torch.cat([v, v_ip], dim=1) - y = self.self_attn.forward(q, full_k, full_v, seq_lens) + y = self.self_attn.forward(q, full_k, full_v, seq_lens, attention_mode_override=attention_mode_override) elif is_longcat and longcat_num_cond_latents > 0: if longcat_num_cond_latents == 1: num_cond_latents_thw = longcat_num_cond_latents * (N // num_latent_frames) # process the noise tokens - x_noise = self.self_attn.forward(q[:, num_cond_latents_thw:].contiguous(), k, v, seq_lens) + x_noise = self.self_attn.forward(q[:, num_cond_latents_thw:].contiguous(), k, v, seq_lens, attention_mode_override=attention_mode_override) # process the condition tokens x_cond = self.self_attn.forward( q[:, :num_cond_latents_thw].contiguous(), k[:, :num_cond_latents_thw].contiguous(), v[:, :num_cond_latents_thw].contiguous(), - seq_lens) + seq_lens, attention_mode_override=attention_mode_override) # merge x_cond and x_noise y = torch.cat([x_cond, x_noise], dim=1).contiguous() elif longcat_num_cond_latents > 1: # video continuation @@ -1237,13 +1237,14 @@ class WanAttentionBlock(nn.Module): q_cond = q[:, num_ref_latents_thw:num_cond_latents_thw].contiguous() k_cond = k[:, num_ref_latents_thw:num_cond_latents_thw].contiguous() v_cond = v[:, num_ref_latents_thw:num_cond_latents_thw].contiguous() - x_ref = self.self_attn.forward(q_ref, k_ref, v_ref, seq_lens) - x_cond = self.self_attn.forward(q_cond, k_cond, v_cond, seq_lens) + x_ref = self.self_attn.forward(q_ref, k_ref, v_ref, seq_lens, attention_mode_override=attention_mode_override) + x_cond = self.self_attn.forward(q_cond, k_cond, v_cond, seq_lens, attention_mode_override=attention_mode_override) # merge x_cond and x_noise y = torch.cat([x_ref, x_cond, x_noise], dim=1).contiguous() else: - y = self.self_attn.forward(q, k, v, seq_lens, lynx_ref_feature=lynx_ref_feature, lynx_ref_scale=lynx_ref_scale, onetoall_ref=onetoall_ref, onetoall_ref_scale=onetoall_ref_scale) + y = self.self_attn.forward(q, k, v, seq_lens, lynx_ref_feature=lynx_ref_feature, lynx_ref_scale=lynx_ref_scale, + onetoall_ref=onetoall_ref, onetoall_ref_scale=onetoall_ref_scale, attention_mode_override=attention_mode_override) del q, k, v @@ -2280,6 +2281,7 @@ class WanModel(torch.nn.Module): self, x, t, context, seq_len, is_uncond=False, current_step_percentage=0.0, current_step=0, last_step=0, total_steps=50, + attention_mode_override=None, clip_fea=None, y=None, device=torch.device('cuda'), freqs=None, @@ -3125,8 +3127,21 @@ class WanModel(torch.nn.Module): if lynx_ref_buffer is None and lynx_ref_feature_extractor: lynx_ref_buffer = {} + attn_override_blocks = attention_mode = None + attention_mode_override_active = False + if attention_mode_override is not None: + attn_override_blocks = attention_mode_override.get("blocks", range(len(self.blocks))) + if attention_mode_override["start_step"] <= current_step < attention_mode_override["end_step"]: + attention_mode_override_active = True + if attention_mode_override["verbose"]: + tqdm.write(f"Applying attention mode override: {attention_mode_override['mode']} at step {current_step} on blocks: {attn_override_blocks if attn_override_blocks is not None else 'all'}") + for b, block in enumerate(self.blocks): mm.throw_exception_if_processing_interrupted() + if attention_mode_override_active and b in attn_override_blocks: + attention_mode = attention_mode_override['mode'] + else: + attention_mode = None block_idx = f"{b:02d}" if lynx_ref_buffer is not None and not lynx_ref_feature_extractor: lynx_ref_feature = lynx_ref_buffer.get(block_idx, None) @@ -3170,7 +3185,7 @@ class WanModel(torch.nn.Module): x_onetoall_ref = onetoall_ref_block_samples[b // interval_ref] # ---run block----# - x, x_ip, lynx_ref_feature, x_ovi = block(x, x_ip=x_ip, lynx_ref_feature=lynx_ref_feature, x_ovi=x_ovi, x_onetoall_ref=x_onetoall_ref, onetoall_freqs=onetoall_freqs, **kwargs) + x, x_ip, lynx_ref_feature, x_ovi = block(x, x_ip=x_ip, lynx_ref_feature=lynx_ref_feature, x_ovi=x_ovi, x_onetoall_ref=x_onetoall_ref, onetoall_freqs=onetoall_freqs, attention_mode_override=attention_mode, **kwargs) # ---post block----# if self.audio_injector is not None and s2v_audio_input is not None: From 2fe483417849fe14ce422c3d616358c8031b5a89 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Mon, 29 Dec 2025 02:48:59 +0200 Subject: [PATCH 21/22] Adjust ultravico frame_tokens --- nodes_model_loading.py | 2 +- ultravico/sageattn/attn_qk_int8_per_block.py | 4 ++-- wanvideo/modules/attention.py | 8 ++++---- wanvideo/modules/model.py | 10 ++++++---- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/nodes_model_loading.py b/nodes_model_loading.py index 01977f4..9b32b99 100644 --- a/nodes_model_loading.py +++ b/nodes_model_loading.py @@ -1016,7 +1016,7 @@ class WanVideoSetAttentionModeOverride: "required": { "model": ("WANVIDEOMODEL", ), "attention_mode": (attention_modes, {"default": "sdpa"}), - "start_step": ("INT", {"default": 1, "min": 1, "max": 10000, "step": 1, "tooltip": "Step to start applying the attention mode override"}), + "start_step": ("INT", {"default": 0, "min": 0, "max": 10000, "step": 1, "tooltip": "Step to start applying the attention mode override"}), "end_step": ("INT", {"default": 10000, "min": 1, "max": 10000, "step": 1, "tooltip": "Step to end applying the attention mode override"}), "verbose": ("BOOLEAN", {"default": False, "tooltip": "Print verbose info about attention mode override during generation"}), }, diff --git a/ultravico/sageattn/attn_qk_int8_per_block.py b/ultravico/sageattn/attn_qk_int8_per_block.py index 3d85856..645d5a4 100644 --- a/ultravico/sageattn/attn_qk_int8_per_block.py +++ b/ultravico/sageattn/attn_qk_int8_per_block.py @@ -38,7 +38,7 @@ def _attn_fwd_inner(acc, l_i, m_i, q, q_scale, kv_len, current_flag, qk = tl.dot(q, k).to(tl.float32) * q_scale * k_scale - window_th = 1560 * 21 / 2 + window_th = frame_tokens * window_width / 2 dist2 = tl.abs(m - n).to(tl.int32) dist_mask = dist2 <= window_th @@ -46,7 +46,7 @@ def _attn_fwd_inner(acc, l_i, m_i, q, q_scale, kv_len, current_flag, qk = tl.where(dist_mask | negative_mask, qk, qk*multi_factor) - window3 = (m <= frame_tokens) & (n > 21*frame_tokens) + window3 = (m <= frame_tokens) & (n > window_width*frame_tokens) qk = tl.where(window3, -1e4, qk) diff --git a/wanvideo/modules/attention.py b/wanvideo/modules/attention.py index 09caac8..3b891d3 100644 --- a/wanvideo/modules/attention.py +++ b/wanvideo/modules/attention.py @@ -80,9 +80,9 @@ except: try: from ...ultravico.sageattn.core import sage_attention as sageattn_ultravico @torch.library.custom_op("wanvideo::sageattn_ultravico", mutates_args=()) - def sageattn_func_ultravico(qkv: List[torch.Tensor], attn_mask: torch.Tensor | None = None, dropout_p: float = 0.0, is_causal: bool = False, multi_factor: float = 0.9 + def sageattn_func_ultravico(qkv: List[torch.Tensor], attn_mask: torch.Tensor | None = None, dropout_p: float = 0.0, is_causal: bool = False, multi_factor: float = 0.9, frame_tokens: int = 1536 ) -> torch.Tensor: - return sageattn_ultravico(qkv, attn_mask=attn_mask, dropout_p=dropout_p, is_causal=is_causal, multi_factor=multi_factor) + return sageattn_ultravico(qkv, attn_mask=attn_mask, dropout_p=dropout_p, is_causal=is_causal, multi_factor=multi_factor, frame_tokens=frame_tokens) @sageattn_func_ultravico.register_fake def _(qkv, attn_mask=None, dropout_p=0.0, is_causal=False, multi_factor=0.9): @@ -94,7 +94,7 @@ except: def attention(q, k, v, q_lens=None, k_lens=None, max_seqlen_q=None, max_seqlen_k=None, dropout_p=0., softmax_scale=None, q_scale=None, causal=False, window_size=(-1, -1), deterministic=False, dtype=torch.bfloat16, - attention_mode='sdpa', attn_mask=None, multi_factor=0.9, heads=128): + attention_mode='sdpa', attn_mask=None, multi_factor=0.9, frame_tokens=1536, heads=128): if "flash" in attention_mode: return flash_attention(q, k, v, q_lens=q_lens, k_lens=k_lens, dropout_p=dropout_p, softmax_scale=softmax_scale, q_scale=q_scale, causal=causal, window_size=window_size, deterministic=deterministic, dtype=dtype, version=2 if attention_mode == 'flash_attn_2' else 3, @@ -108,7 +108,7 @@ def attention(q, k, v, q_lens=None, k_lens=None, max_seqlen_q=None, max_seqlen_k elif attention_mode == 'sageattn': return sageattn_func(q, k, v, tensor_layout="NHD").contiguous() elif attention_mode == 'sageattn_ultravico': - return sageattn_func_ultravico([q, k, v], multi_factor=multi_factor).contiguous() + return sageattn_func_ultravico([q, k, v], multi_factor=multi_factor, frame_tokens=frame_tokens).contiguous() elif attention_mode == 'comfy': return optimized_attention(q.transpose(1,2), k.transpose(1,2), v.transpose(1,2), heads=heads, skip_reshape=True) else: # sdpa diff --git a/wanvideo/modules/model.py b/wanvideo/modules/model.py index 6a31cb9..7db9377 100644 --- a/wanvideo/modules/model.py +++ b/wanvideo/modules/model.py @@ -467,7 +467,7 @@ class WanSelfAttention(nn.Module): v = (self.v(x) + self.v_loras(x)).view(b, s, n, d) return q, k, v - def forward(self, q, k, v, seq_lens, lynx_ref_feature=None, lynx_ref_scale=1.0, attention_mode_override=None, onetoall_ref=None, onetoall_ref_scale=1.0): + def forward(self, q, k, v, seq_lens, lynx_ref_feature=None, lynx_ref_scale=1.0, attention_mode_override=None, onetoall_ref=None, onetoall_ref_scale=1.0, frame_tokens=1536): r""" Args: x(Tensor): Shape [B, L, num_heads, C / num_heads] @@ -477,12 +477,13 @@ class WanSelfAttention(nn.Module): """ attention_mode = self.attention_mode if attention_mode_override is not None: + print("Overriding attention mode to:", attention_mode_override) attention_mode = attention_mode_override if self.ref_adapter is not None and lynx_ref_feature is not None: ref_x = self.ref_adapter(self, q, lynx_ref_feature) - x = attention(q, k, v, k_lens=seq_lens, attention_mode=attention_mode, heads=self.num_heads) + x = attention(q, k, v, k_lens=seq_lens, attention_mode=attention_mode, heads=self.num_heads, frame_tokens=frame_tokens) if self.ref_adapter is not None and lynx_ref_feature is not None: x = x.add(ref_x, alpha=lynx_ref_scale) @@ -1006,7 +1007,7 @@ class WanAttentionBlock(nn.Module): longcat_num_cond_latents=0, longcat_avatar_options=None, #longcat image cond amount x_onetoall_ref=None, onetoall_freqs=None, onetoall_ref=None, onetoall_ref_scale=1.0, #one-to-all e_tr=None, tr_num=0, tr_start=0, #token replacement - attention_mode_override=None, + attention_mode_override=None, frame_tokens=None, ): r""" Args: @@ -1244,7 +1245,7 @@ class WanAttentionBlock(nn.Module): y = torch.cat([x_ref, x_cond, x_noise], dim=1).contiguous() else: y = self.self_attn.forward(q, k, v, seq_lens, lynx_ref_feature=lynx_ref_feature, lynx_ref_scale=lynx_ref_scale, - onetoall_ref=onetoall_ref, onetoall_ref_scale=onetoall_ref_scale, attention_mode_override=attention_mode_override) + onetoall_ref=onetoall_ref, onetoall_ref_scale=onetoall_ref_scale, attention_mode_override=attention_mode_override, frame_tokens=frame_tokens) del q, k, v @@ -3041,6 +3042,7 @@ class WanModel(torch.nn.Module): camera_embed=camera_embed, audio_proj=audio_proj, num_latent_frames = F, + frame_tokens=x.shape[1] // F, original_seq_len=self.original_seq_len, enhance_enabled=enhance_enabled, audio_scale=audio_scale, From 19bcee67ed7408271aadef7921b01b81705e076b Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Mon, 29 Dec 2025 02:50:04 +0200 Subject: [PATCH 22/22] remove print --- wanvideo/modules/model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/wanvideo/modules/model.py b/wanvideo/modules/model.py index 7db9377..4a85818 100644 --- a/wanvideo/modules/model.py +++ b/wanvideo/modules/model.py @@ -477,7 +477,6 @@ class WanSelfAttention(nn.Module): """ attention_mode = self.attention_mode if attention_mode_override is not None: - print("Overriding attention mode to:", attention_mode_override) attention_mode = attention_mode_override if self.ref_adapter is not None and lynx_ref_feature is not None: