mcpField
C
comfyui-node-basics

comfyui-node-basics

github.com/jtydhr88开发308136 次安装2 周前更新
代码仓库

关于 comfyui-node-basics

面向 ComfyUI 节点开发者的 V3 API 入门指南,说明节点类、Schema、执行方法与注册流程。并对照介绍 V1 结构及两种 API 的主要差异。

主要功能

  1. 01V3 节点类结构
  2. 02Schema 输入与输出配置
  3. 03ComfyExtension 注册
  4. 04V1 与 V3 结构对照

适用场景

  1. 01编写首个 V3 自定义节点
  2. 02定义节点输入、输出与类别
  3. 03将节点注册到 ComfyUI
  4. 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 节点都需要:

  1. 继承自 io.ComfyNode
  2. define_schema(cls) —— 返回 io.Schema 的类方法
  3. 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

方面V3V1
基类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