Key updates: Added AddFramesToVideoFolder node to add frames to a video folder Introduced VideoFolderProvider and VideoDefinitionProvider nodes to manage video folders and video definitions Added FadeToInVideoFolder node for fading between frames in a video folder Implemented ListedSVDConditioning node for applying SVD conditioning to a list of parameters Added VideoFolderFFMPEGVideoInterpolate node to interpolate frames in a video folder using FFmpeg Introduced AudioFolderProvider and AudioDefinitionProvider nodes for managing audio folders and definitions Added AddAudioToAudioFolder and AddSilenceToAudioFolder nodes for adding audio files and silence to audio folders Implemented GetAudioFilesLengthsFromAudioFolder node to retrieve lengths of audio files in a folder Added AudioFolderRenderAudio node to join audio files in an audio folder Introduced GenerateMusic node for generating music from descriptions using the AudioCraft library Added XttsNode for text-to-speech conversion using the XTTS library Implemented AdjustAudioVolumeForFiles node to adjust volume for a list of audio files The changes also include the addition of LiteLLM nodes for text generation: Added FuncAnysToText node that runs Python code with multiple input types and outputs a string Introduced FuncAnysToLatent node for running code that outputs a latent representation Added FuncAnysToString node for executing code with various inputs and producing a string output Implemented FuncAnysToList node to run code that takes different input types and returns a list Added FuncAnysToCond node for running code with multiple inputs and generating a conditioning output These new nodes expand the capabilities for video and audio processing, allowing more advanced manipulations and generation of video and audio content within the graph.
87 lines
3.3 KiB
Python
87 lines
3.3 KiB
Python
import os
|
|
import importlib
|
|
|
|
WEB_DIRECTORY = "./web"
|
|
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
|
OLD_NODE_CLASS_MAPPINGS = {
|
|
"Interpolation": "LatentInterpolation",
|
|
"Image Pad To Match": "PadToMatch",
|
|
"Image Stack": "StackImages",
|
|
"Image B/C": "ImageBC",
|
|
"Image RGBA Mod": "RGBA_MOD",
|
|
"Image RGBA Lower Clip": "rgba_lower_clip",
|
|
"Image RGBA Upper Clip": "rgba_upper_clip",
|
|
"Image RGBA Merge": "rgba_merge",
|
|
"Image RGBA Split": "rgba_split",
|
|
"Select From Batch": "select_from_batch",
|
|
"Quantize": "Quantize",
|
|
"Select From RGB Similarity": "SelectFromRGBSimilarity",
|
|
"Load Layered Image": "LoadImage",
|
|
"Code Execution Widget": "ExecWidget",
|
|
"Image Distance Mask": "ImageDistanceMask",
|
|
"Image Text": "TextRender",
|
|
"function": "FuncBase",
|
|
"function render": "FuncRender",
|
|
"function render image": "FuncRenderImage",
|
|
"Tiny Txt 2 Img": "TinyTxtToImg",
|
|
"Preview Image Test": "PreviewImageTest",
|
|
"ETK_KSampler": "KSampler",
|
|
}
|
|
# reverse the dict
|
|
OLD_NODE_CLASS_MAPPINGS = {v: k for k, v in OLD_NODE_CLASS_MAPPINGS.items()}
|
|
|
|
NODE_CLASS_MAPPINGS = {}
|
|
NODE_DISPLAY_NAME_MAPPINGS = {}
|
|
# Try importing optional dependencies
|
|
|
|
import sys
|
|
|
|
if os.getenv("UNIT_TEST", False) or 'pytest' in sys.modules:
|
|
pass
|
|
else: # if not a unit test
|
|
try:
|
|
import comfy.samplers
|
|
|
|
use_generic_nodes = False
|
|
except ImportError:
|
|
use_generic_nodes = True
|
|
print("ETK> Failed to import comfy.samplers, assuming no comfyui skipping SD related nodes")
|
|
|
|
# Load classes from modules in the custom_nodes.EternalKernelLiteGraphNodes package
|
|
folder = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
for file in os.listdir(folder):
|
|
if file == "nodes.py":
|
|
raise ValueError("nodes.py is not an allowed name in this folder")
|
|
if file.endswith(".py") and file[0] != "_":
|
|
# import the NODE_CLASS_MAPPINGS from the file
|
|
try:
|
|
module = importlib.import_module(f".{file[:-3]}", __name__)
|
|
except ImportError:
|
|
try:
|
|
module = importlib.import_module(f"{file[:-3]}") # needed for testing?
|
|
except ModuleNotFoundError:
|
|
module = importlib.import_module(f".{file[:-3]}", __name__)
|
|
|
|
if hasattr(module, "NODE_CLASS_MAPPINGS"):
|
|
mappings = module.NODE_CLASS_MAPPINGS
|
|
NODE_CLASS_MAPPINGS.update(mappings)
|
|
for k, v in mappings.items():
|
|
print(f"ETK: updated with {k}")
|
|
|
|
if hasattr(module, "NODE_DISPLAY_NAME_MAPPINGS"):
|
|
NODE_DISPLAY_NAME_MAPPINGS.update(module.NODE_DISPLAY_NAME_MAPPINGS)
|
|
|
|
# use OLD_NODE_CLASS_MAPPINGS to add the old names to the new nodes
|
|
new_node_class_mappings = {}
|
|
for k, v in OLD_NODE_CLASS_MAPPINGS.items():
|
|
if k in NODE_CLASS_MAPPINGS:
|
|
new_node_class_mappings[v] = NODE_CLASS_MAPPINGS[k]
|
|
# mark it for removeal
|
|
NODE_CLASS_MAPPINGS[k] = None
|
|
else:
|
|
print(f"ETK> Failed to find node {k} in new nodes, skipping...")
|
|
# remove the nodes with None
|
|
NODE_CLASS_MAPPINGS = {k: v for k, v in NODE_CLASS_MAPPINGS.items() if v is not None}
|
|
NODE_CLASS_MAPPINGS.update(new_node_class_mappings)
|