关于 comfyui-node-basics
面向 ComfyUI 节点开发者的 V3 API 入门指南,说明节点类、Schema、执行方法与注册流程。并对照介绍 V1 结构及两种 API 的主要差异。
主要功能
- 01V3 节点类结构
- 02Schema 输入与输出配置
- 03ComfyExtension 注册
- 04V1 与 V3 结构对照
适用场景
- 01编写首个 V3 自定义节点
- 02定义节点输入、输出与类别
- 03将节点注册到 ComfyUI
- 04理解旧版 V1 节点结构
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ jtydhr88/ comfyui-custom-node-skills --skill comfyui-node-basics安装后在 Claude Code 中输入/comfyui-node-basics确认已加载。
详细介绍
ComfyUI 自定义节点基础(V3 API)
ComfyUI 使用 Python 类来定义节点。V3 API 是目前推荐的方式。节点继承自 io.ComfyNode,并定义一个 schema 和 execute 方法。
快速入门
from comfy_api.latest import ComfyExtension, io
class MyNode(io.ComfyNode):
@classmethod
def define_schema(cls):
return io.Schema(
node_id="MyNode",
display_name="My Custom Node",
category="my_category",
inputs=[
io.Image.Input("image"),
io.Float.Input("strength", default=1.0, min=0.0, max=1.0, step=0.01),
],
outputs=[
io.Image.Output("IMAGE"),
],
)
@classmethod
def execute(cls, image, strength):
result = image * strength
return io.NodeOutput(result)
V3 节点类结构
每个 V3 节点都需要:
- 继承自
io.ComfyNode define_schema(cls)—— 返回io.Schema的类方法execute(cls, ...)—— 执行计算的类方法
from typing_extensions import override
from comfy_api.latest import ComfyExtension, io
class ImageBrighten(io.ComfyNode):
@classmethod
def define_schema(cls):
return io.Schema(
node_id="ImageBrighten", # unique identifier
display_name="Brighten Image", # shown in UI
category="image/adjust", # menu path
description="Adjusts image brightness",
inputs=[
io.Image.Input("image"),
io.Float.Input("factor", default=1.2, min=0.0, max=3.0, step=0.1),
],
outputs=[
io.Image.Output("IMAGE"),
],
)
@classmethod
def execute(cls, image, factor):
result = torch.clamp(image * factor, 0.0, 1.0)
return io.NodeOutput(result)
io.Schema 字段
io.Schema(
node_id="UniqueNodeID", # required: unique string ID
display_name="Display Name", # optional: shown in UI menus
category="category/subcategory", # menu hierarchy (default "sd")
description="Node description", # optional: tooltip text
inputs=[...], # list of Input objects
outputs=[...], # list of Output objects
hidden=[...], # list of Hidden enum values
is_output_node=False, # True for nodes with side effects (save, preview)
is_experimental=False, # marks as experimental
is_deprecated=False, # marks as deprecated
is_dev_only=False, # hidden unless dev mode enabled
is_api_node=False, # marks as API-only node
is_input_list=False, # receive full lists instead of individual items
not_idempotent=False, # no cache sharing between identical instances (see lifecycle)
accept_all_inputs=False, # accept arbitrary inputs via **kwargs
enable_expand=False, # allow node expansion (subgraphs)
search_aliases=["alias1", "alias2"],# alternative search terms
essentials_category="Basic", # optional: Essentials tab category
price_badge=None, # optional: PriceBadge for API nodes
has_intermediate_output=False, # True for nodes with interactive UI that produce intermediate outputs
loop_boundary=None, # "start"/"end": core loop validation (v0.36+, experimental)
)
V3 节点注册
V3 节点通过 ComfyExtension 和 comfy_entrypoint() 注册:
from typing_extensions import override
from comfy_api.latest import ComfyExtension, io
class MyNode(io.ComfyNode):
@classmethod
def define_schema(cls):
return io.Schema(
node_id="MyNode",
display_name="My Node",
category="my_nodes",
inputs=[io.String.Input("text", multiline=True)],
outputs=[io.String.Output()],
)
@classmethod
def execute(cls, text):
return io.NodeOutput(text.upper())
class MyExtension(ComfyExtension):
@override
async def get_node_list(self) -> list[type[io.ComfyNode]]:
return [MyNode]
async def comfy_entrypoint() -> MyExtension:
return MyExtension()
comfy_entrypoint() 函数必须在模块级别定义(位于由 ComfyUI 直接导入的文件中)。
V1 节点结构(旧版参考)
V1 节点使用类属性和 NODE_CLASS_MAPPINGS:
class MyNodeV1:
CATEGORY = "my_category"
FUNCTION = "execute"
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("image",)
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"image": ("IMAGE",),
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0}),
}
}
def execute(self, image, strength):
return (image * strength,)
NODE_CLASS_MAPPINGS = {"MyNodeV1": MyNodeV1}
NODE_DISPLAY_NAME_MAPPINGS = {"MyNodeV1": "My Node V1"}
主要区别:V3 与 V1
| 方面 | V3 | V1 |
|---|---|---|
| 基类 | io.ComfyNode | 普通类 |
| 执行方法 | execute 类方法(固定名称) | 实例方法(通过 FUNCTION 自定义名称) |
| 输入 | io.Schema(inputs=[...]) | INPUT_TYPES() 字典 |
| 输出 | io.Schema(outputs=[...]) | RETURN_TYPES 元组 |
| 返回值 | io.NodeOutput(...) | 普通元组 |
| 注册 | ComfyExtension + comfy_entrypoint() | NODE_CLASS_MAPPINGS 字典 |
| 状态 | 无实例状态(类方法) | 允许实例状态 |
| 隐藏输入 | cls.hidden.prompt 等 | 来自 "hidden" 字典的 kwargs |
重要规则
node_id必须在所有节点中全局唯一execute()参数必须与输入 ID 完全匹配- V3 中所有方法都是
@classmethod(无实例状态) - 返回与输出数量匹配的
io.NodeOutput(val1, val2, ...) - 类别层级使用
/分隔符:"image/transform" - 在类别前加上
_,即可在菜单中隐藏:"_for_testing"
另请参阅
comfyui-node-datatypes- 数据类型(IMAGE、LATENT、MASK 等)comfyui-node-inputs- 输入配置详情comfyui-node-outputs- 输出类型和 UI 输出comfyui-node-packaging- 项目结构和打包comfyui-node-lifecycle- 执行生命周期和缓存
评论
支持 Markdown