chore: Dataset nodes clean-up (CORE-237) (#14002)

This commit is contained in:
Alexis Rolland 2026-05-21 15:14:16 +08:00 committed by GitHub
parent 7b7c5fed7c
commit af3d9b60af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 145 additions and 70 deletions

View File

@ -543,7 +543,7 @@ class AudioConcat(IO.ComfyNode):
return IO.Schema( return IO.Schema(
node_id="AudioConcat", node_id="AudioConcat",
search_aliases=["join audio", "combine audio", "append audio"], search_aliases=["join audio", "combine audio", "append audio"],
display_name="Audio Concat", display_name="Concatenate Audio",
description="Concatenates the audio1 to audio2 in the specified direction.", description="Concatenates the audio1 to audio2 in the specified direction.",
category="audio", category="audio",
inputs=[ inputs=[
@ -597,7 +597,7 @@ class AudioMerge(IO.ComfyNode):
return IO.Schema( return IO.Schema(
node_id="AudioMerge", node_id="AudioMerge",
search_aliases=["mix audio", "overlay audio", "layer audio"], search_aliases=["mix audio", "overlay audio", "layer audio"],
display_name="Audio Merge", display_name="Merge Audio",
description="Combine two audio tracks by overlaying their waveforms.", description="Combine two audio tracks by overlaying their waveforms.",
category="audio", category="audio",
inputs=[ inputs=[
@ -667,8 +667,9 @@ class AudioAdjustVolume(IO.ComfyNode):
return IO.Schema( return IO.Schema(
node_id="AudioAdjustVolume", node_id="AudioAdjustVolume",
search_aliases=["audio gain", "loudness", "audio level"], search_aliases=["audio gain", "loudness", "audio level"],
display_name="Audio Adjust Volume", display_name="Adjust Audio Volume",
category="audio", category="audio",
description="Adjust the volume of the audio by a specified amount in decibels (dB).",
inputs=[ inputs=[
IO.Audio.Input("audio"), IO.Audio.Input("audio"),
IO.Int.Input( IO.Int.Input(

View File

@ -47,8 +47,10 @@ class LoadImageDataSetFromFolderNode(io.ComfyNode):
def define_schema(cls): def define_schema(cls):
return io.Schema( return io.Schema(
node_id="LoadImageDataSetFromFolder", node_id="LoadImageDataSetFromFolder",
display_name="Load Image Dataset from Folder", search_aliases=["load folder", "load from folder", "load dataset", "load images", "import dataset"],
category="dataset", display_name="Load Image (from Folder)",
category="image",
description="Load a dataset of images from a specified folder and return a list of images. Supported formats: PNG, JPG, JPEG, WEBP.",
is_experimental=True, is_experimental=True,
inputs=[ inputs=[
io.Combo.Input( io.Combo.Input(
@ -84,14 +86,16 @@ class LoadImageTextDataSetFromFolderNode(io.ComfyNode):
def define_schema(cls): def define_schema(cls):
return io.Schema( return io.Schema(
node_id="LoadImageTextDataSetFromFolder", node_id="LoadImageTextDataSetFromFolder",
display_name="Load Image and Text Dataset from Folder", search_aliases=["load folder", "load from folder", "load dataset", "load images", "import dataset"],
category="dataset", display_name="Load Image-Text (from Folder)",
category="image",
description="Load a dataset of pairs of images and text captions from a specified folder and return them as a list. Supported formats: PNG, JPG, JPEG, WEBP.",
is_experimental=True, is_experimental=True,
inputs=[ inputs=[
io.Combo.Input( io.Combo.Input(
"folder", "folder",
options=folder_paths.get_input_subfolders(), options=folder_paths.get_input_subfolders(),
tooltip="The folder to load images from.", tooltip="The folder to load images and text captions from.",
) )
], ],
outputs=[ outputs=[
@ -206,8 +210,10 @@ class SaveImageDataSetToFolderNode(io.ComfyNode):
def define_schema(cls): def define_schema(cls):
return io.Schema( return io.Schema(
node_id="SaveImageDataSetToFolder", node_id="SaveImageDataSetToFolder",
display_name="Save Image Dataset to Folder", search_aliases=["save folder", "save to folder", "save dataset", "save images", "export dataset"],
category="dataset", display_name="Save Image (to Folder) (DEPRECATED)",
category="image",
description="Save a dataset of images to a specified folder. Supported formats: PNG.",
is_experimental=True, is_experimental=True,
is_output_node=True, is_output_node=True,
is_input_list=True, # Receive images as list is_input_list=True, # Receive images as list
@ -226,6 +232,7 @@ class SaveImageDataSetToFolderNode(io.ComfyNode):
), ),
], ],
outputs=[], outputs=[],
is_deprecated=True, # This node is redundant and superseded by existing Save Image nodes where the target folder can be specified in the filename_prefix
) )
@classmethod @classmethod
@ -246,14 +253,20 @@ class SaveImageTextDataSetToFolderNode(io.ComfyNode):
def define_schema(cls): def define_schema(cls):
return io.Schema( return io.Schema(
node_id="SaveImageTextDataSetToFolder", node_id="SaveImageTextDataSetToFolder",
display_name="Save Image and Text Dataset to Folder", search_aliases=["save folder", "save to folder", "save dataset", "save images", "save text", "export dataset"],
category="dataset", display_name="Save Image-Text (to Folder)",
category="image",
description="Save a dataset of pairs of images and text captions to a specified folder. Images are saved as PNG files and captions are saved as TXT files with the same filename_prefix.",
is_experimental=True, is_experimental=True,
is_output_node=True, is_output_node=True,
is_input_list=True, # Receive both images and texts as lists is_input_list=True, # Receive both images and texts as lists
inputs=[ inputs=[
io.Image.Input("images", tooltip="List of images to save."), io.Image.Input("images", tooltip="List of images to save."),
io.String.Input("texts", tooltip="List of text captions to save."), io.String.Input("texts",
optional=True,
force_input=True,
tooltip="List of text captions to save."
),
io.String.Input( io.String.Input(
"folder_name", "folder_name",
default="dataset", default="dataset",
@ -270,7 +283,7 @@ class SaveImageTextDataSetToFolderNode(io.ComfyNode):
) )
@classmethod @classmethod
def execute(cls, images, texts, folder_name, filename_prefix): def execute(cls, images, folder_name, filename_prefix, texts=None):
# Extract scalar values # Extract scalar values
folder_name = folder_name[0] folder_name = folder_name[0]
filename_prefix = filename_prefix[0] filename_prefix = filename_prefix[0]
@ -279,11 +292,12 @@ class SaveImageTextDataSetToFolderNode(io.ComfyNode):
saved_files = save_images_to_folder(images, output_dir, filename_prefix) saved_files = save_images_to_folder(images, output_dir, filename_prefix)
# Save captions # Save captions
for idx, (filename, caption) in enumerate(zip(saved_files, texts)): if texts:
caption_filename = filename.replace(".png", ".txt") for idx, (filename, caption) in enumerate(zip(saved_files, texts)):
caption_path = os.path.join(output_dir, caption_filename) caption_filename = filename.replace(".png", ".txt")
with open(caption_path, "w", encoding="utf-8") as f: caption_path = os.path.join(output_dir, caption_filename)
f.write(caption) with open(caption_path, "w", encoding="utf-8") as f:
f.write(caption)
logging.info(f"Saved {len(saved_files)} images and captions to {output_dir}.") logging.info(f"Saved {len(saved_files)} images and captions to {output_dir}.")
return io.NodeOutput() return io.NodeOutput()
@ -314,11 +328,13 @@ class ImageProcessingNode(io.ComfyNode):
Child classes should set: Child classes should set:
node_id: Unique node identifier (required) node_id: Unique node identifier (required)
search_aliases: List of search aliases (optional)
display_name: Display name (optional, defaults to node_id) display_name: Display name (optional, defaults to node_id)
description: Node description (optional) description: Node description (optional)
extra_inputs: List of additional io.Input objects beyond "images" (optional) extra_inputs: List of additional io.Input objects beyond "images" (optional)
is_group_process: None (auto-detect), True (group), or False (individual) (optional) is_group_process: None (auto-detect), True (group), or False (individual) (optional)
is_output_list: True (list output) or False (single output) (optional, default True) is_output_list: True (list output) or False (single output) (optional, default True)
is_deprecated: True if the node is deprecated (optional, default False)
Child classes must implement ONE of: Child classes must implement ONE of:
_process(cls, image, **kwargs) -> tensor (for single-item processing) _process(cls, image, **kwargs) -> tensor (for single-item processing)
@ -326,12 +342,13 @@ class ImageProcessingNode(io.ComfyNode):
""" """
node_id = None node_id = None
search_aliases = []
display_name = None display_name = None
description = None description = None
extra_inputs = [] extra_inputs = []
is_group_process = None # None = auto-detect, True/False = explicit is_group_process = None # None = auto-detect, True/False = explicit
is_output_list = None # None = auto-detect based on processing mode is_output_list = None # None = auto-detect based on processing mode
is_deprecated = False
@classmethod @classmethod
def _detect_processing_mode(cls): def _detect_processing_mode(cls):
"""Detect whether this node uses group or individual processing. """Detect whether this node uses group or individual processing.
@ -402,8 +419,10 @@ class ImageProcessingNode(io.ComfyNode):
return io.Schema( return io.Schema(
node_id=cls.node_id, node_id=cls.node_id,
search_aliases=cls.search_aliases,
display_name=cls.display_name or cls.node_id, display_name=cls.display_name or cls.node_id,
category="dataset/image", category=cls.category,
description=cls.description,
is_experimental=True, is_experimental=True,
is_input_list=is_group, # True for group, False for individual is_input_list=is_group, # True for group, False for individual
inputs=inputs, inputs=inputs,
@ -472,11 +491,13 @@ class TextProcessingNode(io.ComfyNode):
Child classes should set: Child classes should set:
node_id: Unique node identifier (required) node_id: Unique node identifier (required)
search_aliases: List of search aliases (optional)
display_name: Display name (optional, defaults to node_id) display_name: Display name (optional, defaults to node_id)
description: Node description (optional) description: Node description (optional)
extra_inputs: List of additional io.Input objects beyond "texts" (optional) extra_inputs: List of additional io.Input objects beyond "texts" (optional)
is_group_process: None (auto-detect), True (group), or False (individual) (optional) is_group_process: None (auto-detect), True (group), or False (individual) (optional)
is_output_list: True (list output) or False (single output) (optional, default True) is_output_list: True (list output) or False (single output) (optional, default True)
is_deprecated: True if the node is deprecated (optional, default False)
Child classes must implement ONE of: Child classes must implement ONE of:
_process(cls, text, **kwargs) -> str (for single-item processing) _process(cls, text, **kwargs) -> str (for single-item processing)
@ -484,12 +505,13 @@ class TextProcessingNode(io.ComfyNode):
""" """
node_id = None node_id = None
search_aliases = []
display_name = None display_name = None
description = None description = None
extra_inputs = [] extra_inputs = []
is_group_process = None # None = auto-detect, True/False = explicit is_group_process = None # None = auto-detect, True/False = explicit
is_output_list = None # None = auto-detect based on processing mode is_output_list = None # None = auto-detect based on processing mode
is_deprecated = False
@classmethod @classmethod
def _detect_processing_mode(cls): def _detect_processing_mode(cls):
"""Detect whether this node uses group or individual processing. """Detect whether this node uses group or individual processing.
@ -627,15 +649,17 @@ class TextProcessingNode(io.ComfyNode):
class ResizeImagesByShorterEdgeNode(ImageProcessingNode): class ResizeImagesByShorterEdgeNode(ImageProcessingNode):
node_id = "ResizeImagesByShorterEdge" node_id = "ResizeImagesByShorterEdge"
display_name = "Resize Images by Shorter Edge" display_name = "Resize Images by Shorter Edge (DEPRECATED)"
description = "Resize images so that the shorter edge matches the specified length while preserving aspect ratio." category = "image/transform"
description = "Resize images so that the shorter edge matches the specified dimension while preserving aspect ratio."
is_deprecated = True # This node is superseded by Resize Image/Mask with resize_type = scale shorter dimension
extra_inputs = [ extra_inputs = [
io.Int.Input( io.Int.Input(
"shorter_edge", "shorter_edge",
default=512, default=512,
min=1, min=1,
max=8192, max=8192,
tooltip="Target length for the shorter edge.", tooltip="Target dimension for the shorter edge.",
), ),
] ]
@ -655,15 +679,17 @@ class ResizeImagesByShorterEdgeNode(ImageProcessingNode):
class ResizeImagesByLongerEdgeNode(ImageProcessingNode): class ResizeImagesByLongerEdgeNode(ImageProcessingNode):
node_id = "ResizeImagesByLongerEdge" node_id = "ResizeImagesByLongerEdge"
display_name = "Resize Images by Longer Edge" display_name = "Resize Images by Longer Edge (DEPRECATED)"
description = "Resize images so that the longer edge matches the specified length while preserving aspect ratio." category = "image/transform"
description = "Resize images so that the longer edge matches the specified dimension while preserving aspect ratio."
is_deprecated = True # This node is superseded by Resize Image/Mask with resize_type = scale longer dimension
extra_inputs = [ extra_inputs = [
io.Int.Input( io.Int.Input(
"longer_edge", "longer_edge",
default=1024, default=1024,
min=1, min=1,
max=8192, max=8192,
tooltip="Target length for the longer edge.", tooltip="Target dimension for the longer edge.",
), ),
] ]
@ -686,8 +712,10 @@ class ResizeImagesByLongerEdgeNode(ImageProcessingNode):
class CenterCropImagesNode(ImageProcessingNode): class CenterCropImagesNode(ImageProcessingNode):
node_id = "CenterCropImages" node_id = "CenterCropImages"
display_name = "Center Crop Images" search_aliases=["crop", "cut", "trim"]
description = "Center crop all images to the specified dimensions." display_name="Crop Image (Center)"
category="image/transform"
description = "Center crop an image to the specified dimensions."
extra_inputs = [ extra_inputs = [
io.Int.Input("width", default=512, min=1, max=8192, tooltip="Crop width."), io.Int.Input("width", default=512, min=1, max=8192, tooltip="Crop width."),
io.Int.Input("height", default=512, min=1, max=8192, tooltip="Crop height."), io.Int.Input("height", default=512, min=1, max=8192, tooltip="Crop height."),
@ -706,10 +734,11 @@ class CenterCropImagesNode(ImageProcessingNode):
class RandomCropImagesNode(ImageProcessingNode): class RandomCropImagesNode(ImageProcessingNode):
node_id = "RandomCropImages" node_id = "RandomCropImages"
display_name = "Random Crop Images" search_aliases=["crop", "cut", "trim"]
description = ( display_name = "Crop Image (Random)"
"Randomly crop all images to the specified dimensions (for data augmentation)." category="image/transform"
) description = "Randomly crop an image to the specified dimensions."
extra_inputs = [ extra_inputs = [
io.Int.Input("width", default=512, min=1, max=8192, tooltip="Crop width."), io.Int.Input("width", default=512, min=1, max=8192, tooltip="Crop width."),
io.Int.Input("height", default=512, min=1, max=8192, tooltip="Crop height."), io.Int.Input("height", default=512, min=1, max=8192, tooltip="Crop height."),
@ -734,7 +763,9 @@ class RandomCropImagesNode(ImageProcessingNode):
class NormalizeImagesNode(ImageProcessingNode): class NormalizeImagesNode(ImageProcessingNode):
node_id = "NormalizeImages" node_id = "NormalizeImages"
display_name = "Normalize Images" search_aliases=["normalize", "normalize colors"]
display_name = "Normalize Image Colors"
category = "image/color"
description = "Normalize images using mean and standard deviation." description = "Normalize images using mean and standard deviation."
extra_inputs = [ extra_inputs = [
io.Float.Input( io.Float.Input(
@ -762,8 +793,10 @@ class NormalizeImagesNode(ImageProcessingNode):
class AdjustBrightnessNode(ImageProcessingNode): class AdjustBrightnessNode(ImageProcessingNode):
node_id = "AdjustBrightness" node_id = "AdjustBrightness"
search_aliases=["brightness"]
display_name = "Adjust Brightness" display_name = "Adjust Brightness"
description = "Adjust brightness of all images." category="image/adjustments"
description = "Adjust the brightness of an image."
extra_inputs = [ extra_inputs = [
io.Float.Input( io.Float.Input(
"factor", "factor",
@ -781,8 +814,10 @@ class AdjustBrightnessNode(ImageProcessingNode):
class AdjustContrastNode(ImageProcessingNode): class AdjustContrastNode(ImageProcessingNode):
node_id = "AdjustContrast" node_id = "AdjustContrast"
search_aliases=["contrast"]
display_name = "Adjust Contrast" display_name = "Adjust Contrast"
description = "Adjust contrast of all images." category="image/adjustments"
description = "Adjust the contrast of an image."
extra_inputs = [ extra_inputs = [
io.Float.Input( io.Float.Input(
"factor", "factor",
@ -800,8 +835,10 @@ class AdjustContrastNode(ImageProcessingNode):
class ShuffleDatasetNode(ImageProcessingNode): class ShuffleDatasetNode(ImageProcessingNode):
node_id = "ShuffleDataset" node_id = "ShuffleDataset"
display_name = "Shuffle Image Dataset" search_aliases=["shuffle", "randomize", "mix"]
description = "Randomly shuffle the order of images in the dataset." display_name = "Shuffle Images List"
category = "image/batch"
description = "Randomly shuffle the order of images in a list."
is_group_process = True # Requires full list to shuffle is_group_process = True # Requires full list to shuffle
extra_inputs = [ extra_inputs = [
io.Int.Input( io.Int.Input(
@ -823,13 +860,15 @@ class ShuffleImageTextDatasetNode(io.ComfyNode):
def define_schema(cls): def define_schema(cls):
return io.Schema( return io.Schema(
node_id="ShuffleImageTextDataset", node_id="ShuffleImageTextDataset",
display_name="Shuffle Image-Text Dataset", search_aliases=["shuffle", "randomize", "mix"],
category="dataset/image", display_name = "Shuffle Pairs of Image-Text",
category = "image/batch",
description = "Randomly shuffle the order of pairs of image-text in a list.",
is_experimental=True, is_experimental=True,
is_input_list=True, is_input_list=True,
inputs=[ inputs=[
io.Image.Input("images", tooltip="List of images to shuffle."), io.Image.Input("images", tooltip="List of images to shuffle."),
io.String.Input("texts", tooltip="List of texts to shuffle."), io.String.Input("texts", tooltip="List of texts to shuffle.", force_input=True),
io.Int.Input( io.Int.Input(
"seed", "seed",
default=0, default=0,
@ -865,8 +904,11 @@ class ShuffleImageTextDatasetNode(io.ComfyNode):
class TextToLowercaseNode(TextProcessingNode): class TextToLowercaseNode(TextProcessingNode):
node_id = "TextToLowercase" node_id = "TextToLowercase"
display_name = "Text to Lowercase" search_aliases=["lowercase"]
description = "Convert all texts to lowercase." display_name = "Convert Text to Lowercase (DEPRECATED)"
category = "text"
description = "Convert text to lowercase."
is_deprecated = True # This node is superseded by the Convert Text Case node
@classmethod @classmethod
def _process(cls, text): def _process(cls, text):
@ -875,8 +917,11 @@ class TextToLowercaseNode(TextProcessingNode):
class TextToUppercaseNode(TextProcessingNode): class TextToUppercaseNode(TextProcessingNode):
node_id = "TextToUppercase" node_id = "TextToUppercase"
display_name = "Text to Uppercase" search_aliases=["uppercase"]
description = "Convert all texts to uppercase." display_name = "Convert Text to Uppercase (DEPRECATED)"
category = "text"
description = "Convert text to uppercase."
is_deprecated = True # This node is superseded by the Convert Text Case node
@classmethod @classmethod
def _process(cls, text): def _process(cls, text):
@ -885,8 +930,10 @@ class TextToUppercaseNode(TextProcessingNode):
class TruncateTextNode(TextProcessingNode): class TruncateTextNode(TextProcessingNode):
node_id = "TruncateText" node_id = "TruncateText"
search_aliases=["truncate", "cut", "shorten"]
display_name = "Truncate Text" display_name = "Truncate Text"
description = "Truncate all texts to a maximum length." category = "text"
description = "Truncate text to a maximum length."
extra_inputs = [ extra_inputs = [
io.Int.Input( io.Int.Input(
"max_length", default=77, min=1, max=10000, tooltip="Maximum text length." "max_length", default=77, min=1, max=10000, tooltip="Maximum text length."
@ -900,8 +947,10 @@ class TruncateTextNode(TextProcessingNode):
class AddTextPrefixNode(TextProcessingNode): class AddTextPrefixNode(TextProcessingNode):
node_id = "AddTextPrefix" node_id = "AddTextPrefix"
display_name = "Add Text Prefix" display_name = "Add Text Prefix (DEPRECATED)"
category = "text"
description = "Add a prefix to all texts." description = "Add a prefix to all texts."
is_deprecated = True # This node is superseded by the Concatenate Text node
extra_inputs = [ extra_inputs = [
io.String.Input("prefix", default="", tooltip="Prefix to add."), io.String.Input("prefix", default="", tooltip="Prefix to add."),
] ]
@ -913,8 +962,10 @@ class AddTextPrefixNode(TextProcessingNode):
class AddTextSuffixNode(TextProcessingNode): class AddTextSuffixNode(TextProcessingNode):
node_id = "AddTextSuffix" node_id = "AddTextSuffix"
display_name = "Add Text Suffix" display_name = "Add Text Suffix (DEPRECATED)"
category = "text"
description = "Add a suffix to all texts." description = "Add a suffix to all texts."
is_deprecated = True # This node is superseded by the Concatenate Text node
extra_inputs = [ extra_inputs = [
io.String.Input("suffix", default="", tooltip="Suffix to add."), io.String.Input("suffix", default="", tooltip="Suffix to add."),
] ]
@ -926,8 +977,10 @@ class AddTextSuffixNode(TextProcessingNode):
class ReplaceTextNode(TextProcessingNode): class ReplaceTextNode(TextProcessingNode):
node_id = "ReplaceText" node_id = "ReplaceText"
display_name = "Replace Text" display_name = "Replace Text (DEPRECATED)"
category = "text"
description = "Replace text in all texts." description = "Replace text in all texts."
is_deprecated = True # This node is superseded by the other Replace Text node
extra_inputs = [ extra_inputs = [
io.String.Input("find", default="", tooltip="Text to find."), io.String.Input("find", default="", tooltip="Text to find."),
io.String.Input("replace", default="", tooltip="Text to replace with."), io.String.Input("replace", default="", tooltip="Text to replace with."),
@ -940,8 +993,10 @@ class ReplaceTextNode(TextProcessingNode):
class StripWhitespaceNode(TextProcessingNode): class StripWhitespaceNode(TextProcessingNode):
node_id = "StripWhitespace" node_id = "StripWhitespace"
display_name = "Strip Whitespace" display_name = "Strip Whitespace (DEPRECATED)"
category = "text"
description = "Strip leading and trailing whitespace from all texts." description = "Strip leading and trailing whitespace from all texts."
is_deprecated = True # This node is superseded by the Trim Text node
@classmethod @classmethod
def _process(cls, text): def _process(cls, text):
@ -952,11 +1007,13 @@ class StripWhitespaceNode(TextProcessingNode):
class ImageDeduplicationNode(ImageProcessingNode): class ImageDeduplicationNode(ImageProcessingNode):
"""Remove duplicate or very similar images from the dataset using perceptual hashing.""" """Remove duplicate or very similar images from a list using perceptual hashing."""
node_id = "ImageDeduplication" node_id = "ImageDeduplication"
display_name = "Image Deduplication" search_aliases=["deduplicate", "remove duplicates", "similarity filter"]
description = "Remove duplicate or very similar images from the dataset." display_name = "Deduplicate Images"
category = "image/batch"
description = "Remove duplicate or very similar images from a list."
is_group_process = True # Requires full list to compare images is_group_process = True # Requires full list to compare images
extra_inputs = [ extra_inputs = [
io.Float.Input( io.Float.Input(
@ -1026,7 +1083,9 @@ class ImageGridNode(ImageProcessingNode):
"""Combine multiple images into a single grid/collage.""" """Combine multiple images into a single grid/collage."""
node_id = "ImageGrid" node_id = "ImageGrid"
display_name = "Image Grid" search_aliases=["grid", "collage", "combine"]
display_name = "Make Image Grid"
category="image/batch"
description = "Arrange multiple images into a grid layout." description = "Arrange multiple images into a grid layout."
is_group_process = True # Requires full list to create grid is_group_process = True # Requires full list to create grid
is_output_list = False # Outputs single grid image is_output_list = False # Outputs single grid image
@ -1102,9 +1161,12 @@ class MergeImageListsNode(ImageProcessingNode):
"""Merge multiple image lists into a single list.""" """Merge multiple image lists into a single list."""
node_id = "MergeImageLists" node_id = "MergeImageLists"
display_name = "Merge Image Lists" search_aliases=["list", "merge list", "make list"]
display_name = "Merge Image Lists (DEPRECATED)"
category = "image/batch"
description = "Concatenate multiple image lists into one." description = "Concatenate multiple image lists into one."
is_group_process = True # Receives images as list is_group_process = True # Receives images as list
is_deprecated = True # This node is superseded by the Create List node
@classmethod @classmethod
def _group_process(cls, images): def _group_process(cls, images):
@ -1119,9 +1181,11 @@ class MergeTextListsNode(TextProcessingNode):
"""Merge multiple text lists into a single list.""" """Merge multiple text lists into a single list."""
node_id = "MergeTextLists" node_id = "MergeTextLists"
display_name = "Merge Text Lists" display_name = "Merge Text Lists (DEPRECATED)"
category = "text"
description = "Concatenate multiple text lists into one." description = "Concatenate multiple text lists into one."
is_group_process = True # Receives texts as list is_group_process = True # Receives texts as list
is_deprecated = True # This node is superseded by the Create List node
@classmethod @classmethod
def _group_process(cls, texts): def _group_process(cls, texts):
@ -1142,8 +1206,10 @@ class ResolutionBucket(io.ComfyNode):
def define_schema(cls): def define_schema(cls):
return io.Schema( return io.Schema(
node_id="ResolutionBucket", node_id="ResolutionBucket",
search_aliases=["bucket by resolution", "group by resolution", "batch by resolution"],
display_name="Resolution Bucket", display_name="Resolution Bucket",
category="dataset", category="training",
description="Group latents and conditionings into buckets",
is_experimental=True, is_experimental=True,
is_input_list=True, is_input_list=True,
inputs=[ inputs=[
@ -1236,7 +1302,8 @@ class MakeTrainingDataset(io.ComfyNode):
node_id="MakeTrainingDataset", node_id="MakeTrainingDataset",
search_aliases=["encode dataset"], search_aliases=["encode dataset"],
display_name="Make Training Dataset", display_name="Make Training Dataset",
category="dataset", category="training",
description="Encode images with VAE and texts with CLIP to create a training dataset of latents and conditionings.",
is_experimental=True, is_experimental=True,
is_input_list=True, # images and texts as lists is_input_list=True, # images and texts as lists
inputs=[ inputs=[
@ -1251,6 +1318,7 @@ class MakeTrainingDataset(io.ComfyNode):
"texts", "texts",
optional=True, optional=True,
tooltip="List of text captions. Can be length n (matching images), 1 (repeated for all), or omitted (uses empty string).", tooltip="List of text captions. Can be length n (matching images), 1 (repeated for all), or omitted (uses empty string).",
force_input=True
), ),
], ],
outputs=[ outputs=[
@ -1320,9 +1388,10 @@ class SaveTrainingDataset(io.ComfyNode):
def define_schema(cls): def define_schema(cls):
return io.Schema( return io.Schema(
node_id="SaveTrainingDataset", node_id="SaveTrainingDataset",
search_aliases=["export training data"], search_aliases=["export dataset", "save dataset"],
display_name="Save Training Dataset", display_name="Save Training Dataset",
category="dataset", category="training",
description="Save encoded training dataset (latents + conditioning) to disk for efficient loading during training.",
is_experimental=True, is_experimental=True,
is_output_node=True, is_output_node=True,
is_input_list=True, # Receive lists is_input_list=True, # Receive lists
@ -1424,7 +1493,8 @@ class LoadTrainingDataset(io.ComfyNode):
node_id="LoadTrainingDataset", node_id="LoadTrainingDataset",
search_aliases=["import dataset", "training data"], search_aliases=["import dataset", "training data"],
display_name="Load Training Dataset", display_name="Load Training Dataset",
category="dataset", category="training",
description="Load encoded training dataset (latents + conditioning) from disk for use in training.",
is_experimental=True, is_experimental=True,
inputs=[ inputs=[
io.String.Input( io.String.Input(

View File

@ -419,15 +419,17 @@ class VoxelToMeshBasic(IO.ComfyNode):
def define_schema(cls): def define_schema(cls):
return IO.Schema( return IO.Schema(
node_id="VoxelToMeshBasic", node_id="VoxelToMeshBasic",
display_name="Voxel to Mesh (Basic)", display_name="Voxel to Mesh (Basic) (DEPRECATED)",
category="3d", category="3d",
description="Converts a voxel grid to a mesh.",
is_deprecated=True, # This node is superseded by the Voxel To Mesh node
inputs=[ inputs=[
IO.Voxel.Input("voxel"), IO.Voxel.Input("voxel"),
IO.Float.Input("threshold", default=0.6, min=-1.0, max=1.0, step=0.01), IO.Float.Input("threshold", default=0.6, min=-1.0, max=1.0, step=0.01),
], ],
outputs=[ outputs=[
IO.Mesh.Output(), IO.Mesh.Output(),
] ],
) )
@classmethod @classmethod
@ -453,9 +455,10 @@ class VoxelToMesh(IO.ComfyNode):
node_id="VoxelToMesh", node_id="VoxelToMesh",
display_name="Voxel to Mesh", display_name="Voxel to Mesh",
category="3d", category="3d",
description="Converts a voxel grid to a mesh.",
inputs=[ inputs=[
IO.Voxel.Input("voxel"), IO.Voxel.Input("voxel"),
IO.Combo.Input("algorithm", options=["surface net", "basic"], advanced=True), IO.Combo.Input("algorithm", options=["surface net", "basic"]),
IO.Float.Input("threshold", default=0.6, min=-1.0, max=1.0, step=0.01), IO.Float.Input("threshold", default=0.6, min=-1.0, max=1.0, step=0.01),
], ],
outputs=[ outputs=[

View File

@ -55,9 +55,10 @@ class ImageCropV2(IO.ComfyNode):
def define_schema(cls): def define_schema(cls):
return IO.Schema( return IO.Schema(
node_id="ImageCropV2", node_id="ImageCropV2",
search_aliases=["trim"], search_aliases=["crop", "cut", "trim"],
display_name="Crop Image", display_name="Crop Image",
category="image/transform", category="image/transform",
description = "Crop an image to the specified dimensions.",
essentials_category="Image Tools", essentials_category="Image Tools",
has_intermediate_output=True, has_intermediate_output=True,
inputs=[ inputs=[

View File

@ -11,8 +11,8 @@ class LTXVAudioVAELoader(io.ComfyNode):
def define_schema(cls) -> io.Schema: def define_schema(cls) -> io.Schema:
return io.Schema( return io.Schema(
node_id="LTXVAudioVAELoader", node_id="LTXVAudioVAELoader",
display_name="LTXV Audio VAE Loader", display_name="Load LTXV Audio VAE",
category="audio", category="loaders",
inputs=[ inputs=[
io.Combo.Input( io.Combo.Input(
"ckpt_name", "ckpt_name",
@ -40,7 +40,7 @@ class LTXVAudioVAEEncode(VAEEncodeAudio):
return io.Schema( return io.Schema(
node_id="LTXVAudioVAEEncode", node_id="LTXVAudioVAEEncode",
display_name="LTXV Audio VAE Encode", display_name="LTXV Audio VAE Encode",
category="audio", category="latent/audio",
inputs=[ inputs=[
io.Audio.Input("audio", tooltip="The audio to be encoded."), io.Audio.Input("audio", tooltip="The audio to be encoded."),
io.Vae.Input( io.Vae.Input(
@ -63,7 +63,7 @@ class LTXVAudioVAEDecode(io.ComfyNode):
return io.Schema( return io.Schema(
node_id="LTXVAudioVAEDecode", node_id="LTXVAudioVAEDecode",
display_name="LTXV Audio VAE Decode", display_name="LTXV Audio VAE Decode",
category="audio", category="latent/audio",
inputs=[ inputs=[
io.Latent.Input("samples", tooltip="The latent to be decoded."), io.Latent.Input("samples", tooltip="The latent to be decoded."),
io.Vae.Input( io.Vae.Input(