嘿,各位好!
想自己动手做个自定义节点,但在网上找不到多少资料,或者看到的都让人觉得太复杂?
我挺喜欢 ComfyUI 的,但不得不说,尽管它出来有几个月了,关于自定义节点的文档真的是糟糕到极点 x)。有些人甚至会说这简直是“地狱级”。
你可能会找到一个50分钟的视频(虽然挺不错但也不全面),但作为初学者,你肯定不想花这么长时间。
你可能会遇到一些不完整的指南,让你越看越糊涂。
甚至可能找到一些针对其他软件的自定义节点指南 x)。
还会有人建议你“直接去研究代码”,但这对初学者来说简直是噩梦,尤其是对 Python 还不太熟悉的情况下 ^^’。
但别担心。你只需等别人替你走过这段艰难的路,然后愿意分享他们的经验。幸运的是,我就是这样的人。这意味着我已经替你吃过这苦头了!
我保证,用不了五分钟,你就能制作出一个随时可用的自定义节点。
创建脚本
我们现在就开始吧,首先进入custom node的文件夹。在这里(先不要新建文件夹),创建一个新的文本文件。给它一个 .py 扩展名,随便取个名字(尽量避免空格和特殊字符)。然后打开这个文件。
任何文本编辑器都可以,但我推荐用 Notepad++(VSCode也行),它对代码的语法有更好的理解。
打开文件,现在是空白的。我们要开始编写代码了,让你的自定义节点在 Comfy 里出现!
...但在这之前,我们得先弄明白我们是怎么开始的:
我们来详细了解一下节点是什么:
节点(就是那个盒子)。
一个名字(实际上有四个名字,不过我们待会儿再说)。
变量,或者是小工具。
输入点。
输出点。
在 Python 代码里,节点是作为一个类来定义的。类名必须始终以大写字母开头,而且只能是一个词。它的样子大概是这样的:
ComfyUI 第一个自定义节点的基础框架 - https://pastebin.com/HML5CVzW
--
把所有这些代码复制粘贴到你的空白文件里。保存之后,打开 ComfyUI。
在你工作流的空白处双击,然后输入“Node”。你应该能在列表里看到 myNode!选它。恭喜你,你成功创建了你的第一个自定义节点!
...但目前来说,它还没那么有趣。我们来加点小工具吧!
创建小工具
变量或小工具,是在“required”这一行之后定义的。具体像这样:
"text": ("STRING", {"default":"Hey Hey!"}),
把这行代码复制下来,然后在你的代码里前面加上16个空格。这行代码必须放在与“required”这个词相关的括号之间。保存后,重启 ComfyUI。
如果你的节点变成红色,软件报错了,那就是你加的空格不够,或者没把这行代码复制到正确的位置。
如果没出错的话,你的自定义节点会变成这样:
如果我把小工具称作“变量”,那是因为你可以手动去改变它们。点击小工具,你就能改变里面的文本。
创建输入
现在我们来设想一下,如果我们想要一个真正的输入点,就是那种会出现一个点的那种。这其实很简单!输入点和小工具其实是一样的(因为小工具本质上也是一种输入,但我们暂时把它们当作两回事)。
你只需将默认设置改为“forceInput”: True。
在代码中的“required”部分,复制粘贴之前的那行(包括它前面的空格)。然后改一下名字(比如从“text”改成“text2”),把所有“default”部分删掉,换成上面的加粗文本。
你的代码行就变成了:
"text2": ("STRING", {"forceInput": True}),
这两个词会让 Comfy 知道这是个输入点而不是小工具。我们来看看它工作得怎么样!重启 Comfy。你会发现你的节点变了...
...但可能还没达到你想要的效果 ^^'。到目前为止,如果你的自定义节点已经在你的工作流里了,当你改变它的输入/小工具/输出时,它的表现可能会出现问题。
就是这样目前的情况。我在教程里提到这一点是因为你得知道这个规则:每次在自定义节点上工作的时候,测试之前一定要先把它从工作流中移除。
回到我们的例子。在 ComfyUI 里移除你的自定义节点。之前我们是双击来搜索它的,但这次我们不用这样做。如果我们想通过上下文菜单来找到它呢?我们来试试吧!
但我们应该去哪里找呢?为了找到答案,读一读代码。找到 CATEGORY 这一行。
找到了吗?如果你找到了,你就会发现我们的例子在“image/mynode2”这个类别下。
在 ComfyUI 里,右键点击你的工作流,然后点击 image。你会看到我们的自定义类别,mynode2!点击它,你就能找到我们这个小节点了。
选它。
现在我们弄明白了。自定义节点有一个名为 text2(或者你起的其他名字)的输入点。
如果我们不想只处理文本怎么办呢?这个我们待会儿再说,但现在,再读一遍我们的代码,你会发现输入/小工具有一个类型,这个例子中是:STRING。你把它改成 INT,输入/小工具就会变成一个整数。
现在你知道怎么添加输入了!下一步显然是学习如何处理输出。
创建输出
这些在类的 RETURN_TYPES 和 RETURN_LINES 这两行里定义。没错,就这两行!
在你的代码里,用下面这些内容填充 RETURN_TYPES 的括号:
"STRING", 'INT', 'FLOAT', 'LATENT'
你刚定义了四个输出,我想你可以猜到它们的类型了!如果你想多玩玩,还可以加更多。但有两个规则千万别忘了:
类型名总是要用大写字母写!
一定要用正确的类型!
你注意到了吗?每个输出的引号都不一样。这个没有规定,所以不用担心。这些符号是可以互换的。
你还可以把每个输出的名字改成你想要的。在 RETURN_LINES 这行,用下面这些内容填充括号:
"TxtO", "IntO", "FloatO", "Latent output. Really cool, huh?"
现在你要注意了,这行里的名字数量要跟你定义的输出类型数量一致。懂了吗?很好。
在 ComfyUI 里,把你的自定义节点移除,然后重启软件。再把自定义节点放回去。
太棒了!输出已经出现了!注意它们已经有了相应的颜色。潜在输出是粉色的;如果你尝试使用条件或图像输出,它们会自动变成橙色和蓝色。类似地,无色的输出已经在寻找兼容的节点。
你现在可以尝试一下:将字符串输出连接到一个与文本相关的节点,或者尝试潜在输出。
命名节点
我们快到了!现在我们需要看一下代码的最后部分:类映射和名称映射。
第一行,类映射,是你在类和节点名称之间创建配对的地方。
NODE_CLASS_MAPPINGS = {
"My First Node": MyNode
}
第一个值是你希望在软件中出现的名称,所以它可以是任何东西,只要确保它在引号之间。第二个必须是代码中定义的类名。
如果你有多个自定义节点,每个都必须在这里有一行,你需要定义在软件中显示的名称,并将其与类名配对。
我不确定第二行(名称映射)是干什么的。你甚至可以让它空着,运行程序时它不会报错。我会让更有知识的人向我们解释^^’。
最后的问题
现在,还有一个最后的问题。目前,我们的自定义节点在自定义节点的默认文件夹中。如果你想把它放在自己的文件夹里怎么办?让我们试试。
创建一个新文件夹,将你的脚本文件拖进去。如果你现在重启 ComfyUI,它会给你一个错误。
为什么?
因为程序需要一个初始化文件来理解该文件夹中的脚本必须被使用。
为什么?
因为...因为 x)。(因为 Python 是狗屎,但我们被困在其中,所以我们必须忍受,因为它实际上无处不在。)
现在让我们来做这件事。在你的自定义节点文件夹中,创建一个新的文本文件,并精确地将其命名为:
init.py
打开它,并复制粘贴这段代码:
from .myfirstnode import MyNode
NODE_CLASS_MAPPINGS = { "MyNode": MyNode }
NODE_DISPLAY_NAME_MAPPINGS = { "FirstNode": "My First Node" }
all = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
--
这里有几个规则需要理解:
在第一行中,点后面的单词必须是你的脚本名称。
在第一行的 import 之后,你必须有你在 python 脚本中定义的所有类的列表,用逗号分隔。
如果你有多个脚本,你必须写几次这一行,每个脚本一次。
相反,对于其他行,你只需要一行。
节点类映射行必须包括你在脚本中定义的所有类映射。只需复制粘贴它们并用逗号分隔。
显示名称映射的工作方式类似。
这两行是初始化文件中的必需内容。注意,它们会覆盖原始脚本中定义的内容。所以一旦你的自定义节点在自己的文件夹中,你必须在初始化文件中定义节点/类名对。
你永远不应该触碰“all行”。
结论
就这样!有了这些,你可以在 ComfyUI 中创建任何东西!当然,我们所做的只是基本框架。
然后,还有肉!你可以使用代码让那个节点做任何你想做的事。绝对每一个 Python 函数都可以工作!而且有了 Python,你甚至可以使用其他语言,比如 javascript(对于视觉效果至关重要)。
但这是你必须自己学习的东西。编程是一种语言;作为一种语言,它极其多样化,你永远不会真正了解它的全部。但就像真正的语言一样,你可以立即从简单的东西开始,并逐步学习!
不过我会给出一些关于 Python 的规则:
空格很重要!
绝对不要用制表符缩进你的行。用多个空格。在 Notepad++ 中,每个缩进键入四次空格。绝对不要用制表符。我花了整整一天的时间来修复一个实际上完美的代码,只是因为我使用了制表符!!!
这些都是纯 Python 规则。但 ComfyUI 也有自己的一套规则。通过这个指南,我们已经回顾了很多,但这里还有一些其他的:
如果你想创建一个自定义节点的包,你不需要有多个脚本。重要的是你有一个类 PER CUSTOM NODE。
一个类有输入、输出和至少一个函数。在我们的代码中可以看到:
FUNCTION = “test”
这行意味着自定义节点应用了这个脚本中定义的名为“test”的函数。
为了让你的自定义节点真正做些什么,你需要确保这行调用的函数实际上做了你想做的事。
如果它是两个输入的总和,例如,总和必须由它调用。
FUNCTION = “mysum”
def sum(self, a,b)
c = a+b
return c
这个代码示例不会工作,因为该函数不是这个自定义节点调用的。然而,你可以创建一个“mysum”函数,最终调用 sum(a,b) 函数。
- 我认为一个函数必须始终将“self”作为其第一个参数。我不确定为什么,也不知道这是特定于 Comfy 还是 Python 的通用规则。无论如何,每当你定义一个函数时,永远不要忘记 self 参数!
我只是触及了表面,但通过个人经验,你会走得更远!现在我将你推荐给这个指南:
https://github.com/chrisgoringe/Comfy-Custom-Node-How-To/wiki
它不完整,所以一开始看起来很吓人,但它包含了很多关于为 ComfyUI 编码的有用信息。毕竟是由一个制作自己的自定义节点的人编写的!
我还会分享一个自定义节点“模板”:
https://drive.google.com/drive/folders/1IfETXm_WFKZNRT1mszXjF_46LxbnGmiA?usp=sharing
这是我们在本教程中使用的自定义节点(经过一些小调整)。每当你想从头开始时,只需将其提取到 custom_nodes 文件夹中,它就可以立即工作。然后你只需要修改脚本!
最后,这里有一些练习供你训练。重写我们刚刚创建的自定义节点,并用它解决这些问题。
将一个小部件转换为输入点。
添加三个输出:一个图像,一个条件,一个模型。
3)
这是一个自定义节点的代码:
ComfyUI 自定义节点基本框架 - https://pastebin.com/rL1CPQhy
--
重写它,使其工作。提示:有三个错误需要修复。
玩得开心,我希望这能帮助到那些有创造力的人^^。
来源:https://www.reddit.com/r/comfyui/comments/18wp6oj/tutorial_create_a_custom_node_in_5_minutes/