Improved AnimateDiff integration for ComfyUI, as well as advanced sampling options dubbed Evolved Sampling usable outside of AnimateDiff. Please read the AnimateDiff repo README and Wiki for more information about how it works at its core.
AnimateDiff workflows will often make use of these helpful node packs:
AnimateDiff Evolved
, and be sure the author is Kosinkadink
. Install it.
custom_nodes
folder.mm_sd_v14
, mm_sd_v15
, mm_sd_v15_v2
, v3_sd15_mm
: HuggingFace | Google Drive | CivitAImm-Stabilized_mid
and mm-Stabilized_high
, by manshoety: HuggingFacemm-p_0.5.pth
and mm-p_0.75.pth
, by manshoety: HuggingFacetemporaldiff-v1-animatediff
by CiaraRowles: HuggingFaceComfyUI/custom_nodes/ComfyUI-AnimateDiff-Evolved/models
ComfyUI/models/animatediff_models
ComfyUI/custom_nodes/ComfyUI-AnimateDiff-Evolved/motion_lora
ComfyUI/models/animatediff_motion_lora
NOTE: you can also use custom locations for models/motion loras by making use of the ComfyUI extra_model_paths.yaml
file. The id for motion model folder is animatediff_models
and the id for motion lora folder is animatediff_motion_lora
.
mm_sd_v15_v2
, mm-p_0.5.pth
, and mm-p_0.75.pth
.
hsxl_temporal_layers.safetensors
.
autoselect
or linear (HotshotXL/default)
beta_schedule, the sweetspot for context_length or total frames (when not using context) is 8 frames, and you will need to use an SDXL checkpoint.autoselect
or linear (AnimateDiff-SDXL)
beta_schedule. Other than that, same rules of thumb apply to AnimateDiff-SDXL as AnimateDiff.autoselect
or lcm
or lcm[100_ots]
beta_schedule. To use fully with LCM, be sure to use appropriate LCM lora, use the lcm
sampler_name in KSampler nodes, and lower cfg to somewhere around 1.0 to 2.0. Don't forget to decrease steps (minimum = ~4 steps), since LCM converges faster (less steps). Increase step count to increase detail as desired.Apply AnimateLCM-I2V Model
Gen2 node usage so that ref_latent
can be provided; use Scale Ref Image and VAE Encode
node to preprocess input images. While this was intended as an img2video model, I found it works best for vid2vid purposes with ref_drift=0.0
, and to use it for only at least 1 step before switching over to other models via chaining with toher Apply AnimateDiff Model (Adv.) nodes. The apply_ref_when_disabled
can be set to True to allow the img_encoder to do its thing even when the end_percent
is reached. AnimateLCM-I2V is also extremely useful for maintaining coherence at higher resolutions (with ControlNet and SD LoRAs active, I could easily upscale from 512x512 source to 1024x1024 in a single pass). TODO: add examplesautoselect
or sqrt_linear (AnimateDiff)
beta_schedule. Requires Apply AnimateDiff-PIA Model
Gen2 node usage if you want to actually provide input images. The pia_input
can be provided via the paper's presets (PIA Input [Paper Presets]
) or by manually entering values (PIA Input [Multival]
).There are two families of nodes that can be used to use AnimateDiff/Evolved Sampling - Gen1 and Gen2. Other than nodes marked specifically for Gen1/Gen2, all other nodes can be used for both Gen1 and Gen2.
Gen1 and Gen2 produce the exact same results (the backend code is identical), the only difference is in how the modes are used. Overall, Gen1 is the simplest way to use basic AnimateDiff features, while Gen2 separates model loading and application from the Evolved Sampling features. This means in practice, Gen2's Use Evolved Sampling node can be used without a model model, letting Context Options and Sample Settings be used without AnimateDiff.
In the following documentation, inputs/outputs will be color coded as follows:
① Gen1 ① | ② Gen2 ② |
---|---|
- All-in-One node - If same model is loaded by multiple Gen1 nodes, duplicates RAM usage. |
- Separates model loading from application and Evolved Sampling - Enables no motion model usage while preserving Evolved Sampling features - Enables multiple motion model usage with Apply AnimateDiff Model (Adv.) Node |
autoselect
will automatically select the recommended beta_schedule for selected motion models - or will use_existing if no motion model selected for Gen2.scale_multival
and effect_multival
inputs across sampling timesteps.Multival
input (defaults to 1.0
). Previously called motion_scale, it directly influences the amount of motion generated by the model. With the Multival nodes, it can accept a float, list of floats, and/or mask inputs, allowing different scale to be applied to not only different frames, but different areas of frames (including per-frame).Multival
input (defaults to 1.0
). Determines the influence of the motion models on the sampling process. Value of 0.0
is equivalent to normal SD output with no AnimateDiff influence. With the Multival nodes, it can accept a float, list of floats, and/or mask inputs, allowing different effect amount to be applied to not only different frames, but different areas of frames (including per-frame).scale_multival
, can only be a float.True
now.For Multival inputs, these nodes allow the use of floats, list of floats, and/or masks to use as input. Scaled Mask node allows customization of dark/light areas of masks in terms of what the values correspond to.
Node | Inputs |
---|---|
🟨mask_optional: Mask for float values - black means 0.0, white means 1.0 (multiplied by float_val). 🟦float_val: Float multiplier. |
|
🟩mask: Mask for float values. 🟦min_float_val: Minimum value. 🟦max_float_val: Maximum value. 🟦scaling: When absolute , black means min_float_val, white means max_float_val. When relative , darkest area in masks (total) means min_float_val, lighest area in massk (total) means max_float_val. |
Allows scheduling (in terms of timesteps) for scale_multival and effect_multival.
The two settings to determine schedule are start_percent and guarantee_steps. When multiple keyframes have the same start_percent, they will be executed in the order they are connected, and run for guarantee_steps before moving on to the next node.
Node |
---|
True
, any missing scale_multival or effect_multival inputs will inherit the previous keyframe's values - if the previous keyframe also inherits missing, the last inherited value will be used.These nodes provide techniques used to extend the lengths of animations to get around the sweetspot limitations of AnimateDiff models (typically 16 frames) and HotshotXL model (8 frames).
Context Options works by diffusing portions of the animation at a time, including main SD diffusion, ControlNets, IPAdapters, etc., effectively limiting VRAM usage to be equivalent to be context_length latents.
View Options, in contrast, work by portioning the latents seen by the motion model. This does NOT decrease VRAM usage, but in general is more stable and faster than Context Options, since the latents don't have to go through the whole SD unet.
Context Options and View Options can be combined to get the best of both worlds - longer context_length can be used to gain more stable output, at the cost of using more VRAM (since context_length determines how much SD sampling is done at the same time on the GPU). Provided you have the VRAM, you could also use Views Only Context Options to use only View Options (and automatically make context_length equivalent to full latents) to get a speed boost in return for the higher VRAM usage.
There are two types of Context/View Options: Standard and Looped. Standard options do not cause looping in the output. Looped options, as the name implies, causes looping in the output (from end to beginning). Prior to the code rework, the only context available was the looping kind.
I recommend using Standard Static at first when not wanting looped outputs.
In the below animations, green shows the Contexts, and red shows the Views. TL;DR green is the amount of latents that are loaded into VRAM (and sampled), while red is the amount of latents that get passed into the motion model at a time.
Behavior |
---|
(latent count: 64, context_length: 16, context_overlap: 4, total steps: 20) |
Node | Inputs |
---|---|
🟦context_length: Amount of latents to diffuse at once. 🟦context_overlap: Minimum common latents between adjacent windows. 🟦fuse_method: Method for averaging results of windows. 🟦use_on_equal_length: When True, allows context to be used when latent count matches context_length. 🟦start_percent: When multiple Context Options are chained, allows scheduling. 🟦guarantee_steps: When scheduling contexts, determines the minimum amount of sampling steps context should be used. 🟦context_length: Amount of latents to diffuse at once. 🟨prev_context: Allows chaining of contexts. 🟨view_options: When context_length > view_length (unless otherwise specified), allows view_options to be used within each context window. |
Behavior |
---|
(latent count: 64, context_length: 16, context_overlap: 4, context_stride: 1, total steps: 20) |
(latent count: 64, context_length: 16, context_overlap: 4, context_stride: 2, total steps: 20) |
Node | Inputs |
---|---|
🟦context_length: Amount of latents to diffuse at once. 🟦context_overlap: Minimum common latents between adjacent windows. 🟦context_stride: Maximum 2^(stride-1) distance between adjacent latents. 🟦fuse_method: Method for averaging results of windows. 🟦use_on_equal_length: When True, allows context to be used when latent count matches context_length. 🟦start_percent: When multiple Context Options are chained, allows scheduling. 🟦guarantee_steps: When scheduling contexts, determines the minimum amount of sampling steps context should be used. 🟦context_length: Amount of latents to diffuse at once. 🟨prev_context: Allows chaining of contexts. 🟨view_options: When context_length > view_length (unless otherwise specified), allows view_options to be used within each context window. |
Behavior |
---|
(latent count: 64, context_length: 16, context_overlap: 4, context_stride: 1, closed_loop: False, total steps: 20) |
(latent count: 64, context_length: 16, context_overlap: 4, context_stride: 1, closed_loop: True, total steps: 20) |
Node | Inputs |
---|---|
🟦context_length: Amount of latents to diffuse at once. 🟦context_overlap: Minimum common latents between adjacent windows. 🟦context_stride: Maximum 2^(stride-1) distance between adjacent latents. 🟦closed_loop: When True, adds additional windows to enhance looping. 🟦fuse_method: Method for averaging results of windows. 🟦use_on_equal_length: When True, allows context to be used when latent count matches context_length - allows loops to be made when latent count == context_length. 🟦start_percent: When multiple Context Options are chained, allows scheduling. 🟦guarantee_steps: When scheduling contexts, determines the minimum amount of sampling steps context should be used. 🟦context_length: Amount of latents to diffuse at once. 🟨prev_context: Allows chaining of contexts. 🟨view_options: When context_length > view_length (unless otherwise specified), allows view_options to be used within each context window. |
Behavior |
---|
(latent count: 64, view_length: 16, view_overlap: 4, View Options◆Standard Static, total steps: 20) |
Node | Inputs |
---|---|
🟩view_opts_req: View_options to be used across all latents. 🟨prev_context: Allows chaining of contexts. |
There are View Options equivalent of these schedules:
Behavior |
---|
(latent count: 64, view_length: 16, view_overlap: 4, Context Options◆Standard Static, context_length: 32, context_overlap: 8, total steps: 20) |
Node | Inputs |
---|---|
🟦view_length: Amount of latents in context to pass into motion model at a time. 🟦view_overlap: Minimum common latents between adjacent windows. 🟦fuse_method: Method for averaging results of windows. |
Behavior |
---|
(latent count: 64, view_length: 16, view_overlap: 4, view_stride: 1, Context Options◆Standard Static, context_length: 32, context_overlap: 8, total steps: 20) |
Node | Inputs |
---|---|
🟦view_length: Amount of latents in context to pass into motion model at a time. 🟦view_overlap: Minimum common latents between adjacent windows. 🟦view_stride: Maximum 2^(stride-1) distance between adjacent latents. 🟦fuse_method: Method for averaging results of windows. |
Behavior |
---|
(latent count: 64, view_length: 16, view_overlap: 4, view_stride: 1, closed_loop: False, Context Options◆Standard Static, context_length: 32, context_overlap: 8, total steps: 20) |
NOTE: this one is probably not going to come out looking well unless you are using this for a very specific reason. |
Node | Inputs |
---|---|
🟦view_length: Amount of latents in context to pass into motion model at a time. 🟦view_overlap: Minimum common latents between adjacent windows. 🟦view_stride: Maximum 2^(stride-1) distance between adjacent latents. 🟦closed_loop: When True, adds additional windows to enhance looping. 🟦use_on_equal_length: When True, allows context to be used when latent count matches context_length - allows loops to be made when latent count == context_length. 🟦fuse_method: Method for averaging results of windows. |
The Sample Settings node allows customization of the sampling process beyond what is exposed on most KSampler nodes. With its default values, it will NOT have any effect, and can safely be attached without changing any behavior.
TL;DR To use FreeNoise, select FreeNoise
from the noise_type dropdown. FreeNoise does not decrease performance in any way. To use FreeInit, attach the FreeInit Iteration Options to the iteration_opts input. NOTE: FreeInit, despite it's name, works by resampling the latents iterations
amount of times - this means if you use iteration=2, total sampling time will be exactly twice as slow since it will be performing the sampling twice.
Noise Layers with the inputs of the same name (or very close to same name) have same intended behavior as the ones for Sample Settings - refer to the inputs below.
Node |
---|
These options allow KSamplers to re-sample the same latents without needing to chain multiple KSamplers together, and also allows specialized iteration behavior to implement features such as FreeInit.
Simply re-runs the KSampler, plugging in the output of the previous iteration into the next one. At the dafault iterations=1, it is no different than not having this node plugged in at all.
Node | Inputs |
---|---|
🟦iterations: Total amount of times KSampler should run back-to-back. 🟦iter_batch_offset: batch_offset to apply on each subsequent iteration. 🟦iter_seed_offset: seed_offset to apply on each subsequent iteration. |
Implements FreeInit, which is the idea that AnimateDiff was trained on latents of existing videos (images with temporal coherence between them) that were then noised rather than from random initial noise, and that when noising existing latents, low-frequency data still remains in the noised latents. It combines the low-frequency noise from existing videos (or, as is the default behavior, the previous iteration) with the high-frequency noise in randomly generated noise to run the subsequent iterations. Each iteration is a full sample - 2 iterations means it will take twice as long to run as compared to having 1 iteration/no iteration_opts connected.
When apply_to_1st_iter is False, the noising/low-freq/high-freq combination will not occur on the first iteration, with the assumption that there are no useful latents passed in to do the noise combining in the first place, thus requiring at least 2 iterations for FreeInit to take effect.
If you have an existing set of latents to use to get low-freq noise from, you may set apply_to_1st_iter to True, and then even if you set iterations=1, FreeInit will still take effect.
Node |
---|
🟦iterations: Total amount of times KSampler should run back-to-back. Refer to explanation above why it is 2 by default (and when it can be set to 1 instead).
🟦init_type: Code implementation for applying FreeInit.
🟦apply_to_1st_iter: When set to True, will do FreeInit low-freq/high-freq combo work even on the 1st iteration it runs Refer to explanation in the above FreeInit Iteration Options section for when this can be set to True.
🟦init_type: Code implementation for applying FreeInit.
🟦iter_batch_offset: batch_offset to apply on each subsequent iteration.
🟦iter_seed_offset: seed_offset to apply on each subsequent iteration. Defaults to 1 so that new random noise is used for each iteration.
🟦filter: Determines low-freq filter to apply to noise. Very technical, look into code/online resources to figure out how the individual filters act.
🟦d_s: Spatial parameter of filter (within latents, I think); very technical. Look into code/online resources if you wish to know what exactly it does.
🟦d_t: Temporal parameter of filter (across latents, I think); very technical. Look into code/online resources if you wish to know what exactly it does.
🟦n_butterworth: Only applies to butterworth
filter; very technical. Look into code/online resources if you wish to know what exactly it does.
🟦sigma_step: Noising step to use/emulate when noising latents to then get low-freq noise out of. 999 actually means last (-1), and any number under 999 will mean the distance away from last. Leave at 999 unless you know what you're trying to do with it.
These nodes allow initial noise to be added onto, weighted, or replaced. In near future, I will add the ability for masks to 'move' the noise relative to the masks' movement instead of just 'cutting and pasting' the noise.
The inputs that are shared with Sample Settings have the same exact effect - only new option is in seed_gen_override, which by default will use same seed_gen as Sample Settings (use existing). You can make a noise layer use a different seed_gen strategy at will, or use a different seed/set of seeds, etc.
The mask_optional
parameter determines where on the initial noise the noise layer should be applied.
Node | Behavior + Inputs |
---|---|
[Add]; Adds noise directly on top. 🟦noise_weight: Multiplier for noise layer before being added on top. |
|
[Add Weighted]; Adds noise, but takes a weighted average between what is already there and itself. 🟦noise_weight: Weight of new noise in the weighted average with existing noise. 🟦balance_multipler: Scale for how much noise_weight should affect existing noise; 1.0 means normal weighted average, and below 1.0 will lessen the weighted reduction by that amount (i.e. if balance_multiplier is set to 0.5 and noise_weight is 0.25, existing noise will only be reduced by 0.125 instead of 0.25, but new noise will be added with the unmodified 0.25 weight). |
|
[Replace]; Directly replaces existing noise from layers underneath with itself. |
NOTE: I've scaled down the gifs to 0.75x size to make them take up less space on the README. The updated workflows have included Context Options and Sample Settings connected. The Context Options (and FreeNoise) do nothing unless context windows are triggered.
Result |
---|
Workflow |
Result |
---|
Workflow |
Result |
---|
Workflow |
Compared to without ContextRef, this tries to make the rest of the animation be more similar to the first context window.
Result |
---|
Workflow |
(open_pose images provided courtesy of toyxyz)
(open_pose images provided courtesy of toyxyz)
TODO: fill this out with a few useful ways, some using control net tile. I'm sorry there is nothing here right now, I have a lot of code to write. I'll try to fill this section out + Advance ControlNet use piece by piece.
Training data used by the authors of the AnimateDiff paper contained Shutterstock watermarks. Since mm_sd_v15 was finetuned on finer, less drastic movement, the motion module attempts to replicate the transparency of that watermark and does not get blurred away like mm_sd_v14. Using other motion modules, or combinations of them using Advanced KSamplers should alleviate watermark issues.