diff --git a/README.md b/README.md index fc09cf5..dcb89fb 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,10 @@ Node source code ## 更新日志 +### 2024-06-11 +- 修复了文档中的一些错误 +- 更新了ComfyUI-AnimateDiff-Evolved/ComfyUI-Custom-Scripts大部分文档,补充了ComfyUI-VideoHelperSuite的部分节点文档 + ### 2024-05-26 - 修复了文档中的一些错误 - 更新了很多节点文档,可查看文档目录 diff --git a/docs/ADE_AnimateDiffCombine.md b/docs/ADE_AnimateDiffCombine.md new file mode 100644 index 0000000..53a5a12 --- /dev/null +++ b/docs/ADE_AnimateDiffCombine.md @@ -0,0 +1,189 @@ +# Documentation +- Class name: WeightAdjustIndivAttnMultNode +- Category: Animate Diff 🎭🅐🅓 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +最初设计用于将多个动画帧组合成一个连贯的序列,此节点有助于从单个帧创建复杂的动画。 + +# Input types +## Required + +- images + - 一个动画帧集合,组合成单个序列,支持从单个帧创建复杂的动画。 + - Comfy dtype: IMAGE + - Python dtype: List[Image.Image] + +- frame_rate + - 指定组合动画序列的播放速度,决定帧的显示速度。 + - Comfy dtype: INT + - Python dtype: int +- loop_count + - 定义动画序列的重复次数,值为0表示无限循环。 + - Comfy dtype: INT + - Python dtype: int +- filename_prefix + - 输出文件名的前缀,有助于组织和识别生成的动画。 + - Comfy dtype: STRING + - Python dtype: str +- format + - 输出动画文件的格式,例如GIF,允许自定义输出类型。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- pingpong + - 一个布尔值,指示动画是否应前后播放,创建无缝循环效果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- save_image + - 确定是否将组合的动画序列保存为图像文件,提供灵活的输出处理方式。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +## Output types +- gif + - 生成的动画文件,根据指定参数组合输入帧。 + - Comfy dtype: GIF + - Python dtype: str + +# Source code + +```python +class AnimateDiffCombine_Deprecated: + ffmpeg_warning_already_shown = False + @classmethod + def INPUT_TYPES(s): + ffmpeg_path = shutil.which("ffmpeg") + #Hide ffmpeg formats if ffmpeg isn't available + if ffmpeg_path is not None: + ffmpeg_formats = ["video/"+x[:-5] for x in folder_paths.get_filename_list(Folders.VIDEO_FORMATS)] + else: + ffmpeg_formats = [] + if not s.ffmpeg_warning_already_shown: + # Deprecated node are now hidden, so no need to show warning unless node is used. + # logger.warning("This warning can be ignored, you should not be using the deprecated AnimateDiff Combine node anyway. If you are, use Video Combine from ComfyUI-VideoHelperSuite instead. ffmpeg could not be found. Outputs that require it have been disabled") + s.ffmpeg_warning_already_shown = True + return { + "required": { + "images": ("IMAGE",), + "frame_rate": ( + "INT", + {"default": 8, "min": 1, "max": 24, "step": 1}, + ), + "loop_count": ("INT", {"default": 0, "min": 0, "max": 100, "step": 1}), + "filename_prefix": ("STRING", {"default": "AnimateDiff"}), + "format": (["image/gif", "image/webp"] + ffmpeg_formats,), + "pingpong": ("BOOLEAN", {"default": False}), + "save_image": ("BOOLEAN", {"default": True}), + }, + "hidden": { + "prompt": "PROMPT", + "extra_pnginfo": "EXTRA_PNGINFO", + }, + } + + RETURN_TYPES = ("GIF",) + OUTPUT_NODE = True + CATEGORY = "" + FUNCTION = "generate_gif" + + def generate_gif( + self, + images, + frame_rate: int, + loop_count: int, + filename_prefix="AnimateDiff", + format="image/gif", + pingpong=False, + save_image=True, + prompt=None, + extra_pnginfo=None, + ): + logger.warning("Do not use AnimateDiff Combine node, it is deprecated. Use Video Combine node from ComfyUI-VideoHelperSuite instead. Video nodes from VideoHelperSuite are actively maintained, more feature-rich, and also automatically attempts to get ffmpeg.") + # convert images to numpy + frames: List[Image.Image] = [] + for image in images: + img = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(img, 0, 255).astype(np.uint8)) + frames.append(img) + + # get output information + output_dir = ( + folder_paths.get_output_directory() + if save_image + else folder_paths.get_temp_directory() + ) + ( + full_output_folder, + filename, + counter, + subfolder, + _, + ) = folder_paths.get_save_image_path(filename_prefix, output_dir) + + metadata = PngInfo() + if prompt is not None: + metadata.add_text("prompt", json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + + # save first frame as png to keep metadata + file = f"{filename}_{counter:05}_.png" + file_path = os.path.join(full_output_folder, file) + frames[0].save( + file_path, + pnginfo=metadata, + compress_level=4, + ) + if pingpong: + frames = frames + frames[-2:0:-1] + + format_type, format_ext = format.split("/") + file = f"{filename}_{counter:05}_.{format_ext}" + file_path = os.path.join(full_output_folder, file) + if format_type == "image": + # Use pillow directly to save an animated image + frames[0].save( + file_path, + format=format_ext.upper(), + save_all=True, + append_images=frames[1:], + duration=round(1000 / frame_rate), + loop=loop_count, + compress_level=4, + ) + else: + # Use ffmpeg to save a video + ffmpeg_path = shutil.which("ffmpeg") + if ffmpeg_path is None: + #Should never be reachable + raise ProcessLookupError("Could not find ffmpeg") + + video_format_path = folder_paths.get_full_path("video_formats", format_ext + ".json") + with open(video_format_path, 'r') as stream: + video_format = json.load(stream) + file = f"{filename}_{counter:05}_.{video_format['extension']}" + file_path = os.path.join(full_output_folder, file) + dimensions = f"{frames[0].width}x{frames[0].height}" + args = [ffmpeg_path, "-v", "error", "-f", "rawvideo", "-pix_fmt", "rgb24", + "-s", dimensions, "-r", str(frame_rate), "-i", "-"] \ + + video_format['main_pass'] + [file_path] + + env=os.environ.copy() + if "environment" in video_format: + env.update(video_format["environment"]) + with subprocess.Popen(args, stdin=subprocess.PIPE, env=env) as proc: + for frame in frames: + proc.stdin.write(frame.tobytes()) + + previews = [ + { + "filename": file, + "subfolder": subfolder, + "type": "output" if save_image else "temp", + "format": format, + } + ] + return {"ui": {"gifs": previews}} + +``` \ No newline at end of file diff --git a/docs/ADE_AnimateDiffLoaderGen1.md b/docs/ADE_AnimateDiffLoaderGen1.md new file mode 100644 index 0000000..f78c3cf --- /dev/null +++ b/docs/ADE_AnimateDiffLoaderGen1.md @@ -0,0 +1,147 @@ +# AnimateDiff Loader 🎭🅐🅓① +## Documentation +- Class name: `ADE_AnimateDiffLoaderGen1` +- Category: `Animate Diff 🎭🅐🅓/① Gen1 nodes ①` +- Output node: `False` +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + + +ADE_AnimateDiffLoaderGen1 节点旨在加载和初始化第一代 AnimateDiff 模型,为后续的动画或图像处理任务奠定基础。它封装了模型加载和配置的复杂性,提供了一个简化的界面来生成动态内容。 +## Input types +### Required +- **`model`** + - 此输入指定要加载的 AnimateDiff 模型,是初始化动画或图像处理过程的核心。 + - Comfy dtype: `MODEL` + - Python dtype: `str` +- **`model_name`** + - model_name 参数允许按名称选择特定的 AnimateDiff 模型,从而实现更有针对性的初始化。 + - Comfy dtype: `COMBO[STRING]` + - Python dtype: `str` +- **`beta_schedule`** + - beta_schedule 参数决定了扩散过程中的 beta 值调度,影响生成内容的质量和特性。 + - Comfy dtype: `COMBO[STRING]` + - Python dtype: `str` +### Optional +- **`context_options`** + - 提供额外的上下文或首选项设置以进行模型加载,允许自定义初始化。 + - Comfy dtype: `CONTEXT_OPTIONS` + - Python dtype: `str` +- **`motion_lora`** + - 指定运动模型的 LoRA 参数,允许对动画动态进行微调控制。 + - Comfy dtype: `MOTION_LORA` + - Python dtype: `str` +- **`ad_settings`** + - 自定义 AnimateDiff 模型在加载过程中的行为的动画和扩散设置。 + - Comfy dtype: `AD_SETTINGS` + - Python dtype: `str` +- **`ad_keyframes`** + - 定义动画的关键帧,指导模型在指定的时间间隔内生成动态内容。 + - Comfy dtype: `AD_KEYFRAMES` + - Python dtype: `str` +- **`sample_settings`** + - 影响采样过程的设置,例如温度和 top-k 筛选,以优化生成输出。 + - Comfy dtype: `SAMPLE_SETTINGS` + - Python dtype: `str` +- **`scale_multival`** + - 用于缩放生成内容中特定效果的强度的乘数。 + - Comfy dtype: `MULTIVAL` + - Python dtype: `str` +- **`effect_multival`** + - 用于调整生成内容中特定效果强度的乘数,提供对输出的创意控制。 + - Comfy dtype: `MULTIVAL` + - Python dtype: `str` +## Output types +- **`model`** + - Comfy dtype: `MODEL` + - 这是加载的 AnimateDiff 模型,准备用于动画或图像处理任务。 + - Python dtype: `str` +## Usage tips +- Infra type: `CPU` + + +## Source code +```python +class AnimateDiffLoaderGen1: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "model_name": (get_available_motion_models(),), + "beta_schedule": (BetaSchedules.ALIAS_LIST, {"default": BetaSchedules.AUTOSELECT}), + #"apply_mm_groupnorm_hack": ("BOOLEAN", {"default": True}), + }, + "optional": { + "context_options": ("CONTEXT_OPTIONS",), + "motion_lora": ("MOTION_LORA",), + "ad_settings": ("AD_SETTINGS",), + "ad_keyframes": ("AD_KEYFRAMES",), + "sample_settings": ("SAMPLE_SETTINGS",), + "scale_multival": ("MULTIVAL",), + "effect_multival": ("MULTIVAL",), + } + } + + RETURN_TYPES = ("MODEL",) + CATEGORY = "Animate Diff 🎭🅐🅓/① Gen1 nodes ①" + FUNCTION = "load_mm_and_inject_params" + + def load_mm_and_inject_params(self, + model: ModelPatcher, + model_name: str, beta_schedule: str,# apply_mm_groupnorm_hack: bool, + context_options: ContextOptionsGroup=None, motion_lora: MotionLoraList=None, ad_settings: AnimateDiffSettings=None, + sample_settings: SampleSettings=None, scale_multival=None, effect_multival=None, ad_keyframes: ADKeyframeGroup=None, + ): + # load motion module and motion settings, if included + motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings) + # confirm that it is compatible with SD model + validate_model_compatibility_gen2(model=model, motion_model=motion_model) + # apply motion model to loaded_mm + if motion_lora is not None: + for lora in motion_lora.loras: + load_motion_lora_as_patches(motion_model, lora) + motion_model.scale_multival = scale_multival + motion_model.effect_multival = effect_multival + motion_model.keyframes = ad_keyframes.clone() if ad_keyframes else ADKeyframeGroup() + + # create injection params + params = InjectionParams(unlimited_area_hack=False, model_name=motion_model.model.mm_info.mm_name) + # apply context options + if context_options: + params.set_context(context_options) + + # set motion_scale and motion_model_settings + if not ad_settings: + ad_settings = AnimateDiffSettings() + ad_settings.attn_scale = 1.0 + params.set_motion_model_settings(ad_settings) + + # backwards compatibility to support old way of masking scale + if params.motion_model_settings.mask_attn_scale is not None: + motion_model.scale_multival = get_combined_multival(scale_multival, (params.motion_model_settings.mask_attn_scale * params.motion_model_settings.attn_scale)) + + # need to use a ModelPatcher that supports injection of motion modules into unet + model = ModelPatcherAndInjector.create_from(model, hooks_only=True) + model.motion_models = MotionModelGroup(motion_model) + model.sample_settings = sample_settings if sample_settings is not None else SampleSettings() + model.motion_injection_params = params + + if model.sample_settings.custom_cfg is not None: + logger.info("[Sample Settings] custom_cfg is set; will override any KSampler cfg values or patches.") + + if model.sample_settings.sigma_schedule is not None: + logger.info("[Sample Settings] sigma_schedule is set; will override beta_schedule.") + model.add_object_patch("model_sampling", model.sample_settings.sigma_schedule.clone().model_sampling) + else: + # save model sampling from BetaSchedule as object patch + # if autoselect, get suggested beta_schedule from motion model + if beta_schedule == BetaSchedules.AUTOSELECT and not model.motion_models.is_empty(): + beta_schedule = model.motion_models[0].model.get_best_beta_schedule(log=True) + new_model_sampling = BetaSchedules.to_model_sampling(beta_schedule, model) + if new_model_sampling is not None: + model.add_object_patch("model_sampling", new_model_sampling) + + del motion_model + return (model,) + diff --git a/docs/ADE_AnimateDiffLoaderV1Advanced.md b/docs/ADE_AnimateDiffLoaderV1Advanced.md new file mode 100644 index 0000000..30d94b1 --- /dev/null +++ b/docs/ADE_AnimateDiffLoaderV1Advanced.md @@ -0,0 +1,135 @@ +# 🚫AnimateDiff Loader (Advanced) [DEPRECATED] 🎭🅐🅓 +## Documentation +- Class name: ADE_AnimateDiffLoaderV1Advanced +- Category: +- Output node: False +- Repo Ref: https://github.com/comfyanonymous/ComfyUI + +该节点旨在高级加载AnimateDiff模型,特别适用于处理弃用功能和遗留配置。它抽象地支持旧版AnimateDiff模型在当前工作流中的集成和利用,确保兼容性和对历史模型功能的访问。 + +# Input types +## Required +- model + - 指定要加载的AnimateDiff模型,重点关注特定遗留应用的弃用模型。 + - Comfy dtype: MODEL + - Python dtype: str +- latents + - 定义在加载AnimateDiff模型期间应用的潜在配置,允许自定义模型的行为。 + - Comfy dtype: LATENT + - Python dtype: str +- model_name + - 确定要加载的特定AnimateDiff模型的名称,使得能够精确选择遗留模型。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- unlimited_area_hack + - 一个布尔标志,用于启用或禁用无限区域黑客,提供特定加载场景的解决方法。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- context_length + - 指定在模型加载期间使用的上下文长度,影响模型处理输入的方式。 + - Comfy dtype: INT + - Python dtype: int +- context_stride + - 确定上下文的步幅,影响模型的加载和处理效率。 + - Comfy dtype: INT + - Python dtype: int +- context_overlap + - 定义在模型加载期间上下文段之间的重叠,优化模型对序列数据的理解。 + - Comfy dtype: INT + - Python dtype: int +- context_schedule + - 选择上下文应用的计划,允许灵活适应各种加载需求。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- closed_loop + - 一个布尔参数,指示模型加载是否应在闭环中操作,影响模型的初始化过程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- beta_schedule + - 选择在模型加载期间使用的beta计划,影响模型的适应性和性能。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +# Output types +- model + - 输出加载的AnimateDiff模型,准备进一步处理或应用。 + - Comfy dtype: MODEL + - Python dtype: str +- latent + - 提供在模型加载期间应用的潜在配置,反映模型行为的定制化。 + - Comfy dtype: LATENT + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +```python +class AnimateDiffLoaderAdvanced_Deprecated: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "latents": ("LATENT",), + "model_name": (get_available_motion_models(),), + "unlimited_area_hack": ("BOOLEAN", {"default": False},), + "context_length": ("INT", {"default": 16, "min": 0, "max": 1000}), + "context_stride": ("INT", {"default": 1, "min": 1, "max": 1000}), + "context_overlap": ("INT", {"default": 4, "min": 0, "max": 1000}), + "context_schedule": (ContextSchedules.LEGACY_UNIFORM_SCHEDULE_LIST,), + "closed_loop": ("BOOLEAN", {"default": False},), + "beta_schedule": (BetaSchedules.get_alias_list_with_first_element(BetaSchedules.SQRT_LINEAR),), + }, + } + + RETURN_TYPES = ("MODEL", "LATENT") + CATEGORY = "" + FUNCTION = "load_mm_and_inject_params" + + def load_mm_and_inject_params(self, + model: ModelPatcher, + latents: Dict[str, torch.Tensor], + model_name: str, unlimited_area_hack: bool, + context_length: int, context_stride: int, context_overlap: int, context_schedule: str, closed_loop: bool, + beta_schedule: str, + ): + # load motion module + motion_model = load_motion_module_gen1(model_name, model) + # get total frames + init_frames_len = len(latents["samples"]) # deprecated - no longer used for anything lol + # set injection params + params = InjectionParams( + unlimited_area_hack=unlimited_area_hack, + apply_mm_groupnorm_hack=True, + model_name=model_name, + apply_v2_properly=False, + ) + context_group = ContextOptionsGroup() + context_group.add( + ContextOptions( + context_length=context_length, + context_stride=context_stride, + context_overlap=context_overlap, + context_schedule=context_schedule, + closed_loop=closed_loop, + ) + ) + # set context settings + params.set_context(context_options=context_group) + # inject for use in sampling code + model = ModelPatcherAndInjector.create_from(model, hooks_only=True) + model.motion_models = MotionModelGroup(motion_model) + model.motion_injection_params = params + + # save model sampling from BetaSchedule as object patch + # if autoselect, get suggested beta_schedule from motion model + if beta_schedule == BetaSchedules.AUTOSELECT and not model.motion_models.is_empty(): + beta_schedule = model.motion_models[0].model.get_best_beta_schedule(log=True) + new_model_sampling = BetaSchedules.to_model_sampling(beta_schedule, model) + if new_model_sampling is not None: + model.add_object_patch("model_sampling", new_model_sampling) + + del motion_model + return (model, latents) + diff --git a/docs/ADE_AnimateDiffLoaderWithContext.md b/docs/ADE_AnimateDiffLoaderWithContext.md new file mode 100644 index 0000000..28b52b0 --- /dev/null +++ b/docs/ADE_AnimateDiffLoaderWithContext.md @@ -0,0 +1,155 @@ +--- + +tags: +- AnimateDiff +- AnimateDiffContext +- Animation + +--- + +# AnimateDiff Loader [Legacy] 🎭🅐🅓① +## Documentation +- Class name: ADE_AnimateDiffLoaderWithContext +- Category: Animate Diff 🎭🅐🅓/① Gen1 nodes ① +- Output node: False + +此节点旨在加载AnimateDiff模型及其特定上下文,有助于集成影响动画过程的额外信息或设置。它在传统AnimateDiff模型与更新的、上下文感知的功能之间架起桥梁,确保兼容性并增强对动画生成的控制。 + +## Input types +### Required +- model + - 指定要加载的AnimateDiff模型,作为动画过程的核心组件。 + - Comfy dtype: MODEL + - Python dtype: str +- model_name + - 通过名称识别特定的AnimateDiff模型,允许在可用选项中进行精确选择。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- beta_schedule + - 调整动画的beta进度,影响扩散过程。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +### Optional +- context_options + - 提供上下文特定选项以修改AnimateDiff模型处理动画的方式,允许定制动画行为。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: str +- motion_lora + - 指定运动的LoRA参数,增强模型生成动态动画的能力。 + - Comfy dtype: MOTION_LORA + - Python dtype: str +- ad_settings + - 定义AnimateDiff的设置,调整动画过程以满足特定要求。 + - Comfy dtype: AD_SETTINGS + - Python dtype: str +- sample_settings + - 确定动画的采样设置,影响生成动画的质量和特征。 + - Comfy dtype: SAMPLE_SETTINGS + - Python dtype: str +- motion_scale + - 控制动画中的运动规模,允许更精细地调整运动强度。 + - Comfy dtype: FLOAT + - Python dtype: str +- apply_v2_models_properly + - 确保正确应用版本2模型,优化兼容性和性能。 + - Comfy dtype: BOOLEAN + - Python dtype: str +- ad_keyframes + - 指定动画的关键帧,引导AnimateDiff模型生成目标动画序列。 + - Comfy dtype: AD_KEYFRAMES + - Python dtype: str + +## Output types +- model + - Comfy dtype: MODEL + - 加载的AnimateDiff模型,准备好生成具有指定上下文和设置的动画。 + - Python dtype: str + +## Usage tips +- Infra type: CPU + + +## Source code +```python +class LegacyAnimateDiffLoaderWithContext: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "model_name": (get_available_motion_models(),), + "beta_schedule": (BetaSchedules.ALIAS_LIST, {"default": BetaSchedules.AUTOSELECT}), + #"apply_mm_groupnorm_hack": ("BOOLEAN", {"default": True}), + }, + "optional": { + "context_options": ("CONTEXT_OPTIONS",), + "motion_lora": ("MOTION_LORA",), + "ad_settings": ("AD_SETTINGS",), + "sample_settings": ("SAMPLE_SETTINGS",), + "motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}), + "apply_v2_models_properly": ("BOOLEAN", {"default": True}), + "ad_keyframes": ("AD_KEYFRAMES",), + } + } + + RETURN_TYPES = ("MODEL",) + CATEGORY = "Animate Diff 🎭🅐🅓/① Gen1 nodes ①" + FUNCTION = "load_mm_and_inject_params" + + + def load_mm_and_inject_params(self, + model: ModelPatcher, + model_name: str, beta_schedule: str,# apply_mm_groupnorm_hack: bool, + context_options: ContextOptionsGroup=None, motion_lora: MotionLoraList=None, ad_settings: AnimateDiffSettings=None, motion_model_settings: AnimateDiffSettings=None, + sample_settings: SampleSettings=None, motion_scale: float=1.0, apply_v2_models_properly: bool=False, ad_keyframes: ADKeyframeGroup=None, + ): + if ad_settings is not None: + motion_model_settings = ad_settings + # load motion module + motion_model = load_motion_module_gen1(model_name, model, motion_lora=motion_lora, motion_model_settings=motion_model_settings) + # set injection params + params = InjectionParams( + unlimited_area_hack=False, + model_name=model_name, + apply_v2_properly=apply_v2_models_properly, + ) + if context_options: + params.set_context(context_options) + # set motion_scale and motion_model_settings + if not motion_model_settings: + motion_model_settings = AnimateDiffSettings() + motion_model_settings.attn_scale = motion_scale + params.set_motion_model_settings(motion_model_settings) + + if params.motion_model_settings.mask_attn_scale is not None: + motion_model.scale_multival = params.motion_model_settings.mask_attn_scale * params.motion_model_settings.attn_scale + else: + motion_model.scale_multival = params.motion_model_settings.attn_scale + + motion_model.keyframes = ad_keyframes.clone() if ad_keyframes else ADKeyframeGroup() + + model = ModelPatcherAndInjector.create_from(model, hooks_only=True) + model.motion_models = MotionModelGroup(motion_model) + model.sample_settings = sample_settings if sample_settings is not None else SampleSettings() + model.motion_injection_params = params + + # save model sampling from BetaSchedule as object patch + # if autoselect, get suggested beta_schedule from motion model + if beta_schedule == BetaSchedules.AUTOSELECT and not model.motion_models.is_empty(): + beta_schedule = model.motion_models[0].model.get_best_beta_schedule(log=True) + new_model_sampling = BetaSchedules.to_model_sampling(beta_schedule, model) + if new_model_sampling is not None: + model.add_object_patch("model_sampling", new_model_sampling) + + del motion_model + return (model,) \ No newline at end of file diff --git a/docs/ADE_AnimateDiffModelSettings.md b/docs/ADE_AnimateDiffModelSettings.md new file mode 100644 index 0000000..14f209b --- /dev/null +++ b/docs/ADE_AnimateDiffModelSettings.md @@ -0,0 +1,117 @@ +# 🚫[DEPR] Motion Model Settings (Advanced) 🎭🅐🅓① +## Documentation +- Class name: ADE_AnimateDiffModelSettings +- Category: +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在配置AnimateDiff过程中的运动模型设置,允许用户微调运动比例参数以实现所需的动画效果。 + +## Input types +### Required +- pe_strength + - 决定位置编码调整的强度,影响动画的空间动态。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_strength + - 控制注意力调整的强度,影响动画元素的焦点和细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- other_strength + - 调整其他模型参数的强度,提供动画效果的额外定制。 + - Comfy dtype: FLOAT + - Python dtype: float +- motion_pe_stretch + - 指定位置编码的拉伸程度,改变运动的时间尺度。 + - Comfy dtype: INT + - Python dtype: int +- cap_initial_pe_length + - 限制初始位置编码长度,设定运动的起始尺度。 + - Comfy dtype: INT + - Python dtype: int +- interpolate_pe_to_length + - 定义位置编码插值的目标长度,影响动画的平滑度和流畅性。 + - Comfy dtype: INT + - Python dtype: int +- initial_pe_idx_offset + - 设置初始位置编码索引偏移,调整动画的起始点。 + - Comfy dtype: INT + - Python dtype: int +- final_pe_idx_offset + - 决定最终位置编码索引偏移,影响动画的终点。 + - Comfy dtype: INT + - Python dtype: int + +### Optional +- mask_motion_scale + - 选择性地应用遮罩以缩放图像不同部分的运动,增强动画的真实性和复杂性。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- min_motion_scale + - 设置运动的最小尺度,确保动画不会低于此阈值。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_motion_scale + - 定义运动的最大尺度,限制动画效果的强度。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- ad_settings + - Comfy dtype: AD_SETTINGS + - 输出配置好的运动模型设置,包含对运动比例参数的调整。 + - Python dtype: AnimateDiffSettings + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class AnimateDiffModelSettingsAdvanced: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "pe_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "attn_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "other_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "motion_pe_stretch": ("INT", {"default": 0, "min": 0, "step": 1}), + "cap_initial_pe_length": ("INT", {"default": 0, "min": 0, "step": 1}), + "interpolate_pe_to_length": ("INT", {"default": 0, "min": 0, "step": 1}), + "initial_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}), + "final_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}), + }, + "optional": { + "mask_motion_scale": ("MASK",), + "min_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}), + "max_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}), + } + } + + RETURN_TYPES = ("AD_SETTINGS",) + CATEGORY = "" #"Animate Diff 🎭🅐🅓/① Gen1 nodes ①/motion settings/experimental" + FUNCTION = "get_motion_model_settings" + + def get_motion_model_settings(self, pe_strength: float, attn_strength: float, other_strength: float, + motion_pe_stretch: int, + cap_initial_pe_length: int, interpolate_pe_to_length: int, + initial_pe_idx_offset: int, final_pe_idx_offset: int, + mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0): + adjust_pe = AdjustGroup(AdjustPE(motion_pe_stretch=motion_pe_stretch, + cap_initial_pe_length=cap_initial_pe_length, interpolate_pe_to_length=interpolate_pe_to_length, + initial_pe_idx_offset=initial_pe_idx_offset, final_pe_idx_offset=final_pe_idx_offset)) + adjust_weight = AdjustGroup(AdjustWeight( + pe_MULT=pe_strength, + attn_MULT=attn_strength, + other_MULT=other_strength, + )) + motion_model_settings = AnimateDiffSettings( + adjust_pe=adjust_pe, + adjust_weight=adjust_weight, + mask_attn_scale=mask_motion_scale, + mask_attn_scale_min=min_motion_scale, + mask_attn_scale_max=max_motion_scale, + ) + + return (motion_model_settings,) \ No newline at end of file diff --git a/docs/ADE_AnimateDiffModelSettingsAdvancedAttnStrengths.md b/docs/ADE_AnimateDiffModelSettingsAdvancedAttnStrengths.md new file mode 100644 index 0000000..9247be0 --- /dev/null +++ b/docs/ADE_AnimateDiffModelSettingsAdvancedAttnStrengths.md @@ -0,0 +1,153 @@ +# 🚫[DEPR] Motion Model Settings (Adv. Attn) 🎭🅐🅓① +## Documentation +- Class name: ADE_AnimateDiffModelSettingsAdvancedAttnStrengths +- Category: +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在配置AnimateDiff模型设置中的高级注意力强度。它允许通过调整各种注意力组件的强度来微调模型的注意力机制,从而更详细地控制动画生成过程。 + +## Input types +### Required +- pe_strength + - 指定位置编码调整的强度,影响模型的空间感知。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_strength + - 定义注意力机制的整体强度,影响模型如何专注于输入的不同部分。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_q_strength + - 调整注意力机制中查询组件的强度,微调模型的查询过程。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_k_strength + - 修改注意力机制中键组件的强度,影响模型如何匹配查询和键。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_v_strength + - 改变注意力机制中值组件的强度,影响基于匹配的查询和键的输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_out_weight_strength + - 控制注意力输出权重的强度,影响最终注意力输出的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_out_bias_strength + - 调整注意力输出偏差的强度,微调应用于注意力输出的偏差。 + - Comfy dtype: FLOAT + - Python dtype: float +- other_strength + - 指定与注意力直接相关的其他模型调整的强度,提供对模型行为的更广泛控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- motion_pe_stretch + - 定义运动中位置编码的拉伸因子,影响运动的空间表示。 + - Comfy dtype: INT + - Python dtype: int +- cap_initial_pe_length + - 限制初始位置编码的长度,限制动画开始时的空间范围。 + - Comfy dtype: INT + - Python dtype: int +- interpolate_pe_to_length + - 确定位置编码插值的长度,影响随时间的空间分辨率。 + - Comfy dtype: INT + - Python dtype: int +- initial_pe_idx_offset + - 设置位置编码索引的初始偏移,调整起始的空间参考点。 + - Comfy dtype: INT + - Python dtype: int +- final_pe_idx_offset + - 设置位置编码索引的最终偏移,调整结束的空间参考点。 + - Comfy dtype: INT + - Python dtype: int + +### Optional +- mask_motion_scale + - 可选张量用于选择性缩放运动,允许在动画中不同部分的运动缩放。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- min_motion_scale + - 设置运动的最小缩放,确保运动强度的下限。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_motion_scale + - 设置运动的最大缩放,确保运动强度的上限。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- ad_settings + - Comfy dtype: AD_SETTINGS + - 返回AnimateDiff模型的高级注意力强度设置,允许对动画生成过程进行精确控制。 + - Python dtype: AnimateDiffSettings + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class AnimateDiffModelSettingsAdvancedAttnStrengths: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "pe_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "attn_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "attn_q_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "attn_k_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "attn_v_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "attn_out_weight_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "attn_out_bias_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "other_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}), + "motion_pe_stretch": ("INT", {"default": 0, "min": 0, "step": 1}), + "cap_initial_pe_length": ("INT", {"default": 0, "min": 0, "step": 1}), + "interpolate_pe_to_length": ("INT", {"default": 0, "min": 0, "step": 1}), + "initial_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}), + "final_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}), + }, + "optional": { + "mask_motion_scale": ("MASK",), + "min_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}), + "max_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}), + } + } + + RETURN_TYPES = ("AD_SETTINGS",) + CATEGORY = "" #"Animate Diff 🎭🅐🅓/① Gen1 nodes ①/motion settings/experimental" + FUNCTION = "get_motion_model_settings" + + def get_motion_model_settings(self, pe_strength: float, attn_strength: float, + attn_q_strength: float, + attn_k_strength: float, + attn_v_strength: float, + attn_out_weight_strength: float, + attn_out_bias_strength: float, + other_strength: float, + motion_pe_stretch: int, + cap_initial_pe_length: int, interpolate_pe_to_length: int, + initial_pe_idx_offset: int, final_pe_idx_offset: int, + mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0): + adjust_pe = AdjustGroup(AdjustPE(motion_pe_stretch=motion_pe_stretch, + cap_initial_pe_length=cap_initial_pe_length, interpolate_pe_to_length=interpolate_pe_to_length, + initial_pe_idx_offset=initial_pe_idx_offset, final_pe_idx_offset=final_pe_idx_offset)) + adjust_weight = AdjustGroup(AdjustWeight( + pe_MULT=pe_strength, + attn_MULT=attn_strength, + attn_q_MULT=attn_q_strength, + attn_k_MULT=attn_k_strength, + attn_v_MULT=attn_v_strength, + attn_out_weight_MULT=attn_out_weight_strength, + attn_out_bias_MULT=attn_out_bias_strength, + other_MULT=other_strength, + )) + motion_model_settings = AnimateDiffSettings( + adjust_pe=adjust_pe, + adjust_weight=adjust_weight, + mask_attn_scale=mask_motion_scale, + mask_attn_scale_min=min_motion_scale, + mask_attn_scale_max=max_motion_scale, + ) + + return (motion_model_settings,) \ No newline at end of file diff --git a/docs/ADE_AnimateDiffModelSettingsSimple.md b/docs/ADE_AnimateDiffModelSettingsSimple.md new file mode 100644 index 0000000..b8685df --- /dev/null +++ b/docs/ADE_AnimateDiffModelSettingsSimple.md @@ -0,0 +1,71 @@ +# 🚫[DEPR] Motion Model Settings (Simple) 🎭🅐🅓① +## Documentation +- Class name: ADE_AnimateDiffModelSettingsSimple +- Category: +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在为AnimateDiff框架中的简单场景配置运动模型设置。它允许调整运动比例参数并应用可选的遮罩,以微调动画过程。 + +## Input types +### Required +- motion_pe_stretch + - 定义运动模型中位置编码的拉伸因子,影响应用的运动的规模和强度。 + - Comfy dtype: INT + - Python dtype: int + +### Optional +- mask_motion_scale + - 可选的遮罩张量,用于选择性地缩放不同区域,增强对运动效果的控制。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- min_motion_scale + - 设置运动的最小比例,提供运动强度的基线。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_motion_scale + - 确定运动的最大比例,限制运动效果的强度。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- ad_settings + - Comfy dtype: AD_SETTINGS + - 输出配置好的运动模型设置,包含对运动比例和可选遮罩的调整。 + - Python dtype: AnimateDiffSettings + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class AnimateDiffModelSettingsSimple: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "motion_pe_stretch": ("INT", {"default": 0, "min": 0, "step": 1}), + }, + "optional": { + "mask_motion_scale": ("MASK",), + "min_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}), + "max_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}), + } + } + + RETURN_TYPES = ("AD_SETTINGS",) + CATEGORY = "" #"Animate Diff 🎭🅐🅓/① Gen1 nodes ①/motion settings/experimental" + FUNCTION = "get_motion_model_settings" + + def get_motion_model_settings(self, motion_pe_stretch: int, + mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0): + adjust_pe = AdjustGroup(AdjustPE(motion_pe_stretch=motion_pe_stretch)) + motion_model_settings = AnimateDiffSettings( + adjust_pe=adjust_pe, + mask_attn_scale=mask_motion_scale, + mask_attn_scale_min=min_motion_scale, + mask_attn_scale_max=max_motion_scale, + ) + + return (motion_model_settings,) \ No newline at end of file diff --git a/docs/ADE_AnimateDiffModelSettings_Release.md b/docs/ADE_AnimateDiffModelSettings_Release.md new file mode 100644 index 0000000..43b218f --- /dev/null +++ b/docs/ADE_AnimateDiffModelSettings_Release.md @@ -0,0 +1,63 @@ +# 🚫[DEPR] Motion Model Settings 🎭🅐🅓① +## Documentation +- Class name: ADE_AnimateDiffModelSettings_Release +- Category: +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在配置AnimateDiff过程中的运动模型设置,重点是高级注意力强度调整。它旨在为用户提供微调通过AnimateDiff框架应用的动画效果的能力。 + +## Input types +### Required +- min_motion_scale + - 指定运动的最小尺度,影响动画效果的细微程度或强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_motion_scale + - 定义运动的最大尺度,影响可以应用于动画的运动强度范围。 + - Comfy dtype: FLOAT + - Python dtype: float + +### Optional +- mask_motion_scale + - 一个遮罩张量,允许对输入的不同区域进行精细控制的运动缩放。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +## Output types +- ad_settings + - Comfy dtype: AD_SETTINGS + - 输出是AnimateDiff模型的配置集,包含对运动尺度和潜在其他参数的调整。 + - Python dtype: AnimateDiffSettings + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class AnimateDiffModelSettings: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "min_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}), + "max_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}), + }, + "optional": { + "mask_motion_scale": ("MASK",), + } + } + + RETURN_TYPES = ("AD_SETTINGS",) + CATEGORY = "" #"Animate Diff 🎭🅐🅓/① Gen1 nodes ①/motion settings" + FUNCTION = "get_motion_model_settings" + + def get_motion_model_settings(self, mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0): + motion_model_settings = AnimateDiffSettings( + mask_attn_scale=mask_motion_scale, + mask_attn_scale_min=min_motion_scale, + mask_attn_scale_max=max_motion_scale, + ) + + return (motion_model_settings,) \ No newline at end of file diff --git a/docs/ADE_AnimateDiffUnload.md b/docs/ADE_AnimateDiffUnload.md new file mode 100644 index 0000000..aa80dad --- /dev/null +++ b/docs/ADE_AnimateDiffUnload.md @@ -0,0 +1,45 @@ +# AnimateDiff Unload 🎭🅐🅓 +## Documentation +- Class name: ADE_AnimateDiffUnload +- Category: Animate Diff 🎭🅐🅓/extras +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在从内存中卸载或释放与AnimateDiff模型相关的资源,确保有效的资源管理并为后续任务释放内存。 + +## Input types +### Required +- model + - 指定要卸载的AnimateDiff模型,允许释放其资源。 + - Comfy dtype: MODEL + - Python dtype: AnimateDiffModel + +## Output types +- model + - Comfy dtype: MODEL + - 确认指定的AnimateDiff模型已成功卸载,确保其资源已释放。 + - Python dtype: NoneType + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class AnimateDiffUnload: + def __init__(self) -> None: + pass + + @classmethod + def INPUT_TYPES(s): + return {"required": {"model": ("MODEL",)}} + + RETURN_TYPES = ("MODEL",) + CATEGORY = "Animate Diff 🎭🅐🅓/extras" + FUNCTION = "unload_motion_modules" + + def unload_motion_modules(self, model: ModelPatcher): + # return model clone with ejected params + #model = eject_params_from_model(model) + model = get_vanilla_model_patcher(model) + return (model.clone(),) \ No newline at end of file diff --git a/docs/ADE_ApplyAnimateDiffModel.md b/docs/ADE_ApplyAnimateDiffModel.md new file mode 100644 index 0000000..70a6ebd --- /dev/null +++ b/docs/ADE_ApplyAnimateDiffModel.md @@ -0,0 +1,106 @@ +# Apply AnimateDiff Model (Adv.) 🎭🅐🅓② +## Documentation +- Class name: ADE_ApplyAnimateDiffModel +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ② +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_ApplyAnimateDiffModel节点旨在应用高级AnimateDiff模型配置以生成图像中的运动。它利用一套全面的参数来微调动画过程,适应各种运动效果和风格。 + +## Input types +### Required +- motion_model + - 指定用于动画的运动模型。它对于定义动画的行为和特性至关重要。 + - Comfy dtype: MOTION_MODEL_ADE + - Python dtype: MotionModelPatcher +- start_percent + - 定义动画效果的起始百分比,标记运动应用的开始。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - 指定动画效果的结束百分比,确定运动停止的点。 + - Comfy dtype: FLOAT + - Python dtype: float + +### Optional +- motion_lora + - 可选参数,允许使用LoRA(低秩适应)技术调整运动,增强动画质量。 + - Comfy dtype: MOTION_LORA + - Python dtype: MotionLoraList +- scale_multival + - 可选参数,影响动画效果的规模,允许微调动画的强度。 + - Comfy dtype: MULTIVAL + - Python dtype: float +- effect_multival + - 可选参数,调整动画的整体效果,允许自定义视觉结果。 + - Comfy dtype: MULTIVAL + - Python dtype: float +- ad_keyframes + - 可选参数,指定动画的关键帧,允许精确控制运动的时间和序列。 + - Comfy dtype: AD_KEYFRAMES + - Python dtype: ADKeyframeGroup +- prev_m_models + - 可选参数,包括要在当前动画过程中考虑的先前运动模型,允许累积效果。 + - Comfy dtype: M_MODELS + - Python dtype: M_MODELS + +## Output types +- m_models + - Comfy dtype: M_MODELS + - 输出动画过程中使用的运动模型,包含所有调整和配置。 + - Python dtype: M_MODELS + +## Usage tips +- Infra type: GPU + + +## Source code +```python +class ApplyAnimateDiffModelNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "motion_model": ("MOTION_MODEL_ADE",), + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}), + }, + "optional": { + "motion_lora": ("MOTION_LORA",), + "scale_multival": ("MULTIVAL",), + "effect_multival": ("MULTIVAL",), + "ad_keyframes": ("AD_KEYFRAMES",), + "prev_m_models": ("M_MODELS",), + } + } + + RETURN_TYPES = ("M_MODELS",) + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②" + FUNCTION = "apply_motion_model" + + def apply_motion_model(self, motion_model: MotionModelPatcher, start_percent: float=0.0, end_percent: float=1.0, + motion_lora: MotionLoraList=None, ad_keyframes: ADKeyframeGroup=None, + scale_multival=None, effect_multival=None, + prev_m_models: MotionModelGroup=None,): + # set up motion models list + if prev_m_models is None: + prev_m_models = MotionModelGroup() + prev_m_models = prev_m_models.clone() + motion_model = motion_model.clone() + # check if internal motion model already present in previous model - create new if so + for prev_model in prev_m_models.models: + if motion_model.model is prev_model.model: + # need to create new internal model based on same state_dict + motion_model = create_fresh_motion_module(motion_model) + # apply motion model to loaded_mm + if motion_lora is not None: + for lora in motion_lora.loras: + load_motion_lora_as_patches(motion_model, lora) + motion_model.scale_multival = scale_multival + motion_model.effect_multival = effect_multival + motion_model.keyframes = ad_keyframes.clone() if ad_keyframes else ADKeyframeGroup() + motion_model.timestep_percent_range = (start_percent, end_percent) + # add to beginning, so that after injection, it will be the earliest of prev_m_models to be run + prev_m_models.add_to_start(mm=motion_model) + return (prev_m_models,) \ No newline at end of file diff --git a/docs/ADE_ApplyAnimateDiffModelSimple.md b/docs/ADE_ApplyAnimateDiffModelSimple.md new file mode 100644 index 0000000..8c46036 --- /dev/null +++ b/docs/ADE_ApplyAnimateDiffModelSimple.md @@ -0,0 +1,72 @@ +# Apply AnimateDiff Model 🎭🅐🅓② +## Documentation +- Class name: ADE_ApplyAnimateDiffModelSimple +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ② +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在应用运动模型以动画化图像或序列,提供一个简化的界面以集成运动效果。它抽象了动画过程中的复杂性,使用户能够轻松地将预定义的运动模型应用于其内容。 + +## Input types +### Required +- motion_model + - 指定要应用的运动模型。它对于定义目标内容的动画行为和效果至关重要。 + - Comfy dtype: MOTION_MODEL_ADE + - Python dtype: MotionModelPatcher + +### Optional +- motion_lora + - 可选参数,用于整合运动Lora调整,增强动画效果。 + - Comfy dtype: MOTION_LORA + - Python dtype: MotionLoraList +- scale_multival + - 可选参数,用于缩放效果,提供应用运动强度的灵活性。 + - Comfy dtype: MULTIVAL + - Python dtype: Optional[MultiVal] +- effect_multival + - 可选参数,用于效果调整,使运动的视觉影响自定义。 + - Comfy dtype: MULTIVAL + - Python dtype: Optional[MultiVal] +- ad_keyframes + - 可选参数,用于指定关键帧,允许更受控和精确的动画效果。 + - Comfy dtype: AD_KEYFRAMES + - Python dtype: Optional[ADKeyframeGroup] + +## Output types +- m_models + - Comfy dtype: M_MODELS + - 输出应用了指定运动效果、关键帧和调整后的运动模型。 + - Python dtype: MotionModelGroup + +## Usage tips +- Infra type: GPU +- Common nodes: unknown + +## Source code +```python +class ApplyAnimateDiffModelBasicNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "motion_model": ("MOTION_MODEL_ADE",), + }, + "optional": { + "motion_lora": ("MOTION_LORA",), + "scale_multival": ("MULTIVAL",), + "effect_multival": ("MULTIVAL",), + "ad_keyframes": ("AD_KEYFRAMES",), + } + } + + RETURN_TYPES = ("M_MODELS",) + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②" + FUNCTION = "apply_motion_model" + + def apply_motion_model(self, + motion_model: MotionModelPatcher, motion_lora: MotionLoraList=None, + scale_multival=None, effect_multival=None, ad_keyframes=None): + # just a subset of normal ApplyAnimateDiffModelNode inputs + return ApplyAnimateDiffModelNode.apply_motion_model(self, motion_model, motion_lora=motion_lora, + scale_multival=scale_multival, effect_multival=effect_multival, + ad_keyframes=ad_keyframes) \ No newline at end of file diff --git a/docs/ADE_ApplyAnimateDiffModelWithCameraCtrl.md b/docs/ADE_ApplyAnimateDiffModelWithCameraCtrl.md new file mode 100644 index 0000000..d6d38e2 --- /dev/null +++ b/docs/ADE_ApplyAnimateDiffModelWithCameraCtrl.md @@ -0,0 +1,106 @@ +# Apply AnimateDiff+CameraCtrl Model 🎭🅐🅓② +## Documentation +- Class name: ADE_ApplyAnimateDiffModelWithCameraCtrl +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点将AnimateDiff模型与摄像机控制相结合,集成运动模型调整和摄像机控制参数以生成动画序列。它利用摄像机控制姿势和其他动画参数来增强AnimateDiff模型的输出,提供更具动态性和可定制的动画体验。 + +## Input types +### Required +- motion_model + - 要进行动画处理的运动模型,结合AnimateDiff模型的功能和摄像机控制特性以增强动画。 + - Comfy dtype: MOTION_MODEL_ADE + - Python dtype: MotionModelPatcher +- cameractrl_poses + - 摄像机控制姿势列表,每个姿势定义动画过程中的特定摄像机位置和方向。 + - Comfy dtype: CAMERACTRL_POSES + - Python dtype: list[list[float]] +- start_percent + - 动画的起始百分比,作为总动画长度的一部分,允许实现部分动画。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - 动画的结束百分比,作为总动画长度的一部分,允许自定义动画的持续时间。 + - Comfy dtype: FLOAT + - Python dtype: float + +### Optional +- motion_lora + - 可选参数,用于指定运动LoRA设置,以进一步自定义动画。 + - Comfy dtype: MOTION_LORA + - Python dtype: MotionLoraList +- scale_multival + - 可选参数,用于应用比例乘数,影响动画元素的整体大小。 + - Comfy dtype: MULTIVAL + - Python dtype: dict +- effect_multival + - 可选参数,用于应用效果乘数,允许在动画中添加其他视觉效果。 + - Comfy dtype: MULTIVAL + - Python dtype: dict +- cameractrl_multival + - 可选参数,用于应用多个摄像机控制值,增强动画中的动态摄像机运动。 + - Comfy dtype: MULTIVAL + - Python dtype: dict +- ad_keyframes + - 可选参数,用于定义动画中的关键帧,允许对动画序列进行精确控制。 + - Comfy dtype: AD_KEYFRAMES + - Python dtype: ADKeyframeGroup +- prev_m_models + - 可选参数,用于整合先前生成的运动模型,促进顺序或分层动画。 + - Comfy dtype: M_MODELS + - Python dtype: MotionModelGroup + +## Output types +- m_models + - Comfy dtype: M_MODELS + - 应用AnimateDiff模型和摄像机控制后生成的运动模型,包括任何指定的动画和效果。 + - Python dtype: MotionModelGroup + +## Usage tips +- Infra type: GPU +- Common nodes: unknown + +## Source code +```python +class ApplyAnimateDiffWithCameraCtrl: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "motion_model": ("MOTION_MODEL_ADE",), + "cameractrl_poses": ("CAMERACTRL_POSES",), + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}), + }, + "optional": { + "motion_lora": ("MOTION_LORA",), + "scale_multival": ("MULTIVAL",), + "effect_multival": ("MULTIVAL",), + "cameractrl_multival": ("MULTIVAL",), + "ad_keyframes": ("AD_KEYFRAMES",), + "prev_m_models": ("M_MODELS",), + } + } + + RETURN_TYPES = ("M_MODELS",) + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl" + FUNCTION = "apply_motion_model" + + def apply_motion_model(self, motion_model: MotionModelPatcher, cameractrl_poses: list[list[float]], start_percent: float=0.0, end_percent: float=1.0, + motion_lora: MotionLoraList=None, ad_keyframes: ADKeyframeGroup=None, + scale_multival=None, effect_multival=None, cameractrl_multival=None, + prev_m_models: MotionModelGroup=None,): + new_m_models = ApplyAnimateDiffModelNode.apply_motion_model(self, motion_model, start_percent=start_percent, end_percent=end_percent, + motion_lora=motion_lora, ad_keyframes=ad_keyframes, + scale_multival=scale_multival, effect_multival=effect_multival, prev_m_models=prev_m_models) + # most recent added model will always be first in list; + curr_model = new_m_models[0].models[0] + # confirm that model contains camera_encoder + if curr_model.model.camera_encoder is None: + raise Exception(f"Motion model '{curr_model.model.mm_info.mm_name}' does not contain a camera_encoder; cannot be used with Apply AnimateDiff-CameraCtrl Model node.") + camera_entries = [CameraEntry(entry) for entry in cameractrl_poses] + curr_model.orig_camera_entries = camera_entries + curr_model.cameractrl_multival = cameractrl_multival + return new_m_models \ No newline at end of file diff --git a/docs/ADE_ApplyAnimateLCMI2VModel.md b/docs/ADE_ApplyAnimateLCMI2VModel.md new file mode 100644 index 0000000..da7bbcd --- /dev/null +++ b/docs/ADE_ApplyAnimateLCMI2VModel.md @@ -0,0 +1,111 @@ +# Apply AnimateLCM-I2V Model 🎭🅐🅓② +## Documentation +- Class name: ADE_ApplyAnimateLCMI2VModel +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在应用AnimateLCM-I2V模型,通过I2V(图像到视频)功能使用潜在代码运动推理来动画化图像。它集成了运动模型和关键帧组,从静态图像生成动态动画视觉效果,并根据指定参数增强其运动和效果。 + +## Input types +### Required +- motion_model + - 运动模型参数对于定义将应用于静态图像的运动特性和动态至关重要。它影响节点的执行,通过确定将引入的动画和运动效果类型来发挥作用。 + - Comfy dtype: MOTION_MODEL_ADE + - Python dtype: MotionModelPatcher +- ref_latent + - 该参数保存要动画化的图像的参考潜在表示。它对于在应用运动效果时保持图像的原始特性至关重要。 + - Comfy dtype: LATENT + - Python dtype: dict +- ref_drift + - 指定在应用运动时偏离原始图像特性的程度,允许动画输出的微妙或显著变化。 + - Comfy dtype: FLOAT + - Python dtype: float +- apply_ref_when_disabled + - 确定即使在禁用运动模型时是否应用参考特性(如漂移),以确保动画过程的连续性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- start_percent + - 定义动画在运动模型时间线中的起始点,允许精确控制动画效果的开始时间。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - 设置动画在运动模型时间线中的结束点,允许自定义动画的持续时间和结尾。 + - Comfy dtype: FLOAT + - Python dtype: float + +### Optional +- motion_lora + - 一组运动特定的LoRA设置,可以应用于进一步自定义动画效果和动态。 + - Comfy dtype: MOTION_LORA + - Python dtype: MotionLoraList +- scale_multival + - 缩放效果的乘数,提供对动画元素大小和比例的额外控制。 + - Comfy dtype: MULTIVAL + - Python dtype: Optional[List[float]] +- effect_multival + - 各种效果的乘数,提供进一步自定义动画视觉外观和动态的能力。 + - Comfy dtype: MULTIVAL + - Python dtype: Optional[List[float]] +- ad_keyframes + - 指定一个关键帧组以进行高级动画控制,允许详细自定义随时间变化的运动和效果。 + - Comfy dtype: AD_KEYFRAMES + - Python dtype: ADKeyframeGroup +- prev_m_models + - 先前应用的运动模型组,使节点能够基于现有动画进行构建或修改,以增强或改变效果。 + - Comfy dtype: M_MODELS + - Python dtype: MotionModelGroup + +## Output types +- m_models + - Comfy dtype: M_MODELS + - 更新的运动模型列表,包括最新应用的带有其配置动画和效果的模型。 + - Python dtype: MotionModelGroup + +## Usage tips +- Infra type: GPU +- Common nodes: unknown + +## Source code +```python +class ApplyAnimateLCMI2VModel: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "motion_model": ("MOTION_MODEL_ADE",), + "ref_latent": ("LATENT",), + "ref_drift": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 10.0, "step": 0.001}), + "apply_ref_when_disabled": ("BOOLEAN", {"default": False}), + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}), + }, + "optional": { + "motion_lora": ("MOTION_LORA",), + "scale_multival": ("MULTIVAL",), + "effect_multival": ("MULTIVAL",), + "ad_keyframes": ("AD_KEYFRAMES",), + "prev_m_models": ("M_MODELS",), + } + } + + RETURN_TYPES = ("M_MODELS",) + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V" + FUNCTION = "apply_motion_model" + + def apply_motion_model(self, motion_model: MotionModelPatcher, ref_latent: dict, ref_drift: float=0.0, apply_ref_when_disabled=False, start_percent: float=0.0, end_percent: float=1.0, + motion_lora: MotionLoraList=None, ad_keyframes: ADKeyframeGroup=None, + scale_multival=None, effect_multival=None, + prev_m_models: MotionModelGroup=None,): + new_m_models = ApplyAnimateDiffModelNode.apply_motion_model(self, motion_model, start_percent=start_percent, end_percent=end_percent, + motion_lora=motion_lora, ad_keyframes=ad_keyframes, + scale_multival=scale_multival, effect_multival=effect_multival, prev_m_models=prev_m_models) + # most recent added model will always be first in list; + curr_model = new_m_models[0].models[0] + # confirm that model contains img_encoder + if curr_model.model.img_encoder is None: + raise Exception(f"Motion model '{curr_model.model.mm_info.mm_name}' does not contain an img_encoder; cannot be used with Apply AnimateLCM-I2V Model node.") + curr_model.orig_img_latents = ref_latent["samples"] + curr_model.orig_ref_drift = ref_drift + curr_model.orig_apply_ref_when_disabled = apply_ref_when_disabled + return new_m_models \ No newline at end of file diff --git a/docs/ADE_AttachLoraHookToCLIP.md b/docs/ADE_AttachLoraHookToCLIP.md new file mode 100644 index 0000000..e29a1af --- /dev/null +++ b/docs/ADE_AttachLoraHookToCLIP.md @@ -0,0 +1,51 @@ +# Set CLIP LoRA Hook 🎭🅐🅓 +## Documentation +- Class name: ADE_AttachLoraHookToCLIP +- Category: Animate Diff 🎭🅐🅓/conditioning +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在将LoRA挂钩附加到CLIP模型上,通过集成额外的计算层或修改来增强其功能。它作为CLIP模型的定制点,允许进行定制调整以影响模型的行为或输出。 + +## Input types +### Required +- clip + - 要附加LoRA挂钩的CLIP模型。此参数至关重要,因为它决定了将被修改的基础模型。 + - Comfy dtype: CLIP + - Python dtype: CLIP +- lora_hook + - 要附加到CLIP模型的LoRA挂钩。此挂钩代表要应用的修改或增强,在定制模型功能中起关键作用。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup + +## Output types +- hook_CLIP + - Comfy dtype: CLIP + - 附加了LoRA挂钩的修改后CLIP模型,代表原始模型的增强版本。 + - Python dtype: CLIPWithHooks + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class SetClipLoraHook: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "clip": ("CLIP",), + "lora_hook": ("LORA_HOOK",), + } + } + + RETURN_TYPES = ("CLIP",) + RETURN_NAMES = ("hook_CLIP",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning" + FUNCTION = "apply_lora_hook" + + def apply_lora_hook(self, clip: CLIP, lora_hook: LoraHookGroup): + new_clip = CLIPWithHooks(clip) + new_clip.set_desired_hooks(lora_hooks=lora_hook) + return (new_clip, ) \ No newline at end of file diff --git a/docs/ADE_AttachLoraHookToConditioning.md b/docs/ADE_AttachLoraHookToConditioning.md new file mode 100644 index 0000000..4d2ccbd --- /dev/null +++ b/docs/ADE_AttachLoraHookToConditioning.md @@ -0,0 +1,53 @@ +# Set Model LoRA Hook 🎭🅐🅓 +## Documentation +- Class name: ADE_AttachLoraHookToConditioning +- Category: Animate Diff 🎭🅐🅓/conditioning/single cond ops +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在将LoRA挂钩附加到条件数据上,从而根据指定的LoRA挂钩动态修改模型行为。它在生成模型的条件过程中,尤其是在动画和差分渲染的背景下,起着定制和控制的关键作用。 + +## Input types +### Required +- conditioning + - 要附加LoRA挂钩的条件数据。此数据决定了模型的行为和输出,附加LoRA挂钩可以进行动态调整。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[Any, Dict[str, Any]]] +- lora_hook + - 要附加到条件数据的LoRA挂钩。此挂钩使得在运行时修改模型参数成为可能,从而增强了对生成过程的控制和定制。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup + +## Output types +- conditioning + - Comfy dtype: CONDITIONING + - 附加了LoRA挂钩的修改后条件数据,使得模型行为可以动态调整。 + - Python dtype: List[Tuple[Any, Dict[str, Any]]] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class SetModelLoraHook: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "conditioning": ("CONDITIONING",), + "lora_hook": ("LORA_HOOK",), + } + } + + RETURN_TYPES = ("CONDITIONING",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/single cond ops" + FUNCTION = "attach_lora_hook" + + def attach_lora_hook(self, conditioning, lora_hook: LoraHookGroup): + c = [] + for t in conditioning: + n = [t[0], t[1].copy()] + n[1]["lora_hook"] = lora_hook + c.append(n) + return (c, ) \ No newline at end of file diff --git a/docs/ADE_CameraCtrlAnimateDiffKeyframe.md b/docs/ADE_CameraCtrlAnimateDiffKeyframe.md new file mode 100644 index 0000000..8f103df --- /dev/null +++ b/docs/ADE_CameraCtrlAnimateDiffKeyframe.md @@ -0,0 +1,86 @@ +# AnimateDiff+CameraCtrl Keyframe 🎭🅐🅓 +## Documentation +- Class name: ADE_CameraCtrlAnimateDiffKeyframe +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在生成和管理包含摄像机控制的动画关键帧,从而在AnimateDiff框架内创建动态和复杂的摄像机运动。它允许指定动画的起始百分比,应用多值进行缩放、效果和摄像机控制,并继承缺失值以确保关键帧之间的连续性。 + +## Input types +### Required +- start_percent + - 指定动画的起始百分比,允许精确控制动画中摄像机运动和效果的时间。 + - Comfy dtype: FLOAT + - Python dtype: float + +### Optional +- prev_ad_keyframes + - 可选。允许包括先前定义的AnimateDiff关键帧,使动画可以进行更复杂的序列链和层叠。 + - Comfy dtype: AD_KEYFRAMES + - Python dtype: ADKeyframeGroup or None +- scale_multival + - 可选。应用缩放因子到动画,允许调整动画元素的大小。 + - Comfy dtype: MULTIVAL + - Python dtype: float or torch.Tensor +- effect_multival + - 可选。应用各种效果到动画,允许添加视觉增强或修改。 + - Comfy dtype: MULTIVAL + - Python dtype: float or torch.Tensor +- cameractrl_multival + - 可选。指定摄像机控制的多个值,允许在动画中创建复杂的摄像机运动。 + - Comfy dtype: MULTIVAL + - Python dtype: float or torch.Tensor +- inherit_missing + - 确定当前关键帧中的缺失值是否应继承自前面的关键帧,以确保动画的连续性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- guarantee_steps + - 指定动画中保证的最小步数,确保一定程度的平滑和连续性。 + - Comfy dtype: INT + - Python dtype: int + +## Output types +- ad_keyframes + - Comfy dtype: AD_KEYFRAMES + - 生成一系列AnimateDiff关键帧,使动画具有复杂的摄像机运动。 + - Python dtype: ADKeyframeGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CameraCtrlADKeyframeNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}, ), + }, + "optional": { + "prev_ad_keyframes": ("AD_KEYFRAMES", ), + "scale_multival": ("MULTIVAL",), + "effect_multival": ("MULTIVAL",), + "cameractrl_multival": ("MULTIVAL",), + "inherit_missing": ("BOOLEAN", {"default": True}, ), + "guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}), + } + } + + RETURN_TYPES = ("AD_KEYFRAMES", ) + FUNCTION = "load_keyframe" + + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl" + + def load_keyframe(self, + start_percent: float, prev_ad_keyframes=None, + scale_multival: Union[float, torch.Tensor]=None, effect_multival: Union[float, torch.Tensor]=None, + cameractrl_multival: Union[float, torch.Tensor]=None, + inherit_missing: bool=True, guarantee_steps: int=1): + return ADKeyframeNode.load_keyframe(self, + start_percent=start_percent, prev_ad_keyframes=prev_ad_keyframes, + scale_multival=scale_multival, effect_multival=effect_multival, cameractrl_multival=cameractrl_multival, + inherit_missing=inherit_missing, guarantee_steps=guarantee_steps + ) \ No newline at end of file diff --git a/docs/ADE_CameraManualPoseAppend.md b/docs/ADE_CameraManualPoseAppend.md new file mode 100644 index 0000000..1d82720 --- /dev/null +++ b/docs/ADE_CameraManualPoseAppend.md @@ -0,0 +1,48 @@ +# Manual Append CameraCtrl Poses 🎭🅐🅓② +## Documentation +- Class name: ADE_CameraManualPoseAppend +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_CameraManualPoseAppend节点用于手动追加摄像机控制姿势,允许在动画中自定义和扩展摄像机运动。此节点有助于集成用户定义的摄像机姿势,增强动画项目中动态视觉叙事的能力。 + +## Input types +### Required +- poses_first + - 指定要追加的初始摄像机控制姿势集。它在确定摄像机运动的起点方面起着关键作用。 + - Comfy dtype: CAMERACTRL_POSES + - Python dtype: list[list[float]] +- poses_last + - 定义要追加的最终摄像机控制姿势集。它决定摄像机运动的终点,允许摄像机状态之间的无缝过渡。 + - Comfy dtype: CAMERACTRL_POSES + - Python dtype: list[list[float]] + +## Output types +- cameractrl_poses + - Comfy dtype: CAMERACTRL_POSES + - 输出组合的摄像机控制姿势集,表示初始和最终姿势的无缝集成,以实现动画中动态摄像机运动。 + - Python dtype: list[list[float]] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CameraCtrlManualAppendPose: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "poses_first": ("CAMERACTRL_POSES",), + "poses_last": ("CAMERACTRL_POSES",), + } + } + + RETURN_TYPES = ("CAMERACTRL_POSES",) + FUNCTION = "camera_manual_append" + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses" + + def camera_manual_append(self, poses_first: list[list[float]], poses_last: list[list[float]]): + return (combine_poses(poses0=poses_first, poses1=poses_last),) \ No newline at end of file diff --git a/docs/ADE_CameraPoseAdvanced.md b/docs/ADE_CameraPoseAdvanced.md new file mode 100644 index 0000000..f6b128b --- /dev/null +++ b/docs/ADE_CameraPoseAdvanced.md @@ -0,0 +1,127 @@ +# Create CameraCtrl Poses (Adv.) 🎭🅐🅓② +## Documentation +- Class name: ADE_CameraPoseAdvanced +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_CameraPoseAdvanced节点旨在为动画创建高级摄像机控制姿势。它允许组合多种运动类型和强度,以生成复杂的摄像机运动,增强动画序列中的动态视觉叙事。 + +## Input types +### Required +- motion_type1 + - 指定要应用的第一种摄像机运动类型,影响整体摄像机运动及其对动画的视觉影响。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength1 + - 指定第一种运动类型的强度乘数,调整摄像机运动的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- motion_type2 + - 定义第二种摄像机运动类型,有助于增加摄像机路径的复杂性和深度。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength2 + - 定义第二种运动类型的强度乘数,修改摄像机路径的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- motion_type3 + - 指示第三种摄像机运动类型,为摄像机轨迹增加另一层运动。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength3 + - 指示第三种运动类型的强度乘数,改变摄像机运动的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- motion_type4 + - 指定第四种摄像机运动类型,进一步丰富摄像机的运动及其对场景的影响。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength4 + - 指定第四种运动类型的强度乘数,影响摄像机轨迹的深度。 + - Comfy dtype: FLOAT + - Python dtype: float +- motion_type5 + - 定义第五种摄像机运动类型,通过额外的运动细微差别增强动画。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength5 + - 定义第五种运动类型的强度乘数,影响摄像机运动的细微差别。 + - Comfy dtype: FLOAT + - Python dtype: float +- motion_type6 + - 指示第六种摄像机运动类型,完成复杂摄像机控制的运动集。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength6 + - 指示第六种运动类型的强度乘数,微调摄像机运动的复杂性。 + - Comfy dtype: FLOAT + - Python dtype: float +- speed + - 控制摄像机运动的速度,影响摄像机在姿势之间过渡的快慢。 + - Comfy dtype: FLOAT + - Python dtype: float +- frame_length + - 确定应用摄像机运动的帧数,定义运动的持续时间。 + - Comfy dtype: INT + - Python dtype: int + +### Optional +- prev_poses + - 可选。可以与新运动结合的先前摄像机姿势,以实现动画中的无缝过渡。 + - Comfy dtype: CAMERACTRL_POSES + - Python dtype: list[list[float]] + +## Output types +- cameractrl_poses + - Comfy dtype: CAMERACTRL_POSES + - 生成的摄像机控制姿势,代表指定运动和参数对摄像机在动画中路径的综合效果。 + - Python dtype: list[list[float]] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CameraCtrlPoseAdvanced: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "motion_type1": (CAM._LIST,), + "strength1": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "motion_type2": (CAM._LIST,), + "strength2": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "motion_type3": (CAM._LIST,), + "strength3": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "motion_type4": (CAM._LIST,), + "strength4": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "motion_type5": (CAM._LIST,), + "strength5": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "motion_type6": (CAM._LIST,), + "strength6": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "speed": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01}), + "frame_length": ("INT", {"default": 16}), + }, + "optional": { + "prev_poses": ("CAMERACTRL_POSES",), + } + } + + RETURN_TYPES = ("CAMERACTRL_POSES",) + FUNCTION = "camera_pose_combo" + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses" + + def camera_pose_combo(self, + motion_type1: str, motion_type2: str, motion_type3: str, + motion_type4: str, motion_type5: str, motion_type6: str, + speed: float, frame_length: int, + prev_poses: list[list[float]]=None, + strength1=1.0, strength2=1.0, strength3=1.0, strength4=1.0, strength5=1.0, strength6=1.0): + return CameraCtrlPoseCombo.camera_pose_combo(self, + motion_type1=motion_type1, motion_type2=motion_type2, motion_type3=motion_type3, + motion_type4=motion_type4, motion_type5=motion_type5, motion_type6=motion_type6, + speed=speed, frame_length=frame_length, prev_poses=prev_poses, + strength1=strength1, strength2=strength2, strength3=strength3, + strength4=strength4, strength5=strength5, strength6=strength6) \ No newline at end of file diff --git a/docs/ADE_CameraPoseBasic.md b/docs/ADE_CameraPoseBasic.md new file mode 100644 index 0000000..6cb6380 --- /dev/null +++ b/docs/ADE_CameraPoseBasic.md @@ -0,0 +1,67 @@ +# Create CameraCtrl Poses 🎭🅐🅓② +## Documentation +- Class name: ADE_CameraPoseBasic +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在根据指定的运动类型、速度和帧长创建基本的摄像机控制姿势。它允许生成可用于控制摄像机在3D环境中的运动和方向的姿势,从而实现动态和可定制的动画。 + +## Input types +### Required +- motion_type + - 指定要应用于摄像机的运动类型,影响摄像机运动的方向和性质。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- speed + - 确定摄像机移动的速度,允许控制动画的节奏。 + - Comfy dtype: FLOAT + - Python dtype: float +- frame_length + - 定义应用摄像机运动的帧数,设置摄像机运动的持续时间。 + - Comfy dtype: INT + - Python dtype: int + +### Optional +- prev_poses + - 可选。提供先前的摄像机姿势,以与新生成的姿势结合,实现动画之间的无缝过渡。 + - Comfy dtype: CAMERACTRL_POSES + - Python dtype: list[list[float]] + +## Output types +- cameractrl_poses + - Comfy dtype: CAMERACTRL_POSES + - 输出生成的摄像机控制姿势,准备用于动画。 + - Python dtype: list[list[float]] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CameraCtrlPoseBasic: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "motion_type": (CAM._LIST,), + "speed": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01}), + "frame_length": ("INT", {"default": 16}), + }, + "optional": { + "prev_poses": ("CAMERACTRL_POSES",), + } + } + + RETURN_TYPES = ("CAMERACTRL_POSES",) + FUNCTION = "camera_pose_basic" + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses" + + def camera_pose_basic(self, motion_type: str, speed: float, frame_length: int, prev_poses: list[list[float]]=None): + motion = CAM.get(motion_type) + RT = get_camera_motion(motion.rotate, motion.translate, speed, frame_length) + new_motion = ndarray_to_poses(RT=RT) + if prev_poses is not None: + new_motion = combine_poses(prev_poses, new_motion) + return (new_motion,) \ No newline at end of file diff --git a/docs/ADE_CameraPoseCombo.md b/docs/ADE_CameraPoseCombo.md new file mode 100644 index 0000000..6dffa65 --- /dev/null +++ b/docs/ADE_CameraPoseCombo.md @@ -0,0 +1,100 @@ +# Create CameraCtrl Poses (Combo) 🎭🅐🅓② +## Documentation +- Class name: ADE_CameraPoseCombo +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_CameraPoseCombo节点旨在通过组合多种运动类型及其相应的强度来创建复杂的摄像机控制姿势。它允许在动画序列中自定义摄像机运动,从而生成动态且细致的摄像机行为。 + +## Input types +### Required +- motion_type1 + - 指定要包含在组合中的第一种摄像机运动类型。每种运动类型都对整体摄像机运动模式有所贡献。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- motion_type2 + - 指定要包含在组合中的第二种摄像机运动类型,增加摄像机运动的复杂性。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- motion_type3 + - 指定第三种摄像机运动类型,进一步丰富摄像机的运动模式。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- motion_type4 + - 指定第四种摄像机运动类型,对摄像机运动的多样性有所贡献。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- motion_type5 + - 指定第五种摄像机运动类型,为摄像机运动的复杂性增加另一层。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- motion_type6 + - 指定第六种摄像机运动类型,完成综合摄像机控制的运动集。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- speed + - 控制摄像机运动的速度,影响摄像机在姿势之间过渡的快慢。 + - Comfy dtype: FLOAT + - Python dtype: float +- frame_length + - 确定摄像机运动发生的帧数,定义动画的持续时间。 + - Comfy dtype: INT + - Python dtype: int + +### Optional +- prev_poses + - 可选。可以与新运动结合的先前摄像机姿势,以实现动画中的无缝过渡。此输入对于创建流畅且连续的摄像机运动至关重要,尤其是在需要保持叙述或视觉连续性的场景中。 + - Comfy dtype: CAMERACTRL_POSES + - Python dtype: list[list[float]] + +## Output types +- cameractrl_poses + - Comfy dtype: CAMERACTRL_POSES + - 组合指定的运动和强度后生成的摄像机控制姿势,准备用于动画。 + - Python dtype: list[list[float]] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CameraCtrlPoseCombo: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "motion_type1": (CAM._LIST,), + "motion_type2": (CAM._LIST,), + "motion_type3": (CAM._LIST,), + "motion_type4": (CAM._LIST,), + "motion_type5": (CAM._LIST,), + "motion_type6": (CAM._LIST,), + "speed": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01}), + "frame_length": ("INT", {"default": 16}), + }, + "optional": { + "prev_poses": ("CAMERACTRL_POSES",), + } + } + + RETURN_TYPES = ("CAMERACTRL_POSES",) + FUNCTION = "camera_pose_combo" + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses" + + def camera_pose_combo(self, + motion_type1: str, motion_type2: str, motion_type3: str, + motion_type4: str, motion_type5: str, motion_type6: str, + speed: float, frame_length: int, + prev_poses: list[list[float]]=None, + strength1=1.0, strength2=1.0, strength3=1.0, strength4=1.0, strength5=1.0, strength6=1.0): + combined_motion = CameraMotion.combine([ + CAM.get(motion_type1).multiply(strength1), CAM.get(motion_type2).multiply(strength2), CAM.get(motion_type3).multiply(strength3), + CAM.get(motion_type4).multiply(strength4), CAM.get(motion_type5).multiply(strength5), CAM.get(motion_type6).multiply(strength6) + ]) + RT = get_camera_motion(combined_motion.rotate, combined_motion.translate, speed, frame_length) + new_motion = ndarray_to_poses(RT=RT) + if prev_poses is not None: + new_motion = combine_poses(prev_poses, new_motion) + return (new_motion,) \ No newline at end of file diff --git a/docs/ADE_CombineLoraHooks.md b/docs/ADE_CombineLoraHooks.md new file mode 100644 index 0000000..9d5723b --- /dev/null +++ b/docs/ADE_CombineLoraHooks.md @@ -0,0 +1,52 @@ +# Combine LoRA Hooks [2] 🎭🅐🅓 +## Documentation +- Class name: ADE_CombineLoraHooks +- Category: Animate Diff 🎭🅐🅓/conditioning/combine lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在将多个LoRA挂钩组聚合成一个统一的LoRA挂钩组。它有助于组合各种LoRA挂钩,通过整合每个单独挂钩提供的不同修改或增强,实现更复杂和细致的模型条件。 + +## Input types +### Required +### Optional +- lora_hook_A + - 表示要组合的第一个LoRA挂钩组。在聚合过程中起关键作用,贡献其修改或增强到最终的统一LoRA挂钩组。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_B + - 表示要组合的第二个LoRA挂钩组。贡献其独特的修改或增强到统一LoRA挂钩组,丰富整体的条件效果。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup + +## Output types +- lora_hook + - Comfy dtype: LORA_HOOK + - 输出是一个统一的LoRA挂钩组,结合了输入LoRA挂钩组的修改或增强。此聚合挂钩有助于更复杂的模型条件。 + - Python dtype: LoraHookGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CombineLoraHooks: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + }, + "optional": { + "lora_hook_A": ("LORA_HOOK",), + "lora_hook_B": ("LORA_HOOK",), + } + } + + RETURN_TYPES = ("LORA_HOOK",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/combine lora hooks" + FUNCTION = "combine_lora_hooks" + + def combine_lora_hooks(self, lora_hook_A: LoraHookGroup=None, lora_hook_B: LoraHookGroup=None): + candidates = [lora_hook_A, lora_hook_B] + return (LoraHookGroup.combine_all_lora_hooks(candidates),) \ No newline at end of file diff --git a/docs/ADE_CombineLoraHooksEight.md b/docs/ADE_CombineLoraHooksEight.md new file mode 100644 index 0000000..8c7a9ab --- /dev/null +++ b/docs/ADE_CombineLoraHooksEight.md @@ -0,0 +1,87 @@ +# Combine LoRA Hooks [8] 🎭🅐🅓 +## Documentation +- Class name: ADE_CombineLoraHooksEight +- Category: Animate Diff 🎭🅐🅓/conditioning/combine lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在将多达八个LoRA挂钩组合成一个统一的LoRA挂钩组。它有助于整合多个LoRA挂钩的修改,允许在生成任务中对模型行为进行更复杂和细致的调整。 + +## Input types +### Required +### Optional +- lora_hook_A + - 表示要组合的第一个LoRA挂钩组。在聚合过程中起基础性作用,为组合后的LoRA挂钩组设定初始条件。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_B + - 表示要组合的第二个LoRA挂钩组。其包含的修改扩大了组合后LoRA挂钩组的能力和修改范围。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_C + - 作为组合过程中的第三个LoRA挂钩组,贡献了额外的修改,进一步丰富了组合后LoRA挂钩组的功能。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_D + - 表示要组合的第四个LoRA挂钩组,增加了组合后LoRA挂钩组中的修改多样性。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_E + - 作为组合过程中的第五个LoRA挂钩组,通过引入更多细微调整增强了组合后LoRA挂钩组。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_F + - 表示要组合的第六个LoRA挂钩组,其包含的修改拓宽了组合后LoRA挂钩组的范围。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_G + - 作为组合过程中的第七个LoRA挂钩组,增加了组合后LoRA挂钩组中的复杂性和深度。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_H + - 作为第八个也是最后一个要组合的LoRA挂钩组,完成了聚合,最大化了组合后LoRA挂钩组中的修改和调整。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup + +## Output types +- lora_hook + - Comfy dtype: LORA_HOOK + - 组合多达八个LoRA挂钩后的统一LoRA挂钩组。此组合组能够对模型行为应用一整套全面的修改。 + - Python dtype: LoraHookGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CombineLoraHookEightOptional: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + }, + "optional": { + "lora_hook_A": ("LORA_HOOK",), + "lora_hook_B": ("LORA_HOOK",), + "lora_hook_C": ("LORA_HOOK",), + "lora_hook_D": ("LORA_HOOK",), + "lora_hook_E": ("LORA_HOOK",), + "lora_hook_F": ("LORA_HOOK",), + "lora_hook_G": ("LORA_HOOK",), + "lora_hook_H": ("LORA_HOOK",), + } + } + + RETURN_TYPES = ("LORA_HOOK",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/combine lora hooks" + FUNCTION = "combine_lora_hooks" + + def combine_lora_hooks(self, + lora_hook_A: LoraHookGroup=None, lora_hook_B: LoraHookGroup=None, + lora_hook_C: LoraHookGroup=None, lora_hook_D: LoraHookGroup=None, + lora_hook_E: LoraHookGroup=None, lora_hook_F: LoraHookGroup=None, + lora_hook_G: LoraHookGroup=None, lora_hook_H: LoraHookGroup=None): + candidates = [lora_hook_A, lora_hook_B, lora_hook_C, lora_hook_D, + lora_hook_E, lora_hook_F, lora_hook_G, lora_hook_H] + return (LoraHookGroup.combine_all_lora_hooks(candidates),) \ No newline at end of file diff --git a/docs/ADE_CombineLoraHooksFour.md b/docs/ADE_CombineLoraHooksFour.md new file mode 100644 index 0000000..228e36f --- /dev/null +++ b/docs/ADE_CombineLoraHooksFour.md @@ -0,0 +1,63 @@ +# Combine LoRA Hooks [4] 🎭🅐🅓 +## Documentation +- Class name: ADE_CombineLoraHooksFour +- Category: Animate Diff 🎭🅐🅓/conditioning/combine lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在聚合和组合多达四个LoRA挂钩成一个统一的LoRA挂钩组。它有助于整合多个LoRA挂钩的修改,允许在Animate Diff框架中对模型行为进行更复杂和细致的调整。 + +## Input types +### Required +### Optional +- lora_hook_A + - 表示要组合的第一个LoRA挂钩组。在聚合过程中起关键作用,贡献整体修改。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_B + - 作为组合的第二个LoRA挂钩组。其包含的修改允许进行层叠,增强模型的适应性。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_C + - 第三个LoRA挂钩组,增加了另一层定制,进一步优化了模型行为。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- lora_hook_D + - 表示第四个也是最后一个要组合的LoRA挂钩组,完成了修改集,使模型能够进行全面调整。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup + +## Output types +- lora_hook + - Comfy dtype: LORA_HOOK + - 组合多达四个LoRA挂钩后的统一组。此组合挂钩组允许增强和更复杂的模型条件。 + - Python dtype: LoraHookGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CombineLoraHookFourOptional: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + }, + "optional": { + "lora_hook_A": ("LORA_HOOK",), + "lora_hook_B": ("LORA_HOOK",), + "lora_hook_C": ("LORA_HOOK",), + "lora_hook_D": ("LORA_HOOK",), + } + } + + RETURN_TYPES = ("LORA_HOOK",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/combine lora hooks" + FUNCTION = "combine_lora_hooks" + + def combine_lora_hooks(self, + lora_hook_A: LoraHookGroup=None, lora_hook_B: LoraHookGroup=None, + lora_hook_C: LoraHookGroup=None, lora_hook_D: LoraHookGroup=None,): + candidates = [lora_hook_A, lora_hook_B, lora_hook_C, lora_hook_D] \ No newline at end of file diff --git a/docs/ADE_ConditioningSetMask.md b/docs/ADE_ConditioningSetMask.md new file mode 100644 index 0000000..fcb8d47 --- /dev/null +++ b/docs/ADE_ConditioningSetMask.md @@ -0,0 +1,77 @@ +# Set Props on Cond 🎭🅐🅓 +## Documentation +- Class name: ADE_ConditioningSetMask +- Category: Animate Diff 🎭🅐🅓/conditioning/single cond ops +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在将掩码应用于条件数据,根据指定参数调整条件的区域和强度。它使得条件输入的动态修改成为可能,以更好地符合预期结果,如关注或排除数据中的特定区域。 + +## Input types +### Required +- cond_ADD + - 要添加或修改的条件数据。此参数对于在现有条件框架中引入新的上下文或内容至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Tensor +- strength + - 定义掩码对条件数据影响的强度,允许对修改影响进行精细控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- set_cond_area + - 确定掩码效果是应用于默认区域还是掩码的边界,提供在特定区域进行定位的灵活性。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +### Optional +- opt_mask + - 一个可选掩码,指定要修改的条件数据区域,提供对条件影响的额外控制。 + - Comfy dtype: MASK + - Python dtype: Tensor +- opt_lora_hook + - 一个可选参数,允许将Lora挂钩应用于条件,进一步定制条件过程。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- opt_timesteps + - 可选的时间步条件,允许对条件数据进行时间调整。 + - Comfy dtype: TIMESTEPS_COND + - Python dtype: TimestepsCond + +## Output types +- conditioning + - Comfy dtype: CONDITIONING + - 修改后的条件数据,反映了应用的掩码和调整,包括添加的任何额外条件数据。 + - Python dtype: Tensor + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class ConditioningSetMaskHooked: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "cond_ADD": ("CONDITIONING",), + "strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "set_cond_area": (COND_CONST._LIST_COND_AREA,), + }, + "optional": { + "opt_mask": ("MASK", ), + "opt_lora_hook": ("LORA_HOOK",), + "opt_timesteps": ("TIMESTEPS_COND",) + } + } + + RETURN_TYPES = ("CONDITIONING",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/single cond ops" + FUNCTION = "append_and_hook" + + def append_and_hook(self, cond_ADD, + strength: float, set_cond_area: str, + opt_mask: Tensor=None, opt_lora_hook: LoraHookGroup=None, opt_timesteps: TimestepsCond=None): + (final_conditioning,) = set_mask_conds(conds=[cond_ADD], + strength=strength, set_cond_area=set_cond_area, + opt_mask=opt_mask, opt_lora_hook=opt_lora_hook, opt_timesteps=opt_timesteps) + return (final_conditioning,) \ No newline at end of file diff --git a/docs/ADE_ConditioningSetMaskAndCombine.md b/docs/ADE_ConditioningSetMaskAndCombine.md new file mode 100644 index 0000000..7cdd864 --- /dev/null +++ b/docs/ADE_ConditioningSetMaskAndCombine.md @@ -0,0 +1,82 @@ +# Set Props and Combine Cond 🎭🅐🅓 +## Documentation +- Class name: ADE_ConditioningSetMaskAndCombine +- Category: Animate Diff 🎭🅐🅓/conditioning/single cond ops +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点专门用于生成模型的高级条件数据操作,特别关注掩码和附加条件层的应用和组合。它通过应用掩码、强度调整和整合新的条件数据来增强或修改现有条件,从而允许对生成过程进行更精确的控制。 + +## Input types +### Required +- cond + - 要增强或修改的原始条件数据。它作为应用附加条件层和掩码的基础,直接影响最终输出。 + - Comfy dtype: CONDITIONING + - Python dtype: CustomType[CONDITIONING] +- cond_ADD + - 要与原始条件结合的附加条件数据。此层应用于现有条件之上,允许引入新特性或修改。 + - Comfy dtype: CONDITIONING + - Python dtype: CustomType[CONDITIONING] +- strength + - 一个标量值,确定掩码应用于条件的强度。它控制附加条件和掩码对原始数据的影响程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- set_cond_area + - 指定在条件数据中进行修改的区域,而不提及特定类型。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +### Optional +- opt_mask + - 一个可选掩码,可以应用于条件数据。它允许选择性地增强或修改条件中的特定区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- opt_lora_hook + - 一个可选的LoraHookGroup,可以应用于进一步操作条件数据。它提供了修改条件的额外灵活性。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- opt_timesteps + - 用于条件操作的可选时间步。此参数允许在生成过程中的特定点应用修改。 + - Comfy dtype: TIMESTEPS_COND + - Python dtype: TimestepsCond + +## Output types +- conditioning + - Comfy dtype: CONDITIONING + - 应用附加条件层、掩码和调整后的增强或修改的条件数据。 + - Python dtype: CustomType[CONDITIONING] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class ConditioningSetMaskAndCombineHooked: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "cond": ("CONDITIONING",), + "cond_ADD": ("CONDITIONING",), + "strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "set_cond_area": (COND_CONST._LIST_COND_AREA,), + }, + "optional": { + "opt_mask": ("MASK", ), + "opt_lora_hook": ("LORA_HOOK",), + "opt_timesteps": ("TIMESTEPS_COND",) + } + } + + RETURN_TYPES = ("CONDITIONING",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/single cond ops" + FUNCTION = "append_and_combine" + + def append_and_combine(self, conditioning, conditioning_ADD, + strength: float, set_cond_area: str, + opt_mask: Tensor=None, opt_lora_hook: LoraHookGroup=None, opt_timesteps: TimestepsCond=None): + (final_conditioning,) = set_mask_and_combine_conds(conds=[conditioning], new_conds=[conditioning_ADD], + strength=strength, set_cond_area=set_cond_area, + opt_mask=opt_mask, opt_lora_hook=opt_lora_hook, opt_timesteps=opt_timesteps) + return (final_conditioning,) \ No newline at end of file diff --git a/docs/ADE_ConditioningSetUnmaskedAndCombine.md b/docs/ADE_ConditioningSetUnmaskedAndCombine.md new file mode 100644 index 0000000..a53ef9c --- /dev/null +++ b/docs/ADE_ConditioningSetUnmaskedAndCombine.md @@ -0,0 +1,60 @@ +# Set Unmasked Cond 🎭🅐🅓 +## Documentation +- Class name: ADE_ConditioningSetUnmaskedAndCombine +- Category: Animate Diff 🎭🅐🅓/conditioning/single cond ops +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点专门用于生成模型的高级条件数据操作,特别关注取消掩码和组合不同的条件输入集。它通过应用复杂的条件转换来增强或修改生成过程。 + +## Input types +### Required +- cond + - 作为转换基础的主要条件输入。它在决定生成过程的初始状态或上下文方面起着关键作用。 + - Comfy dtype: CONDITIONING + - Python dtype: list +- cond_DEFAULT + - 旨在与主要条件输入结合的附加条件输入。此输入通常代表修改或增强基础条件的默认或补充信息。 + - Comfy dtype: CONDITIONING + - Python dtype: list + +### Optional +- opt_lora_hook + - 一个可选参数,允许将Lora挂钩应用于条件输入,为条件过程提供进一步的定制和控制机制。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup + +## Output types +- conditioning + - Comfy dtype: CONDITIONING + - 结合并取消掩码提供的条件输入的结果,代表用于生成模型的修改或增强的条件状态。 + - Python dtype: list + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class ConditioningSetUnmaskedAndCombineHooked: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "cond": ("CONDITIONING",), + "cond_DEFAULT": ("CONDITIONING",), + }, + "optional": { + "opt_lora_hook": ("LORA_HOOK",), + } + } + + RETURN_TYPES = ("CONDITIONING",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/single cond ops" + FUNCTION = "append_and_combine" + + def append_and_combine(self, cond, cond_DEFAULT, + opt_lora_hook: LoraHookGroup=None): + (final_conditioning,) = set_unmasked_and_combine_conds(conds=[cond], new_conds=[cond_DEFAULT], + opt_lora_hook=opt_lora_hook) + return (final_conditioning,) \ No newline at end of file diff --git a/docs/ADE_CustomCFGKeyframe.md b/docs/ADE_CustomCFGKeyframe.md new file mode 100644 index 0000000..54cbd35 --- /dev/null +++ b/docs/ADE_CustomCFGKeyframe.md @@ -0,0 +1,69 @@ + +# Custom CFG Keyframe 🎭🅐🅓 +## Documentation +- Class name: ADE_CustomCFGKeyframe +- Category: Animate Diff 🎭🅐🅓/sample settings +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_CustomCFGKeyframe节点旨在创建和管理Animate Diff框架内的自定义配置关键帧。它允许在动画时间线上指定各种动画参数,从而精确控制动画的行为和外观。 + +## Input types +### Required +- cfg_multival + - 定义关键帧的配置值,可以影响动画过程的各个方面。对于在特定时间段定制动画特性至关重要。 + - Comfy dtype: MULTIVAL + - Python dtype: Union[float, torch.Tensor] +- start_percent + - 指定关键帧在动画时间线中的起始点,以百分比表示,允许精确的时间控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- guarantee_steps + - 确定应用关键帧配置的最小步数,确保一定的效果持续时间。 + - Comfy dtype: INT + - Python dtype: int + +### Optional +- prev_custom_cfg + - 通过指定先前的自定义配置组,允许自定义配置关键帧的链式连接,从而实现复杂的动画序列。 + - Comfy dtype: CUSTOM_CFG + - Python dtype: CustomCFGKeyframeGroup or None + +## Output types +- custom_cfg + - Comfy dtype: CUSTOM_CFG + - 输出一个封装了定义关键帧的自定义配置对象,准备集成到动画管道中。 + - Python dtype: CustomCFGKeyframeGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CustomCFGKeyframeNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "cfg_multival": ("MULTIVAL",), + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}), + }, + "optional": { + "prev_custom_cfg": ("CUSTOM_CFG",), + } + } + + RETURN_TYPES = ("CUSTOM_CFG",) + CATEGORY = "Animate Diff 🎭🅐🅓/sample settings" + FUNCTION = "create_custom_cfg" + + def create_custom_cfg(self, cfg_multival: Union[float, Tensor], start_percent: float=0.0, guarantee_steps: int=1, + prev_custom_cfg: CustomCFGKeyframeGroup=None): + if not prev_custom_cfg: + prev_custom_cfg = CustomCFGKeyframeGroup() + prev_custom_cfg = prev_custom_cfg.clone() + keyframe = CustomCFGKeyframe(cfg_multival=cfg_multival, start_percent=start_percent, guarantee_steps=guarantee_steps) + prev_custom_cfg.add(keyframe) + return (prev_custom_cfg,) \ No newline at end of file diff --git a/docs/ADE_EmptyLatentImageLarge.md b/docs/ADE_EmptyLatentImageLarge.md new file mode 100644 index 0000000..cddc65b --- /dev/null +++ b/docs/ADE_EmptyLatentImageLarge.md @@ -0,0 +1,55 @@ +# Empty Latent Image (Big Batch) 🎭🅐🅓 +## Documentation +- Class name: ADE_EmptyLatentImageLarge +- Category: Animate Diff 🎭🅐🅓/extras +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_EmptyLatentImageLarge节点旨在初始化一个用零填充的大型潜在图像张量。此张量作为进一步生成过程的空白画布,允许在潜在层面上创建和操作图像。 + +## Input types +### Required +- width + - 指定要生成的潜在图像的宽度。它决定了生成张量的水平维度。 + - Comfy dtype: INT + - Python dtype: int +- height + - 确定潜在图像的高度。它影响生成张量的垂直维度。 + - Comfy dtype: INT + - Python dtype: int +- batch_size + - 控制一次生成的潜在图像的数量。它影响生成张量的第一个维度,允许批处理多个图像。 + - Comfy dtype: INT + - Python dtype: int + +## Output types +- latent + - Comfy dtype: LATENT + - 输出是一个表示一批空白潜在图像的张量。每个图像都用零初始化,准备进行后续生成修改。 + - Python dtype: torch.Tensor + +## Usage tips +- Infra type: GPU + + +## Source code +```python +class EmptyLatentImageLarge: + def __init__(self, device="cpu"): + self.device = device + + @classmethod + def INPUT_TYPES(s): + return {"required": { "width": ("INT", {"default": 512, "min": 64, "max": comfy_nodes.MAX_RESOLUTION, "step": 8}), + "height": ("INT", {"default": 512, "min": 64, "max": comfy_nodes.MAX_RESOLUTION, "step": 8}), + "batch_size": ("INT", {"default": 1, "min": 1, "max": 262144})}} + RETURN_TYPES = ("LATENT",) + FUNCTION = "generate" + + CATEGORY = "Animate Diff 🎭🅐🅓/extras" + + def generate(self, width, height, batch_size=1): + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + return ({"samples":latent}, ) \ No newline at end of file diff --git a/docs/ADE_InjectI2VIntoAnimateDiffModel.md b/docs/ADE_InjectI2VIntoAnimateDiffModel.md new file mode 100644 index 0000000..f155012 --- /dev/null +++ b/docs/ADE_InjectI2VIntoAnimateDiffModel.md @@ -0,0 +1,65 @@ +# 🧪Inject I2V into AnimateDiff Model 🎭🅐🅓② +## Documentation +- Class name: ADE_InjectI2VIntoAnimateDiffModel +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V/🧪experimental +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在将I2V(Image to Video)模型集成到AnimateDiff框架中,通过引入运动模型增强其功能。它作为桥梁,丰富AnimateDiff的动画过程,增加更多的运动动态,从而实现更复杂和细致的动画输出。 + +## Input types +### Required +- model_name + - 指定要加载的运动模型的名称,在确定动画的运动动态方面起着至关重要的作用。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- motion_model + - 表示要注入到AnimateDiff模型中的运动模型对象,对于在动画过程中应用特定的运动动态至关重要。 + - Comfy dtype: MOTION_MODEL_ADE + - Python dtype: MotionModelPatcher + +### Optional +- ad_settings + - AnimateDiff过程的可选设置,允许自定义动画的外观和行为。 + - Comfy dtype: AD_SETTINGS + - Python dtype: AnimateDiffSettings + +## Output types +- MOTION_MODEL + - Comfy dtype: MOTION_MODEL_ADE + - 注入了I2V功能的增强版AnimateDiff模型,准备好用于动画任务。 + - Python dtype: MotionModelPatcher + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class LoadAnimateDiffAndInjectI2VNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model_name": (get_available_motion_models(),), + "motion_model": ("MOTION_MODEL_ADE",), + }, + "optional": { + "ad_settings": ("AD_SETTINGS",), + } + } + + RETURN_TYPES = ("MOTION_MODEL_ADE",) + RETURN_NAMES = ("MOTION_MODEL",) + + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V/🧪experimental" + FUNCTION = "load_motion_model" + + def load_motion_model(self, model_name: str, motion_model: MotionModelPatcher, ad_settings: AnimateDiffSettings=None): + # make sure model w/ encoder actually has encoder + if motion_model.model.img_encoder is None: + raise Exception("Passed-in motion model was expected to have an img_encoder, but did not.") + # load motion module and motion settings, if included + loaded_motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings) + inject_img_encoder_into_model(motion_model=loaded_motion_model, w_encoder=motion_model) + return (loaded_motion_model,) \ No newline at end of file diff --git a/docs/ADE_LoadAnimateDiffModel.md b/docs/ADE_LoadAnimateDiffModel.md new file mode 100644 index 0000000..0f9e1a8 --- /dev/null +++ b/docs/ADE_LoadAnimateDiffModel.md @@ -0,0 +1,56 @@ +# Load AnimateDiff Model 🎭🅐🅓② +## Documentation +- Class name: ADE_LoadAnimateDiffModel +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ② +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在加载AnimateDiff模型,便于在AnimateDiff框架内集成和应用运动模型以实现动画目的。它作为动画管道中的基础组件,使用户能够利用高级动画技术。 + +## Input types +### Required +- model_name + - 指定要加载的运动模型的名称。这是一个关键输入,因为它决定了在AnimateDiff框架内将使用哪个运动模型进行动画。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +### Optional +- ad_settings + - 可选参数,允许包括特定的动画设置,提供对动画过程的额外定制和控制。 + - Comfy dtype: AD_SETTINGS + - Python dtype: AnimateDiffSettings + +## Output types +- MOTION_MODEL + - Comfy dtype: MOTION_MODEL_ADE + - 输出已加载的运动模型,准备在动画管道中进一步处理和应用。 + - Python dtype: MotionModelPatcher + +## Usage tips +- Infra type: GPU + + +## Source code +```python +class LoadAnimateDiffModelNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model_name": (get_available_motion_models(),), + }, + "optional": { + "ad_settings": ("AD_SETTINGS",), + } + } + + RETURN_TYPES = ("MOTION_MODEL_ADE",) + RETURN_NAMES = ("MOTION_MODEL",) + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②" + FUNCTION = "load_motion_model" + + def load_motion_model(self, model_name: str, ad_settings: AnimateDiffSettings=None): + # load motion module and motion settings, if included + motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings) + return (motion_model,) \ No newline at end of file diff --git a/docs/ADE_LoadAnimateDiffModelWithCameraCtrl.md b/docs/ADE_LoadAnimateDiffModelWithCameraCtrl.md new file mode 100644 index 0000000..145bb1f --- /dev/null +++ b/docs/ADE_LoadAnimateDiffModelWithCameraCtrl.md @@ -0,0 +1,60 @@ +# Load AnimateDiff+CameraCtrl Model 🎭🅐🅓② +## Documentation +- Class name: ADE_LoadAnimateDiffModelWithCameraCtrl +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在加载具有集成摄像机控制功能的AnimateDiff模型,使得可以直接在AnimateDiff框架内应用摄像机运动和调整。它有助于将动态摄像机控制参数整合到AnimateDiff模型中,从而增强动画过程并实现更复杂的视觉效果。 + +## Input types +### Required +- model_name + - 指定要加载的运动模型的名称。它对于识别将添加摄像机控制功能的特定AnimateDiff模型至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- camera_ctrl + - 定义要注入到AnimateDiff模型中的摄像机控制参数。此输入对于定制动画中的摄像机运动和效果至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +### Optional +- ad_settings + - AnimateDiff模型的可选设置,允许进一步定制动画过程。 + - Comfy dtype: AD_SETTINGS + - Python dtype: dict + +## Output types +- MOTION_MODEL + - Comfy dtype: MOTION_MODEL_ADE + - 集成了摄像机控制功能的修改后的AnimateDiff模型,准备用于动画任务。 + - Python dtype: MotionModel + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class LoadAnimateDiffModelWithCameraCtrl: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model_name": (get_available_motion_models(),), + "camera_ctrl": (get_available_motion_models(),), + }, + "optional": { + "ad_settings": ("AD_SETTINGS",), + } + } + + RETURN_TYPES = ("MOTION_MODEL_ADE",) + RETURN_NAMES = ("MOTION_MODEL",) + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl" + FUNCTION = "load_camera_ctrl" + + def load_camera_ctrl(self, model_name: str, camera_ctrl: str, ad_settings: AnimateDiffSettings=None): + loaded_motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings) + inject_camera_encoder_into_model(motion_model=loaded_motion_model, camera_ctrl_name=camera_ctrl) + return (loaded_motion_model,) \ No newline at end of file diff --git a/docs/ADE_LoadAnimateLCMI2VModel.md b/docs/ADE_LoadAnimateLCMI2VModel.md new file mode 100644 index 0000000..553e048 --- /dev/null +++ b/docs/ADE_LoadAnimateLCMI2VModel.md @@ -0,0 +1,66 @@ +# Load AnimateLCM-I2V Model 🎭🅐🅓② +## Documentation +- Class name: ADE_LoadAnimateLCMI2VModel +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_LoadAnimateLCMI2VModel节点旨在加载和准备用于动画过程的AnimateLCM-I2V运动模型。它确保所选的运动模型与AnimateLCM-I2V格式兼容并具有图像编码器,从而促进将运动模型集成到动画工作流程中。 + +## Input types +### Required +- model_name + - 指定要加载的运动模型的名称,确保该模型可用且与AnimateLCM-I2V格式兼容。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +### Optional +- ad_settings + - Animate Diff过程的可选设置,可以应用于运动模型,允许自定义动画。 + - Comfy dtype: AD_SETTINGS + - Python dtype: AnimateDiffSettings or None + +## Output types +- MOTION_MODEL + - Comfy dtype: MOTION_MODEL_ADE + - 已加载的运动模型,准备用于动画过程。 + - Python dtype: MotionModelPatcher +- encoder_only + - Comfy dtype: MOTION_MODEL_ADE + - 仅包含编码器的运动模型版本,适用于特定的动画任务。 + - Python dtype: MotionModelPatcher + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class LoadAnimateLCMI2VModelNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model_name": (get_available_motion_models(),), + }, + "optional": { + "ad_settings": ("AD_SETTINGS",), + } + } + + RETURN_TYPES = ("MOTION_MODEL_ADE", "MOTION_MODEL_ADE") + RETURN_NAMES = ("MOTION_MODEL", "encoder_only") + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V" + FUNCTION = "load_motion_model" + + def load_motion_model(self, model_name: str, ad_settings: AnimateDiffSettings=None): + # load motion module and motion settings, if included + motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings) + # make sure model is an AnimateLCM-I2V model + if motion_model.model.mm_info.mm_format != AnimateDiffFormat.ANIMATELCM: + raise Exception(f"Motion model '{motion_model.model.mm_info.mm_name}' is not an AnimateLCM-I2V model; selected model is not AnimateLCM, and does not contain an img_encoder.") + if motion_model.model.img_encoder is None: + raise Exception(f"Motion model '{motion_model.model.mm_info.mm_name}' is not an AnimateLCM-I2V model; selected model IS AnimateLCM, but does NOT contain an img_encoder.") + # create encoder-only motion model + encoder_only_motion_model = create_fresh_encoder_only_model(motion_model=motion_model) + return (motion_model, encoder_only_motion_model) \ No newline at end of file diff --git a/docs/ADE_LoadCameraPoses.md b/docs/ADE_LoadCameraPoses.md new file mode 100644 index 0000000..4b78e48 --- /dev/null +++ b/docs/ADE_LoadCameraPoses.md @@ -0,0 +1,54 @@ +# Load CameraCtrl Poses (File) 🎭🅐🅓② +## Documentation +- Class name: ADE_LoadCameraPoses +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +`ADE_LoadCameraPoses`节点旨在从指定的文件加载摄像机控制姿势,便于在Animate Diff框架内操纵和动画化摄像机位置。它作为创建动态和复杂摄像机运动的基础元素,用于动画序列。 + +## Input types +### Required +- pose_filename + - 指定要从中加载摄像机控制姿势的文件名。此文件名应对应包含所需摄像机姿势的文件,使节点能够检索和利用这些姿势进行动画化。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +## Output types +- cameractrl_poses + - Comfy dtype: CAMERACTRL_POSES + - 输出一系列摄像机控制姿势,这些姿势结构为浮点数列表,表示摄像机在动画上下文中的位置、方向和其他相关参数。 + - Python dtype: list[list[float]] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class LoadCameraPoses: + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))] + files = [f for f in files if f.endswith(".txt")] + return { + "required": { + "pose_filename": (sorted(files),), + } + } + + RETURN_TYPES = ("CAMERACTRL_POSES",) + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses" + FUNCTION = "load_camera_poses" + + def load_camera_poses(self, pose_filename: str): + file_path = folder_paths.get_annotated_filepath(pose_filename) + with open(file_path, 'r') as f: + poses = f.readlines() + # first line of file is the link to source, so can be skipped, + # and the rest is a header-less CSV file separated by single spaces + poses = [pose.strip().split(' ') for pose in poses[1:]] + poses = [[float(x) for x in pose] for pose in poses] + poses = set_original_pose_dims(poses, pose_width=CAM.DEFAULT_POSE_WIDTH, pose_height=CAM.DEFAULT_POSE_HEIGHT) + return (poses,) \ No newline at end of file diff --git a/docs/ADE_LoraHookKeyframe.md b/docs/ADE_LoraHookKeyframe.md new file mode 100644 index 0000000..0d9832d --- /dev/null +++ b/docs/ADE_LoraHookKeyframe.md @@ -0,0 +1,70 @@ +# LoRA Hook Keyframe 🎭🅐🅓 +## Documentation +- Class name: ADE_LoraHookKeyframe +- Category: Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点用于创建LoRA挂钩关键帧,这是在动画序列中特定点调整LoRA(低秩适应)挂钩影响的机制。它允许动态调度LoRA挂钩的强度,从而在动画过程中精确控制其效果。 + +## Input types +### Required +- strength_model + - 指定关键帧处LoRA挂钩的强度,影响挂钩在动画中此点对模型行为的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_percent + - 确定关键帧效果的起始点,占总动画长度的百分比,允许精确控制LoRA挂钩影响的时间。 + - Comfy dtype: FLOAT + - Python dtype: float +- guarantee_steps + - 保证关键帧效果将应用的最小步数,确保LoRA挂钩的影响至少维持此持续时间。 + - Comfy dtype: INT + - Python dtype: int + +### Optional +- prev_hook_kf + - 可选的前一个LoRA挂钩关键帧组,新的关键帧将添加到其中,允许链式连接多个关键帧以实现复杂的动画效果。 + - Comfy dtype: LORA_HOOK_KEYFRAMES + - Python dtype: LoraHookKeyframeGroup + +## Output types +- HOOK_KF + - Comfy dtype: LORA_HOOK_KEYFRAMES + - 返回一组LoRA挂钩关键帧,包括新创建的关键帧,便于在动画中管理和应用多个关键帧。 + - Python dtype: LoraHookKeyframeGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CreateLoraHookKeyframe: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}), + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}), + }, + "optional": { + "prev_hook_kf": ("LORA_HOOK_KEYFRAMES",), + } + } + + RETURN_TYPES = ("LORA_HOOK_KEYFRAMES",) + RETURN_NAMES = ("HOOK_KF",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks" + FUNCTION = "create_hook_keyframe" + + def create_hook_keyframe(self, strength_model: float, start_percent: float, guarantee_steps: float, + prev_hook_kf: LoraHookKeyframeGroup=None): + if prev_hook_kf: + prev_hook_kf = prev_hook_kf.clone() + else: + prev_hook_kf = LoraHookKeyframeGroup() + keyframe = LoraHookKeyframe(strength=strength_model, start_percent=start_percent, guarantee_steps=guarantee_steps) + prev_hook_kf.add(keyframe) + return (prev_hook_kf,) \ No newline at end of file diff --git a/docs/ADE_LoraHookKeyframeFromStrengthList.md b/docs/ADE_LoraHookKeyframeFromStrengthList.md new file mode 100644 index 0000000..e2fa264 --- /dev/null +++ b/docs/ADE_LoraHookKeyframeFromStrengthList.md @@ -0,0 +1,91 @@ +# LoRA Hook Keyframes From List 🎭🅐🅓 +## Documentation +- Class name: ADE_LoraHookKeyframeFromStrengthList +- Category: Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点用于根据强度列表创建一系列LoRA挂钩关键帧,从而动态调整模型行为的多个步骤。它允许自定义关键帧属性,如强度和起始百分比,从而精确控制动画或转换过程。 + +## Input types +### Required +- strengths_float + - 指定序列中每个关键帧的强度。此参数可以接受单个浮点值或浮点值列表,允许灵活定义每个关键帧的强度。 + - Comfy dtype: FLOAT + - Python dtype: Union[float, List[float]] +- start_percent + - 定义关键帧序列的起始百分比,设置动画或转换的起始点。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - 设置关键帧序列的结束百分比,标记动画或转换的终点。 + - Comfy dtype: FLOAT + - Python dtype: float +- print_keyframes + - 一个布尔标志,启用时会将每个关键帧的详细信息打印到日志中,有助于调试和可视化关键帧序列。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +### Optional +- prev_hook_kf + - 一个可选参数,允许从前一个LoRA挂钩关键帧序列继续,启用序列之间的无缝过渡。 + - Comfy dtype: LORA_HOOK_KEYFRAMES + - Python dtype: LoraHookKeyframeGroup + +## Output types +- HOOK_KF + - Comfy dtype: LORA_HOOK_KEYFRAMES + - 返回一组LoRA挂钩关键帧,表示将应用于模型的一系列调整。 + - Python dtype: LoraHookKeyframeGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CreateLoraHookKeyframeFromStrengthList: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "strengths_float": ("FLOAT", {"default": -1, "min": -1, "step": 0.001, "forceInput": True}), + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "print_keyframes": ("BOOLEAN", {"default": False}), + }, + "optional": { + "prev_hook_kf": ("LORA_HOOK_KEYFRAMES",), + } + } + + RETURN_TYPES = ("LORA_HOOK_KEYFRAMES",) + RETURN_NAMES = ("HOOK_KF",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks" + FUNCTION = "create_hook_keyframes" + + def create_hook_keyframes(self, strengths_float: Union[float, list[float]], + start_percent: float, end_percent: float, + prev_hook_kf: LoraHookKeyframeGroup=None, print_keyframes=False): + if prev_hook_kf: + prev_hook_kf = prev_hook_kf.clone() + else: + prev_hook_kf = LoraHookKeyframeGroup() + if type(strengths_float) in (float, int): + strengths_float = [float(strengths_float)] + elif isinstance(strengths_float, Iterable): + pass + else: + raise Exception(f"strengths_floast must be either an interable input or a float, but was {type(strengths_float).__repr__}.") + percents = InterpolationMethod.get_weights(num_from=start_percent, num_to=end_percent, length=len(strengths_float), method=InterpolationMethod.LINEAR) + + is_first = True + for percent, strength in zip(percents, strengths_float): + guarantee_steps = 0 + if is_first: + guarantee_steps = 1 + is_first = False + prev_hook_kf.add(LoraHookKeyframe(strength=strength, start_percent=percent, guarantee_steps=guarantee_steps)) + if print_keyframes: + logger.info(f"LoraHookKeyframe - start_percent:{percent} = {strength}") + return (prev_hook_kf,) \ No newline at end of file diff --git a/docs/ADE_LoraHookKeyframeInterpolation.md b/docs/ADE_LoraHookKeyframeInterpolation.md new file mode 100644 index 0000000..e35c7df --- /dev/null +++ b/docs/ADE_LoraHookKeyframeInterpolation.md @@ -0,0 +1,102 @@ +# LoRA Hook Keyframes Interpolation 🎭🅐🅓 +## Documentation +- Class name: ADE_LoraHookKeyframeInterpolation +- Category: Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点用于创建插值的LoRA挂钩关键帧,从而动态调整模型行为随时间的变化。它基于指定的起始和结束百分比、强度和插值方法生成一系列关键帧,从而实现对模型参数的细粒度控制。 + +## Input types +### Required +- start_percent + - 定义插值的起始百分比,设置生成关键帧序列的起始点。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - 指定插值的结束百分比,确定生成关键帧序列的终点。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_start + - 设置插值的初始强度值,标记强度调整范围的开始。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_end + - 确定插值的结束强度值,结束强度调整范围。 + - Comfy dtype: FLOAT + - Python dtype: float +- interpolation + - 选择用于生成关键帧序列的插值方法,影响起始和结束值之间的过渡。 + - Comfy dtype: COMBO[STRING] + - Python dtype: InterpolationMethod +- intervals + - 指定起始和结束点之间生成的间隔(或关键帧)数,影响插值的粒度。 + - Comfy dtype: INT + - Python dtype: int +- print_keyframes + - 可选。控制是否记录生成的关键帧,有助于调试和可视化插值过程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +### Optional +- prev_hook_kf + - 可选。允许包括先前定义的一组LoRA挂钩关键帧,新的插值关键帧将添加到其中。 + - Comfy dtype: LORA_HOOK_KEYFRAMES + - Python dtype: LoraHookKeyframeGroup + +## Output types +- HOOK_KF + - Comfy dtype: LORA_HOOK_KEYFRAMES + - 返回一组LoRA挂钩关键帧,包括先前存在的和新插值的关键帧,准备在模型条件中应用。 + - Python dtype: LoraHookKeyframeGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CreateLoraHookKeyframeInterpolation: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "strength_start": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ), + "strength_end": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ), + "interpolation": (InterpolationMethod._LIST, ), + "intervals": ("INT", {"default": 5, "min": 2, "max": 100, "step": 1}), + "print_keyframes": ("BOOLEAN", {"default": False}), + }, + "optional": { + "prev_hook_kf": ("LORA_HOOK_KEYFRAMES",), + } + } + + RETURN_TYPES = ("LORA_HOOK_KEYFRAMES",) + RETURN_NAMES = ("HOOK_KF",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks" + FUNCTION = "create_hook_keyframes" + + def create_hook_keyframes(self, + start_percent: float, end_percent: float, + strength_start: float, strength_end: float, interpolation: str, intervals: int, + prev_hook_kf: LoraHookKeyframeGroup=None, print_keyframes=False): + if prev_hook_kf: + prev_hook_kf = prev_hook_kf.clone() + else: + prev_hook_kf = LoraHookKeyframeGroup() + percents = InterpolationMethod.get_weights(num_from=start_percent, num_to=end_percent, length=intervals, method=interpolation) + strengths = InterpolationMethod.get_weights(num_from=strength_start, num_to=strength_end, length=intervals, method=interpolation) + + is_first = True + for percent, strength in zip(percents, strengths): + guarantee_steps = 0 + if is_first: + guarantee_steps = 1 + is_first = False + prev_hook_kf.add(LoraHookKeyframe(strength=strength, start_percent=percent, guarantee_steps=guarantee_steps)) + if print_keyframes: + logger.info(f"LoraHookKeyframe - start_percent:{percent} = {strength}") + return (prev_hook_kf,) \ No newline at end of file diff --git a/docs/ADE_PairedConditioningSetMask.md b/docs/ADE_PairedConditioningSetMask.md new file mode 100644 index 0000000..8498d3e --- /dev/null +++ b/docs/ADE_PairedConditioningSetMask.md @@ -0,0 +1,87 @@ +# Set Props on Conds 🎭🅐🅓 +## Documentation +- Class name: ADE_PairedConditioningSetMask +- Category: Animate Diff 🎭🅐🅓/conditioning +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_PairedConditioningSetMask节点旨在对一对条件输入应用掩码和条件调整。它利用强度、设置条件区域以及可选元素如掩码、Lora挂钩和时间步条件等附加参数来微调条件过程,旨在根据指定的调整增强或修改生成内容的属性。 + +## Input types +### Required +- positive_ADD + - 指定要调整的正向条件输入。它在定义要在生成内容中增强或修改的属性或特性方面起着关键作用。 + - Comfy dtype: CONDITIONING + - Python dtype: CONDITIONING +- negative_ADD + - 指定要调整的负向条件输入。它对于定义要以与正向条件相反的方式减弱或改变的属性或特性至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: CONDITIONING +- strength + - 决定条件调整的强度。较高的值表示对条件输入的影响更强。 + - Comfy dtype: FLOAT + - Python dtype: float +- set_cond_area + - 定义要受调整影响的条件输入区域。它允许对条件输入进行有针对性的修改。 + - Comfy dtype: COMBO[STRING] + - Python dtype: COND_CONST._LIST_COND_AREA + +### Optional +- opt_mask + - 一个可选掩码,可以应用于条件输入以进行更精确的调整。 + - Comfy dtype: MASK + - Python dtype: Tensor +- opt_lora_hook + - 一个可选的Lora挂钩,可以应用于附加条件转换。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- opt_timesteps + - 可选的时间步条件,允许对条件输入进行时间调整。 + - Comfy dtype: TIMESTEPS_COND + - Python dtype: TimestepsCond + +## Output types +- positive + - Comfy dtype: CONDITIONING + - 应用指定调整后的正向条件输出。 + - Python dtype: CONDITIONING +- negative + - Comfy dtype: CONDITIONING + - 应用指定调整后的负向条件输出。 + - Python dtype: CONDITIONING + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class PairedConditioningSetMaskHooked: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "positive_ADD": ("CONDITIONING", ), + "negative_ADD": ("CONDITIONING", ), + "strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "set_cond_area": (COND_CONST._LIST_COND_AREA,), + }, + "optional": { + "opt_mask": ("MASK", ), + "opt_lora_hook": ("LORA_HOOK",), + "opt_timesteps": ("TIMESTEPS_COND",) + } + } + + RETURN_TYPES = ("CONDITIONING", "CONDITIONING") + RETURN_NAMES = ("positive", "negative") + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning" + FUNCTION = "append_and_hook" + + def append_and_hook(self, positive_ADD, negative_ADD, + strength: float, set_cond_area: str, + opt_mask: Tensor=None, opt_lora_hook: LoraHookGroup=None, opt_timesteps: TimestepsCond=None): + final_positive, final_negative = set_mask_conds(conds=[positive_ADD, negative_ADD], + strength=strength, set_cond_area=set_cond_area, + opt_mask=opt_mask, opt_lora_hook=opt_lora_hook, opt_timesteps=opt_timesteps) + return (final_positive, final_negative) \ No newline at end of file diff --git a/docs/ADE_PairedConditioningSetMaskAndCombine.md b/docs/ADE_PairedConditioningSetMaskAndCombine.md new file mode 100644 index 0000000..6af2f92 --- /dev/null +++ b/docs/ADE_PairedConditioningSetMaskAndCombine.md @@ -0,0 +1,97 @@ +# Set Props and Combine Conds 🎭🅐🅓 +## Documentation +- Class name: ADE_PairedConditioningSetMaskAndCombine +- Category: Animate Diff 🎭🅐🅓/conditioning +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点专门用于生成模型的成对条件数据的高级操作,特别关注掩码和附加条件层的应用和组合。它通过应用掩码、强度调整和整合新的条件元素来增强或修改现有条件,从而更精确地控制生成过程。 + +## Input types +### Required +- positive + - 要增强或修改的原始正向条件数据。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - 要增强或修改的原始负向条件数据。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- positive_ADD + - 要与原始条件结合的附加正向条件数据。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative_ADD + - 要与原始条件结合的附加负向条件数据。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- strength + - 定义掩码或条件修改强度的参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- set_cond_area + - 指定掩码或修改应用于条件的区域。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +### Optional +- opt_mask + - 一个可选掩码,可以应用于条件数据以进行选择性修改。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- opt_lora_hook + - 一个可选参数,允许将Lora挂钩应用于条件数据,提供额外的转换或控制层。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- opt_timesteps + - 可选的时间步条件,允许进行时间调整。 + - Comfy dtype: TIMESTEPS_COND + - Python dtype: TimestepsCond + +## Output types +- positive + - Comfy dtype: CONDITIONING + - 应用掩码、强度调整并与附加条件结合后的增强或修改后的正向条件数据。 + - Python dtype: torch.Tensor +- negative + - Comfy dtype: CONDITIONING + - 应用掩码、强度调整并与附加条件结合后的增强或修改后的负向条件数据。 + - Python dtype: torch.Tensor + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class PairedConditioningSetMaskAndCombineHooked: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "positive": ("CONDITIONING",), + "negative": ("CONDITIONING",), + "positive_ADD": ("CONDITIONING",), + "negative_ADD": ("CONDITIONING",), + "strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "set_cond_area": (COND_CONST._LIST_COND_AREA,), + }, + "optional": { + "opt_mask": ("MASK", ), + "opt_lora_hook": ("LORA_HOOK",), + "opt_timesteps": ("TIMESTEPS_COND",) + } + } + + RETURN_TYPES = ("CONDITIONING", "CONDITIONING") + RETURN_NAMES = ("positive", "negative") + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning" + FUNCTION = "append_and_combine" + + def append_and_combine(self, positive, negative, positive_ADD, negative_ADD, + strength: float, set_cond_area: str, + opt_mask: Tensor=None, opt_lora_hook: LoraHookGroup=None, opt_timesteps: TimestepsCond=None): + final_positive, final_negative = set_mask_and_combine_conds(conds=[positive, negative], new_conds=[positive_ADD, negative_ADD], + strength=strength, set_cond_area=set_cond_area, + opt_mask=opt_mask, opt_lora_hook=opt_lora_hook, opt_timesteps=opt_timesteps) + return (final_positive, final_negative,) \ No newline at end of file diff --git a/docs/ADE_PairedConditioningSetUnmaskedAndCombine.md b/docs/ADE_PairedConditioningSetUnmaskedAndCombine.md new file mode 100644 index 0000000..ab66c01 --- /dev/null +++ b/docs/ADE_PairedConditioningSetUnmaskedAndCombine.md @@ -0,0 +1,75 @@ +# Set Unmasked Conds 🎭🅐🅓 +## Documentation +- Class name: ADE_PairedConditioningSetUnmaskedAndCombine +- Category: Animate Diff 🎭🅐🅓/conditioning +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在处理和组合成对的条件输入,应用取消掩码和可选的LoRA挂钩转换。它专注于将默认或基线条件与当前条件整合,准备进一步处理或生成任务,从而增强对条件过程的灵活性和控制。 + +## Input types +### Required +- positive + - 要与其默认对应项结合的当前正向条件输入。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- negative + - 要与其默认对应项结合的当前负向条件输入。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- positive_DEFAULT + - 要与当前正向条件结合的默认正向条件输入。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- negative_DEFAULT + - 要与当前负向条件结合的默认负向条件输入。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] + +### Optional +- opt_lora_hook + - 一个可选的LoRA挂钩,用于在结合条件输入之前对其进行转换。 + - Comfy dtype: LORA_HOOK + - Python dtype: Optional[LoraHookGroup] + +## Output types +- positive + - Comfy dtype: CONDITIONING + - 将当前和默认输入整合后的组合正向条件输出。 + - Python dtype: Dict[str, Any] +- negative + - Comfy dtype: CONDITIONING + - 将当前和默认输入整合后的组合负向条件输出。 + - Python dtype: Dict[str, Any] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class PairedConditioningSetUnmaskedAndCombineHooked: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "positive": ("CONDITIONING",), + "negative": ("CONDITIONING",), + "positive_DEFAULT": ("CONDITIONING",), + "negative_DEFAULT": ("CONDITIONING",), + }, + "optional": { + "opt_lora_hook": ("LORA_HOOK",), + } + } + + RETURN_TYPES = ("CONDITIONING", "CONDITIONING") + RETURN_NAMES = ("positive", "negative") + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning" + FUNCTION = "append_and_combine" + + def append_and_combine(self, positive, negative, positive_DEFAULT, negative_DEFAULT, + opt_lora_hook: LoraHookGroup=None): + final_positive, final_negative = set_unmasked_and_combine_conds(conds=[positive, negative], new_conds=[positive_DEFAULT, negative_DEFAULT], + opt_lora_hook=opt_lora_hook) + return (final_positive, final_negative,) \ No newline at end of file diff --git a/docs/ADE_RawSigmaSchedule.md b/docs/ADE_RawSigmaSchedule.md new file mode 100644 index 0000000..4b395cd --- /dev/null +++ b/docs/ADE_RawSigmaSchedule.md @@ -0,0 +1,78 @@ +# Create Raw Sigma Schedule 🎭🅐🅓 +## Documentation +- Class name: ADE_RawSigmaSchedule +- Category: Animate Diff 🎭🅐🅓/sample settings/sigma schedule +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在根据给定的beta计划生成一个sigma计划。它将beta计划转换为sigma计划,这对于控制扩散模型中的噪声水平至关重要,特别是在动画和图像合成的背景下。 + +## Input types +### Required +- raw_beta_schedule + - 指定要转换为sigma计划的beta计划。此参数对于确定整个扩散过程中的噪声水平的进展和强度至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- linear_start + - 定义用于sigma计划生成的线性插值的起点。它影响扩散过程中的初始噪声水平。 + - Comfy dtype: FLOAT + - Python dtype: float +- linear_end + - 设置sigma计划中线性插值的终点,影响扩散过程中的最终噪声水平。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampling + - 确定sigma计划中使用的采样方法,影响噪声水平的插值和应用方式。类型“ModelSamplingType”应理解为实际选择的采样方法的占位符。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- lcm_original_timesteps + - 指定使用LCM采样时要考虑的原始时间步数,影响sigma计划的粒度。 + - Comfy dtype: INT + - Python dtype: int +- lcm_zsnr + - 一个布尔标志,指示是否对sigma计划应用零信噪比(zSNR)调整,增强计划与某些扩散过程的兼容性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +## Output types +- sigma_schedule + - Comfy dtype: SIGMA_SCHEDULE + - 生成的sigma计划,概述了扩散过程每一步要应用的具体噪声水平。 + - Python dtype: SigmaSchedule + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class RawSigmaScheduleNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "raw_beta_schedule": (BetaSchedules.RAW_BETA_SCHEDULE_LIST,), + "linear_start": ("FLOAT", {"default": 0.00085, "min": 0.0, "max": 1.0, "step": 0.000001}), + "linear_end": ("FLOAT", {"default": 0.012, "min": 0.0, "max": 1.0, "step": 0.000001}), + #"cosine_s": ("FLOAT", {"default": 8e-3, "min": 0.0, "max": 1.0, "step": 0.000001}), + "sampling": (ModelSamplingType._FULL_LIST,), + "lcm_original_timesteps": ("INT", {"default": 50, "min": 1, "max": 1000}), + "lcm_zsnr": ("BOOLEAN", {"default": False}), + } + } + + RETURN_TYPES = ("SIGMA_SCHEDULE",) + CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule" + FUNCTION = "get_sigma_schedule" + + def get_sigma_schedule(self, raw_beta_schedule: str, linear_start: float, linear_end: float,# cosine_s: float, + sampling: str, lcm_original_timesteps: int, lcm_zsnr: bool): + new_config = ModelSamplingConfig(beta_schedule=raw_beta_schedule, linear_start=linear_start, linear_end=linear_end) + if sampling != ModelSamplingType.LCM: + lcm_original_timesteps=None + lcm_zsnr=False + model_type = ModelSamplingType.from_alias(sampling) + new_model_sampling = BetaSchedules._to_model_sampling(alias=BetaSchedules.AUTOSELECT, model_type=model_type, config_override=new_config, original_timesteps=lcm_original_timesteps) + if lcm_zsnr: + SigmaSchedule.apply_zsnr(new_model_sampling=new_model_sampling) + return (SigmaSchedule(model_sampling=new_model_sampling, model_type=model_type),) \ No newline at end of file diff --git a/docs/ADE_RegisterLoraHook.md b/docs/ADE_RegisterLoraHook.md new file mode 100644 index 0000000..e745bab --- /dev/null +++ b/docs/ADE_RegisterLoraHook.md @@ -0,0 +1,96 @@ +# Register LoRA Hook 🎭🅐🅓 +## Documentation +- Class name: ADE_RegisterLoraHook +- Category: Animate Diff 🎭🅐🅓/conditioning/register lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在AnimateDiff框架内注册LoRA挂钩,从而实现模型行为的动态修改,以增强动画和图像处理能力。 + +## Input types +### Required +- model + - 要应用LoRA挂钩的模型,作为动态行为修改的基础。 + - Comfy dtype: MODEL + - Python dtype: ModelPatcher or ModelPatcherAndInjector +- clip + - 可能与主模型一起可选修改的CLIP模型,允许同步调整。 + - Comfy dtype: CLIP + - Python dtype: CLIP +- lora_name + - 要应用的特定LoRA挂钩的标识符,决定行为修改的性质。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength_model + - 定义LoRA挂钩对模型影响的强度,允许对行为修改进行精细控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - 指定LoRA挂钩对CLIP模型影响的强度,使其行为精确调整。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- model + - Comfy dtype: MODEL + - 应用LoRA挂钩后的模型,准备进行增强的动画和图像处理任务。 + - Python dtype: ModelPatcher or ModelPatcherAndInjector +- clip + - Comfy dtype: CLIP + - 可选修改后的CLIP模型,与主模型同步调整以实现增强。 + - Python dtype: CLIP +- lora_hook + - Comfy dtype: LORA_HOOK + - 已注册的LoRA挂钩,封装了指定的修改,准备应用于模型。 + - Python dtype: LoraHookGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class MaskableLoraLoader: + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "clip": ("CLIP",), + "lora_name": (folder_paths.get_filename_list("loras"), ), + "strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}), + "strength_clip": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}), + } + } + + RETURN_TYPES = ("MODEL", "CLIP", "LORA_HOOK") + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/register lora hooks" + FUNCTION = "load_lora" + + def load_lora(self, model: Union[ModelPatcher, ModelPatcherAndInjector], clip: CLIP, lora_name: str, strength_model: float, strength_clip: float): + if strength_model == 0 and strength_clip == 0: + return (model, clip) + + lora_path = folder_paths.get_full_path("loras", lora_name) + lora = None + if self.loaded_lora is not None: + if self.loaded_lora[0] == lora_path: + lora = self.loaded_lora[1] + else: + temp = self.loaded_lora + self.loaded_lora = None + del temp + + if lora is None: + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + self.loaded_lora = (lora_path, lora) + + lora_hook = LoraHook(lora_name=lora_name) + lora_hook_group = LoraHookGroup() + lora_hook_group.add(lora_hook) + model_lora, clip_lora = load_hooked_lora_for_models(model=model, clip=clip, lora=lora, lora_hook=lora_hook, + strength_model=strength_model, strength_clip=strength_clip) + return (model_lora, clip_lora, lora_hook_group) \ No newline at end of file diff --git a/docs/ADE_RegisterLoraHookModelOnly.md b/docs/ADE_RegisterLoraHookModelOnly.md new file mode 100644 index 0000000..e0b21f1 --- /dev/null +++ b/docs/ADE_RegisterLoraHookModelOnly.md @@ -0,0 +1,57 @@ +# Register LoRA Hook (Model Only) 🎭🅐🅓 +## Documentation +- Class name: ADE_RegisterLoraHookModelOnly +- Category: Animate Diff 🎭🅐🅓/conditioning/register lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在将模型注册为LoRA(低秩适应)挂钩,专注于模型而不涉及任何CLIP模型。它通过LoRA技术实现模型行为的修改和增强,为将LoRA挂钩集成到模型中提供了一种简化的方法,以实现高级定制和性能调优。 + +## Input types +### Required +- model + - 要注册LoRA挂钩的模型。它是LoRA适应的主要目标,决定了应用修改的范围和影响。 + - Comfy dtype: MODEL + - Python dtype: Union[ModelPatcher, ModelPatcherAndInjector] +- lora_name + - 要应用的LoRA配置的名称。指定要使用的特定LoRA适应设置和参数,指导定制过程。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength_model + - 一个浮点值,表示LoRA适应对模型的强度。此参数控制应用的LoRA修改的强度,允许对模型行为进行精细调整。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- model + - Comfy dtype: MODEL + - 注册了LoRA挂钩后的模型。此输出反映了模型的修改状态,展示了LoRA适应的效果。 + - Python dtype: ModelPatcher +- lora_hook + - Comfy dtype: LORA_HOOK + - 已与模型注册的LoRA挂钩。此输出表示应用的LoRA适应机制,便于进一步定制和性能调优。 + - Python dtype: LoraHook + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class MaskableLoraLoaderModelOnly(MaskableLoraLoader): + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "lora_name": (folder_paths.get_filename_list("loras"), ), + "strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}), + } + } + + RETURN_TYPES = ("MODEL", "LORA_HOOK") + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/register lora hooks" + FUNCTION = "load_lora_model_only" + + def load_lora_model_only(self, model: ModelPatcher, lora_name: str, strength_model: float): + model_lora, clip_lora, lora_hook = self.load_lora(mod \ No newline at end of file diff --git a/docs/ADE_RegisterModelAsLoraHook.md b/docs/ADE_RegisterModelAsLoraHook.md new file mode 100644 index 0000000..fdcef86 --- /dev/null +++ b/docs/ADE_RegisterModelAsLoraHook.md @@ -0,0 +1,83 @@ +# Register Model as LoRA Hook 🎭🅐🅓 +## Documentation +- Class name: ADE_RegisterModelAsLoraHook +- Category: Animate Diff 🎭🅐🅓/conditioning/register lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在将模型注册为AnimateDiff框架中的LoRA挂钩,从而在生成过程中实现模型行为的动态修改和控制。它通过LoRA(低秩适应)技术与模型集成,允许根据特定条件或输入对模型输出进行增强定制和微调。 + +## Input types +### Required +- model + - 表示LoRA挂钩将应用到的目标模型参数。它对于定义LoRA适应的范围和上下文至关重要,影响模型行为在生成过程中的修改方式。 + - Comfy dtype: MODEL + - Python dtype: Union[ModelPatcher, ModelPatcherAndInjector] +- clip + - 指定过程中涉及的CLIP模型(如果有),提供LoRA适应可能与主模型一起应用的上下文。 + - Comfy dtype: CLIP + - Python dtype: CLIP +- ckpt_name + - 指示加载模型状态的检查点名称,对于使用特定预训练权重或配置初始化模型至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength_model + - 控制应用于模型的LoRA修改的强度参数。它允许对LoRA对模型行为的影响进行微调,从而实现生成过程的精确调整。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - 类似于strength_model,此参数调整LoRA修改的强度,但特别针对过程中涉及的CLIP模型。它允许分别控制不同生成框架组件的适应强度。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- model + - Comfy dtype: MODEL + - 应用LoRA挂钩后的模型,反映通过输入参数指定的动态适应。 + - Python dtype: ModelPatcher +- clip + - Comfy dtype: CLIP + - 如果过程中涉及CLIP模型,则应用LoRA挂钩的CLIP模型。它指示LoRA修改应用于CLIP组件。 + - Python dtype: CLIP +- lora_hook + - Comfy dtype: LORA_HOOK + - 已注册并应用于模型和/或CLIP的LoRA挂钩,封装了所做的具体适应。 + - Python dtype: LoraHook + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class MaskableSDModelLoader: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "clip": ("CLIP",), + "ckpt_name": (folder_paths.get_filename_list("checkpoints"), ), + "strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}), + "strength_clip": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}), + } + } + + RETURN_TYPES = ("MODEL", "CLIP", "LORA_HOOK") + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/register lora hooks" + FUNCTION = "load_model_as_lora" + + def load_model_as_lora(self, model: ModelPatcher, clip: CLIP, ckpt_name: str, strength_model: float, strength_clip: float): + ckpt_path = folder_paths.get_full_path("checkpoints", ckpt_name) + out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths("embeddings")) + model_loaded = out[0] + clip_loaded = out[1] + + lora_hook = LoraHook(lora_name=ckpt_name) + lora_hook_group = LoraHookGroup() + lora_hook_group.add(lora_hook) + model_lora, clip_lora = load_model_as_hooked_lora_for_models(model=model, clip=clip, + model_loaded=model_loaded, clip_loaded=clip_loaded, + lora_hook=lora_hook, + strength_model=strength_model, strength_clip=strength_clip) + return (model_lora, clip_lora, lora_hook_group) \ No newline at end of file diff --git a/docs/ADE_RegisterModelAsLoraHookModelOnly.md b/docs/ADE_RegisterModelAsLoraHookModelOnly.md new file mode 100644 index 0000000..3d1e3e9 --- /dev/null +++ b/docs/ADE_RegisterModelAsLoraHookModelOnly.md @@ -0,0 +1,59 @@ +# Register Model as LoRA Hook (MO) 🎭🅐🅓 +## Documentation +- Class name: ADE_RegisterModelAsLoraHookModelOnly +- Category: Animate Diff 🎭🅐🅓/conditioning/register lora hooks +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点专门用于将模型注册为LoRA挂钩,重点是仅对模型进行修改。它允许将LoRA(低秩适应)技术集成到特定模型中,增强其适应性和性能,以便执行特定任务,而不影响其他组件。 + +## Input types +### Required +- model + - 要使用LoRA技术进行适应的模型。它作为应用低秩适应的主要目标,旨在增强其性能或适应性,以执行特定任务。 + - Comfy dtype: MODEL + - Python dtype: ModelPatcher +- ckpt_name + - 要从中应用LoRA配置的检查点名称。此参数指定要使用的LoRA适应集,指导模型行为的定制。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength_model + - 一个浮点值,决定LoRA适应对模型的强度。它调节LoRA参数对模型行为的影响程度。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- model + - Comfy dtype: MODEL + - 应用指定LoRA适应后的模型。此输出反映了通过LoRA技术定制后的增强版模型。 + - Python dtype: ModelPatcher +- lora_hook + - Comfy dtype: LORA_HOOK + - 已集成到模型中的LoRA挂钩的引用。此输出提供了对应用的LoRA适应的访问,便于进一步操作或分析。 + - Python dtype: LoraHook + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class MaskableSDModelLoaderModelOnly(MaskableSDModelLoader): + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "ckpt_name": (folder_paths.get_filename_list("checkpoints"), ), + "strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}), + } + } + + RETURN_TYPES = ("MODEL", "LORA_HOOK") + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/register lora hooks" + FUNCTION = "load_model_as_lora_model_only" + + def load_model_as_lora_model_only(self, model: ModelPatcher, ckpt_name: str, strength_model: float): + model_lora, clip_lora, lora_hook = self.load_model_as_lora(model=model, clip=None, ckpt_name=ckpt_name, + strength_model=strength_model, strength_clip=0) + return (model_lora, lora_hook) \ No newline at end of file diff --git a/docs/ADE_ReplaceCameraParameters.md b/docs/ADE_ReplaceCameraParameters.md new file mode 100644 index 0000000..eb86e29 --- /dev/null +++ b/docs/ADE_ReplaceCameraParameters.md @@ -0,0 +1,70 @@ +# Replace Camera Parameters 🎭🅐🅓② +## Documentation +- Class name: ADE_ReplaceCameraParameters +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在修改动画或图像处理管道中的摄像机控制参数,允许根据预定义或动态生成的标准调整摄像机姿势。此功能对于实现特定的视觉效果、视角或需要特定摄像机方向或运动的动画至关重要。 + +## Input types +### Required +- poses + - 表示要修改的摄像机姿势的参数。它在确定最终输出中起着关键作用,通过指定初始摄像机位置和方向来进行调整。 + - Comfy dtype: CAMERACTRL_POSES + - Python dtype: list[list[float]] +- fx + - 摄像机在x轴上的焦距。调整此参数会影响摄像机沿x轴的视野,从而影响渲染场景的视角和比例。 + - Comfy dtype: FLOAT + - Python dtype: float +- fy + - 摄像机在y轴上的焦距。与“fx”类似,此参数修改沿y轴的视野,影响场景的深度和高度感知。 + - Comfy dtype: FLOAT + - Python dtype: float +- cx + - 摄像机光学中心的x坐标。改变此值会水平移动场景的中心点,可用于校正或实现某些视觉效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- cy + - 摄像机光学中心的y坐标。此参数垂直移动场景的中心点,允许调整垂直对齐或模拟摄像机倾斜效果。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- cameractrl_poses + - Comfy dtype: CAMERACTRL_POSES + - 应用新的摄像机参数后的修改摄像机姿势。此输出对于依赖更新摄像机方向的渲染或进一步处理的下游过程至关重要。 + - Python dtype: list[list[float]] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CameraCtrlReplaceCameraParameters: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "poses":("CAMERACTRL_POSES",), + "fx": ("FLOAT", {"default": CAM.DEFAULT_FX, "min": 0, "max": 1, "step": 0.000000001}), + "fy": ("FLOAT", {"default": CAM.DEFAULT_FY, "min": 0, "max": 1, "step": 0.000000001}), + "cx": ("FLOAT", {"default": CAM.DEFAULT_CX, "min": 0, "max": 1, "step": 0.01}), + "cy": ("FLOAT", {"default": CAM.DEFAULT_CY, "min": 0, "max": 1, "step": 0.01}), + }, + } + + RETURN_TYPES = ("CAMERACTRL_POSES",) + FUNCTION = "set_camera_parameters" + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses" + + def set_camera_parameters(self, poses: list[list[float]], fx: float, fy: float, cx: float, cy: float): + new_poses = copy.deepcopy(poses) + for pose in new_poses: + # fx,fy,cx,fy are in indexes 1-4 of the 19-long pose list + pose[1] = fx + pose[2] = fy + pose[3] = cx + pose[4] = cy + return (new_poses,) \ No newline at end of file diff --git a/docs/ADE_ReplaceOriginalPoseAspectRatio.md b/docs/ADE_ReplaceOriginalPoseAspectRatio.md new file mode 100644 index 0000000..7c735ce --- /dev/null +++ b/docs/ADE_ReplaceOriginalPoseAspectRatio.md @@ -0,0 +1,61 @@ +--- + +tags: +- Animation +- CameraControl + +--- + +# Replace Orig. Pose Aspect Ratio 🎭🅐🅓② +## Documentation +- Class name: ADE_ReplaceOriginalPoseAspectRatio +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在调整AnimateDiff框架内原始姿势的纵横比,特别用于摄像机控制应用。它修改姿势的尺寸以匹配新的纵横比,确保动画和视觉效果根据所需的空间维度准确渲染。 + +## Input types +### Required +- poses + - 要调整的姿势列表。每个姿势是一个浮点数列表,表示摄像机控制点的空间和旋转参数。 + - Comfy dtype: CAMERACTRL_POSES + - Python dtype: list[list[float]] +- orig_pose_width + - 姿势的原始宽度,将用于计算新的纵横比。 + - Comfy dtype: INT + - Python dtype: int +- orig_pose_height + - 姿势的原始高度,将用于计算新的纵横比。 + - Comfy dtype: INT + - Python dtype: int + +## Output types +- cameractrl_poses + - Comfy dtype: CAMERACTRL_POSES + - 应用新纵横比后的调整姿势,准备在AnimateDiff框架内进行进一步处理或动画。 + - Python dtype: list[list[float]] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class CameraCtrlSetOriginalAspectRatio: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "poses":("CAMERACTRL_POSES",), + "orig_pose_width": ("INT", {"default": 1280, "min": 1, "max": BIGMAX}), + "orig_pose_height": ("INT", {"default": 720, "min": 1, "max": BIGMAX}), + } + } + + RETURN_TYPES = ("CAMERACTRL_POSES",) + FUNCTION = "set_aspect_ratio" + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses" + + def set_aspect_ratio(self, poses: list[list[float]], orig_pose_width: int, orig_pose_height: int): + return (set_original_pose_dims(poses, pose_width=orig_pose_width, pose_height=orig_pose_height),) \ No newline at end of file diff --git a/docs/ADE_SetLoraHookKeyframe.md b/docs/ADE_SetLoraHookKeyframe.md new file mode 100644 index 0000000..88e80dc --- /dev/null +++ b/docs/ADE_SetLoraHookKeyframe.md @@ -0,0 +1,50 @@ +# Set LoRA Hook Keyframes 🎭🅐🅓 +## Documentation +- Class name: ADE_SetLoraHookKeyframe +- Category: Animate Diff 🎭🅐🅓/conditioning +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点用于将一组LoRA挂钩关键帧分配给特定的LoRA挂钩组。它允许在动画时间线上定制和动态调整LoRA挂钩行为,从而在动画过程的不同阶段精确控制模型的响应。 + +## Input types +### Required +- lora_hook + - 将应用关键帧的LoRA挂钩组。此参数对于识别将接收新关键帧设置的目标挂钩组至关重要。 + - Comfy dtype: LORA_HOOK + - Python dtype: LoraHookGroup +- hook_kf + - 将分配给指定LoRA挂钩组的LoRA挂钩关键帧集。此参数定义了动画时间线上LoRA挂钩的时间、强度和其他特性。 + - Comfy dtype: LORA_HOOK_KEYFRAMES + - Python dtype: LoraHookKeyframeGroup + +## Output types +- lora_hook + - Comfy dtype: LORA_HOOK + - 应用了新关键帧集的更新LoRA挂钩组。此输出反映了对LoRA挂钩所做的更改,包含了指定的关键帧设置。 + - Python dtype: LoraHookGroup + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class SetLoraHookKeyframes: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "lora_hook": ("LORA_HOOK",), + "hook_kf": ("LORA_HOOK_KEYFRAMES",), + } + } + + RETURN_TYPES = ("LORA_HOOK",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning" + FUNCTION = "set_hook_keyframes" + + def set_hook_keyframes(self, lora_hook: LoraHookGroup, hook_kf: LoraHookKeyframeGroup): + new_lora_hook = lora_hook.clone() + new_lora_hook.set_keyframes_on_hooks(hook_kf=hook_kf) + return (new_lora_hook,) \ No newline at end of file diff --git a/docs/ADE_SigmaSchedule.md b/docs/ADE_SigmaSchedule.md new file mode 100644 index 0000000..4987ac2 --- /dev/null +++ b/docs/ADE_SigmaSchedule.md @@ -0,0 +1,46 @@ +# Create Sigma Schedule 🎭🅐🅓 +## Documentation +- Class name: ADE_SigmaSchedule +- Category: Animate Diff 🎭🅐🅓/sample settings/sigma schedule +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_SigmaSchedule节点旨在根据给定的beta计划生成一个sigma计划。它抽象了sigma计划创建的复杂性,提供了一种简便的方法来获得符合特定模型采样类型和配置的sigma计划。 + +## Input types +### Required +- beta_schedule + - 指定用于生成sigma计划的beta计划。此参数至关重要,因为它决定了将派生sigma计划的基本配置。 + - Comfy dtype: COMBO[STRING] + - Python dtype: BetaSchedules.ALIAS_ACTIVE_LIST + +## Output types +- sigma_schedule + - Comfy dtype: SIGMA_SCHEDULE + - 输出一个sigma计划对象,它对于定义基于扩散的生成模型中的噪声级别进程至关重要。 + - Python dtype: SigmaSchedule (custom type from the animatediff package) + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class SigmaScheduleNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "beta_schedule": (BetaSchedules.ALIAS_ACTIVE_LIST,), + } + } + + RETURN_TYPES = ("SIGMA_SCHEDULE",) + CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule" + FUNCTION = "get_sigma_schedule" + + def get_sigma_schedule(self, beta_schedule: str): + model_type = ModelSamplingType.from_alias(ModelSamplingType.EPS) + new_model_sampling = BetaSchedules._to_model_sampling(alias=beta_schedule, + model_type=model_type) + return (SigmaSchedule(model_sampling=new_model_sampling, model_type=model_type),) \ No newline at end of file diff --git a/docs/ADE_SigmaScheduleSplitAndCombine.md b/docs/ADE_SigmaScheduleSplitAndCombine.md new file mode 100644 index 0000000..c3dd89c --- /dev/null +++ b/docs/ADE_SigmaScheduleSplitAndCombine.md @@ -0,0 +1,59 @@ +# Sigma Schedule Split Combine 🎭🅐🅓 +## Documentation +- Class name: ADE_SigmaScheduleSplitAndCombine +- Category: Animate Diff 🎭🅐🅓/sample settings/sigma schedule +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在通过基于指定的权重和插值方法拆分和组合sigma计划来操作它们。它允许创建两个输入计划的混合新sigma计划,从而实现sigma值随时间的自定义进程。 + +## Input types +### Required +- schedule_Start + - 用于拆分和组合过程的起始sigma计划,决定新sigma计划的初始部分。 + - Comfy dtype: SIGMA_SCHEDULE + - Python dtype: SigmaSchedule +- schedule_End + - 用于拆分和组合过程的结束sigma计划,影响新sigma计划的后段。 + - Comfy dtype: SIGMA_SCHEDULE + - Python dtype: SigmaSchedule +- idx_split_percent + - 初始sigma计划拆分的百分比,决定两个计划之间的过渡点。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- sigma_schedule + - Comfy dtype: SIGMA_SCHEDULE + - 结果sigma计划,是根据指定的拆分百分比修改的起始和结束输入计划的混合体。 + - Python dtype: SigmaSchedule + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class SplitAndCombineSigmaScheduleNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "schedule_Start": ("SIGMA_SCHEDULE",), + "schedule_End": ("SIGMA_SCHEDULE",), + "idx_split_percent": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}) + } + } + + RETURN_TYPES = ("SIGMA_SCHEDULE",) + CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule" + FUNCTION = "get_sigma_schedule" + + def get_sigma_schedule(self, schedule_Start: SigmaSchedule, schedule_End: SigmaSchedule, idx_split_percent: float): + validate_sigma_schedule_compatibility(schedule_Start, schedule_End) + # first, calculate index to act as split; get diff from 1.0 since sigmas are flipped at this stage + idx = int((1.0-idx_split_percent) * schedule_Start.total_sigmas()) + new_sigmas = torch.cat([schedule_End.model_sampling.sigmas[:idx], schedule_Start.model_sampling.sigmas[idx:]], dim=0) + new_schedule = schedule_Start.clone() + new_schedule.model_sampling.set_sigmas(new_sigmas) + return (new_schedule,) \ No newline at end of file diff --git a/docs/ADE_SigmaScheduleWeightedAverage.md b/docs/ADE_SigmaScheduleWeightedAverage.md new file mode 100644 index 0000000..95e9492 --- /dev/null +++ b/docs/ADE_SigmaScheduleWeightedAverage.md @@ -0,0 +1,57 @@ +# Sigma Schedule Weighted Mean 🎭🅐🅓 +## Documentation +- Class name: ADE_SigmaScheduleWeightedAverage +- Category: Animate Diff 🎭🅐🅓/sample settings/sigma schedule +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在通过计算两个提供的sigma计划的加权平均值来创建一个新的sigma计划。它允许根据指定的加权因子将两个计划的特性混合成一个新的计划。 + +## Input types +### Required +- schedule_A + - 第一个要混合的sigma计划。它是加权平均计算的基础之一。 + - Comfy dtype: SIGMA_SCHEDULE + - Python dtype: SigmaSchedule +- schedule_B + - 第二个与第一个混合的sigma计划。它为加权平均计算做出贡献,补充第一个计划。 + - Comfy dtype: SIGMA_SCHEDULE + - Python dtype: SigmaSchedule +- weight_A + - 第一个sigma计划的加权因子。它决定了第一个计划在最终混合计划中的特性比例。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- sigma_schedule + - Comfy dtype: SIGMA_SCHEDULE + - 根据指定的加权因子混合两个输入计划后的结果sigma计划。 + - Python dtype: SigmaSchedule + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class WeightedAverageSigmaScheduleNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "schedule_A": ("SIGMA_SCHEDULE",), + "schedule_B": ("SIGMA_SCHEDULE",), + "weight_A": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}), + } + } + + RETURN_TYPES = ("SIGMA_SCHEDULE",) + CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule" + FUNCTION = "get_sigma_schedule" + + def get_sigma_schedule(self, schedule_A: SigmaSchedule, schedule_B: SigmaSchedule, weight_A: float): + validate_sigma_schedule_compatibility(schedule_A, schedule_B) + new_sigmas = schedule_A.model_sampling.sigmas * weight_A + schedule_B.model_sampling.sigmas * (1-weight_A) + combo_schedule = schedule_A.clone() + combo_schedule.model_sampling.set_sigmas(new_sigmas) + return (combo_schedule,) \ No newline at end of file diff --git a/docs/ADE_SigmaScheduleWeightedAverageInterp.md b/docs/ADE_SigmaScheduleWeightedAverageInterp.md new file mode 100644 index 0000000..c9c2e31 --- /dev/null +++ b/docs/ADE_SigmaScheduleWeightedAverageInterp.md @@ -0,0 +1,72 @@ +# Sigma Schedule Interpolated Mean 🎭🅐🅓 +## Documentation +- Class name: ADE_SigmaScheduleWeightedAverageInterp +- Category: Animate Diff 🎭🅐🅓/sample settings/sigma schedule +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点旨在通过基于指定的权重范围和插值方法在两个给定的sigma计划之间进行插值来创建一个新的sigma计划。它有效地将两个输入计划的特性融合成一个新的计划,从而在扩散过程中实现动态调整。 + +## Input types +### Required +- schedule_A + - 第一个要插值的sigma计划。 + - Comfy dtype: SIGMA_SCHEDULE + - Python dtype: SigmaSchedule +- schedule_B + - 第二个要插值的sigma计划。 + - Comfy dtype: SIGMA_SCHEDULE + - Python dtype: SigmaSchedule +- weight_A_Start + - 插值中第一个sigma计划的起始权重。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_A_End + - 插值中第一个sigma计划的结束权重。 + - Comfy dtype: FLOAT + - Python dtype: float +- interpolation + - 用于混合sigma计划的插值方法。 + - Comfy dtype: COMBO[STRING] + - Python dtype: InterpolationMethod + +## Output types +- sigma_schedule + - Comfy dtype: SIGMA_SCHEDULE + - 插值后的结果sigma计划。 + - Python dtype: SigmaSchedule + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class InterpolatedWeightedAverageSigmaScheduleNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "schedule_A": ("SIGMA_SCHEDULE",), + "schedule_B": ("SIGMA_SCHEDULE",), + "weight_A_Start": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}), + "weight_A_End": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}), + "interpolation": (InterpolationMethod._LIST,), + } + } + + RETURN_TYPES = ("SIGMA_SCHEDULE",) + CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule" + FUNCTION = "get_sigma_schedule" + + def get_sigma_schedule(self, schedule_A: SigmaSchedule, schedule_B: SigmaSchedule, + weight_A_Start: float, weight_A_End: float, interpolation: str): + validate_sigma_schedule_compatibility(schedule_A, schedule_B) + # get reverse weights, since sigmas are currently reversed + weights = InterpolationMethod.get_weights(num_from=weight_A_Start, num_to=weight_A_End, + length=schedule_A.total_sigmas(), method=interpolation, reverse=True) + weights = weights.to(schedule_A.model_sampling.sigmas.dtype).to(schedule_A.model_sampling.sigmas.device) + new_sigmas = schedule_A.model_sampling.sigmas * weights + schedule_B.model_sampling.sigmas * (1.0-weights) + combo_schedule = schedule_A.clone() + combo_schedule.model_sampling.set_sigmas(new_sigmas) + return (combo_schedule,) \ No newline at end of file diff --git a/docs/ADE_TimestepsConditioning.md b/docs/ADE_TimestepsConditioning.md new file mode 100644 index 0000000..ef33ebf --- /dev/null +++ b/docs/ADE_TimestepsConditioning.md @@ -0,0 +1,48 @@ +# Timesteps Conditioning 🎭🅐🅓 +## Documentation +- Class name: ADE_TimestepsConditioning +- Category: Animate Diff 🎭🅐🅓/conditioning +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点专注于调整在动画或扩散过程中特定条件的应用时间,允许精确控制在动画进程中引入某些效果或修改的时间。这使得条件的应用更加动态和细致,从而提高生成内容的整体质量和灵活性。 + +## Input types +### Required +- start_percent + - 指定应用给定条件的起始点(占总动画长度的百分比),允许精确的时间控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - 定义条件应用的结束点(占总动画长度的百分比),使效果能够定制到动画的特定阶段。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- timesteps_cond + - Comfy dtype: TIMESTEPS_COND + - 条件的时间调整,封装为一种特定类型,表示在整个动画或扩散过程中的条件调度。 + - Python dtype: TimestepsCond + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class ConditioningTimestepsNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}) + } + } + + RETURN_TYPES = ("TIMESTEPS_COND",) + CATEGORY = "Animate Diff 🎭🅐🅓/conditioning" + FUNCTION = "create_schedule" + + def create_schedule(self, start_percent: float, end_percent: float): + return (TimestepsCond(start_percent=start_percent, end_percent=end_percent),) \ No newline at end of file diff --git a/docs/ADE_UpscaleAndVAEEncode.md b/docs/ADE_UpscaleAndVAEEncode.md new file mode 100644 index 0000000..12af467 --- /dev/null +++ b/docs/ADE_UpscaleAndVAEEncode.md @@ -0,0 +1,74 @@ +# Scale Ref Image and VAE Encode 🎭🅐🅓② +## Documentation +- Class name: ADE_UpscaleAndVAEEncode +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_UpscaleAndVAEEncode节点旨在通过首先将图像放大到更高分辨率,然后使用变分自编码器(VAE)将其编码为潜在表示来处理图像。此节点是AnimateDiff套件的一部分,专门用于在应用进一步的生成或转换过程之前增强图像质量。 + +## Input types +### Required +- image + - 表示要放大和编码的输入图像的参数。它在确定最终潜在表示的质量和分辨率方面起着关键作用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- vae + - 指定用于将放大的图像编码为其潜在表示的变分自编码器模型。它影响编码效率和生成的潜在空间的质量。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- latent_size + - 表示要生成的潜在表示的大小。它决定输出潜在空间的维度。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- scale_method + - 定义用于放大图像的方法。它影响放大图像的质量。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- crop + - 指定放大后应用的裁剪方法,影响最终图像的构图。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +## Output types +- latent + - Comfy dtype: LATENT + - 输出是输入图像的潜在表示,由VAE在放大后编码。它以压缩形式捕捉图像的基本特征,适合进一步的生成任务。 + - Python dtype: Dict[str, torch.Tensor] + +## Usage tips +- Infra type: GPU +- Common nodes: unknown + +## Source code +```python +class UpscaleAndVaeEncode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "image": ("IMAGE",), + "vae": ("VAE",), + "latent_size": ("LATENT",), + "scale_method": (ScaleMethods._LIST_IMAGE,), + "crop": (CropMethods._LIST, {"default": CropMethods.CENTER},), + } + } + + RETURN_TYPES = ("LATENT",) + FUNCTION = "preprocess_images" + + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V" + + def preprocess_images(self, image: torch.Tensor, vae: VAE, latent_size: torch.Tensor, scale_method: str, crop: str): + b, c, h, w = latent_size["samples"].size() + image = image.movedim(-1,1) + image = comfy.utils.common_upscale(samples=image, width=w*8, height=h*8, upscale_method=scale_method, crop=crop) + image = image.movedim(1,-1) + # now that images are the expected size, VAEEncode them + try: # account for old ComfyUI versions (TODO: remove this when other changes require ComfyUI update) + if not hasattr(vae, "vae_encode_crop_pixels"): + image = VAEEncode.vae_encode_crop_pixels(image) + except Exception: + pass + return ({"samples": vae.encode(image[:,:,:,:3])},) \ No newline at end of file diff --git a/docs/ADE_UseEvolvedSampling.md b/docs/ADE_UseEvolvedSampling.md new file mode 100644 index 0000000..6621107 --- /dev/null +++ b/docs/ADE_UseEvolvedSampling.md @@ -0,0 +1,113 @@ +# Use Evolved Sampling 🎭🅐🅓② +## Documentation +- Class name: ADE_UseEvolvedSampling +- Category: Animate Diff 🎭🅐🅓/② Gen2 nodes ② +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADE_UseEvolvedSampling节点将先进的采样技术集成到动画扩散过程中,利用进化模型采样配置来增强生成动画的质量和效率。它根据模型配置和动态条件调整采样过程,旨在优化动画输出的视觉保真度和计算性能。 + +## Input types +### Required +- model + - 指定用于动画扩散过程的模型,影响生成动画的整体质量和特性。 + - Comfy dtype: MODEL + - Python dtype: Model +- beta_schedule + - 决定在采样过程中应用的beta计划,影响动画过渡的平滑度和质量。 + - Comfy dtype: COMBO[STRING] + - Python dtype: BetaSchedules.ALIAS_LIST + +### Optional +- m_models + - 可选。为动画过程提供额外的模型,可能增强输出的多样性和丰富性。 + - Comfy dtype: M_MODELS + - Python dtype: list +- context_options + - 可选。定义可以修改采样过程行为的上下文特定选项,定制其以满足特定需求或偏好。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: dict +- sample_settings + - 可选。指定与采样过程相关的设置,如分辨率和时间调整,直接影响动画的视觉质量。 + - Comfy dtype: SAMPLE_SETTINGS + - Python dtype: dict + +## Output types +- model + - Comfy dtype: MODEL + - 增强的模型实例,配备进化的采样配置以改进动画扩散。 + - Python dtype: Model + +## Usage tips +- Infra type: CPU + + +## Source code +```python +class UseEvolvedSamplingNode: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "beta_schedule": (BetaSchedules.ALIAS_LIST, {"default": BetaSchedules.AUTOSELECT}), + }, + "optional": { + "m_models": ("M_MODELS",), + "context_options": ("CONTEXT_OPTIONS",), + "sample_settings": ("SAMPLE_SETTINGS",), + #"beta_schedule_override": ("BETA_SCHEDULE",), + } + } + + RETURN_TYPES = ("MODEL",) + CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②" + FUNCTION = "use_evolved_sampling" + + def use_evolved_sampling(self, model: ModelPatcher, beta_schedule: str, m_models: MotionModelGroup=None, context_options: ContextOptionsGroup=None, + sample_settings: SampleSettings=None, beta_schedule_override=None): + if m_models is not None: + m_models = m_models.clone() + # for each motion model, confirm that it is compatible with SD model + for motion_model in m_models.models: + validate_model_compatibility_gen2(model=model, motion_model=motion_model) + # create injection params + model_name_list = [motion_model.model.mm_info.mm_name for motion_model in m_models.models] + model_names = ",".join(model_name_list) + # TODO: check if any apply_v2_properly is set to False + params = InjectionParams(unlimited_area_hack=False, model_name=model_names) + else: + params = InjectionParams() + # apply context options + if context_options: + params.set_context(context_options) + # need to use a ModelPatcher that supports injection of motion modules into unet + model = ModelPatcherAndInjector.create_from(model, hooks_only=True) + model.motion_models = m_models + model.sample_settings = sample_settings if sample_settings is not None else SampleSettings() + model.motion_injection_params = params + + if model.sample_settings.custom_cfg is not None: + logger.info("[Sample Settings] custom_cfg is set; will override any KSampler cfg values or patches.") + + if model.sample_settings.sigma_schedule is not None: + logger.info("[Sample Settings] sigma_schedule is set; will override beta_schedule.") + model.add_object_patch("model_sampling", model.sample_settings.sigma_schedule.clone().model_sampling) + else: + # save model_sampling from BetaSchedule as object patch + # if autoselect, get suggested beta_schedule from motion model + if beta_schedule == BetaSchedules.AUTOSELECT: + if model.motion_models is None or model.motion_models.is_empty(): + beta_schedule = BetaSchedules.USE_EXISTING + else: + beta_schedule = model.motion_models[0].model.get_best_beta_schedule(log=True) + new_model_sampling = BetaSchedules.to_model_sampling(beta_schedule, model) + if new_model_sampling is not None: + model.add_object_patch("model_sampling", new_model_sampling) + + del m_models + return (model,) \ No newline at end of file diff --git a/docs/AnimateDiffLoaderV1.md b/docs/AnimateDiffLoaderV1.md new file mode 100644 index 0000000..c3db36c --- /dev/null +++ b/docs/AnimateDiffLoaderV1.md @@ -0,0 +1,97 @@ +# 🚫AnimateDiff Loader [DEPRECATED] 🎭🅐🅓 +## Documentation +- Class name: AnimateDiffLoaderV1 +- Category: +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点用于初始化和准备AnimateDiff模型,便于其进行动画生成任务。它抽象了加载模型的复杂性,确保其正确设置以供后续使用。 + +## Input types +### Required +- model + - 该参数用于指定要加载的AnimateDiff模型,使节点能够正确初始化和准备模型以进行动画任务。 + - Comfy dtype: MODEL + - Python dtype: str +- latents + - 该参数允许指定初始化模型可能需要的潜在向量,提供一种自定义模型初始状态的方法。 + - Comfy dtype: LATENT + - Python dtype: str +- model_name + - 用于从可用选项中选择特定运动模型,该参数确保根据提供的名称加载正确版本的AnimateDiff模型。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- unlimited_area_hack + - 一个布尔参数,启用时应用特定的黑客技术以绕过可动画区域的限制,为动画任务提供更多灵活性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- beta_schedule + - 指定在模型操作期间使用的beta计划,影响AnimateDiff模型的行为和性能。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +## Output types +- model + - Comfy dtype: MODEL + - 表示已加载的AnimateDiff模型,准备进行动画生成任务。 + - Python dtype: str +- latent + - Comfy dtype: LATENT + - 输出与已加载模型相关的潜在向量,可用于进一步的自定义或动画过程。 + - Python dtype: str + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class AnimateDiffLoader_Deprecated: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "latents": ("LATENT",), + "model_name": (get_available_motion_models(),), + "unlimited_area_hack": ("BOOLEAN", {"default": False},), + "beta_schedule": (BetaSchedules.get_alias_list_with_first_element(BetaSchedules.SQRT_LINEAR),), + }, + } + + RETURN_TYPES = ("MODEL", "LATENT") + CATEGORY = "" + FUNCTION = "load_mm_and_inject_params" + + def load_mm_and_inject_params( + self, + model: ModelPatcher, + latents: Dict[str, torch.Tensor], + model_name: str, unlimited_area_hack: bool, beta_schedule: str, + ): + # load motion module + motion_model = load_motion_module_gen1(model_name, model) + # get total frames + init_frames_len = len(latents["samples"]) # deprecated - no longer used for anything lol + # set injection params + params = InjectionParams( + unlimited_area_hack=unlimited_area_hack, + apply_mm_groupnorm_hack=True, + model_name=model_name, + apply_v2_properly=False, + ) + # inject for use in sampling code + model = ModelPatcherAndInjector.create_from(model, hooks_only=True) + model.motion_models = MotionModelGroup(motion_model) + model.motion_injection_params = params + + # save model sampling from BetaSchedule as object patch + # if autoselect, get suggested beta_schedule from motion model + if beta_schedule == BetaSchedules.AUTOSELECT and not model.motion_models.is_empty(): + beta_schedule = model.motion_models[0].model.get_best_beta_schedule(log=True) + new_model_sampling = BetaSchedules.to_model_sampling(beta_schedule, model) + if new_model_sampling is not None: + model.add_object_patch("model_sampling", new_model_sampling) + + del motion_model + return (model, latents) \ No newline at end of file diff --git a/docs/CheckpointLoader%7Cpysssss.md b/docs/CheckpointLoader%7Cpysssss.md new file mode 100644 index 0000000..dbc922e --- /dev/null +++ b/docs/CheckpointLoader%7Cpysssss.md @@ -0,0 +1,57 @@ +# Checkpoint Loader 🐍 +## Documentation +- Class name: CheckpointLoader|pysssss +- Category: loaders +- Output node: False +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +此节点是CheckpointLoaderSimple的一个专门版本,增强了对图像的处理能力以及检查点名称的处理。它有助于加载模型检查点,重点是图像相关配置,使其适用于视觉内容为主要关注点的场景。 + +## Input types +### Required +- ckpt_name + - 指定要加载的检查点名称。此参数至关重要,因为它决定节点将尝试加载哪个特定检查点,从而影响模型的配置及其后续性能。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +## Output types +- model + - Comfy dtype: MODEL + - 加载的模型对象,这是检查点加载过程的主要输出。它代表模型的整体,准备进一步使用或分析。 + - Python dtype: torch.nn.Module +- clip + - Comfy dtype: CLIP + - 与加载的检查点相关的CLIP模型(如果适用)。这对于涉及文本和图像理解或生成的任务相关。 + - Python dtype: torch.nn.Module +- vae + - Comfy dtype: VAE + - 从检查点加载的VAE(变分自编码器)组件。这对于涉及图像生成或操作的任务至关重要。 + - Python dtype: torch.nn.Module + +## Usage tips +- Infra type: CPU + + +## Source code +```python +class CheckpointLoaderSimpleWithImages(CheckpointLoaderSimple): + @classmethod + def INPUT_TYPES(s): + types = super().INPUT_TYPES() + names = types["required"]["ckpt_name"][0] + populate_items(names, "checkpoints") + return types + + def load_checkpoint(self, **kwargs): + kwargs["ckpt_name"] = kwargs["ckpt_name"]["content"] + return super().load_checkpoint(**kwargs) \ No newline at end of file diff --git a/docs/CheckpointLoaderSimpleWithNoiseSelect.md b/docs/CheckpointLoaderSimpleWithNoiseSelect.md new file mode 100644 index 0000000..8303698 --- /dev/null +++ b/docs/CheckpointLoaderSimpleWithNoiseSelect.md @@ -0,0 +1,86 @@ +# Load Checkpoint w/ Noise Select 🎭🅐🅓 +## Documentation +- Class name: CheckpointLoaderSimpleWithNoiseSelect +- Category: Animate Diff 🎭🅐🅓/extras +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +此节点专门用于加载模型检查点,重点是噪声选择,允许在生成任务中更细致地控制模型的初始化和行为。它通过结合beta计划调整和可选的噪声缩放因子扩展了标准检查点加载功能,以满足高级自定义需求。 + +## Input types +### Required +- ckpt_name + - 指定要加载的检查点名称。此参数对于从预定义的可用检查点列表中识别特定模型检查点文件至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- beta_schedule + - 决定应用于模型的beta计划。此参数允许调整模型的采样行为,增强模型性能的灵活性。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +### Optional +- use_custom_scale_factor + - 一个布尔标志,指示是否应用自定义噪声缩放因子。设置为true时,它可以微调噪声对模型输出的影响。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- scale_factor + - 定义噪声缩放因子的大小,前提是'use_custom_scale_factor'为true。它允许对应用于模型的噪声水平进行精确控制。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- model + - Comfy dtype: MODEL + - 加载的模型,按照指定的beta计划和噪声缩放选项进行配置。 + - Python dtype: torch.nn.Module +- clip + - Comfy dtype: CLIP + - 如果适用,加载检查点相关的CLIP模型。 + - Python dtype: torch.nn.Module +- vae + - Comfy dtype: VAE + - 如果适用,加载检查点相关的VAE模型。 + - Python dtype: torch.nn.Module + +## Usage tips +- Infra type: GPU + + +## Source code +```python +class CheckpointLoaderSimpleWithNoiseSelect: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "ckpt_name": (folder_paths.get_filename_list("checkpoints"), ), + "beta_schedule": (BetaSchedules.ALIAS_LIST, {"default": BetaSchedules.USE_EXISTING}, ) + }, + "optional": { + "use_custom_scale_factor": ("BOOLEAN", {"default": False}), + "scale_factor": ("FLOAT", {"default": 0.18215, "min": 0.0, "max": 1.0, "step": 0.00001}) + } + } + RETURN_TYPES = ("MODEL", "CLIP", "VAE") + FUNCTION = "load_checkpoint" + + CATEGORY = "Animate Diff 🎭🅐🅓/extras" + + def load_checkpoint(self, ckpt_name, beta_schedule, output_vae=True, output_clip=True, use_custom_scale_factor=False, scale_factor=0.18215): + ckpt_path = folder_paths.get_full_path("checkpoints", ckpt_name) + out = load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths("embeddings")) + # register chosen beta schedule on model - convert to beta_schedule name recognized by ComfyUI + new_model_sampling = BetaSchedules.to_model_sampling(beta_schedule, out[0]) + if new_model_sampling is not None: + out[0].model.model_sampling = new_model_sampling + if use_custom_scale_factor: + out[0].model.latent_format.scale_factor = scale_factor + return out \ No newline at end of file diff --git a/docs/ConstrainImage%7Cpysssss.md b/docs/ConstrainImage%7Cpysssss.md new file mode 100644 index 0000000..a5f845b --- /dev/null +++ b/docs/ConstrainImage%7Cpysssss.md @@ -0,0 +1,107 @@ +# Constrain Image 🐍 +## Documentation +- Class name: ConstrainImage|pysssss +- Category: image +- Output node: False +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +此节点旨在调整图像的尺寸以适应指定的最大和最小尺寸,同时保持图像的纵横比。如果图像超过最大尺寸,它可以选择性地裁剪图像。 + +## Input types +### Required +- images + - 要约束的图像。此参数至关重要,因为它直接影响节点的核心功能,即调整大小和潜在裁剪图像以满足指定的尺寸约束。 + - Comfy dtype: IMAGE + - Python dtype: List[Image] +- max_width + - 指定图像在处理后可以具有的最大宽度。它在确定图像是否以及如何需要调整大小方面起关键作用。 + - Comfy dtype: INT + - Python dtype: int +- max_height + - 定义图像在处理后可以具有的最大高度,影响调整大小逻辑以确保图像适合指定的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- min_width + - 设置图像应具有的最小宽度,确保图像不会调整到低于此宽度。 + - Comfy dtype: INT + - Python dtype: int +- min_height + - 决定图像应具有的最小高度,防止图像调整到低于此高度。 + - Comfy dtype: INT + - Python dtype: int +- crop_if_required + - 一个标志,指示如果图像超过最大尺寸,是否应裁剪图像,影响最终输出可能会改变图像的构图。 + - Comfy dtype: COMBO[STRING] + - Python dtype: bool + +## Output types +- image + - Comfy dtype: IMAGE + - 已处理的图像,调整大小并在必要时裁剪以适应指定的约束。 + - Python dtype: List[Image] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class ConstrainImage: + """ + A node that constrains an image to a maximum and minimum size while maintaining aspect ratio. + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "images": ("IMAGE",), + "max_width": ("INT", {"default": 1024, "min": 0}), + "max_height": ("INT", {"default": 1024, "min": 0}), + "min_width": ("INT", {"default": 0, "min": 0}), + "min_height": ("INT", {"default": 0, "min": 0}), + "crop_if_required": (["yes", "no"], {"default": "no"}), + }, + } + + RETURN_TYPES = ("IMAGE",) + FUNCTION = "constrain_image" + CATEGORY = "image" + OUTPUT_IS_LIST = (True,) + + def constrain_image(self, images, max_width, max_height, min_width, min_height, crop_if_required): + crop_if_required = crop_if_required == "yes" + results = [] + for image in images: + i = 255. * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)).convert("RGB") + + current_width, current_height = img.size + aspect_ratio = current_width / current_height + + constrained_width = max(min(current_width, min_width), max_width) + constrained_height = max(min(current_height, min_height), max_height) + + if constrained_width / constrained_height > aspect_ratio: + constrained_width = max(int(constrained_height * aspect_ratio), min_width) + if crop_if_required: + constrained_height = int(current_height / (current_width / constrained_width)) + else: + constrained_height = max(int(constrained_width / aspect_ratio), min_height) + if crop_if_required: + constrained_width = int(current_width / (current_height / constrained_height)) + + resized_image = img.resize((constrained_width, constrained_height), Image.LANCZOS) + + if crop_if_required and (constrained_width > max_width or constrained_height > max_height): + left = max((constrained_width - max_width) // 2, 0) + top = max((constrained_height - max_height) // 2, 0) + right = min(constrained_width, max_width) + left + bottom = min(constrained_height, max_height) + top + resized_image = resized_image.crop((left, top, right, bottom)) + + resized_image = np.array(resized_image).astype(np.float32) / 255.0 + resized_image = torch.from_numpy(resized_image)[None,] + results.append(resized_image) + + return (results,) \ No newline at end of file diff --git a/docs/ConstrainImageforVideo%7Cpysssss.md b/docs/ConstrainImageforVideo%7Cpysssss.md new file mode 100644 index 0000000..5e320c1 --- /dev/null +++ b/docs/ConstrainImageforVideo%7Cpysssss.md @@ -0,0 +1,108 @@ +# Constrain Image for Video 🐍 +## Documentation +- Class name: ConstrainImageforVideo|pysssss +- Category: image +- Output node: False +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +此节点旨在调整图像的尺寸以适应指定的最大和最小尺寸,同时保持纵横比。它提供了在必要时裁剪图像以满足尺寸约束的选项。 + +## Input types +### Required +- images + - 要处理的图像。它们将被调整以适应指定的尺寸约束,同时保持其纵横比。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- max_width + - 图像允许的最大宽度。宽度超过此值的图像将调整为此宽度。 + - Comfy dtype: INT + - Python dtype: int +- max_height + - 图像允许的最大高度。高度超过此值的图像将调整为此高度。 + - Comfy dtype: INT + - Python dtype: int +- min_width + - 图像允许的最小宽度。宽度小于此值的图像将调整为此宽度。 + - Comfy dtype: INT + - Python dtype: int +- min_height + - 图像允许的最小高度。高度小于此值的图像将调整为此高度。 + - Comfy dtype: INT + - Python dtype: int +- crop_if_required + - 决定是否在调整大小不足以满足尺寸约束时裁剪图像。 + - Comfy dtype: COMBO[STRING] + - Python dtype: bool + +## Output types +- IMAGE + - Comfy dtype: IMAGE + - 已处理的图像,调整大小并在必要时裁剪以适应指定的尺寸约束。 + - Python dtype: List[torch.Tensor] + +## Usage tips +- Infra type: GPU +- Common nodes: unknown + +## Source code +```python +class ConstrainImageforVideo: + """ + A node that constrains an image to a maximum and minimum size while maintaining aspect ratio. + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "images": ("IMAGE",), + "max_width": ("INT", {"default": 1024, "min": 0}), + "max_height": ("INT", {"default": 1024, "min": 0}), + "min_width": ("INT", {"default": 0, "min": 0}), + "min_height": ("INT", {"default": 0, "min": 0}), + "crop_if_required": (["yes", "no"], {"default": "no"}), + }, + } + + RETURN_TYPES = ("IMAGE",) + RETURN_NAMES = ("IMAGE",) + FUNCTION = "constrain_image_for_video" + CATEGORY = "image" + + def constrain_image_for_video(self, images, max_width, max_height, min_width, min_height, crop_if_required): + crop_if_required = crop_if_required == "yes" + results = [] + for image in images: + i = 255. * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)).convert("RGB") + + current_width, current_height = img.size + aspect_ratio = current_width / current_height + + constrained_width = max(min(current_width, min_width), max_width) + constrained_height = max(min(current_height, min_height), max_height) + + if constrained_width / constrained_height > aspect_ratio: + constrained_width = max(int(constrained_height * aspect_ratio), min_width) + if crop_if_required: + constrained_height = int(current_height / (current_width / constrained_width)) + else: + constrained_height = max(int(constrained_width / aspect_ratio), min_height) + if crop_if_required: + constrained_width = int(current_width / (current_height / constrained_height)) + + resized_image = img.resize((constrained_width, constrained_height), Image.LANCZOS) + + if crop_if_required and (constrained_width > max_width or constrained_height > max_height): + left = max((constrained_width - max_width) // 2, 0) + top = max((constrained_height - max_height) // 2, 0) + right = min(constrained_width, max_width) + left + bottom = min(constrained_height, max_height) + top + resized_image = resized_image.crop((left, top, right, bottom)) + + resized_image = np.array(resized_image).astype(np.float32) / 255.0 + resized_image = torch.from_numpy(resized_image)[None,] + results.append(resized_image) + all_images = torch.cat(results, dim=0) + + return (all_images, all_images.size(0),) \ No newline at end of file diff --git a/docs/LoadText%7Cpysssss.md b/docs/LoadText%7Cpysssss.md new file mode 100644 index 0000000..3c3716a --- /dev/null +++ b/docs/LoadText%7Cpysssss.md @@ -0,0 +1,70 @@ +# Load Text 🐍 +## Documentation +- Class name: LoadText|pysssss +- Category: utils +- Output node: False +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +LoadText节点用于从指定目录中的文件加载文本内容。它有助于检索文本数据,使其在工作流程中进一步处理或显示。 + +## Input types +### Required +- root_dir + - 指定将从中加载文件的目录。对于定位文件并确保使用正确的路径进行文件访问至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- file + - 要加载的特定文件。此参数对于确定要检索和加载的文本文件的内容至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +## Output types +- string + - Comfy dtype: STRING + - 返回指定文本文件的内容,作为字符串。 + - Python dtype: str + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class LoadText(TextFileNode): + @classmethod + def IS_CHANGED(self, **kwargs): + return os.path.getmtime(self.file) + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "root_dir": (list(get_valid_dirs()), {}), + "file": (["[none]"], { + "pysssss.binding": [{ + "source": "root_dir", + "callback": [{ + "type": "set", + "target": "$this.disabled", + "value": True + }, { + "type": "fetch", + "url": "/pysssss/text-file/{$source.value}", + "then": [{ + "type": "set", + "target": "$this.options.values", + "value": "$result" + }, { + "type": "validate-combo" + }, { + "type": "set", + "target": "$this.disabled", + "value": False + }] + }], + }] + }) + }, + } + + FUNCTION = "load_text" \ No newline at end of file diff --git a/docs/LoraLoader%7Cpysssss.md b/docs/LoraLoader%7Cpysssss.md new file mode 100644 index 0000000..f73d985 --- /dev/null +++ b/docs/LoraLoader%7Cpysssss.md @@ -0,0 +1,65 @@ +# Lora Loader 🐍 +## Documentation +- Class name: LoraLoader|pysssss +- Category: loaders +- Output node: False +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +此节点专门用于加载和应用LoRA(低秩适应)调整到模型和CLIP,增强其功能或根据指定的LoRA配置改变其行为。它扩展了基础加载器的功能,还处理图像特定的LoRA配置,使其在各种多媒体应用中具有多功能性。 + +## Input types +### Required +- model + - 将应用LoRA调整的模型。它对于定义将通过LoRA增强或修改的基础架构至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 将应用LoRA调整的CLIP模型,允许增强或改变多模态理解和表示。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- lora_name + - 指定要应用的LoRA配置的名称,决定模型和CLIP的具体调整和增强。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- strength_model + - 定义应用于模型的LoRA调整的强度,允许对修改进行精细控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - 定义应用于CLIP模型的LoRA调整的强度,能够精确控制增强。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- model + - Comfy dtype: MODEL + - 应用LoRA调整的模型,反映增强或改变的功能。 + - Python dtype: torch.nn.Module +- clip + - Comfy dtype: CLIP + - 应用LoRA调整的CLIP模型,展示增强或改变的多模态理解和表示。 + - Python dtype: torch.nn.Module + +## Usage tips +- Infra type: GPU + + +## Source code +```python +class LoraLoaderWithImages(LoraLoader): + @classmethod + def INPUT_TYPES(s): + types = super().INPUT_TYPES() + names = types["required"]["lora_name"][0] + populate_items(names, "loras") + return types + + def load_lora(self, **kwargs): + kwargs["lora_name"] = kwargs["lora_name"]["content"] + return super().load_lora(**kwargs) \ No newline at end of file diff --git a/docs/MathExpression%7Cpysssss.md b/docs/MathExpression%7Cpysssss.md new file mode 100644 index 0000000..24a890f --- /dev/null +++ b/docs/MathExpression%7Cpysssss.md @@ -0,0 +1,164 @@ +# Math Expression 🐍 +## Documentation +- Class name: MathExpression|pysssss +- Category: utils +- Output node: True +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +MathExpression节点允许评估数学表达式,包括基本的算术运算、函数调用和变量引用。它支持动态和灵活的数学操作,用户可以输入包含预定义变量并使用各种数学函数的表达式。 + +## Input types +### Required +- expression + - 要评估的数学表达式。支持算术运算、函数调用和变量引用。其灵活性允许基于输入进行动态计算。 + - Comfy dtype: STRING + - Python dtype: str + +### Optional +- a + - 可以在表达式中引用的可选变量。支持整数、浮点数、图像和潜在类型,增加了数学运算的多样性。 + - Comfy dtype: INT,FLOAT,IMAGE,LATENT + - Python dtype: Union[int, float, object] +- b + - 类似于'a'的可选变量,为表达式提供了额外的参考点,以进行更复杂的计算。 + - Comfy dtype: INT,FLOAT,IMAGE,LATENT + - Python dtype: Union[int, float, object] +- c + - 作为表达式中的另一个参考点的可选变量,进一步扩展了计算的可能性。 + - Comfy dtype: INT,FLOAT,IMAGE,LATENT + - Python dtype: Union[int, float, object] + +## Output types +- int + - Comfy dtype: INT + - unknown + - Python dtype: unknown +- float + - Comfy dtype: FLOAT + - unknown + - Python dtype: unknown +- ui + - 提供一个用户界面元素来显示数学表达式评估的结果。 + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class MathExpression: + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "expression": ("STRING", {"multiline": True, "dynamicPrompts": False, "pysssss.autocomplete": { + "words": autocompleteWords, + "separator": "" + }}), + }, + "optional": { + "a": ("INT,FLOAT,IMAGE,LATENT", ), + "b": ("INT,FLOAT,IMAGE,LATENT",), + "c": ("INT,FLOAT,IMAGE,LATENT", ), + }, + "hidden": {"extra_pnginfo": "EXTRA_PNGINFO", + "prompt": "PROMPT"}, + } + + RETURN_TYPES = ("INT", "FLOAT", ) + FUNCTION = "evaluate" + CATEGORY = "utils" + OUTPUT_NODE = True + + @classmethod + def IS_CHANGED(s, expression, **kwargs): + if "random" in expression: + return float("nan") + return expression + + def get_widget_value(self, extra_pnginfo, prompt, node_name, widget_name): + workflow = extra_pnginfo["workflow"] if "workflow" in extra_pnginfo else { "nodes": [] } + node_id = None + for node in workflow["nodes"]: + name = node["type"] + if "properties" in node: + if "Node name for S&R" in node["properties"]: + name = node["properties"]["Node name for S&R"] + if name == node_name: + node_id = node["id"] + break + if "title" in node: + name = node["title"] + if name == node_name: + node_id = node["id"] + break + if node_id is not None: + values = prompt[str(node_id)] + if "inputs" in values: + if widget_name in values["inputs"]: + return values["inputs"][widget_name] + raise NameError(f"Widget not found: {node_name}.{widget_name}") + raise NameError(f"Node not found: {node_name}.{widget_name}") + + def get_size(self, target, property): + if isinstance(target, dict) and "samples" in target: + # Latent + if property == "width": + return target["samples"].shape[3] * 8 + return target["samples"].shape[2] * 8 + else: + # Image + if property == "width": + return target.shape[2] + return target.shape[1] + + def evaluate(self, expression, prompt, extra_pnginfo={}, a=None, b=None, c=None): + expression = expression.replace('\n', ' ').replace('\r', '') + node = ast.parse(expression, mode='eval').body + + lookup = {"a": a, "b": b, "c": c} + + def eval_expr(node): + if isinstance(node, ast.Num): + return node.n + elif isinstance(node, ast.BinOp): + return operators[type(node.op)](float(eval_expr(node.left)), float(eval_expr(node.right))) + elif isinstance(node, ast.UnaryOp): + return operators[type(node.op)](eval_expr(node.operand)) + elif isinstance(node, ast.Attribute): + if node.value.id in lookup: + if node.attr == "width" or node.attr == "height": + return self.get_size(lookup[node.value.id], node.attr) + + return self.get_widget_value(extra_pnginfo, prompt, node.value.id, node.attr) + elif isinstance(node, ast.Name): + if node.id in lookup: + val = lookup[node.id] + if isinstance(val, (int, float, complex)): + return val + else: + raise TypeError( + f"Compex types (LATENT/IMAGE) need to reference their width/height, e.g. {node.id}.width") + raise NameError(f"Name not found: {node.id}") + elif isinstance(node, ast.Call): + if node.func.id in functions: + fn = functions[node.func.id] + l = len(node.args) + if l < fn["args"][0] or (fn["args"][1] is not None and l > fn["args"][1]): + if fn["args"][1] is None: + toErr = " or more" + else: + toErr = f" to {fn['args'][1]}" + raise SyntaxError( + f"Invalid function call: {node.func.id} requires {fn['args'][0]}{toErr} arguments") + args = [] + for arg in node.args: + args.append(eval_expr(arg)) + return fn["call"](*args) + raise NameError(f"Invalid function call: {node.func.id}") + else: + raise TypeError(node) + + r = eval_expr(node) + return {"ui": {"value": [r]}, "result": (int(r), float(r),)} \ No newline at end of file diff --git a/docs/PlaySound%7Cpysssss.md b/docs/PlaySound%7Cpysssss.md new file mode 100644 index 0000000..1547fbf --- /dev/null +++ b/docs/PlaySound%7Cpysssss.md @@ -0,0 +1,65 @@ +# PlaySound 🐍 +## Documentation +- Class name: PlaySound|pysssss +- Category: utils +- Output node: True +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +PlaySound节点用于播放具有可自定义设置(如音量和播放模式)的音频文件。它抽象了音频播放的复杂性,提供了一个简单的界面,用于在工作流程中触发音效或通知。 + +## Input types +### Required +- any + - 作为通配符输入,允许与各种数据类型或结构灵活集成,而不强制执行特定格式。 + - Comfy dtype: * + - Python dtype: AnyType +- mode + - 决定播放条件,可以是总是播放声音或仅在队列为空时播放,从而控制声音的发生。 + - Comfy dtype: COMBO[STRING] + - Python dtype: List[str] +- volume + - 控制音频音量,范围从0到1,允许对声音级别进行精细调整。 + - Comfy dtype: FLOAT + - Python dtype: float +- file + - 指定要播放的音频文件,提供了一个默认选项,允许定制音效。 + - Comfy dtype: STRING + - Python dtype: str + +## Output types +- * + - Comfy dtype: * + - unknown + - Python dtype: unknown +- ui + - 返回一个UI组件结构,虽然在此上下文中,它似乎是一个没有活动元素的占位符。 + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class PlaySound: + @classmethod + def INPUT_TYPES(s): + return {"required": { + "any": (any, {}), + "mode": (["always", "on empty queue"], {}), + "volume": ("FLOAT", {"min": 0, "max": 1, "step": 0.1, "default": 0.5}), + "file": ("STRING", { "default": "notify.mp3" }) + }} + + FUNCTION = "nop" + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True,) + OUTPUT_NODE = True + RETURN_TYPES = (any,) + + CATEGORY = "utils" + + def IS_CHANGED(self, **kwargs): + return float("NaN") + + def nop(self, any, mode, volume, file): + return {"ui": {"a": []}, "result": (any,)} \ No newline at end of file diff --git a/docs/Repeater%7Cpysssss.md b/docs/Repeater%7Cpysssss.md new file mode 100644 index 0000000..0f32214 --- /dev/null +++ b/docs/Repeater%7Cpysssss.md @@ -0,0 +1,67 @@ +# Repeater 🐍 +## Documentation +- Class name: Repeater|pysssss +- Category: utils +- Output node: False +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +Repeater节点旨在将给定的输入源重复指定次数,可以根据所选模式输出为单个节点或多个节点。它抽象了重复数据的功能,便于在工作流程中创建多个数据实例或节点。 + +## Input types +### Required +- source + - 表示要重复的数据的源输入。其作用至关重要,因为它决定了将根据指定的重复次数重复的基本内容。 + - Comfy dtype: * + - Python dtype: AnyType +- repeats + - 指定源输入应重复的次数。此参数直接影响输出,确定重复数据的数量。 + - Comfy dtype: INT + - Python dtype: int +- output + - 确定重复数据应作为单个节点还是多个节点输出,影响输出的结构。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- node_mode + - 控制重复节点是重用还是新创建,影响节点在序列化时添加到图中的方式。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str + +## Output types +- * + - Comfy dtype: * + - 输出是重复数据的列表,根据output和node_mode参数可以具有不同的结构。 + - Python dtype: List[AnyType] + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class Repeater: + @classmethod + def INPUT_TYPES(s): + return {"required": { + "source": (any, {}), + "repeats": ("INT", {"min": 0, "max": 5000, "default": 2}), + "output": (["single", "multi"], {}), + "node_mode": (["reuse", "create"], {}), + }} + + RETURN_TYPES = (any,) + FUNCTION = "repeat" + OUTPUT_NODE = False + OUTPUT_IS_LIST = (True,) + + CATEGORY = "utils" + + def repeat(self, repeats, output, node_mode, **kwargs): + if output == "multi": + # Multi outputs are split to indiviual nodes on the frontend when serializing + return ([kwargs["source"]],) + elif node_mode == "reuse": + # When reusing we have a single input node, repeat that N times + return ([kwargs["source"]] * repeats,) + else: + # When creating new nodes, they'll be added dynamically when the graph is serialized + return ((list(kwargs.values())),) \ No newline at end of file diff --git a/docs/ReroutePrimitive%7Cpysssss.md b/docs/ReroutePrimitive%7Cpysssss.md new file mode 100644 index 0000000..19527e6 --- /dev/null +++ b/docs/ReroutePrimitive%7Cpysssss.md @@ -0,0 +1,52 @@ +# Reroute Primitive 🐍 +## Documentation +- Class name: ReroutePrimitive|pysssss +- Category: utils +- Output node: False +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +ReroutePrimitive节点旨在传递任何给定输入而不进行修改,充当数据流架构中的通用连接器。它抽象掉了数据类型的复杂性,允许灵活地重新路由数据流。 + +## Input types +### Required +- value + - 'value'参数作为节点将未修改传递的通用输入。它是节点功能的核心,使其能够在各种数据处理场景中充当多功能连接器。 + - Comfy dtype: * + - Python dtype: AnyType + +## Output types +- * + - Comfy dtype: * + - 输出是包含未修改输入值的元组,促进无缝的数据重新路由。 + - Python dtype: Tuple[AnyType] + +## Usage tips +- Infra type: CPU + + +## Source code +```python +class ReroutePrimitive: + @classmethod + def INPUT_TYPES(cls): + return { + "required": {"value": (any, )}, + } + + @classmethod + def VALIDATE_INPUTS(s, **kwargs): + return True + + RETURN_TYPES = (any,) + FUNCTION = "route" + CATEGORY = "utils" + + def route(self, value): + return (value,) \ No newline at end of file diff --git a/docs/SaveText%7Cpysssss.md b/docs/SaveText%7Cpysssss.md new file mode 100644 index 0000000..1f12516 --- /dev/null +++ b/docs/SaveText%7Cpysssss.md @@ -0,0 +1,98 @@ +# Save Text 🐍 +## Documentation +- Class name: SaveText|pysssss +- Category: utils +- Output node: False +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +SaveText节点用于将文本写入文件,并提供附加到现有文件或创建新文件的选项。它抽象了文件处理的复杂性,确保根据指定参数准确保存文本数据。 + +## Input types +### Required +- root_dir + - 指定文件将保存到的根目录。对于确定文件的保存位置并确保文件路径正确构建至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- file + - 要保存文本的文件的名称。此参数对于确定要写入或创建的特定文件至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- append + - 控制文本是应附加到现有文件还是应创建新文件。它影响文本的保存方式,是通过添加到现有内容还是重新开始。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- insert + - 决定在附加文本到现有文件之前是否应插入换行符。它影响附加文本的格式。 + - Comfy dtype: BOOLEAN + - Python dtype: str +- text + - 要写入文件的文本内容。此参数是节点功能的核心,因为它指定要保存的实际数据。 + - Comfy dtype: STRING + - Python dtype: str + +## Output types +- string + - Comfy dtype: STRING + - 返回写入文件的文本,提供操作成功的反馈。 + - Python dtype: str + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class SaveText(TextFileNode): + @classmethod + def IS_CHANGED(self, **kwargs): + return float("nan") + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "root_dir": (list(get_valid_dirs()), {}), + "file": ("STRING", {"default": "file.txt"}), + "append": (["append", "overwrite", "new only"], {}), + "insert": ("BOOLEAN", { + "default": True, "label_on": "new line", "label_off": "none", + "pysssss.binding": [{ + "source": "append", + "callback": [{ + "type": "if", + "condition": [{ + "left": "$source.value", + "op": "eq", + "right": '"append"' + }], + "true": [{ + "type": "set", + "target": "$this.disabled", + "value": False + }], + "false": [{ + "type": "set", + "target": "$this.disabled", + "value": True + }], + }] + }] + }), + "text": ("STRING", {"forceInput": True, "multiline": True}) + }, + } + + FUNCTION = "write_text" + + def write_text(self, **kwargs): + self.file = get_file(kwargs["root_dir"], kwargs["file"]) + if kwargs["append"] == "new only" and os.path.exists(self.file): + raise FileExistsError( + self.file + " already exists and 'new only' is selected.") + with open(self.file, "a+" if kwargs["append"] == "append" else "w") as f: + is_append = f.tell() != 0 + if is_append and kwargs["insert"]: + f.write("\n") + f.write(kwargs["text"]) + + return super().load_text(**kwargs) \ No newline at end of file diff --git a/docs/ShowText%7Cpysssss.md b/docs/ShowText%7Cpysssss.md new file mode 100644 index 0000000..25f7ce4 --- /dev/null +++ b/docs/ShowText%7Cpysssss.md @@ -0,0 +1,75 @@ +# Show Text 🐍 +## Documentation +- Class name: ShowText|pysssss +- Category: utils +- Output node: True +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +ShowText节点用于在工作流程中显示文本,允许基于输入文本动态更新UI元素。如果提供了特定的元数据,它还可以修改工作流程中的小部件值,从而增强交互功能。 + +## Input types +### Required +- text + - 要显示或处理的主要文本。此输入对于节点的操作至关重要,作为显示或进一步操作的主要内容。 + - Comfy dtype: STRING + - Python dtype: str + +## Output types +- string + - Comfy dtype: STRING + - unknown + - Python dtype: unknown +- ui + - 要显示的文本的UI表示,以适合UI渲染的格式封装文本。 + +## Usage tips +- Infra type: CPU + + +## Source code +```python +class ShowText: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "text": ("STRING", {"forceInput": True}), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + "extra_pnginfo": "EXTRA_PNGINFO", + }, + } + + INPUT_IS_LIST = True + RETURN_TYPES = ("STRING",) + FUNCTION = "notify" + OUTPUT_NODE = True + OUTPUT_IS_LIST = (True,) + + CATEGORY = "utils" + + def notify(self, text, unique_id=None, extra_pnginfo=None): + if unique_id is not None and extra_pnginfo is not None: + if not isinstance(extra_pnginfo, list): + print("Error: extra_pnginfo is not a list") + elif ( + not isinstance(extra_pnginfo[0], dict) + or "workflow" not in extra_pnginfo[0] + ): + print("Error: extra_pnginfo[0] is not a dict or missing 'workflow' key") + else: + workflow = extra_pnginfo[0]["workflow"] + node = next( + (x for x in workflow["nodes"] if str(x["id"]) == str(unique_id[0])), + None, + ) + if node: + node["widgets_values"] = [text] + + return {"ui": {"text": text}, "result": (text,)} \ No newline at end of file diff --git a/docs/StringFunction%7Cpysssss.md b/docs/StringFunction%7Cpysssss.md new file mode 100644 index 0000000..9f754d2 --- /dev/null +++ b/docs/StringFunction%7Cpysssss.md @@ -0,0 +1,91 @@ +# String Function 🐍 +## Documentation +- Class name: StringFunction|pysssss +- Category: utils +- Output node: True +- Repo Ref: https://github.com/pythongosssss/ComfyUI-Custom-Scripts + +String Function节点提供了操作字符串的实用工具,包括追加、替换以及可选的标签清理。它将复杂的字符串操作抽象为一个简单的界面,满足各种文本处理需求。 + +## Input types +### Required +- action + - 指定要执行的字符串操作,如在文本输入中追加或替换内容。 + - Comfy dtype: COMBO[STRING] + - Python dtype: Tuple[List[str], Dict] +- tidy_tags + - 决定是否清理文本输入中的HTML标签,提供整理或保持原样的选项。 + - Comfy dtype: COMBO[STRING] + - Python dtype: Tuple[List[str], Dict] +- text_a + - 用于操作的主要文本输入。 + - Comfy dtype: STRING + - Python dtype: str +- text_b + - 用于操作的次要文本输入,与'text_a'一起使用。 + - Comfy dtype: STRING + - Python dtype: str + +### Optional +- text_c + - 可选的第三个文本输入用于操作。 + - Comfy dtype: STRING + - Python dtype: str + +## Output types +- string + - Comfy dtype: STRING + - 字符串操作的结果,作为单个字符串返回。 + - Python dtype: str + +## Usage tips +- Infra type: CPU + + +## Source code +```python +class StringFunction: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "action": (["append", "replace"], {}), + "tidy_tags": (["yes", "no"], {}), + "text_a": ("STRING", {"multiline": True, "dynamicPrompts": False}), + "text_b": ("STRING", {"multiline": True, "dynamicPrompts": False}), + }, + "optional": { + "text_c": ("STRING", {"multiline": True, "dynamicPrompts": False}) + } + } + + RETURN_TYPES = ("STRING",) + FUNCTION = "exec" + CATEGORY = "utils" + OUTPUT_NODE = True + + def exec(self, action, tidy_tags, text_a, text_b, text_c=""): + # Converted inputs are sent as the string of 'undefined' if not connected + if text_a == "undefined": + text_a = "" + if text_b == "undefined": + text_b = "" + if text_c == "undefined": + text_c = "" + + tidy_tags = tidy_tags == "yes" + out = "" + if action == "append": + out = (", " if tidy_tags else "").join(filter(None, [text_a, text_b, text_c])) + else: + if text_c is None: + text_c = "" + if text_b.startswith("/") and text_b.endsWith("/"): + regex = text_b[1:-1] + out = re.sub(regex, text_c, text_a) + else: + out = text_a.replace(text_b, text_c) + if tidy_tags: + out = out.replace(" ", " ").replace(" ,", ",").replace(",,", ",").replace(",,", ",") + return {"ui": {"text": (out,)}, "result": (out,)} \ No newline at end of file diff --git a/docs/VHS_LoadAudioUpload.md b/docs/VHS_LoadAudioUpload.md new file mode 100644 index 0000000..08ed9be --- /dev/null +++ b/docs/VHS_LoadAudioUpload.md @@ -0,0 +1,77 @@ +# Load Audio (Upload)🎥🅥🅗🅢 +## Documentation +- Class name: VHS_LoadAudioUpload +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +VHS_LoadAudioUpload节点用于在视频助手套件中上传和处理音频文件。它允许用户上传音频文件,并指定音频处理的开始时间和持续时间。此节点对于需要音频操作或分析的应用至关重要,为套件中的进一步音频相关操作提供基础。 + +## Input types +### Required +- audio + - 指定要上传和处理的音频文件。此参数对于确定将进行处理的音频内容至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- start_time + - 定义应处理音频文件的起始点(以秒为单位)。此参数允许选择性地处理音频内容,增强灵活性。 + - Comfy dtype: FLOAT + - Python dtype: float +- duration + - 指定应从开始时间处理音频的持续时间(以秒为单位)。这允许精确控制要分析或操作的音频文件片段。 + - Comfy dtype: FLOAT + - Python dtype: float + +## Output types +- audio + - Comfy dtype: VHS_AUDIO + - 表示处理后的音频数据,准备在套件中的后续操作中使用。 + - Python dtype: torch.Tensor + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class LoadAudioUpload: + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + files = [] + for f in os.listdir(input_dir): + if os.path.isfile(os.path.join(input_dir, f)): + file_parts = f.split('.') + if len(file_parts) > 1 and (file_parts[-1] in audio_extensions): + files.append(f) + return {"required": { + "audio": (sorted(files),), + "start_time": ("FLOAT" , {"default": 0, "min": 0, "max": 10000000, "step": 0.01}), + "duration": ("FLOAT" , {"default": 0, "min": 0, "max": 10000000, "step": 0.01}), + }, + } + + CATEGORY = "Video Helper Suite 🎥🅥🅗🅢" + + RETURN_TYPES = ("VHS_AUDIO", ) + RETURN_NAMES = ("audio",) + FUNCTION = "load_audio" + + def load_audio(self, start_time, duration, **kwargs): + audio_file = folder_paths.get_annotated_filepath(kwargs['audio'].strip("\"")) + if audio_file is None or validate_path(audio_file) != True: + raise Exception("audio_file is not a valid path: " + audio_file) + + audio = get_audio(audio_file, start_time, duration) + + return (lambda : audio,) + + @classmethod + def IS_CHANGED(s, audio, start_time, duration): + audio_file = folder_paths.get_annotated_filepath(audio.strip("\"")) + return hash_path(audio_file) + + @classmethod + def VALIDATE_INPUTS(s, audio, **kwargs): + audio_file = folder_paths.get_annotated_filepath(audio.strip("\"")) + return validate_path(audio_file, allow_none=True) \ No newline at end of file diff --git a/docs/VHS_LoadImagesPath.md b/docs/VHS_LoadImagesPath.md new file mode 100644 index 0000000..dc1945b --- /dev/null +++ b/docs/VHS_LoadImagesPath.md @@ -0,0 +1,90 @@ +# Load Images (Path) 🎥🅥🅗🅢 +## Documentation +- Class name: VHS_LoadImagesPath +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +VHS_LoadImagesPath节点用于将图像从指定目录路径加载到视频编辑或处理工作流程中。它支持过滤和选择选项,以自定义加载的图像集,从而在视频助手套件中高效管理和处理图像批次。 + +## Input types +### Required +- directory + - 指定要从中加载图像的目录。此参数对于确定要处理的图像来源至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +### Optional +- image_load_cap + - 限制从目录加载的图像数量,允许控制处理批次的大小。 + - Comfy dtype: INT + - Python dtype: int +- skip_first_images + - 跳过目录开头指定数量的图像,允许根据顺序选择性加载图像。 + - Comfy dtype: INT + - Python dtype: int +- select_every_nth + - 加载目录中的每第n张图像,提供了一种稀释要处理的图像集的方法。 + - Comfy dtype: INT + - Python dtype: int + +## Output types +- image + - Comfy dtype: IMAGE + - 加载的图像,准备在工作流程中进一步处理或操作。 + - Python dtype: torch.Tensor +- mask + - Comfy dtype: MASK + - 为加载的图像生成的蒙版,对于需要分割或选择性编辑的图像编辑任务很有用。 + - Python dtype: torch.Tensor +- int + - Comfy dtype: INT + - 加载的图像总数,在应用加载参数后提供批次大小的见解。 + - Python dtype: int + +## Usage tips +- Infra type: CPU +- Common nodes: + - [ImpactImageBatchToImageList](../../ComfyUI-Impact-Pack/Nodes/ImpactImageBatchToImageList.md) + - [PreviewImage](../../Comfy/Nodes/PreviewImage.md) + - [IPAdapterEncoder](../../ComfyUI_IPAdapter_plus/Nodes/IPAdapterEncoder.md) + - LinearBatchCreativeInterpolation + +## Source code +```python +class LoadImagesFromDirectoryPath: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "directory": ("STRING", {"default": "X://path/to/images", "vhs_path_extensions": []}), + }, + "optional": { + "image_load_cap": ("INT", {"default": 0, "min": 0, "max": BIGMAX, "step": 1}), + "skip_first_images": ("INT", {"default": 0, "min": 0, "max": BIGMAX, "step": 1}), + "select_every_nth": ("INT", {"default": 1, "min": 1, "max": BIGMAX, "step": 1}), + } + } + + RETURN_TYPES = ("IMAGE", "MASK", "INT") + FUNCTION = "load_images" + + CATEGORY = "Video Helper Suite 🎥🅥🅗🅢" + + def load_images(self, directory: str, **kwargs): + if directory is None or validate_load_images(directory) != True: + raise Exception("directory is not valid: " + directory) + + return load_images(directory, **kwargs) + + @classmethod + def IS_CHANGED(s, directory: str, **kwargs): + if directory is None: + return "input" + return is_changed_load_images(directory, **kwargs) + + @classmethod + def VALIDATE_INPUTS(s, directory: str, **kwargs): + if directory is None: + return True + return validate_load_images(directory) \ No newline at end of file diff --git a/docs/VHS_LoadVideoPath.md b/docs/VHS_LoadVideoPath.md new file mode 100644 index 0000000..e498d4e --- /dev/null +++ b/docs/VHS_LoadVideoPath.md @@ -0,0 +1,115 @@ +# Load Video (Path) 🎥🅥🅗🅢 +## Documentation +- Class name: VHS_LoadVideoPath +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +VHS_LoadVideoPath节点用于从指定路径加载视频文件,以便整合到视频处理工作流程中。它确保视频文件可访问,验证路径,并为视频的后续处理或分析任务做好准备。 + +## Input types +### Required +- video + - 指定要加载的视频文件的路径,使节点能够访问和处理视频。 + - Comfy dtype: STRING + - Python dtype: str +- force_rate + - 决定对加载的视频强制执行的帧率,允许在不同视频之间进行一致的帧率处理。 + - Comfy dtype: INT + - Python dtype: int +- force_size + - 允许指定视频的所需分辨率,便于视频尺寸标准化处理。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- custom_width + - 设置视频的自定义宽度,使对视频尺寸进行精确控制。 + - Comfy dtype: INT + - Python dtype: int +- custom_height + - 设置视频的自定义高度,使对视频尺寸进行精确控制。 + - Comfy dtype: INT + - Python dtype: int +- frame_load_cap + - 限制从视频中加载的帧数,有助于在内存约束内处理视频。 + - Comfy dtype: INT + - Python dtype: int +- skip_first_frames + - 跳过视频中的指定数量的初始帧,有助于在视频的后续部分开始处理。 + - Comfy dtype: INT + - Python dtype: int +- select_every_nth + - 选择每第n帧进行加载,允许对视频帧进行稀疏采样。 + - Comfy dtype: INT + - Python dtype: int + +### Optional +- meta_batch + - 将加载的视频与特定批次关联,便于在视频助手套件中进行批处理操作。 + - Comfy dtype: VHS_BatchManager + - Python dtype: VHS_BatchManager + +## Output types +- IMAGE + - Comfy dtype: IMAGE + - 加载的视频帧作为图像,准备进一步处理。 + - Python dtype: List[Image] +- frame_count + - Comfy dtype: INT + - 从视频中加载的帧总数。 + - Python dtype: int +- audio + - Comfy dtype: VHS_AUDIO + - 从视频中提取的音轨(如果有)。 + - Python dtype: VHS_AUDIO +- video_info + - Comfy dtype: VHS_VIDEOINFO + - 有关加载视频的元数据和信息。 + - Python dtype: VHS_VIDEOINFO + +## Usage tips +- Infra type: CPU +- Common nodes: unknown + +## Source code +```python +class LoadVideoPath: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "video": ("STRING", {"default": "X://insert/path/here.mp4", "vhs_path_extensions": video_extensions}), + "force_rate": ("INT", {"default": 0, "min": 0, "max": 60, "step": 1}), + "force_size": (["Disabled", "Custom Height", "Custom Width", "Custom", "256x?", "?x256", "256x256", "512x?", "?x512", "512x512"],), + "custom_width": ("INT", {"default": 512, "min": 0, "max": DIMMAX, "step": 8}), + "custom_height": ("INT", {"default": 512, "min": 0, "max": DIMMAX, "step": 8}), + "frame_load_cap": ("INT", {"default": 0, "min": 0, "max": BIGMAX, "step": 1}), + "skip_first_frames": ("INT", {"default": 0, "min": 0, "max": BIGMAX, "step": 1}), + "select_every_nth": ("INT", {"default": 1, "min": 1, "max": BIGMAX, "step": 1}), + }, + "optional": { + "meta_batch": ("VHS_BatchManager",) + }, + "hidden": { + "unique_id": "UNIQUE_ID" + }, + } + + CATEGORY = "Video Helper Suite 🎥🅥🅗🅢" + + RETURN_TYPES = ("IMAGE", "INT", "VHS_AUDIO", "VHS_VIDEOINFO",) + RETURN_NAMES = ("IMAGE", "frame_count", "audio", "video_info",) + + FUNCTION = "load_video" + + def load_video(self, **kwargs): + if kwargs['video'] is None or validate_path(kwargs['video']) != True: + raise Exception("video is not a valid path: " + kwargs['video']) + return load_video_cv(**kwargs) + + @classmethod + def IS_CHANGED(s, video, **kwargs): + return hash_path(video) + + @classmethod + def VALIDATE_INPUTS(s, video, **kwargs): + return validate_path(video, allow_none=True) \ No newline at end of file