132 lines
5.7 KiB
Markdown
132 lines
5.7 KiB
Markdown
---
|
|
tags:
|
|
- AnimationScheduling
|
|
- Frame
|
|
- Keyframe
|
|
---
|
|
|
|
# Latent Keyframe Interpolation 🛂🅐🅒🅝
|
|
## Documentation
|
|
- Class name: `LatentKeyframeTiming`
|
|
- Category: `Adv-ControlNet 🛂🅐🅒🅝/keyframes`
|
|
- Output node: `False`
|
|
|
|
This node is responsible for creating and managing latent keyframes within a generative model's control network. It allows for the dynamic adjustment and sequencing of keyframes based on specified timing and strength parameters, facilitating the controlled transformation or animation of generated content.
|
|
## Input types
|
|
### Required
|
|
- **`batch_index_from`**
|
|
- Specifies the starting index of the batch for keyframe creation, marking the beginning of the sequence where adjustments are applied.
|
|
- Comfy dtype: `INT`
|
|
- Python dtype: `int`
|
|
- **`batch_index_to_excl`**
|
|
- Defines the exclusive end index of the batch for keyframe creation, indicating the point just beyond the last batch index where adjustments cease.
|
|
- Comfy dtype: `INT`
|
|
- Python dtype: `int`
|
|
- **`strength_from`**
|
|
- Sets the initial strength or intensity level for the starting keyframe, influencing the beginning of the transformation or animation effect.
|
|
- Comfy dtype: `FLOAT`
|
|
- Python dtype: `float`
|
|
- **`strength_to`**
|
|
- Determines the final strength or intensity level for the ending keyframe, shaping the culmination of the transformation or animation effect.
|
|
- Comfy dtype: `FLOAT`
|
|
- Python dtype: `float`
|
|
- **`interpolation`**
|
|
- Chooses the method of interpolation between keyframe strengths, affecting the transition smoothness and dynamics between the start and end points.
|
|
- Comfy dtype: `COMBO[STRING]`
|
|
- Python dtype: `str`
|
|
### Optional
|
|
- **`prev_latent_kf`**
|
|
- An optional parameter for including a previously defined latent keyframe or keyframe group, enabling the extension or modification of existing sequences.
|
|
- Comfy dtype: `LATENT_KEYFRAME`
|
|
- Python dtype: `LatentKeyframeGroup`
|
|
- **`print_keyframes`**
|
|
- A flag to enable or disable the printing of keyframe details, aiding in debugging or visualization of the keyframe sequence.
|
|
- Comfy dtype: `BOOLEAN`
|
|
- Python dtype: `bool`
|
|
## Output types
|
|
- **`LATENT_KF`**
|
|
- Comfy dtype: `LATENT_KEYFRAME`
|
|
- Outputs a modified or newly created latent keyframe group, incorporating the specified adjustments and interpolations to the keyframes.
|
|
- Python dtype: `LatentKeyframeGroup`
|
|
## Usage tips
|
|
- Infra type: `CPU`
|
|
- Common nodes: unknown
|
|
|
|
|
|
## Source code
|
|
```python
|
|
class LatentKeyframeInterpolationNode:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"batch_index_from": ("INT", {"default": 0, "min": BIGMIN, "max": BIGMAX, "step": 1}),
|
|
"batch_index_to_excl": ("INT", {"default": 0, "min": BIGMIN, "max": BIGMAX, "step": 1}),
|
|
"strength_from": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
|
"strength_to": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
|
"interpolation": ([SI.LINEAR, SI.EASE_IN, SI.EASE_OUT, SI.EASE_IN_OUT], ),
|
|
},
|
|
"optional": {
|
|
"prev_latent_kf": ("LATENT_KEYFRAME", ),
|
|
"print_keyframes": ("BOOLEAN", {"default": False})
|
|
}
|
|
}
|
|
|
|
RETURN_NAMES = ("LATENT_KF", )
|
|
RETURN_TYPES = ("LATENT_KEYFRAME", )
|
|
FUNCTION = "load_keyframe"
|
|
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/keyframes"
|
|
|
|
def load_keyframe(self,
|
|
batch_index_from: int,
|
|
strength_from: float,
|
|
batch_index_to_excl: int,
|
|
strength_to: float,
|
|
interpolation: str,
|
|
prev_latent_kf: LatentKeyframeGroup=None,
|
|
prev_latent_keyframe: LatentKeyframeGroup=None, # old name
|
|
print_keyframes=False):
|
|
|
|
if (batch_index_from > batch_index_to_excl):
|
|
raise ValueError("batch_index_from must be less than or equal to batch_index_to.")
|
|
|
|
if (batch_index_from < 0 and batch_index_to_excl >= 0):
|
|
raise ValueError("batch_index_from and batch_index_to must be either both positive or both negative.")
|
|
|
|
prev_latent_keyframe = prev_latent_keyframe if prev_latent_keyframe else prev_latent_kf
|
|
if not prev_latent_keyframe:
|
|
prev_latent_keyframe = LatentKeyframeGroup()
|
|
else:
|
|
prev_latent_keyframe = prev_latent_keyframe.clone()
|
|
curr_latent_keyframe = LatentKeyframeGroup()
|
|
|
|
steps = batch_index_to_excl - batch_index_from
|
|
diff = strength_to - strength_from
|
|
if interpolation == SI.LINEAR:
|
|
weights = np.linspace(strength_from, strength_to, steps)
|
|
elif interpolation == SI.EASE_IN:
|
|
index = np.linspace(0, 1, steps)
|
|
weights = diff * np.power(index, 2) + strength_from
|
|
elif interpolation == SI.EASE_OUT:
|
|
index = np.linspace(0, 1, steps)
|
|
weights = diff * (1 - np.power(1 - index, 2)) + strength_from
|
|
elif interpolation == SI.EASE_IN_OUT:
|
|
index = np.linspace(0, 1, steps)
|
|
weights = diff * ((1 - np.cos(index * np.pi)) / 2) + strength_from
|
|
|
|
for i in range(steps):
|
|
keyframe = LatentKeyframe(batch_index_from + i, float(weights[i]))
|
|
curr_latent_keyframe.add(keyframe)
|
|
|
|
if print_keyframes:
|
|
for keyframe in curr_latent_keyframe.keyframes:
|
|
logger.info(f"keyframe {keyframe.batch_index}:{keyframe.strength}")
|
|
|
|
# replace values with prev_latent_keyframes
|
|
for latent_keyframe in prev_latent_keyframe.keyframes:
|
|
curr_latent_keyframe.add(latent_keyframe)
|
|
|
|
return (curr_latent_keyframe,)
|
|
|
|
```
|