ComfyUI创建自定义节点
方法1.直接写py文件
找到ComfyUI/custom_nodes
里面有一个示例文件:example_node.py.example
可以直接删除【.example】后缀,然后在example_node.py中进行修改
方法2.创建文件夹
这种方法是为了方便,如果你要添加多个节点,每个节点内容放一个文件夹,这样比较清晰
在ComfyUI/custom_nodes下创建一个文件夹:例如my_note(拼错了不要在意),这个文件夹名在节点上也会有显示:
然后再my_node下创建__init__.py文件(如果是这种方法,在文件夹下的话,py文件名必须得是__init__)
__init__.py的内容和example_node.py.example的内容一样,可以复制过去,然后进行参数、功能函数的补充和修改
注意点
以方法2为例
1.__init__.py中class类名字要和 NODE_CLASS_MAPPINGS一致
2. INPUT_TYPES是输入参数调整,也是显示在节点上的内容
3.FUNCTION 是入口函数,要和主功能函数名称要一样,否则找不到
4.CATEGORY 是自定义节点的名字;NODE_DISPLAY_NAME_MAPPINGS是节点的细分
可以自己决定写什么
5.主要的参数和功能的话,需要自己写 ,参数在INPUT_TYPES函数;功能可以自定义函数名字,在中example_node.py.example是这个👇,在这修改功能就行
example_node.py.example内容、注释讲解
class Example:
"""
示例节点
类方法
-------------
INPUT_TYPES (字典):
告诉主程序节点的输入参数。
IS_CHANGED:
可选方法,用于控制节点是否重新执行。
属性
----------
RETURN_TYPES (`tuple`):
输出元组中每个元素的类型。
RETURN_NAMES (`tuple`):
可选:每个输出元素的名称。
FUNCTION (`str`):
入口方法的名称。例如,如果 `FUNCTION = "execute"`,那么就会运行 `Example().execute()`。
OUTPUT_NODE ([`bool`]):
如果此节点是一个输出节点,表示从图形中输出结果/图像。类似“SaveImage”节点的就是输出节点。
后端会遍历这些输出节点并尝试执行它们的父节点,前提是它们的父图已正确连接。
如果没有该属性,默认为 False。
CATEGORY (`str`):
节点在 UI 中显示的类别。
DEPRECATED (`bool`):
指示该节点是否已弃用。弃用的节点默认在 UI 中隐藏,但在现有工作流中仍然有效。
EXPERIMENTAL (`bool`):
指示该节点是否为实验性节点。实验性节点在 UI 中标记为实验性,未来版本中可能会有重大变化或删除。在生产工作流中使用时需谨慎。
execute(s) -> tuple || None:
入口方法。此方法的名称必须与 `FUNCTION` 属性的值相同。例如,如果 `FUNCTION = "execute"`,那么该方法名必须是 `execute`;如果 `FUNCTION = "foo"`,那么方法名必须是 `foo`。
"""
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
"""
返回包含所有输入字段配置的字典。
一些类型(字符串)包括:“MODEL”,“VAE”,“CLIP”,“CONDITIONING”,“LATENT”,“IMAGE”,“INT”,“STRING”,“FLOAT”。
输入类型“INT”,“STRING”或“FLOAT”是节点字段的特殊值。
类型可以是列表,表示选择项。
返回: `dict`:
- 键 input_fields_group (`string`): 可以是 required(必需),hidden(隐藏)或 optional(可选)。每个节点类必须有 `required` 属性。
- 值 input_fields (`dict`): 包含输入字段配置:
* 键 field_name (`string`): 入口方法的参数名。
* 值 field_config (`tuple`):
+ 第一个值是字符串,表示字段类型或选择项列表。
+ 第二个值是类型为 "INT"、"STRING" 或 "FLOAT" 的配置。
"""
return {
"required": {
"image": ("IMAGE",), # 图片类型输入
"int_field": ("INT", {
"default": 0,
"min": 0, # 最小值
"max": 4096, # 最大值
"step": 64, # 滑动步长
"display": "number", # 仅显示效果:作为“数字”或“滑动条”显示
"lazy": True # 仅在需要时才评估此字段
}),
"float_field": ("FLOAT", {
"default": 1.0,
"min": 0.0,
"max": 10.0,
"step": 0.01,
"round": 0.001, # 精度值,默认为步长值。可以设置为 False 禁用四舍五入。
"display": "number",
"lazy": True
}),
"print_to_screen": (["enable", "disable"],), # 打印开关输入
"string_field": ("STRING", {
"multiline": False, # 如果为 True,则字段显示为多行文本框(类似于 ClipTextEncode 节点)
"default": "Hello World!", # 默认字符串
"lazy": True
}),
},
}
RETURN_TYPES = ("IMAGE",) # 输出类型是图像
FUNCTION = "test" # 入口方法名
CATEGORY = "Example" # 节点类别
def check_lazy_status(self, image, string_field, int_field, float_field, print_to_screen):
"""
返回需要评估的输入名称列表。
如果有任何懒加载输入(lazy inputs)尚未被评估,当请求的字段值可用时,这个函数将被调用。
评估过的输入会作为参数传递给此函数,未评估的输入会传入值为 None。
如果打印到屏幕选项为“enable”,则返回需要评估的字段。
"""
if print_to_screen == "enable":
return ["int_field", "float_field", "string_field"]
else:
return []
def test(self, image, string_field, int_field, float_field, print_to_screen):
"""
入口方法,处理图像并打印输入字段的内容。
如果打印选项为“enable”,则输出输入字段的内容。
如果 `print_to_screen` 为“enable”,将显示文本内容和数值,处理图像(此处仅是反转图像颜色)。
"""
if print_to_screen == "enable":
print(f"""您的输入包含:
字符串字段(输入文本):{string_field}
整型字段:{int_field}
浮动字段:{float_field}
""")
# 对图像做一些处理(这里只是简单反转图像)
image = 1.0 - image
return (image,)
# @classmethod
# def IS_CHANGED(s, image, string_field, int_field, float_field, print_to_screen):
# return "" # 此方法用于判断是否需要重新执行节点
# 设置 Web 目录,目录中的所有 .js 文件将由前端加载作为前端扩展
# WEB_DIRECTORY = "./somejs"
# 添加自定义 API 路由
from aiohttp import web
from server import PromptServer
@PromptServer.instance.routes.get("/hello")
async def get_hello(request):
return web.json_response("hello")
# 定义所有要导出的节点及其名称的字典
# 注意:节点名称应唯一
NODE_CLASS_MAPPINGS = {
"Example": Example # 定义节点名称与类的映射
}
# 定义节点的人类友好可读标题
NODE_DISPLAY_NAME_MAPPINGS = {
"Example": "示例节点" # 这里是“Example”节点的友好显示名称
}