# Documentation - Class name: LatentKeyframeInterpolationNode - Category: Adv-ControlNet 🛂🅐🅒🅝/keyframes - Output node: False - Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git LatentKeyframeInterpolationNode 旨在在潜在空间中对关键帧进行插值,允许在生成过程中进行平滑过渡。它通过根据指定的强度和插值方法(可以是线性或各种缓动函数)计算中间关键帧来实现这一点。该节点在增强潜在表示生成的流畅性和控制方面发挥着关键作用。 # Input types ## Required - batch_index_from - 插值开始的批次索引,定义了关键帧序列中的初始位置。这对于确定过渡的起始点至关重要。 - Comfy dtype: INT - Python dtype: int - strength_from - 起始关键帧处的强度值,它影响插值过程中初始状态的强度。 - Comfy dtype: FLOAT - Python dtype: float - batch_index_to_excl - 计算插值的批次索引,不包括索引本身,定义序列的结束位置。 - Comfy dtype: INT - Python dtype: int - strength_to - 结束关键帧处的强度值,确定插值后最终状态的强度。 - Comfy dtype: FLOAT - Python dtype: float - interpolation - 在关键帧之间使用的插值类型,可以是线性的或者是一个缓动函数,以实现更自然的过渡。 - Comfy dtype: COMBO[LINEAR, EASE_IN, EASE_OUT, EASE_IN_OUT] - Python dtype: str ## Optional - prev_latent_kf - 一个可选的先前的潜在关键帧组,它为插值提供上下文,允许更有信息量的生成过程。 - Comfy dtype: LATENT_KEYFRAME - Python dtype: LatentKeyframeGroup - print_keyframes - 一个布尔标志,当设置为 true 时,将打印生成的关键帧的详细信息,用于调试目的。 - Comfy dtype: BOOLEAN - Python dtype: bool # Output types - LATENT_KF - 生成的插值潜在关键帧组,代表初始和最终状态之间的过渡。 - Comfy dtype: LATENT_KEYFRAME - Python dtype: LatentKeyframeGroup # Usage tips - Infra type: CPU # Source code ``` 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, 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}') for latent_keyframe in prev_latent_keyframe.keyframes: curr_latent_keyframe.add(latent_keyframe) return (curr_latent_keyframe,) ```